カスタム検索
リボン関連

ボタンのイメージを外部から読み込む(PNG対応版)

ボタンのイメージを外部から読み込む」でボタンの画像を外部から読み込む方法を紹介しましたが、今回はPNG形式にも対応した方法を紹介します。

 

1. Office 2007ファイルを開きます(今回はExcelファイル)。
2. 標準モジュールに下記コードを貼り付けて上書き保存した後、ファイルを閉じます。

Private Declare Function GdipCreateBitmapFromFile Lib "GDIPlus" (ByVal filename As Long, bitmap As Long) As Long
Private Declare Function GdipCreateHBITMAPFromBitmap Lib "GDIPlus" (ByVal bitmap As Long, hbmReturn As Long, ByVal background As Long) As Long
Private Declare Function GdipDisposeImage Lib "GDIPlus" (ByVal image As Long) As Long
Private Declare Function GdiplusShutdown Lib "GDIPlus" (ByVal token As Long) As Long
Private Declare Function GdiplusStartup Lib "GDIPlus" (token As Long, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
Private Declare Function IIDFromString Lib "ole32" (ByVal lpsz As Long, lpiid As Any) As Long
Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (PicDesc As PICTDESC, RefIID As Long, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long

Private Const IID_IPictureDisp As String = "{7BF80981-BF32-101A-8BBB-00AA00300CAB}"
Private Const PICTYPE_BITMAP As Long = 1

Private Type PICTDESC
  Size As Long
  Type As Long
  hPic As Long
  hPal As Long
End Type

Private Type GdiplusStartupInput
  GdiplusVersion As Long
  DebugEventCallback As Long
  SuppressBackgroundThread As Long
  SuppressExternalCodecs As Long
End Type

Private Function ConvertToIPicture(ByVal hPic As Long) As IPicture
  Dim IID(0 To 3) As Long
  Dim IPic As IPicture
  Dim uPicInfo As PICTDESC
  
  With uPicInfo
    .Size = Len(uPicInfo)
    .Type = PICTYPE_BITMAP
    .hPic = hPic
    .hPal = 0&
  End With
  
  Call IIDFromString(StrPtr(IID_IPictureDisp), IID(0))
  Call OleCreatePictureIndirect(uPicInfo, IID(0), True, IPic)
  Set ConvertToIPicture = IPic
End Function

Private Function LoadImage(ByVal strFName As String) As IPicture
  Dim uGdiInput As GdiplusStartupInput
  Dim hGdiPlus As Long
  Dim hGdiImage As Long
  Dim hBitmap As Long

  uGdiInput.GdiplusVersion = 1&

  If GdiplusStartup(hGdiPlus, uGdiInput) = 0& Then
    If GdipCreateBitmapFromFile(StrPtr(strFName), hGdiImage) = 0& Then
      Call GdipCreateHBITMAPFromBitmap(hGdiImage, hBitmap, 0&)
      Set LoadImage = ConvertToIPicture(hBitmap)
      Call GdipDisposeImage(hGdiImage)
    End If
    Call GdiplusShutdown(hGdiPlus)
  End If
End Function

Sub myButton_getImage(control As IRibbonControl, ByRef image)
  Set image = LoadImage("M:\Images\image.png")
End Sub
※ 上記コードでは「M:\Images\image.png」を読み込みます。

3. Custom UI Editor Toolで2.のファイルを開きます。
4. 下記コードを貼り付け、上書き保存します。
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
  <ribbon startFromScratch="false">
    <tabs>
      <tab id="customTab" label="Custom Tab" insertBeforeMso="TabHome">
        <group id="customGroup" label="Custom Group">
          <button id="myButton" label="My Button" getImage="myButton_getImage" size="large" onAction="myButton_onAction" />
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>
5. 4.のファイルをマクロを有効にして開くとCustom Tabタブの「My Button」ボタンに、2.のコードで指定した画像が表示されていることが確認できます。

以上で作業は終了です。
上記のように「getImage」属性で指定したプロシージャ内でLoadImage関数を使って画像を指定すれば、透過PNG等のLoadPicture関数では対応していない画像も外部から読み込むことができます。
なお、LoadImage関数は下記Webページのコードを参考にさせていただきました。

[getImage and VBA Callback - Greg Maxey]
http://www.eggheadcafe.com/software/aspnet/32977416/getimage-and-vba-callback.aspx