C++開發(fā)截屏小程序功能
C++開發(fā)截屏小程序,Win32程序,可以顯示截屏區(qū)域并保存。
上次的流星雨屏幕程序就簡單涉及到GDI繪圖了,這次簡單介紹幾個API函數(shù),涉及到GDI的。

GetDC,獲取當(dāng)前創(chuàng)建的窗口的設(shè)備環(huán)境。
CreateDC,獲取當(dāng)前屏幕的設(shè)備環(huán)境。
CreateCompatibleDC,創(chuàng)建一個兼容性的設(shè)備環(huán)境(相當(dāng)于一個虛擬的設(shè)備環(huán)境)
BitBlt,這個函數(shù),相當(dāng)于拷貝,將一個環(huán)境的設(shè)備內(nèi)容拷貝到另一個設(shè)備中。
CreateCompatibleBitmap,創(chuàng)建一塊畫布,將其放在兼容性的DC里面,這樣就可以在里面畫圖了,當(dāng)然還要放入畫筆和畫刷這些。
介紹完這些函數(shù)之后,那么設(shè)計思路就來了:
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; // 將實例句柄存儲在全局變量中
//創(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); //注冊類
// 執(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)前屏幕圖片放到一個緩沖區(qū)中。在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.接著再將它放到我們創(chuàng)建的窗口中,這時就會看到整個桌面就不動了,就呈現(xiàn)的是一張圖片,
5.之后我們就可以在這張圖片上繪制我們想截取的區(qū)域。
6.呈現(xiàn)的是靜止的圖片,如果繪制之后,需要更新,這就用到一個函數(shù)InvalidateRgn,會無效選定的區(qū)域,這樣會觸發(fā)消息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;
接下來就是繪制想要區(qū)域的操作,需要用到的幾個鼠標(biāo)的消息函數(shù),鼠標(biāo)按下,鼠標(biāo)彈起,鼠標(biāo)移動,鼠標(biāo)雙擊。
那么思路來了:
鼠標(biāo)按下,確定左上角的點,然后鼠標(biāo)移動繪制矩形區(qū)域,然后鼠標(biāo)彈起,確定右下角的點,這樣矩形區(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
StretchBlt函數(shù)和BitBlt函數(shù)用法案例詳解
這篇文章主要介紹了StretchBlt函數(shù)和BitBlt函數(shù)用法案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-08-08
舉例講解C語言的fork()函數(shù)創(chuàng)建子進程的用法
fork函數(shù)是Linux下一個近乎專有的C語言函數(shù),因為使用時需要調(diào)用unistd.h這個頭文件,這里我們就在Linux環(huán)境下舉例講解C語言的fork()函數(shù)創(chuàng)建子進程的用法,需要的朋友可以參考下2016-06-06

