问题 有没有办法用vba在MS-Access中截取屏幕截图?


我想使用vba截取屏幕截图(然后将其作为电子邮件附件发送)。理想情况下,我想截取只有活动表单的屏幕截图。有没有办法做到这一点?


6454
2018-03-16 18:19


起源

你需要这个自动化吗?这就是为什么你不能使用Alt + PrintScreen? - Matthew Jones
是的,它必须是自动化的。我想把它放在代码中,以便当用户执行某个操作时,会截取屏幕截图并通过电子邮件发送给管理员。 - dmr
或者快照可以作为bmp保存到错误消息表中。连同其他信息,如活动表格名称,工作站编号,用户ID,日期/时间等。 - Tony Toews
我在我的博客上发布了这个主题的摘要,并收到了以下回复。我用Stephan Lebans(OLEToDisk)代码做一个例子来获取截图并转换为JPG并最终发送到电子邮件您可以在这里下载:(Access XP) logicielappui.com/tips/AccXP_Notification.zip (法语)我希望这会对你有所帮助。罗伯特西玛德 - Tony Toews


答案:


您必须使用Windows API调用才能执行此操作。以下代码适用于MS Access 2007.它将保存BMP文件。

Option Compare Database
Option Explicit

Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal _
  bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)

Private Const VK_SNAPSHOT = &H2C

Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long

Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Integer) As Long

Private Declare Function CloseClipboard Lib "user32" () As Long

Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" _
(PicDesc As uPicDesc, RefIID As GUID, ByVal fPictureOwnsHandle As Long, _
IPic As IPicture) As Long

'\\ Declare a UDT to store a GUID for the IPicture OLE Interface
Private Type GUID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(0 To 7) As Byte
End Type

'\\ Declare a UDT to store the bitmap information
Private Type uPicDesc
    Size As Long
    Type As Long
    hPic As Long
    hPal As Long
End Type

Private Const CF_BITMAP = 2
Private Const PICTYPE_BITMAP = 1

Sub PrintScreen()
    keybd_event VK_SNAPSHOT, 1, 0, 0
End Sub

Public Sub MyPrintScreen(FilePathName As String)

    Call PrintScreen

    Dim IID_IDispatch As GUID
    Dim uPicinfo As uPicDesc
    Dim IPic As IPicture
    Dim hPtr As Long

    OpenClipboard 0
    hPtr = GetClipboardData(CF_BITMAP)
    CloseClipboard

    '\\ Create the interface GUID for the picture
    With IID_IDispatch
        .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

    '\\ Fill uPicInfo with necessary parts.
    With uPicinfo
        .Size = Len(uPicinfo) '\\ Length of structure.
        .Type = PICTYPE_BITMAP '\\ Type of Picture
        .hPic = hPtr '\\ Handle to image.
        .hPal = 0 '\\ Handle to palette (if bitmap).
    End With

   '\\ Create the Range Picture Object
   OleCreatePictureIndirect uPicinfo, IID_IDispatch, True, IPic

    '\\ Save Picture Object
    stdole.SavePicture IPic, FilePathName

End Sub

有一个 知识库文章 进一步深入。


10
2018-03-16 18:46



很抱歉从死里复活,但这对Access 2003也有用吗?如果没有,我可以让它工作吗? - Magisch
我刚刚完成了代码..我不明白为什么只要DLL存在就无法在Access 2003中运行。你有没有尝试过? - Raj More
实施工作....粗略。如果剪贴板内容实际上是一个打印屏幕,那里没有检查,但这很好,因为你直接调用它。我现在留下的主要问题是由此产生的图像文件很大...大约6mb用于完整的打印屏幕。从我对Access 2003的看法来看,没有内置的方法可以将IPicture变成.png并压缩它,你碰巧知道吗? - Magisch
您可以根据此答案调整代码 stackoverflow.com/questions/12813280/... - Raj More
顺便说一句,你的回答和后续的帮助对我构建一个今天在相对紧迫的时间限制下投入生产的模块有很大帮助。所以,另外我要感谢你给这个答案100点奖励:) - Magisch


使用raj的示例获取图像然后将其保存

Dim oPic
On Error Resume Next
Set oPic = Clipboard.GetData
On Error GoTo 0
If oPic Is Nothing Then
  'no image in clipboard'
Else
  SavePicture oPic, "c:\temp\pic.bmp"
end if

1
2018-03-16 18:53



什么是 PastePicture? - Raj More
这是一个外部的lib,我编辑了我的原始帖子 - bugtussle