C++ GetDC 所有监视器 [英] C++ GetDC All Monitors

查看:39
本文介绍了C++ GetDC 所有监视器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我正在制作一些模仿屏幕熔化效果的东西,但我只能让它在我的主显示器上工作.我尽可能多地查找,在 GetDC 上只有一个论坛适用于所有显示器,但它没有用,所做的只是从我的主显示器到我的辅助显示器制作一个矩形,效果仍然只起作用我的主显示器.这是我读到的线程:GetDC(NULL) 获取主监视器或虚拟屏幕?

LRESULT CALLBACK Melter(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) {开关(消息){案例 WM_CREATE:{HDC 桌面 = GetDC(HWND_DESKTOP);HDC 窗口 = GetDC(hWnd);BitBlt(Window, 0, 0, ScreenWidth, ScreenHeight, Desktop, 0, 0, SRCCOPY);ReleaseDC(hWnd, Window);ReleaseDC(HWND_DESKTOP,桌面);SetTimer(hWnd, 0, 间隔, 0);ShowWindow(hWnd, SW_SHOW);休息;}案例 WM_PAINT:{ValidateRect(hWnd, 0);休息;}案例 WM_TIMER:{HDC 窗口 = GetDC(hWnd);int uX = (rand() % ScreenWidth) - (150/2), uY = (rand() % 15), Width = (rand() % 150);BitBlt(窗口,uX,uY,宽度,屏幕高度,窗口,uX,0,SRCCOPY);ReleaseDC(hWnd, Window);休息;}案例 WM_DESTROY:{KillTimer(hWnd, 0);PostQuitMessage(EXIT_SUCCESS);休息;}返回退出成功;}返回 DefWindowProc(hWnd, Message, wParam, lParam);}

我更改的行是 HDC Window = GetDC(Window) 到 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 宽度 = (rand() % 150);BitBlt(窗口,uX,uY,宽度,屏幕高度,窗口,uX,0,SRCCOPY);

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

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

LRESULT CALLBACK Melter(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) {开关(消息){案例 WM_PAINT:{油漆结构 ps;auto hdc = BeginPaint(hWnd, &ps);矩形 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);休息;}案例 WM_DESTROY:PostQuitMessage(0);休息;}返回 DefWindowProc(hWnd, Message, wParam, lParam);}

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. This is the thread I read: 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);
}

The line I changed was HDC Window = GetDC(Window) to HDC Window = GetDC(NULL) and then some other stuff like the 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. Still doesn't work though.

解决方案

GetDC(HWND_DESKTOP) (same as GetDC(0)) already returns the DC for all monitors. The problem with above code is mainly with the usage of BitBlt and choosing the coordinates. See the MCVE below that addresses the question.

Don't draw in response to WM_CREATE, it's just going to get erased in WM_PAINT or when background is erased.

Don't call ValidateRect in response to WM_PAINT. If you want to erase the window then just use FillRect, or force repaint from a command or another route.

Use GetSystemMetrics(SM_CXVIRTUALSCREEN) and GetSystemMetrics(SM_CYVIRTUALSCREEN) to return width and height for the virtual monitor.

Also be sure the process is DPI aware. For testing you can call SetProcessDPIAware(); at the start of the program. Ideally DPI awareness should be set in manifest file.

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. Presumably you want to copy from desktop DC to client 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.

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++ GetDC 所有监视器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