C++开发截屏小程序功能的方法

这篇文章主要讲解了C++开发截屏小程序功能的方法,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。

目前创新互联建站已为上千家的企业提供了网站建设、域名、雅安服务器托管网站托管运营、企业网站设计、新疆网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。

C++开发截屏小程序,Win32程序,可以显示截屏区域并保存。

上次的流星雨屏幕程序就简单涉及到GDI绘图了,这次简单介绍几个API函数,涉及到GDI的。

C++开发截屏小程序功能的方法

GetDC,获取当前创建的窗口的设备环境。
CreateDC,获取当前屏幕的设备环境。
CreateCompatibleDC,创建一个兼容性的设备环境(相当于一个虚拟的设备环境)
BitBlt,这个函数,相当于拷贝,将一个环境的设备内容拷贝到另一个设备中。
CreateCompatibleBitmap,创建一块画布,将其放在兼容性的DC里面,这样就可以在里面画图了,当然还要放入画笔和画刷这些。

介绍完这些函数之后,那么设计思路就来了:

1.首先当然还是定义并创建窗口,还有消息循环。

ATOM MyRegisterClass(HINSTANCE hInstance)
{
 WNDCLASSEX wcex;
 
 wcex.cbSize = sizeof(WNDCLASSEX);
 wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
 wcex.lpfnWndProc = WndProc;
 wcex.cbClsExtra = 0;
 wcex.cbWndExtra = 0;
 wcex.hInstance = hInstance;
 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDC_CAPTURESCREEN));
 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
 wcex.hbrBackground = (HBRUSH)(BLACK_BRUSH);
 wcex.lpszMenuName = NULL;
 wcex.lpszClassName = szWindowClass;
 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

 return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{

 hInst = hInstance; // 将实例句柄存储在全局变量中
 //创建自己的窗口
 hWnd = CreateWindow(szWindowClass, szTitle, WS_POPUP,
 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

 if (!hWnd)
 {
 return FALSE;
 }
 //显示和更新窗口
 ShowWindow(hWnd, SW_MAXIMIZE);
 UpdateWindow(hWnd);

 return TRUE;
}

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
 _In_opt_ HINSTANCE hPrevInstance,
 _In_ LPTSTR lpCmdLine,
 _In_ int  nCmdShow)
{
 //playsound只能播放wav格式,而mcisendstring可以播放任意格式的。
 
 //PlaySound("yixi.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
 mciSendString("open ./abc.mp3 alias bk",
 0, 0, 0);
 mciSendString("play bk repeat", 0, 0, 0);

 UNREFERENCED_PARAMETER(hPrevInstance);
 UNREFERENCED_PARAMETER(lpCmdLine);

 // TODO: 在此放置代码。
 MSG msg;
 HACCEL hAccelTable;

 // 初始化全局字符串
 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
 LoadString(hInstance, IDC_CAPTURESCREEN, szWindowClass, MAX_LOADSTRING);
 
 MyRegisterClass(hInstance); //注册类

 // 执行应用程序初始化: 
 if (!InitInstance(hInstance, nCmdShow)) //初始化窗口
 {

 return FALSE;
 }

 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CAPTURESCREEN));

 // 主消息循环: 
 while (GetMessage(&msg, NULL, 0, 0))
 {
 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
 {
 TranslateMessage(&msg);
 DispatchMessage(&msg);
 }
 }
 return (int)msg.wParam;
}

2.之后获取当前屏幕的设备环境,

3.然后将它保存到兼容性的DC中,这就相当于将当前屏幕图片放到一个缓冲区中。在WM_CREATE消息里面做这个动作。

void ScreenDisplay()
{
 HDC disDc = ::CreateDC("DISPLAY", NULL, NULL, NULL);
 g_memDC = ::CreateCompatibleDC(disDc);
 g_ScreenW = GetDeviceCaps(disDc, HORZRES);
 g_ScreenH = GetDeviceCaps(disDc, VERTRES);
 HBITMAP hbitmap = CreateCompatibleBitmap(disDc, g_ScreenW, g_ScreenH);
 SelectObject(g_memDC, hbitmap);
 BitBlt(g_memDC, 0, 0, g_ScreenW, g_ScreenH, disDc, 0, 0, SRCCOPY);
}

