Win32 窗口在几分钟后不绘制

Posted

技术标签:

【中文标题】Win32 窗口在几分钟后不绘制【英文标题】:Win32 Window Doesn't Draw After minute or so 【发布时间】:2021-04-06 09:43:12 【问题描述】:

我陷入了困境。

我在搞乱位图和窗口。

我遵循了这个教程:https://docs.microsoft.com/en-us/windows/win32/gdi/capturing-an-image

我基本上是在为我的桌面拍摄多张照片并将它们显示到一个窗口中。

它按预期工作得很好,但大约一两分钟后,窗口不会更新,我找不到错误或发生这种情况的原因。

代码如下:

 LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
    switch (message) 
    case WM_DESTROY: 
        PostQuitMessage(0); // Exit the program if the window gets closed.
     break;
    case WM_SIZE: 
     break;
    
    return DefWindowProc(hWnd, message, wParam, lParam); // Handle any messages the switch statement didn't


HWND SpawnWindow() 
    WNDCLASSEX WindowClass;
    SecureZeroMemory(&WindowClass, sizeof(WNDCLASSEX));
    WindowClass.cbClsExtra = NULL;
    WindowClass.cbWndExtra = NULL;
    WindowClass.cbSize = sizeof(WNDCLASSEX);
    WindowClass.style = CS_HREDRAW | CS_VREDRAW;
    WindowClass.lpfnWndProc = WinProc;
    WindowClass.hInstance = NULL;
    WindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    WindowClass.hIcon = LoadIcon(0, IDI_APPLICATION);
    WindowClass.hIconSm = LoadIcon(0, IDI_APPLICATION);
    WindowClass.hbrBackground = NULL;
    WindowClass.lpszClassName = L"Class NAme";
    WindowClass.lpszMenuName = L"Menu Name";

    RegisterClassEx(&WindowClass);

    return CreateWindowEx(NULL, L"Class Name", L"Window Title", WS_VISIBLE | WS_TILEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);


void DoMessages() 
    MSG msg = ;
    while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) 
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    
    std::cout << msg.message << "\n";


int main() 
    HWND WindowToGetPic = SpawnWindow();

    HDC DesktopDC = GetDC(0);
    HDC WindowDC = GetDC(WindowToGetPic);

    if (!DesktopDC)
        std::cout << "DC NULL!\n";

    HDC TempDC = CreateCompatibleDC(DesktopDC);
    HDC TempDCWindow = CreateCompatibleDC(WindowDC);

    if (!TempDC)
        std::cout << "TempDC NULL!\n";

    while (true) 
        /*

            after calling CreateCompatibleDC you mus then call CreateCompatiableBitmap with the DC recieved
            then call SelectObject

        */
        HBITMAP hBitmap = CreateCompatibleBitmap(TempDC, 1920, 1080);/* screen res */

        SelectObject(TempDC, hBitmap);

        SetStretchBltMode(TempDC, HALFTONE);

        RECT WindowDimensions;
        GetClientRect(WindowToGetPic, &WindowDimensions);

        if (!BitBlt(WindowDC, 0, 0, WindowDimensions.right - WindowDimensions.left, WindowDimensions.bottom - WindowDimensions.top, DesktopDC, 0, 0, SRCCOPY))
            std::cout << "BitBlt ERROR\n";

        DoMessages();
        InvalidateRect(WindowHwnd, NULL, TRUE);
    
    std::cin.ignore();

    return 0;

如果有人可以对此进行测试,或者发现为什么一两分钟后窗口没有更新,我将不胜感激。

提前谢谢你!

【问题讨论】:

【参考方案1】:

我认为你已经用尽了所有资源。 例如,

你每个周期都创建位图并且不释放它。

您调用 SelectObject 并且不将所选对象返回到原始状态。

【讨论】:

【参考方案2】:

你有几个资源泄漏:

当您处理完 GetDC 返回的 HDC 后,请致电 ReleaseDC

当您处理完 CreateCompatibleDC 返回的 HDC 后,请致电 DeleteDC

当您完成hBitmap 后,将原始位图选择回 DC 并调用 DeleteObject。原始位图由SelectObject 返回。

这一切都包含在文档中(Google 会找到)。

【讨论】:

以上是关于Win32 窗口在几分钟后不绘制的主要内容,如果未能解决你的问题,请参考以下文章

Win32知识之窗口绘制.窗口第一讲

c++ - Win32 窗口在第一次绘制后冻结(directx 11)

Win 32 API,用垂直分隔条绘制两个子窗口

位图未在 Win32 C++ 中绘制

C++ Win32 窗口重叠事件

win32-UpdateLayeredWindow