【问题标题】:C++ GetDC All MonitorsC++ GetDC 所有监视器
【发布时间】:2018-11-16 00:17:19
【问题描述】:

基本上,我正在制作一些模仿屏幕融化效果的东西,但我只能在我的主显示器上让它工作。我已经尽可能多地查找了所有显示器的GetDC论坛,但它没有用,它所做的只是从我的主显示器到我的辅助显示器制作一个矩形,效果仍然只能工作我的主显示器。这是我阅读的主题:GetDC(NULL) gets primary monitor or virtual screen?

LRESULT CALLBACK Melter(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) {
    switch (Message) {
        case WM_CREATE: {
            HDC Desktop = GetDC(HWND_DESKTOP);
            HDC Window = GetDC(hWnd);

            BitBlt(Window, 0, 0, ScreenWidth, ScreenHeight, Desktop, 0, 0, SRCCOPY);
            ReleaseDC(hWnd, Window);
            ReleaseDC(HWND_DESKTOP, Desktop);

            SetTimer(hWnd, 0, Interval, 0);
            ShowWindow(hWnd, SW_SHOW);

            break;
        }
        case WM_PAINT: {
            ValidateRect(hWnd, 0);
            break;
        }
        case WM_TIMER: {
            HDC Window = GetDC(hWnd);
            int uX = (rand() % ScreenWidth) - (150 / 2), uY = (rand() % 15), Width = (rand() % 150);

            BitBlt(Window, uX, uY, Width, ScreenHeight, Window, uX, 0, SRCCOPY);
            ReleaseDC(hWnd, Window);

            break;
        }
        case WM_DESTROY: {
            KillTimer(hWnd, 0);
            PostQuitMessage(EXIT_SUCCESS);
            break;
        }
        return EXIT_SUCCESS;
    }

    return DefWindowProc(hWnd, Message, wParam, lParam);
}

我更改的行是HDC Window = GetDC(Window) to HDC Window = GetDC(NULL),然后是其他一些东西,例如RECT。如果有人可以帮助我,那就太好了,谢谢:)

PS,ScreenWidth = 3600,ScreenHeight = 1080 而 PMScreenWidth = 1920,PMScreenHeight = 1080。PM 与主监视器中一样,所以我将该函数中的所有内容设置为 ScreenWidth/ScreenHeight 所以它的宽度/高度所有显示器。不过还是不行。

【问题讨论】:

标签: c++ visual-studio visual-c++ multiple-monitors


【解决方案1】:

GetDC(HWND_DESKTOP)(与GetDC(0) 相同)已为所有监视器返回 DC。上面代码的问题主要在于BitBlt的使用和坐标的选择。请参阅下面解决问题的 MCVE。

不要响应WM_CREATE而绘制,它只会在WM_PAINT或背景被擦除时被擦除。

请勿在回复WM_PAINT 时致电ValidateRect。如果您想擦除窗口,则只需使用FillRect,或从命令或其他路线强制重绘。

使用GetSystemMetrics(SM_CXVIRTUALSCREEN)GetSystemMetrics(SM_CYVIRTUALSCREEN) 返回虚拟监视器的宽度和高度。

还要确保该过程可识别 DPI。对于测试,您可以在程序开始时调用SetProcessDPIAware();。理想情况下,应在清单文件中设置 DPI 感知。

int uX = (rand() % ScreenWidth) - (150 / 2);
int uY = (rand() % 15);
int Width = (rand() % 150);
BitBlt(Window, uX, uY, Width, ScreenHeight, Window, uX, 0, SRCCOPY);

上面的代码是从客户端 DC 复制位到同一个客户端 DC,它不会做任何事情。大概你想从桌面 DC 复制到客户端 DC。

而且,坐标基本上是随机挑选的。它假定主监视器位于左上角。如果uX 大于窗口自身的宽度,则不会被复制,除非窗口拉伸整个虚拟监视器。

LRESULT CALLBACK Melter(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) {

    switch(Message) 
    {
    case WM_PAINT: 
    {
        PAINTSTRUCT ps;
        auto hdc = BeginPaint(hWnd, &ps);
        RECT rc;
        GetClientRect(hWnd, &rc);

        HDC hdesktop = GetDC(0);

        int screenx = GetSystemMetrics(SM_XVIRTUALSCREEN);
        int screeny = GetSystemMetrics(SM_YVIRTUALSCREEN);
        int screenw = GetSystemMetrics(SM_CXVIRTUALSCREEN);
        int screenh = GetSystemMetrics(SM_CYVIRTUALSCREEN);

        StretchBlt(hdc, 0, 0, rc.right, rc.bottom,
            hdesktop, screenx, screeny, screenw, screenh, SRCCOPY);

        ReleaseDC(0, hdesktop);

        EndPaint(hWnd, &ps);
        break;
    }

    case WM_DESTROY: 
        PostQuitMessage(0);
        break;
    }

    return DefWindowProc(hWnd, Message, wParam, lParam);
}

【讨论】:

  • 感谢您的建议,但即使 ScreemWidth 是 Primary Monitor + SecondaryMonitor,它在第二台显示器上似乎仍然没有做任何事情。我也会继续查看一些文档,看看是否能找到有用的东西。
  • 顺便说一句,您的代码与您的问题无关。请参阅有关如何创建 MCVE 以解决特定问题的帮助页面。不要提前开始编写一堆代码。见编辑。
【解决方案2】:

你可以使用

HDC dc = CreateDC(("DISPLAY"), NULL, NULL, NULL);

查看以下链接:

  1. Using Multiple Monitors as Independent Displays
  2. CreateDCA function
  3. Multiple Display Monitors Functions

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-11
    • 2012-10-03
    • 2012-07-08
    • 1970-01-01
    • 2021-12-20
    相关资源
    最近更新 更多