基本上,我正在模仿屏幕熔化效果,但是我只能在主显示器上使用它。我已经竭尽所能,所有显示器上的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,因此它是所有监视器的宽度/高度。仍然不起作用。

最佳答案

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

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

不要响应ValidateRect呼叫WM_PAINT。如果要擦除窗口,则只需使用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);
}

关于c++ - C++ GetDC所有监视器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53329673/

10-13 00:13