C++開發截屏小程序

C++開發截屏小程序,Win32程序,可以顯示截屏區域並保存。

  上次的流星雨屏幕程序就簡單涉及到GDI繪圖了,這次簡單介紹幾個API函數,涉及到GDI的。

在這裏插入圖片描述
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;
}
  1. 之後獲取當前屏幕的設備環境
  2. 然後將它保存到兼容性的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);
}
  1. 接着再將它放到我們創建的窗口中,這時就會看到整個桌面就不動了,就呈現的是一張圖片,

  2. 之後我們就可以在這張圖片上繪製我們想截取的區域

  3. 呈現的是靜止的圖片,如果繪製之後,需要更新,這就用到一個函數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;
  1. 接下來就是繪製想要區域的操作,需要用到的幾個鼠標的消息函數,鼠標按下鼠標彈起鼠標移動鼠標雙擊

  那麼思路來了:

  鼠標按下,確定左上角的點,然後鼠標移動繪製矩形區域,然後鼠標彈起,確定右下角的點,這樣矩形區域繪製完成。

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

代碼地址:https://download.csdn.net/download/qq_34430371/12316559

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章