简体   繁体   English

C++ GetDC 所有监视器

[英]C++ GetDC All Monitors

Basically, I'm making something that imitates a screen melting effect, but I can only get it working on my primary monitor.基本上,我正在制作一些模仿屏幕熔化效果的东西,但我只能让它在我的主显示器上工作。 I've looked up as much as I could and there was only one forum on GetDC for all monitors but it was to no use, all it done was make a rectangle from my primary monitor to my secondary monitor with the effect still only working on my primary monitor.我尽可能多地查找,在 GetDC 上只有一个论坛适用于所有显示器,但它没有用,所做的只是从我的主显示器到我的辅助显示器制作一个矩形,效果仍然只起作用我的主显示器。 This is the thread I read: GetDC(NULL) gets primary monitor or virtual screen?这是我读到的线程: GetDC(NULL) 获取主监视器或虚拟屏幕?

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);
}

The line I changed was HDC Window = GetDC(Window) to HDC Window = GetDC(NULL) and then some other stuff like the RECT .我更改的行是HDC Window = GetDC(Window) to HDC Window = GetDC(NULL) ,然后是其他一些东西,如RECT It'd be great if someone could help me, thanks :)如果有人可以帮助我,那就太好了,谢谢:)

PS, ScreenWidth = 3600, ScreenHeight = 1080 whilst PMScreenWidth = 1920, PMScreenHeight = 1080. PM as in Primary Monitor, so I've got all the stuff in that function set to ScreenWidth/ScreenHeight so it's the width/height of all monitors. PS, ScreenWidth = 3600, ScreenHeight = 1080 而 PMScreenWidth = 1920, PMScreenHeight = 1080. PM 就像在主监视器中一样,所以我将该函数中的所有内容都设置为 ScreenWidth/ScreenHeight 所以它是所有监视器的宽度/高度。 Still doesn't work though.不过还是不行。

GetDC(HWND_DESKTOP) (same as GetDC(0) ) already returns the DC for all monitors. GetDC(HWND_DESKTOP) (与GetDC(0)相同)已经返回所有显示器的 DC。 The problem with above code is mainly with the usage of BitBlt and choosing the coordinates.上面代码的问题主要是BitBlt的使用和坐标的选择。 See the MCVE below that addresses the question.请参阅下面解决该问题的 MCVE。

Don't draw in response to WM_CREATE , it's just going to get erased in WM_PAINT or when background is erased.不要在响应WM_CREATE绘制,它只会在WM_PAINT或背景被擦除时被擦除。

Don't call ValidateRect in response to WM_PAINT .不要调用ValidateRect来响应WM_PAINT If you want to erase the window then just use FillRect , or force repaint from a command or another route.如果您想擦除窗口,则只需使用FillRect ,或从命令或其他路线强制重绘。

Use GetSystemMetrics(SM_CXVIRTUALSCREEN) and GetSystemMetrics(SM_CYVIRTUALSCREEN) to return width and height for the virtual monitor.使用GetSystemMetrics(SM_CXVIRTUALSCREEN)GetSystemMetrics(SM_CYVIRTUALSCREEN)返回虚拟监视器的宽度和高度。

Also be sure the process is DPI aware.还要确保该过程是 DPI 感知的。 For testing you can call SetProcessDPIAware();对于测试,您可以调用SetProcessDPIAware(); at the start of the program.在程序开始时。 Ideally DPI awareness should be set in manifest file.理想情况下,应在清单文件中设置 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);

Above code is copying bits from client DC the the same client DC, it's not going to do anything.上面的代码是从客户端 DC 复制位到同一个客户端 DC,它不会做任何事情。 Presumably you want to copy from desktop DC to client DC.大概您想从桌面 DC 复制到客户端 DC。

Moreover, the coordinates are basically picked at random.而且,坐标基本上是随机选取的。 It assumes the primary monitor is on top-left.它假设主监视器位于左上角。 If uX is greater than window's own width, it will not get copied, unless the window stretches the whole virtual monitor.如果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);
}

You can use您可以使用

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

Check below links:检查以下链接:

  1. Using Multiple Monitors as Independent Displays 使用多台显示器作为独立显示器
  2. CreateDCA function 创建DCA函数
  3. Multiple Display Monitors Functions 多显示器功能

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM