使用 SharpDX 在屏幕捕获中包含鼠标光标
Include mouse cursor in screen capture using SharpDX
我正在使用 ScreenCapture sample of SharpDX 库来截取全屏游戏的屏幕截图(因为常见的 GDI+ 捕获技术在这里不起作用, 即使是 Windows 默认的 "Print" 键也无法正确截取游戏的屏幕截图。
我在我的应用程序中使用的代码与上面链接的官方示例(翻译为 VB.NET)几乎相同,因此我认为没有必要在这里发布相同的代码块。
我遇到的问题是我想在捕获的图像中包含鼠标光标。
也许 SharpDX 有一些方法或 property/parameter 以友好的方式包含鼠标光标?如果没有,那么考虑到鼠标如何实现这一点游戏光标是个性化的(不是默认的白色Windows箭头)?
您可以利用 WinAPI 的 GetCursorInfo()
function to get a handle to the current cursor. By then calling Icon.FromHandle()
并将光标句柄作为参数传递,您将获得作为可绘制图标的光标。
由于不同的光标可能有不同的热点,您也必须考虑到这一点。为此,您可以使用 WinAPI 的 GetIconInfo()
函数获取热点的 X 和 Y 坐标,然后您只需用热点位置减去光标位置即可。
光标绘制方法:
Public Shared Sub DrawCursor(ByVal Graphics As Graphics)
Dim CursorInfo As New NativeMethods.CURSORINFO With {.cbSize = Marshal.SizeOf(GetType(NativeMethods.CURSORINFO))}
'Get the cursor info.
If NativeMethods.GetCursorInfo(CursorInfo) = True Then
Using CursorIcon As System.Drawing.Icon = System.Drawing.Icon.FromHandle(CursorInfo.hCursor) 'Get the cursor icon.
Dim IconInfo As New NativeMethods.ICONINFO
Try
Dim ModifierPoint As New Point(0, 0) 'Declare the modifier point (the cursor's hotspot).
'Get the info for the cursor icon.
If NativeMethods.GetIconInfo(CursorInfo.hCursor, IconInfo) = True Then
If IconInfo.fIcon = False Then 'If the cursor is an icon the hotspot will always be (0, 0).
ModifierPoint = New Point(IconInfo.xHotspot, IconInfo.yHotspot) 'Set the hotspot modifier.
End If
End If
'Normalize the coordinates according to the hotspot.
Dim FinalPoint As New Point(CursorInfo.ptScreenPos.x - ModifierPoint.X, CursorInfo.ptScreenPos.y - ModifierPoint.Y)
'Draw the cursor.
Graphics.DrawIcon(CursorIcon, New Rectangle(FinalPoint, CursorIcon.Size))
Finally
'Some cleaning up...
If IconInfo.hbmMask <> IntPtr.Zero Then
NativeMethods.DeleteObject(IconInfo.hbmMask)
IconInfo.hbmMask = IntPtr.Zero
End If
If IconInfo.hbmColor <> IntPtr.Zero Then
NativeMethods.DeleteObject(IconInfo.hbmColor)
IconInfo.hbmColor = IntPtr.Zero
End If
End Try
End Using
End If
End Sub
NativeMethods.vb:
Imports System.Runtime.InteropServices
Public NotInheritable Class NativeMethods
<StructLayout(LayoutKind.Sequential)> _
Public Structure POINT
Public x As Integer
Public y As Integer
End Structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure CURSORINFO
Public cbSize As Integer
Public flags As Integer
Public hCursor As IntPtr
Public ptScreenPos As POINT
End Structure
<DllImport("user32.dll")> _
Public Shared Function GetCursorInfo(ByRef pci As CURSORINFO) As Boolean
End Function
<StructLayout(LayoutKind.Sequential)> _
Public Structure ICONINFO
Public fIcon As Boolean
Public xHotspot As Integer
Public yHotspot As Integer
Public hbmMask As IntPtr
Public hbmColor As IntPtr
End Structure
<DllImport("user32.dll")> _
Public Shared Function GetIconInfo(ByVal hIcon As IntPtr, ByRef piconinfo As ICONINFO) As Boolean
End Function
<DllImport("gdi32.dll")> _
Public Shared Function DeleteObject(ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
End Class
如果你截取结果截图,你会像这样在上面画光标:
Using g As Graphics = Graphics.FromImage(yourImage)
DrawCursor(g)
End Using
我正在使用 ScreenCapture sample of SharpDX 库来截取全屏游戏的屏幕截图(因为常见的 GDI+ 捕获技术在这里不起作用, 即使是 Windows 默认的 "Print" 键也无法正确截取游戏的屏幕截图。
我在我的应用程序中使用的代码与上面链接的官方示例(翻译为 VB.NET)几乎相同,因此我认为没有必要在这里发布相同的代码块。
我遇到的问题是我想在捕获的图像中包含鼠标光标。
也许 SharpDX 有一些方法或 property/parameter 以友好的方式包含鼠标光标?如果没有,那么考虑到鼠标如何实现这一点游戏光标是个性化的(不是默认的白色Windows箭头)?
您可以利用 WinAPI 的 GetCursorInfo()
function to get a handle to the current cursor. By then calling Icon.FromHandle()
并将光标句柄作为参数传递,您将获得作为可绘制图标的光标。
由于不同的光标可能有不同的热点,您也必须考虑到这一点。为此,您可以使用 WinAPI 的 GetIconInfo()
函数获取热点的 X 和 Y 坐标,然后您只需用热点位置减去光标位置即可。
光标绘制方法:
Public Shared Sub DrawCursor(ByVal Graphics As Graphics)
Dim CursorInfo As New NativeMethods.CURSORINFO With {.cbSize = Marshal.SizeOf(GetType(NativeMethods.CURSORINFO))}
'Get the cursor info.
If NativeMethods.GetCursorInfo(CursorInfo) = True Then
Using CursorIcon As System.Drawing.Icon = System.Drawing.Icon.FromHandle(CursorInfo.hCursor) 'Get the cursor icon.
Dim IconInfo As New NativeMethods.ICONINFO
Try
Dim ModifierPoint As New Point(0, 0) 'Declare the modifier point (the cursor's hotspot).
'Get the info for the cursor icon.
If NativeMethods.GetIconInfo(CursorInfo.hCursor, IconInfo) = True Then
If IconInfo.fIcon = False Then 'If the cursor is an icon the hotspot will always be (0, 0).
ModifierPoint = New Point(IconInfo.xHotspot, IconInfo.yHotspot) 'Set the hotspot modifier.
End If
End If
'Normalize the coordinates according to the hotspot.
Dim FinalPoint As New Point(CursorInfo.ptScreenPos.x - ModifierPoint.X, CursorInfo.ptScreenPos.y - ModifierPoint.Y)
'Draw the cursor.
Graphics.DrawIcon(CursorIcon, New Rectangle(FinalPoint, CursorIcon.Size))
Finally
'Some cleaning up...
If IconInfo.hbmMask <> IntPtr.Zero Then
NativeMethods.DeleteObject(IconInfo.hbmMask)
IconInfo.hbmMask = IntPtr.Zero
End If
If IconInfo.hbmColor <> IntPtr.Zero Then
NativeMethods.DeleteObject(IconInfo.hbmColor)
IconInfo.hbmColor = IntPtr.Zero
End If
End Try
End Using
End If
End Sub
NativeMethods.vb:
Imports System.Runtime.InteropServices
Public NotInheritable Class NativeMethods
<StructLayout(LayoutKind.Sequential)> _
Public Structure POINT
Public x As Integer
Public y As Integer
End Structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure CURSORINFO
Public cbSize As Integer
Public flags As Integer
Public hCursor As IntPtr
Public ptScreenPos As POINT
End Structure
<DllImport("user32.dll")> _
Public Shared Function GetCursorInfo(ByRef pci As CURSORINFO) As Boolean
End Function
<StructLayout(LayoutKind.Sequential)> _
Public Structure ICONINFO
Public fIcon As Boolean
Public xHotspot As Integer
Public yHotspot As Integer
Public hbmMask As IntPtr
Public hbmColor As IntPtr
End Structure
<DllImport("user32.dll")> _
Public Shared Function GetIconInfo(ByVal hIcon As IntPtr, ByRef piconinfo As ICONINFO) As Boolean
End Function
<DllImport("gdi32.dll")> _
Public Shared Function DeleteObject(ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
End Class
如果你截取结果截图,你会像这样在上面画光标:
Using g As Graphics = Graphics.FromImage(yourImage)
DrawCursor(g)
End Using