【问题标题】:Getting bitmap of what minimized window would look like if normalized获取标准化后最小化窗口的位图
【发布时间】:2012-03-15 07:33:46
【问题描述】:

我正在尝试定期编写我的应用程序窗口外观的副本。如果窗口被规范化,事情就会正常工作,即在桌面上。但是如果窗口被最小化,我只会得到最小化的命令栏。

我尝试了各种方法,将 SendMessage 与 WM_PRINT 和 PrintWindow 结合使用,但均未成功。在下面使用 SendMessage 的代码中,我知道规范化窗口的适当大小用于创建位图。我知道通过 DefWindowProc 对 WM_PRINT 的默认处理生成了 WM_PRINTCLIENT 消息。 hWnd 是最小化窗口的句柄。

        HDC                 scrdc, memdc;
        HBITMAP             membit;
        WINDOWPLACEMENT     WP;
        EncoderParameters   encoderParameters;
        ULONG               quality;
        Status              status;
        RECT                Rect;

        WP.length  = sizeof (WP);
        WP.flags   = 0;
        WP.showCmd = 0;

        GetWindowPlacement (hWnd, &WP);
        int WPHeight = WP.rcNormalPosition.bottom - WP.rcNormalPosition.top;
        int WPWidth  = WP.rcNormalPosition.right  - WP.rcNormalPosition.left;

        scrdc = GetWindowDC (hWnd);                                 // source DC
        GetWindowRect(hWnd,&Rect);                                  //  source Rectangle
        int Height = Rect.bottom-Rect.top;                          //   source height
        int Width  = Rect.right-Rect.left;                          //    source width

        if (WP.showCmd == SW_SHOWMINIMIZED)
        {
            Height = WPHeight;
            Width  = WPWidth;
        }

        memdc = CreateCompatibleDC(scrdc);                          // destination DC
        membit = CreateCompatibleBitmap(scrdc, Width, Height);      //  destination bitmap
        HBITMAP hOldBitmap =(HBITMAP) SelectObject(memdc, membit);  //   add bitmap to DC

// copy screen to new BitMap

//      BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);   

//      PrintWindow (hWnd, memdc, 0);

        BitBlt 
        (
            memdc,
            0,
            0,
            GetDeviceCaps(memdc,HORZRES),
            GetDeviceCaps(memdc,VERTRES),
            NULL,
            NULL,
            NULL,
            WHITENESS
        );

        SendMessage (hWnd, WM_PRINT, unsigned int (memdc), PRF_CLIENT|PRF_NONCLIENT);

这是 WM_PRINT、WM_PRINTCLIENT 和 WM_PAINT 处理程序的代码

    case WM_PRINT:
        return DefWindowProc (hWnd, message, wParam, lParam);

    case WM_PRINTCLIENT:
        Screen.WMPrint (hWnd, HDC (wParam), NULL);
        return true;
        return DefWindowProc (hWnd, message, wParam, lParam);

    case WM_PAINT:                          
        Screen.WMPaint (hWnd);
        break;

我也知道 Screen.WMPrint 在 HDC 中书写了正确的内容。

因此,如果有人能给我一些提示或建议一种方法,我将不胜感激。我可以使用 Screen.WMPaint 但我只得到客户区并错过了命令栏和边框。

我不想规范化窗口,因为这会惹恼用户。

【问题讨论】:

  • 会隐藏窗口,恢复它,使用PrintWindow,最小化它,最后显示它工作吗?您可能也可以对任务栏中的活动做一些事情。

标签: c++ windows winapi


【解决方案1】:

这很难,因为当您的窗口最小化时,它看起来并不像未最小化的自己。

WM_PRINT 通过调用通常的 WM_NCPAINT 处理程序来打印窗口的非客户区(因为您正在传递标志)。该处理程序查看窗口状态,因此如果将其最小化,您将无法获得所需的内容。然后它会尝试打印客户区,但是(我怀疑)这里的最小化状态也会导致这部分被跳过——有效的最小化窗口没有客户区。

调用您的内部绘制程序可能是最简单的解决方案。是的,它只会给你客户区。请注意,当您将鼠标悬停在最小化窗口的磁贴上时,您在 Windows 7 任务栏上看到的预览也排除了非客户区。我觉得太难了。

【讨论】:

  • 我知道这很难!我已经为此苦苦挣扎了几天。如果不出意外,我将使用我的内部绘图程序并绘制自己的边框。
  • 在窗口仍然正常化的同时最小化窗口之前是否会收到一些 WM 消息?如果是这样,我可以使用 SendMessage (WM_NCPAINT) 来捕获帧的位图,而它仍然是标准化的吗?然后我可以用它作为我内部绘画程序的基础。
  • @Mike D:我相信在最小化之前你会得到一个WM_WINPOSCHANGING。你必须检查参数才能看到它是什么样的大小和位置变化。
【解决方案2】:

在您的 WM_PAINT 处理程序中,假设您使用双缓冲,使您的 backbuffer hdc 全局,然后当您想要拍摄您的程序的快照时,只需将该 HDC bitblt 到屏幕外位图就可以了.

您的 WM_PAINT 处理程序应如下所示: http://pastebin.com/aNvtHiD6

【讨论】:

  • 糟糕,我不小心在该代码中声明了 hdcBuffer 两次。您希望它在全球范围内声明,而不是在本地声明。 ^_^
  • 我不想要最后一次绘制的窗口图像。该程序即使在最小化时也在从外部控制设备收集数据。因此,该窗口在未来某个时间看起来会完全不同。
【解决方案3】:

这可能只是可能构建这样的位图。我认为在每次绘制操作后,必须在整个窗口的位图上显示标题栏和边框。然后可以擦除客户区。这将提供一个起点,可以在其中进行各种 GDI 操作。一个额外的复杂性是任何控件,如滚动条、日期控件、编辑框等,都必须单独捕获并添加到位图中。对于我的应用程序,我决定不处理最小化的情况。我在将控件放到新位图上时遇到了很多麻烦。控件出现问题是因为不能简单地将它们设为主窗口的子窗口,因为您所拥有的只是一张位图,窗口本身被最小化或控件被遮挡或离开屏幕。

【讨论】:

    猜你喜欢
    • 2015-07-21
    • 2011-05-22
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多