2009-10-02 85 views
2

要收到賞金,請提供工作代碼的答案。謝謝。如何將stdole.StdPicture轉換爲其他類型?

我有一個類型爲vbPicTypeIcon的stdole.StdPicture對象。我需要將其轉換爲Type vbPicTypeBitmap。由於項目限制,我需要使用Win32或VBA來完成這項工作。我正試圖將文件的圖標加載到命令欄按鈕。這是我到目前爲止。它產生了一個可愛的黑色方塊:)我對圖形領域非常陌生,所以如果這是一個基本問題,請原諒我。

Option Explicit 

Private Const vbPicTypeBitmap As Long = 1 
Private Const vbPicTypeIcon As Long = 3 

Private Const SHGFI_ICON As Long = &H100& 
Private Const SHGFI_SMALLICON As Long = &H1& 

Private Type PICTDESC 
    cbSize As Long 
    pictType As Long 
    hIcon As Long 
    hPal As Long 
End Type 

Private Type typSHFILEINFO 
    hIcon As Long 
    iIcon As Long 
    dwAttributes As Long 
    szDisplayName As String * 260 
    szTypeName As String * 80 
End Type 

Private Declare Function DestroyIcon Lib "user32" (ByVal hIcon As Long) As Long 
Private Declare Function SHGetFileInfoA Lib "shell32.dll" (ByVal pszPath As String, ByVal dwFileAttributes As Long, psfi As typSHFILEINFO, ByVal cbSizeFileInfo As Long, ByVal uFlags As Long) As Long 
Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (lpPictDesc As PICTDESC, riid As Any, ByVal fOwn As Long, ipic As stdole.IPictureDisp) As Long 

Public Sub Test() 
    Dim btn As Office.CommandBarButton 
    Dim lngRslt As Long 
    Dim lngAppInstc As Long 
    Dim strFilePath As String 
    Dim tFI As typSHFILEINFO 
    Dim pic As stdole.IPictureDisp 
    Set btn = TestEnv.GetTestButton 
    lngAppInstc = Excel.Application.Hinstance 
    strFilePath = TestEnv.GetTestFile 
    If LenB(strFilePath) = 0& Then 
     Err.Raise 70& 
    End If 
    SHGetFileInfoA strFilePath, 0&, tFI, LenB(tFI), SHGFI_ICON Or SHGFI_SMALLICON 
    Set pic = IconToPicture(tFI.hIcon) 
    btn.Picture = pic 
Exit_Proc: 
    On Error Resume Next 
    If tFI.hIcon Then 
     lngRslt = DestroyIcon(tFI.hIcon) 
    End If 
    Exit Sub 
Err_Hnd: 
    MsgBox Err.Description, vbCritical Or vbMsgBoxHelpButton, Err.Number, Err.HelpFile, Err.HelpContext 
    Resume Exit_Proc 
    Resume 
End Sub 

Private Function IconToPicture(ByVal hIcon As Long) As stdole.IPictureDisp 
    'Modified from code by Francesco Balena on DevX 
    Dim pic As PICTDESC 
    Dim guid(0 To 3) As Long 
    Dim pRtnVal As stdole.IPictureDisp 
    pic.cbSize = LenB(pic) 
    'pic.pictType = vbPicTypeBitmap 
    pic.pictType = vbPicTypeIcon 
    pic.hIcon = hIcon 
    ' this is the IPicture GUID {7BF80980-BF32-101A-8BBB-00AA00300CAB} 
    ' we use an array of Long to initialize it faster 
    guid(0) = &H7BF80980 
    guid(1) = &H101ABF32 
    guid(2) = &HAA00BB8B 
    guid(3) = &HAB0C3000 
    ' create the picture, 
    ' return an object reference right into the function result 
    OleCreatePictureIndirect pic, guid(0), True, pRtnVal 
    Set IconToPicture = pRtnVal 
End Function 
+0

我下面的代碼,在需要時清理,只使用API​​和不正是你想要的。樣本中只有一個表格和一個圖片框才能證明其有效。 – jac

+0

嗨Beaner,有很多編輯,所以你可能錯過了它。但解決方案必須在VBA中工作。 VBA沒有優化校準。不幸的是我爲什麼要問這個問題:)抱歉有任何混淆。 – Oorang

+0

您可能錯過了它,但picturebox不再是轉換的一部分。我將它放在那裏以顯示示例中的轉換圖像。就像我說的,我沒有時間清理代碼。現在它已經被清理了一些,我完全刪除了picturebox以消除混淆。轉換是所有WinAPI – jac

