C++開發(fā)截屏小程序功能
C++開發(fā)截屏小程序,Win32程序,可以顯示截屏區(qū)域并保存。
上次的流星雨屏幕程序就簡單涉及到GDI繪圖了,這次簡單介紹幾個(gè)API函數(shù),涉及到GDI的。
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)閉粘貼板 } }
代碼地址:http://xiazai.jb51.net/202004/yuanma/CaptureScreen_jb51.rar
總結(jié)
到此這篇關(guān)于C++開發(fā)截屏小程序的文章就介紹到這了,更多相關(guān)C++開發(fā)截屏小程序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言中關(guān)于動(dòng)態(tài)內(nèi)存分配的詳解
動(dòng)態(tài)內(nèi)存是指在堆上分配的內(nèi)存,而靜態(tài)內(nèi)存是指在棧上分配的內(nèi)存。棧上分配的內(nèi)存是由系統(tǒng)分配和釋放的,空間有限,在復(fù)合語句或函數(shù)運(yùn)行結(jié)束后就會(huì)被系統(tǒng)自動(dòng)釋放而堆上分配的內(nèi)存則不會(huì)有這個(gè)問題。2021-09-09淺談C結(jié)構(gòu)和C++結(jié)構(gòu)之間的區(qū)別
這篇文章主要介紹了淺談C結(jié)構(gòu)和C++結(jié)構(gòu)之間的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04c++ 數(shù)字類型和字符串類型互轉(zhuǎn)詳解
今天小編就為大家分享一篇講解c++ 數(shù)字類型和字符串類型互轉(zhuǎn)的文章,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-09-09C語言基礎(chǔ)之malloc和free函數(shù)詳解
這篇文章主要介紹了C語言基礎(chǔ)之malloc和free函數(shù)詳解的相關(guān)資料,需要的朋友可以參考下2017-04-04使用用C++做一顆會(huì)跳動(dòng)的愛心實(shí)例代碼
大家好,本篇文章主要講的是使用用C++做一顆會(huì)跳動(dòng)的愛心實(shí)例代碼,感興趣的同學(xué)趕快來看一看吧,歡迎借鑒學(xué)習(xí)C++做一顆會(huì)跳動(dòng)的愛心實(shí)例代碼2021-12-12C/C++高精度(加減乘除)算法的實(shí)現(xiàn)
高精度的算法,一般的方式是用一個(gè)很長的數(shù)組去記錄數(shù)據(jù),數(shù)組的每一位記錄固定位數(shù)的數(shù)字,記錄順序是低位到高位。本文將通過實(shí)例為大家介紹下高精度算法的實(shí)現(xiàn),感興趣的可以了解一下2022-12-12簡單比較C語言中的execl()函數(shù)與execlp()函數(shù)
這篇文章主要介紹了C語言中的execl()函數(shù)與execlp()函數(shù)的簡單比較,是C語言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-08-08linux c語言操作數(shù)據(jù)庫(連接sqlite數(shù)據(jù)庫)
linux下c語言操作sqlite數(shù)據(jù)庫實(shí)例方法,大家參考使用吧2013-12-12C語言實(shí)現(xiàn)獲取內(nèi)存信息并輸出的實(shí)例
這篇文章主要介紹了C語言實(shí)現(xiàn)獲取內(nèi)存信息并輸出的實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-03-03