C#屏幕捕捉编程之C#使用Screen类等方式截屏(2)
小结:
C#类库方式:代码简洁、学习代价低
Win32API方式:代码复杂、学习难度高
一般而言用C#方式,并且执行效率上看,在我的机器上两者区别不大。Win32API方式略有优势。
关键点:鼠标呢?
上面两个代码其实都没有捕捉到鼠标,很不爽的一个地方
通过网络搜索和试验,在Win32API方式下我完成了对鼠标形状及位置的捕获。Win32API在win平台上应该是万能的,呵呵。
总体思路是在捕获全屏后,单独获取鼠标位置及形状。然后“画”到先前捕获的位图上
public static Bitmap GetDesktopImage()
{
//As m_HBitmap is IntPtr we can not check it against null. For this purspose IntPtr.Zero is used.
if (m_HBitmap!=IntPtr.Zero)
{
//Here we select the compatible bitmap in memeory device context and keeps the refrence to Old bitmap.
IntPtr hOld = (IntPtr) PlatformInvokeGDI32.SelectObject(hMemDC, m_HBitmap);
//We copy the Bitmap to the memory device context.
PlatformInvokeGDI32.BitBlt(hMemDC, 0, 0,size.cx,size.cy, hDC, 0, 0, PlatformInvokeGDI32.SRCCOPY);
#region 绘制鼠标
PlatformInvokeUSER32.CURSORINFO pci = new PlatformInvokeUSER32.CURSORINFO();
pci.cbSize = Marshal.SizeOf(pci);
PlatformInvokeUSER32.GetCursorInfo(out pci);
IntPtr dc = hMemDC;
//这个偏移量是我在使用时发现的问题,不一定是10,没有精确论证过。只是目前看起来位置正确。
PlatformInvokeUSER32.DrawIconEx(dc, pci.ptScreenPos.X-10, pci.ptScreenPos.Y-10, pci.hCursor, 32, 32, 1, IntPtr.Zero, PlatformInvokeUSER32.DI_NORMAL);
#endregion
//We select the old bitmap back to the memory device context.
PlatformInvokeGDI32.SelectObject(hMemDC, hOld);
//老外的原始代码中,静态构造里是没东西的。所有那些都是在本函数中声明、使用并且销毁的。
//如果有喜欢销毁东西癖好的,可以在这里销毁hDC、hMemDC以及m_HBitmap
//不过我觉得没有这个必要,并且不销毁能提高点点速度
return System.Drawing.Image.FromHbitmap(m_HBitmap);
}
//If m_HBitmap is null retunrn null.
return null;
}
经使用,完美解决问题。
最后把完整的抓屏解决方案的代码打包放这里带鼠标的全屏抓图