回答

1

在vbAccelerator.com上給this post一槍。

編輯:我發現VBA最接近的東西是officeblogs.net。該代碼雖然採取圖標,而不是圖標句柄。

+0

嗨C磅。也許我應該提到我需要這個解決方案來在VBA中工作。這是造成這個問題的原因。不幸的是,VBA無法訪問圖片對象。這就是爲什麼我特意嘗試使用stdole.IPictureDisp。是否有可能讓你提到的代碼產生正確的對象? – Oorang

+0

對不起,只有VB的鏈接。我添加了一些可能適用於VBA的編輯。 –

+0

嗨CPG, 再次,我們都圍繞這個問題,但不是那裏。這是VB.Net代碼。我可以編寫它並編譯它,但是我分發了一個額外的文件(正如前面提到的,我試圖避免)。它還帶回一個Icon類型的StdPicture。深入潛水後,我意識到爲什麼圖片屬性的分配不起作用是因爲StdPicture對象需要是位圖類型。所以據我可以告訴問題歸結爲試圖找出如何轉換所述圖標。我結束了使用SHGetFileInfoA到右邊16X16圖標句柄然後 Oorang

1

好的,我清理了代碼。 ExtractAssociatedIcon方法返回一個64x64圖標,因此對於我剛剛硬編碼該示例的示例。圖片框已被刪除,圖像被分配到表單的圖片屬性,以避免混淆。

實施例:將代碼複製到一個新的窗體並運行

Option Explicit 

Private Declare Function ExtractAssociatedIcon Lib "shell32.dll" Alias "ExtractAssociatedIconA" (ByVal hInst As Long, ByVal lpIconPath As String, lpiIcon As Long) As Long 
Private Declare Function DestroyIcon Lib "user32" (ByVal hIcon As Long) As Long 
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long 
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long 
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long 
Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long 
Private Declare Function FillRect Lib "user32" (ByVal hdc As Long, lpRect As RECT, ByVal hBrush As Long) As Long 
Private Declare Function DrawIconEx Lib "user32" (ByVal hdc As Long, ByVal xLeft As Long, ByVal yTop As Long, ByVal hIcon As Long, ByVal cxWidth As Long, ByVal cyWidth As Long, ByVal istepIfAniCur As Long, ByVal hbrFlickerFreeDraw As Long, ByVal diFlags As Long) As Long 
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long 
Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (ByRef PicDesc As PICTDESC_BMP, ByRef RefIID As GUID, ByVal fPictureOwnsHandle As Long, ByRef IPic As IPicture) As Long 

Private Type GUID 
    Data1 As Long 
    Data2 As Integer 
    Data3 As Integer 
    Data4(7) As Byte 
End Type 

Private Type PICTDESC_BMP 
    Size As Long 
    Type As Long 
    hBmp As Long 
    hPal As Long 
    Reserved As Long 
End Type 

Const DI_MASK = &H1 
Const DI_IMAGE = &H2 
Const DI_NORMAL = DI_MASK Or DI_IMAGE 

Private Type RECT 
     Left As Long 
     Top As Long 
     Right As Long 
     Bottom As Long 
End Type 

Private Sub Form_Load() 

    Call GetIcon("C:\Program Files\Internet Explorer\iexplore.exe") 

End Sub 

Private Sub GetIcon(ByVal sFileName As String) 
    Dim hIcon As Long 
    Dim hAssocIcon As Long 
    Dim sAssocFile As String * 260 
    Dim sCommand As String 
    Dim lDC As Long 
    Dim lBmp As Long 
    Dim R As RECT 
    Dim OldBMP As Long 

    Me.AutoRedraw = True 
    hIcon = ExtractAssociatedIcon(App.hInstance, sFileName, hAssocIcon) 
    If hIcon <> 0 Then 'no icons found - use icon generic icon resource 
     'Create a device context, compatible with the screen 
     lDC = CreateCompatibleDC(GetDC(0&)) 
     'Create a bitmap, compatible with the screen 
     lBmp = CreateCompatibleBitmap(GetDC(0&), 64, 64) 
     'Select the bitmap into the device context 
     OldBMP = SelectObject(lDC, lBmp) 
     ' Set the rectangles' values 
     R.Left = 0 
     R.Top = 0 
     R.Right = 64 
     R.Bottom = 64 
     ' Fill the rect with white 
     FillRect lDC, R, 0 
     ' Draw the icon 
     Call DrawIconEx(lDC, 0, 0, hIcon, 64, 64, 0, 0, DI_NORMAL) 
     Me.Picture = PictureFromBitmap(lBmp, 0&) 
     DestroyIcon (hIcon) 
    End If 
    Call SelectObject(lDC, OldBMP) 
    Call DeleteObject(lDC) 

