【发布时间】:2021-05-11 10:58:57
【问题描述】:
我正在尝试用 C++ 制作截图工具。我设法通过这段代码创建了一个无边框的全屏窗口;
WindProc:
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
switch (message)
{
case WM_CHAR: //this is just for a program exit besides window's borders/taskbar
if (wparam==VK_ESCAPE)
{
DestroyWindow(hwnd);
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wparam, lparam);
}
}
创建窗口;
WNDCLASS windowClass={0};
windowClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
windowClass.hCursor=LoadCursor(NULL, IDC_ARROW);
windowClass.hInstance=NULL;
windowClass.lpfnWndProc=WndProc;
windowClass.lpszClassName=TEXT("Window in Console"); //needs to be the same name
//when creating the window as well
windowClass.style=CS_HREDRAW | CS_VREDRAW;
//also register the class
if (!RegisterClass(&windowClass))
MessageBoxA(NULL, "Could not register class", "Error", MB_OK);
HWND windowHandle=CreateWindowA("Window in Console",
NULL,
WS_POPUP, //borderless
0, //x coordinate of window start point
0, //y start point
GetSystemMetrics(SM_CXSCREEN), //width of window
GetSystemMetrics(SM_CYSCREEN), //height of the window
NULL, //handles and such, not needed
NULL,
NULL,
NULL);
ShowWindow(windowHandle, SW_RESTORE);
现在剩下要做的就是截取屏幕截图并将其绘制在表单上。我在这部分失败了。
当我在谷歌上搜索时,我第一次看到 SetPixel 函数,但绘制表单花了大约半分钟。它非常缓慢。然后人们说使用设备上下文(据我了解,它在内存中的表单绘图数据)并在此基础上进行绘制,它会比更新窗口快得多。这就是我所做的;
int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
HDC hdc = GetDC(windowHandle);
BitBlt(hdc, 0, 0, nScreenWidth, nScreenHeight, GetDC(NULL), 0, 0, SRCCOPY | CAPTUREBLT);
UpdateWindow(windowHandle);
ShowWindow(windowHandle, SW_RESTORE);
UpdateWindow(windowHandle);
如您所料,它没有用。我的表格是空白的。我不明白我是否应该在 WindProc 上的 WM_PAINT 消息上写这个。我对此尝试了很多变体,实际上有一点我猜它起作用了,但是当我改变一些东西时它就停止了工作,我无法让它再次工作......
谢谢。
【问题讨论】:
-
BitBlt 部分应该在一个案例 WM_PAINT 内。如果您检测到屏幕截图的按键,您还需要调用 InvalidateRect。
-
一般情况下,你应该画
WM_PAINT,使用BeginPaint返回的DC而不是GetDC。 -
伙计们非常感谢你们的cmets。它为我指明了正确的方向。我找到了解决方案,我会在早上发布。(几个小时后)。谢谢