Option Explicit
#If VBA7 Then
Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hDC As LongPtr) As Long
Private Declare PtrSafe Function CreateCompatibleBitmap Lib "gdi32" (ByVal hDC As LongPtr, ByVal nWidth As Long, ByVal nHeight As Long) As LongPtr
Private Declare PtrSafe Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As LongPtr) As LongPtr
Private Declare PtrSafe Function DeleteDC Lib "gdi32" (ByVal hDC As LongPtr) As Long
Private Declare PtrSafe Function DeleteObject Lib "gdi32" (ByVal hObject As LongPtr) As Long
Private Declare PtrSafe Function SelectObject Lib "gdi32" (ByVal hDC As LongPtr, ByVal hObject As LongPtr) As LongPtr
Private Declare PtrSafe Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hUF As LongPtr) As Long
Private Declare PtrSafe Function GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
Private Declare PtrSafe Function PrintWindow Lib "user32" (ByVal hwnd As LongPtr, ByVal hdcBlt As LongPtr, ByVal nFlags As Long) As Long
Private Declare PtrSafe Function OleCreatePictureIndirect Lib "oleaut32.dll" (PicDesc As uPicDesc, RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long
Private Declare PtrSafe Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
#Else
Private Enum LongPtr
[_]
End Enum
Private Declare Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hDC As LongPtr) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hDC As LongPtr, ByVal nWidth As Long, ByVal nHeight As Long) As LongPtr
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As LongPtr) As LongPtr
Private Declare Function DeleteDC Lib "gdi32" (ByVal hDC As LongPtr) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As LongPtr) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As LongPtr, ByVal hObject As LongPtr) As LongPtr
Private Declare Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hUF As LongPtr) As Long
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
Private Declare Function PrintWindow Lib "user32" (ByVal hwnd As LongPtr, ByVal hdcBlt As LongPtr, ByVal nFlags As Long) As Long
Private Declare Function OleCreatePictureIndirect Lib "oleaut32.dll" (PicDesc As uPicDesc, RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long
Private Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
#End If
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type uPicDesc
Size As Long
Type As Long
hPic As LongPtr
hPal As LongPtr
End Type
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
Private Sub CommandButton1_Click()
Dim sPath As String, sFile As String
sPath = ThisWorkbook.Path
sFile = "FormPicTest.bmp"
If SaveUserFormToDisk(Me, sPath, sFile) Then
MsgBox "UserForm Image saved as: " & sPath & sFile, vbInformation, "SaveUserFormToDisk."
Else
MsgBox "Failed to save UserForm Image to disk.", vbCritical
End If
End Sub
Private Function SaveUserFormToDisk( _
ByVal Form As UserForm, _
ByRef Path As String, _
ByVal FileName As String, _
Optional ByVal FullContent As Boolean = True _
) As Boolean
Const PICTYPE_BITMAP = &H1
Const CF_BITMAP = &H2
Const S_OK = &H0
Const PW_CLIENTONLY = &H1
Const PW_RENDERFULLCONTENT = &H2
Const INVALID_FILE_ATTRIBUTES = -1&
Dim IID_IDispatch As GUID, uPicInfo As uPicDesc
Dim stdPic As StdPicture, lRet As Long
Dim hwnd As LongPtr, hDC As LongPtr, hMemDc As LongPtr
Dim hMemBmp As LongPtr, hPrevBmp As LongPtr
Dim tRect As RECT
On Error GoTo errHandler
If Right(Path, 1) <> "\" Then Path = Path & "\"
Call IUnknown_GetWindow(Form, VarPtr(hwnd))
hDC = GetDC(hwnd)
Call GetWindowRect(hwnd, tRect)
With tRect
hMemBmp = CreateCompatibleBitmap(hDC, .Right - .Left, .Bottom - .Top)
End With
hMemDc = CreateCompatibleDC(hDC)
hPrevBmp = SelectObject(hMemDc, hMemBmp)
Call PrintWindow(hwnd, hMemDc, IIf(FullContent, PW_RENDERFULLCONTENT, PW_CLIENTONLY))
With IID_IDispatch: .Data1 = &H20400: .Data4(0) = &HC0: .Data4(7) = &H46: End With
With uPicInfo: .Size = Len(uPicInfo): .Type = PICTYPE_BITMAP: .hPic = hMemBmp: .hPal = CF_BITMAP: End With
lRet = OleCreatePictureIndirect(uPicInfo, IID_IDispatch, True, stdPic)
If lRet = S_OK Then
stdole.SavePicture stdPic, Path & FileName
If GetFileAttributes(Path & FileName) <> INVALID_FILE_ATTRIBUTES Then
SaveUserFormToDisk = True
End If
End If
errHandler:
Call SelectObject(hMemDc, hPrevBmp)
Call DeleteObject(hMemBmp)
Call DeleteDC(hMemDc)
Call ReleaseDC(hwnd, hDC)
End Function