屏幕截图小软件的编写——WINDOWS API

    xiaoxiao2021-12-14  17

    近期在学习windows api编程,完全模仿的学习了,熟悉windows api和纯windows api编程

    屏幕截图步骤:

    1.如何捕获屏幕

    2.捕获屏幕后怎么做到选定区域

    3.选定区域后将图片写入剪贴板

    具体还有很多细节需要考虑,如选定区域需要用不同颜色的画笔,如何知道区域被选择了......

    主要代码如下,核心都在窗口回调函数中,不详细解释,几个重要的API函数在后面说明

    //函数前置声明 void CaptureScreen(); void WriteDateToClipBoard(); // 全局变量: HINSTANCE hInst; // 当前实例 WCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本 WCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名 int screenW, screenH; HDC g_memDC; //全局内存DC,存储位图 RECT rect; //截图矩形区域 bool isSelect=FALSE, isDrawing=FALSE; LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; //画刷 LOGBRUSH brush; brush.lbStyle = BS_NULL; HBRUSH hBrush = CreateBrushIndirect(&brush); //画笔 LOGPEN pen; POINT penWidth; penWidth.x = 2; penWidth.y = 2; pen.lopnColor = 0x0000FFFF; pen.lopnStyle = BS_SOLID; pen.lopnWidth = penWidth; HPEN hPen = CreatePenIndirect(&pen); //窗口信息 WINDOWINFO windowInfo; windowInfo.cbSize = sizeof(WINDOWINFO); switch (message) { case WM_COMMAND: { int wmId = LOWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; case WM_CREATE: CaptureScreen(); break; case WM_PAINT: { hdc = BeginPaint(hWnd, &ps); // TODO: 在此处添加使用 hdc 的任何绘图代码... HDC memDC = CreateCompatibleDC(hdc); HBITMAP hbmp = CreateCompatibleBitmap(hdc, screenW, screenH); SelectObject(memDC, hbmp); BitBlt(memDC, 0, 0, screenW, screenH, g_memDC, 0, 0, SRCCOPY); SelectObject(memDC, hPen); SelectObject(memDC, hBrush); if (isDrawing || isSelect) { BitBlt(memDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, g_memDC, rect.left, rect.top, SRCCOPY); Rectangle(memDC, rect.left, rect.top, rect.right, rect.bottom); } BitBlt(hdc, 0, 0, screenW, screenH, memDC, 0, 0, SRCCOPY); DeleteObject(hbmp); DeleteObject(memDC); EndPaint(hWnd, &ps); } break; case WM_LBUTTONDOWN: if (!isSelect) { POINT point; GetCursorPos(&point); //获取矩形区域起点 rect.top = point.y; rect.left = point.x; rect.right = point.x; rect.bottom = point.y; isDrawing = TRUE; InvalidateRgn(hWnd, NULL, FALSE); } break; case WM_LBUTTONUP: if (isDrawing&&!isSelect) { isDrawing = FALSE; POINT point; GetCursorPos(&point); //获取矩形区域终点 rect.right = point.x; rect.bottom = point.y; isSelect = TRUE; InvalidateRgn(hWnd, NULL, FALSE); } break; case WM_LBUTTONDBLCLK: if (isSelect) { WriteDateToClipBoard(); InvalidateRgn(hWnd, NULL, FALSE); ShowWindow(hWnd, SW_MINIMIZE); } isSelect = FALSE; isDrawing = FALSE; break; case WM_MOUSEMOVE: //鼠标移动实时捕获鼠标位置 if (isDrawing&&!isSelect) { POINT pt; GetCursorPos(&pt); rect.right = pt.x; rect.bottom = pt.y; InvalidateRgn(hWnd, 0, false); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // “关于”框的消息处理程序。 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; } void CaptureScreen() { HDC disDC = ::CreateDC(L"DISPLAY", 0, 0, 0);//截取整个屏幕 screenW = GetDeviceCaps(disDC, HORZRES); screenH = GetDeviceCaps(disDC, VERTRES); //创建与DC相兼容的内存DC和位图 g_memDC = CreateCompatibleDC(disDC); HBITMAP hbmp = CreateCompatibleBitmap(disDC, screenW, screenH); SelectObject(g_memDC, hbmp); BitBlt(g_memDC, 0, 0, screenW, screenH, disDC, 0, 0, SRCCOPY); DeleteDC(disDC); DeleteObject(hbmp); } void WriteDateToClipBoard() { HDC hMemDC, hdc; HBITMAP hMemBmp, hbmp; //计算矩形区域的长和宽 int width, height; width = rect.right - rect.left; height = rect.bottom - rect.top; //创建相兼容的内存DC和位图 hdc = CreateDC(L"DISPLAY", 0, 0, 0); hMemDC = CreateCompatibleDC(hdc); hbmp = CreateCompatibleBitmap(hdc, width, height); hMemBmp = (HBITMAP)SelectObject(hMemDC, hbmp); BitBlt(hMemDC, 0, 0, width, height, g_memDC, rect.left, rect.bottom, SRCCOPY); hbmp = (HBITMAP)SelectObject(hMemDC, hMemBmp); DeleteDC(hdc); DeleteDC(hMemDC); //清空,写入,关闭剪贴板 if (OpenClipboard(0)) { EmptyClipboard(); SetClipboardData(CF_BITMAP, hbmp); CloseClipboard(); } DeleteObject(hbmp); DeleteObject(hMemBmp); } 窗口风格要是POPUP的,这样才能覆盖整个屏幕 DC,即device context,学会使用DC和内存DC传送位图,虽然还不是很理解,先抄,模仿别人的......

    按我现在的理解,DC相当于一个容器,可以将画刷画笔等工具放入其中.....

    SelectObject函数说明,摘录自MSDN

    HGDIOBJ SelectObject( _In_ HDC     hdc, _In_ HGDIOBJ hgdiobj );

    Parameters

    hdc [in]

    A handle to the DC.

    hgdiobj [in]

    A handle to the object to be selected.

    参数只能是这几个GDI对象Bitmap ,Brush ,Font,Pen,Region

    初次接触windows api编程,所有API 都不熟悉,完全copy加模仿,此程序运行后只能截图一次

    以后接触多了后再来写,改进思想如下:

    1.能够对屏幕进行实时截图,即软件运行时可以在任意时刻对屏幕截图

    2.能够撤销之前截图

    转载请注明原文地址: https://ju.6miu.com/read-971737.html

    最新回复(0)