End Sub 

Private Function PictureFromBitmap(ByVal hBmp As Long, ByVal hPal As Long) As StdPicture 
    Dim IPictureIID As GUID 
    Dim IPic As IPicture 
    Dim tagPic As PICTDESC_BMP 
    Dim lpGUID As Long 

    ' Fill in the IPicture GUID 
    ' {7BF80980-BF32-101A-8BBB-00AA00300CAB} 
    With IPictureIID 
     .Data1 = &H7BF80980 
     .Data2 = &HBF32 
     .Data3 = &H101A 
     .Data4(0) = &H8B 
     .Data4(1) = &HBB 
     .Data4(2) = &H0 
     .Data4(3) = &HAA 
     .Data4(4) = &H0 
     .Data4(5) = &H30 
     .Data4(6) = &HC 
     .Data4(7) = &HAB 
    End With 

    ' Set the properties on the picture object 
    With tagPic 
     .Size = Len(tagPic) 
     .Type = vbPicTypeBitmap 
     .hBmp = hBmp 
     .hPal = hPal 
    End With 

    ' Create a picture that will delete it's bitmap when it is finished with it 
    Call OleCreatePictureIndirect(tagPic, IPictureIID, 1, IPic) 

    ' Return the picture to the caller 
    Set PictureFromBitmap = IPic 
End Function 
+0

嗨,謝謝你的回覆。這是我想要的道路,但不是將圖標加載到Picture控件中,而是試圖將它加載到Office.CommandBarButton.Picture中,這是一個IPictureDisp對象。 – Oorang

+0

我只是建議你使用這種方法,以隱藏的Picturebox加載你的圖標,然後使用「Clipboard.Clear」,Clipboard.SetData(Picture1.Picture,vbCFBitmap)和CommandBarControl.PasteFace將圖標放到你的按鈕上。 – jac

+0

嗨Beaner,這個問題的一個限制是它也必須在VBA中工作。很遺憾,VBA無法訪問圖片對象。這就是爲什麼我試圖將一個圖標句柄合併到stdole.IPictureDisp中。 – Oorang

0

LoadPicture它返回支持IPictureDisp的對象。它可能不是vbPicTypeBitmap。不確定您是否可以在VBA中調用GdipCreateBitmapFromFile。

+0

你好,LoadPicture只適用於這些文件類型:bmp,ico,cur,rle,wmf,emf,gif&jpg。由於我從Exes拉我的圖標,我需要有一種方法來保存圖標句柄中的文件。如果你知道如何解決這個問題,我會考慮解決方案。 – Oorang

+0

嘗試GdipCreateBitmapFromHICON/GdipSaveImageToFile –

0

在Google Groups上搜索標題爲Convert StdPicture from Icon to Bitmap的主題。

UPDATE

不,我不能讓它工作。

但是當我正在嘗試它時,我感到了一種可怕的似曾相識......然後想起我幾年前肯定做過這樣的事情,即在運行時向面向Excel的CommandBarButtons添加帶有面具的圖標,不知道哪個版本的Excel它被打開了。可悲的是我找不到代碼(不是在源代碼控制中,所以沒有發佈它?我幾乎可以肯定我的工作)。

我想我在這些文章中大量舉債:

How To Create a Transparent Picture For Office CommandBar Buttons

How To Set the Mask and Picture Properties for Office XP CommandBars

而且由於Excel有沒有剪貼板中,我似乎記得從斯蒂芬·布倫的PastePicture.zip借款。

希望這不會給你關上一雁追逐:)

+0

這看起來很有前途,但我無法將它變成一個有效的示例。雖然我確實想出了一種方法來讓Excel以一貫的方式崩潰到桌面:)請您提供一個可用的示例嗎? – Oorang

+0

我絕對想要避開剪貼板。劫持它是一種可怕的做法。我考慮的另一種方法是試圖將圖標保存到臨時文件夾,然後使用加載圖片。但它仍然需要保存爲位圖才能正確加載。然而,因爲這將是另一個研究問題,我想我會保存這個計劃B. – Oorang

相關問題