4.接着再将它放到我们创建的窗口中,这时就会看到整个桌面就不动了,就呈现的是一张图片,

5.之后我们就可以在这张图片上绘制我们想截取的区域。

6.呈现的是静止的图片,如果绘制之后,需要更新,这就用到一个函数InvalidateRgn,会无效选定的区域,这样会触发消息WM_PAINT,所以在这个消息里面将重新绘制图形,然后显示即可。

case WM_PAINT:
 hdc = BeginPaint(hWnd, &ps);
 // TODO: 在此添加任意绘图代码...
 SelectObject(hdc, hpen);
 SelectObject(hdc, hBrush);
 BitBlt(hdc, 0, 0, g_ScreenW, g_ScreenH, g_memDC, 0, 0, SRCCOPY);
 Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
 EndPaint(hWnd, &ps);
break;

接下来就是绘制想要区域的操作,需要用到的几个鼠标的消息函数,鼠标按下,鼠标弹起,鼠标移动,鼠标双击。
那么思路来了:

鼠标按下,确定左上角的点,然后鼠标移动绘制矩形区域,然后鼠标弹起,确定右下角的点,这样矩形区域绘制完成。

case WM_LBUTTONDOWN:
{
  if (!Iselect)
  {
   POINT pt;
   GetCursorPos(&pt);
   rect.left = pt.x;
   rect.top = pt.y;
   rect.right = pt.x;
   rect.bottom = pt.x;
   InvalidateRgn(hWnd, 0, FALSE);
   Isdowmn = TRUE;
  }


}
 break;
case WM_LBUTTONUP:
{
  if (Isdowmn == TRUE&&!Iselect)
  {
  POINT pt;
  GetCursorPos(&pt);
  rect.right = pt.x;
  rect.bottom = pt.y;
  InvalidateRgn(hWnd, 0, FALSE);
  Isdowmn = FALSE;
  Iselect = TRUE;
  }
}
 break;
case WM_MOUSEMOVE:
{
  if (Isdowmn == TRUE&&!Iselect)
  {
  POINT pt;
  GetCursorPos(&pt);
  rect.right = pt.x;
  rect.bottom = pt.y;
  InvalidateRgn(hWnd, 0, FALSE);
  }
}
 break;

最后鼠标双击将截取到的图片保存剪切板,这样就完成了屏幕截取。

case WM_LBUTTONDBLCLK:
 if (Iselect == TRUE)
 {
 int iNum = MessageBox(hWnd, "截图成功!", "张一西", MB_OKCANCEL | MB_ICONINFORMATION);
 if (iNum == 1)
 {
  CopyToCliboard();
  Iselect = FALSE;
  PostQuitMessage(0);
 }
 else
 {
  Iselect = FALSE;
 }
 }
 break;
void CopyToCliboard()
{
 HDC hScreenDC = ::CreateDC("DISPLAY", 0, 0, 0);
 HDC memDC = ::CreateCompatibleDC(hScreenDC);
 int Width = rect.right - rect.left-2;
 int Height = rect.bottom - rect.top-2;
 HBITMAP hBmap = CreateCompatibleBitmap(hScreenDC, Width, Height);
 HBITMAP hOldBmap = (HBITMAP)SelectObject(memDC, hBmap);
 BitBlt(memDC, 0, 0, Width, Height, hScreenDC, rect.left+1, rect.top+1, SRCCOPY);
 HBITMAP hNewBmap = (HBITMAP)SelectObject(memDC, hOldBmap);
 if (OpenClipboard(0))      //打开粘贴板
 {
 EmptyClipboard();      //清空粘贴板
 SetClipboardData(CF_BITMAP, hNewBmap); //把图片放入粘贴板
 CloseClipboard();      //关闭粘贴板
 }
}

看完上述内容,是不是对C++开发截屏小程序功能的方法有进一步的了解,如果还想学习更多内容,欢迎关注创新互联行业资讯频道。


本文名称:C++开发截屏小程序功能的方法
本文链接:http://myzitong.com/article/jgcjjd.html