溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C++開發(fā)截屏小程序功能的方法

發(fā)布時(shí)間:2020-08-04 13:45:52 來源:億速云 閱讀:231 作者:小豬 欄目:編程語(yǔ)言

這篇文章主要講解了C++開發(fā)截屏小程序功能的方法,內(nèi)容清晰明了,對(duì)此有興趣的小伙伴可以學(xué)習(xí)一下,相信大家閱讀完之后會(huì)有幫助。

C++開發(fā)截屏小程序,Win32程序,可以顯示截屏區(qū)域并保存。

上次的流星雨屏幕程序就簡(jiǎn)單涉及到GDI繪圖了,這次簡(jiǎn)單介紹幾個(gè)API函數(shù),涉及到GDI的。

C++開發(fā)截屏小程序功能的方法

GetDC,獲取當(dāng)前創(chuàng)建的窗口的設(shè)備環(huán)境。
CreateDC,獲取當(dāng)前屏幕的設(shè)備環(huán)境。
CreateCompatibleDC,創(chuàng)建一個(gè)兼容性的設(shè)備環(huán)境(相當(dāng)于一個(gè)虛擬的設(shè)備環(huán)境)
BitBlt,這個(gè)函數(shù),相當(dāng)于拷貝,將一個(gè)環(huán)境的設(shè)備內(nèi)容拷貝到另一個(gè)設(shè)備中。
CreateCompatibleBitmap,創(chuàng)建一塊畫布,將其放在兼容性的DC里面,這樣就可以在里面畫圖了,當(dāng)然還要放入畫筆和畫刷這些。

介紹完這些函數(shù)之后,那么設(shè)計(jì)思路就來了:

1.首先當(dāng)然還是定義并創(chuàng)建窗口,還有消息循環(huán)。

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; // 將實(shí)例句柄存儲(chǔ)在全局變量中
 //創(chuàng)建自己的窗口
 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); //注冊(cè)類

 // 執(zhí)行應(yīng)用程序初始化: 
 if (!InitInstance(hInstance, nCmdShow)) //初始化窗口
 {

 return FALSE;
 }

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

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

2.之后獲取當(dāng)前屏幕的設(shè)備環(huán)境,

3.然后將它保存到兼容性的DC中,這就相當(dāng)于將當(dāng)前屏幕圖片放到一個(gè)緩沖區(qū)中。在WM_CREATE消息里面做這個(gè)動(dòng)作。

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.接著再將它放到我們創(chuàng)建的窗口中,這時(shí)就會(huì)看到整個(gè)桌面就不動(dòng)了,就呈現(xiàn)的是一張圖片,

5.之后我們就可以在這張圖片上繪制我們想截取的區(qū)域。

6.呈現(xiàn)的是靜止的圖片,如果繪制之后,需要更新,這就用到一個(gè)函數(shù)InvalidateRgn,會(huì)無效選定的區(qū)域,這樣會(huì)觸發(fā)消息WM_PAINT,所以在這個(gè)消息里面將重新繪制圖形,然后顯示即可。

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;

接下來就是繪制想要區(qū)域的操作,需要用到的幾個(gè)鼠標(biāo)的消息函數(shù),鼠標(biāo)按下,鼠標(biāo)彈起,鼠標(biāo)移動(dòng),鼠標(biāo)雙擊。
那么思路來了:

鼠標(biāo)按下,確定左上角的點(diǎn),然后鼠標(biāo)移動(dòng)繪制矩形區(qū)域,然后鼠標(biāo)彈起,確定右下角的點(diǎn),這樣矩形區(qū)域繪制完成。

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;

最后鼠標(biāo)雙擊將截取到的圖片保存剪切板,這樣就完成了屏幕截取。

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();      //關(guān)閉粘貼板
 }
}

看完上述內(nèi)容,是不是對(duì)C++開發(fā)截屏小程序功能的方法有進(jìn)一步的了解,如果還想學(xué)習(xí)更多內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI