1、新建win32空白项目
1 // ScreenCapture.cpp : 定义应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include "ScreenCapture.h" 6 7 #define MAX_LOADSTRING 100 8 9 // 全局变量: 10 HINSTANCE hInst; // 当前实例 11 TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本 12 TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名 13 14 // 此代码模块中包含的函数的前向声明: 15 ATOM MyRegisterClass(HINSTANCE hInstance); 16 BOOL InitInstance(HINSTANCE, int); 17 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 18 INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); 19 20 HDC g_srcMemDc; 21 HDC g_grayMemDc; 22 int screenW; 23 int screenH; 24 25 RECT rect = { 0 }; //画图的矩形区域 26 bool isDrawing = false; 27 bool isSelect = false; 28 29 30 void GetScreenCapture(); 31 void CovertToGrayBitmap(HBITMAP hSourceBmp, HDC sourceDc); 32 void WriteDatatoClipBoard(); 33 34 int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, 35 _In_opt_ HINSTANCE hPrevInstance, 36 _In_ LPTSTR lpCmdLine, 37 _In_ int nCmdShow) 38 { 39 UNREFERENCED_PARAMETER(hPrevInstance); 40 UNREFERENCED_PARAMETER(lpCmdLine); 41 42 // TODO: 在此放置代码。 43 MSG msg; 44 HACCEL hAccelTable; 45 46 // 初始化全局字符串 47 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 48 LoadString(hInstance, IDC_SCREENCAPTURE, szWindowClass, MAX_LOADSTRING); 49 MyRegisterClass(hInstance); 50 51 // 执行应用程序初始化: 52 if (!InitInstance(hInstance, nCmdShow)) 53 { 54 return FALSE; 55 } 56 57 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SCREENCAPTURE)); 58 59 // 主消息循环: 60 while (GetMessage(&msg, NULL, 0, 0)) 61 { 62 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 63 { 64 TranslateMessage(&msg); 65 DispatchMessage(&msg); 66 } 67 } 68 69 return (int)msg.wParam; 70 } 71 72 73 74 // 75 // 函数: MyRegisterClass() 76 // 77 // 目的: 注册窗口类。 78 // 79 ATOM MyRegisterClass(HINSTANCE hInstance) 80 { 81 WNDCLASSEX wcex; 82 83 wcex.cbSize = sizeof(WNDCLASSEX); 84 85 wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; 86 wcex.lpfnWndProc = WndProc; 87 wcex.cbClsExtra = 0; 88 wcex.cbWndExtra = 0; 89 wcex.hInstance = hInstance; 90 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SCREENCAPTURE)); 91 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 92 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 93 wcex.lpszMenuName = 0;//MAKEINTRESOURCE(IDC_SCREENCAPTURE); 94 wcex.lpszClassName = szWindowClass; 95 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); 96 97 return RegisterClassEx(&wcex); 98 } 99 100 //101 // 函数: InitInstance(HINSTANCE, int)102 //103 // 目的: 保存实例句柄并创建主窗口104 //105 // 注释:106 //107 // 在此函数中,我们在全局变量中保存实例句柄并108 // 创建和显示主程序窗口。109 //110 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)111 {112 HWND hWnd;113 114 hInst = hInstance; // 将实例句柄存储在全局变量中115 116 hWnd = CreateWindow(szWindowClass, szTitle, WS_POPUP,117 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);118 119 if (!hWnd)120 {121 return FALSE;122 }123 124 ShowWindow(hWnd, SW_MAXIMIZE);125 UpdateWindow(hWnd);126 127 return TRUE;128 }129 130 //131 // 函数: WndProc(HWND, UINT, WPARAM, LPARAM)132 //133 // 目的: 处理主窗口的消息。134 //135 // WM_COMMAND - 处理应用程序菜单136 // WM_PAINT - 绘制主窗口137 // WM_DESTROY - 发送退出消息并返回138 //139 //140 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)141 {142 int wmId, wmEvent;143 PAINTSTRUCT ps;144 HDC hdc;145 146 LOGBRUSH brush;147 brush.lbStyle = BS_NULL;148 HBRUSH hBrush = CreateBrushIndirect(&brush);149 150 LOGPEN pen;151 POINT penWidth;152 penWidth.x = 2;153 penWidth.y = 2;154 pen.lopnColor = 0x0000FFFF;155 pen.lopnStyle = PS_SOLID;156 pen.lopnWidth = penWidth;157 HPEN hPen = CreatePenIndirect(&pen);158 159 160 switch (message)161 {162 case WM_COMMAND:163 wmId = LOWORD(wParam);164 wmEvent = HIWORD(wParam);165 // 分析菜单选择:166 switch (wmId)167 {168 case IDM_ABOUT:169 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);170 break;171 case IDM_EXIT:172 DestroyWindow(hWnd);173 break;174 default:175 return DefWindowProc(hWnd, message, wParam, lParam);176 }177 break;178 179 case WM_CREATE:180 GetScreenCapture();181 break;182 case WM_PAINT:183 {184 hdc = BeginPaint(hWnd, &ps);185 186 HDC memDc = CreateCompatibleDC(hdc);187 HBITMAP bmp = CreateCompatibleBitmap(hdc, screenW, screenH);188 SelectObject(memDc, bmp);189 190 BitBlt(memDc, 0, 0, screenW, screenH, g_grayMemDc, 0, 0, SRCCOPY);191 SelectObject(memDc, hBrush);192 SelectObject(memDc, hPen);193 194 if (isDrawing || isSelect)195 {196 197 BitBlt(memDc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, g_srcMemDc, rect.left, rect.top, SRCCOPY);198 Rectangle(memDc, rect.left, rect.top, rect.right, rect.bottom);199 }200 201 BitBlt(hdc, 0, 0, screenW, screenH, memDc, 0, 0, SRCCOPY);202 203 DeleteObject(bmp);204 DeleteObject(memDc);205 206 EndPaint(hWnd, &ps);207 }208 break;209 210 case WM_LBUTTONDOWN:211 {212 if (!isSelect)213 {214 POINT pt;215 GetCursorPos(&pt);216 rect.left = pt.x;217 rect.top = pt.y;218 rect.right = pt.x;219 rect.bottom = pt.y;220 221 isDrawing = true;222 InvalidateRgn(hWnd, 0, false);223 }224 }225 break;226 227 case WM_LBUTTONUP:228 {229 if (isDrawing && !isSelect)230 {231 isDrawing = false;232 POINT pt;233 GetCursorPos(&pt);234 rect.right = pt.x;235 rect.bottom = pt.y;236 237 isSelect = true;238 239 InvalidateRgn(hWnd, 0, false);240 }241 }242 break;243 244 case WM_MOUSEMOVE:245 {246 if (isDrawing&& !isSelect)247 {248 POINT pt;249 GetCursorPos(&pt);250 rect.right = pt.x;251 rect.bottom = pt.y;252 InvalidateRgn(hWnd, 0, false);253 }254 }255 break;256 case WM_LBUTTONDBLCLK:257 {258 if (isSelect)259 {260 WriteDatatoClipBoard();261 InvalidateRgn(hWnd, 0, false);262 ShowWindow(hWnd, SW_MINIMIZE);263 }264 isSelect = false;265 266 }267 break;268 case WM_DESTROY:269 PostQuitMessage(0);270 break;271 default:272 return DefWindowProc(hWnd, message, wParam, lParam);273 }274 return 0;275 }276 277 // “关于”框的消息处理程序。278 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)279 {280 UNREFERENCED_PARAMETER(lParam);281 switch (message)282 {283 case WM_INITDIALOG:284 return (INT_PTR)TRUE;285 286 case WM_COMMAND:287 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)288 {289 EndDialog(hDlg, LOWORD(wParam));290 return (INT_PTR)TRUE;291 }292 break;293 }294 return (INT_PTR)FALSE;295 }296 297 298 void GetScreenCapture()299 {300 HDC disDc = ::CreateDC(L"DISPLAY", 0, 0, 0); //创建屏幕相关的DC301 screenW = GetDeviceCaps(disDc, HORZRES);//水平分辨率302 screenH = GetDeviceCaps(disDc, VERTRES);//垂直分辨率303 304 g_srcMemDc = CreateCompatibleDC(disDc); //创建于屏幕兼容的DC(内存DC)305 HBITMAP hbMap = CreateCompatibleBitmap(disDc, screenW, screenH); //模拟一张画布,其中是没有数据的306 SelectObject(g_srcMemDc, hbMap); //将画图选入内存DC,其中还是没有数据的307 BitBlt(g_srcMemDc, 0, 0, screenW, screenH, disDc, 0, 0, SRCCOPY); //将屏幕的dc中的画图,拷贝至内存DC中308 309 //获取屏幕的灰度图片310 g_grayMemDc = CreateCompatibleDC(disDc);311 HBITMAP grayMap = CreateCompatibleBitmap(disDc, screenW, screenH); //模拟一张画布,其中是没有数据的312 SelectObject(g_grayMemDc, grayMap); //将画图选入内存DC,其中还是没有数据的313 BitBlt(g_grayMemDc, 0, 0, screenW, screenH, disDc, 0, 0, SRCCOPY); //将屏幕的dc中的画图,拷贝至内存DC中314 315 CovertToGrayBitmap(grayMap, g_grayMemDc); //将彩色图片转换灰度图片316 317 DeleteObject(hbMap);318 DeleteObject(grayMap);319 DeleteObject(disDc);320 }321 322 void CovertToGrayBitmap(HBITMAP hSourceBmp, HDC sourceDc)323 {324 HBITMAP retBmp = hSourceBmp;325 BITMAPINFO bmpInfo;326 ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));327 bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);328 GetDIBits(sourceDc, retBmp, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS);329 330 BYTE* bits = new BYTE[bmpInfo.bmiHeader.biSizeImage];331 GetBitmapBits(retBmp, bmpInfo.bmiHeader.biSizeImage, bits);332 333 int bytePerPixel = 4;//默认32位334 if (bmpInfo.bmiHeader.biBitCount == 24)335 {336 bytePerPixel = 3;337 }338 for (DWORD i = 0; i < bmpInfo.bmiHeader.biSizeImage; i += bytePerPixel)339 {340 BYTE r = *(bits + i);341 BYTE g = *(bits + i + 1);342 BYTE b = *(bits + i + 2);343 *(bits + i) = *(bits + i + 1) = *(bits + i + 2) = (r + b + g) / 3;344 }345 SetBitmapBits(hSourceBmp, bmpInfo.bmiHeader.biSizeImage, bits);346 delete[] bits;347 }348 349 void WriteDatatoClipBoard()350 {351 HDC hMemDc, hScrDc;352 HBITMAP hBmp, hOldBmp;353 int width, height;354 width = rect.right - rect.left;355 height = rect.bottom - rect.top;356 357 hScrDc = CreateDC(L"DISPLAY", NULL, NULL, NULL);358 hMemDc = CreateCompatibleDC(hScrDc);359 hBmp = CreateCompatibleBitmap(hScrDc, width, height);360 361 hOldBmp = (HBITMAP)SelectObject(hMemDc, hBmp);362 BitBlt(hMemDc, 0, 0, width, height, g_srcMemDc, rect.left, rect.top, SRCCOPY);363 hBmp = (HBITMAP)SelectObject(hMemDc, hOldBmp);364 DeleteDC(hMemDc);365 DeleteDC(hScrDc);366 //复制到剪贴板367 if (OpenClipboard(0))368 {369 EmptyClipboard();370 SetClipboardData(CF_BITMAP, hBmp);371 CloseClipboard();372 }373 374 DeleteObject(hBmp);375 DeleteObject(hMemDc);376 DeleteObject(hScrDc);377 378 }