Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ SetWindowPos()跨进程DPI感知_C++_Windows_Winapi_Dpi - Fatal编程技术网

C++ SetWindowPos()跨进程DPI感知

C++ SetWindowPos()跨进程DPI感知,c++,windows,winapi,dpi,C++,Windows,Winapi,Dpi,我正在创建一个程序,使用SetWindowPos()从另一个进程移动/调整窗口大小。我自己的程序是PROCESS\u PER\u MONITOR\u DPI\u AWARE。其他程序可以是PROCESS\u DPI\u unknowledge、PROCESS\u SYSTEM\u DPI\u AWARE或PROCESS\u PER\u MONITOR\u DPI\u AWARE 因为我自己的程序是PROCESS\u PER\u MONITOR\u DPI\u AWARE,所以我传递给SetWin

我正在创建一个程序,使用
SetWindowPos()
从另一个进程移动/调整窗口大小。我自己的程序是
PROCESS\u PER\u MONITOR\u DPI\u AWARE
。其他程序可以是
PROCESS\u DPI\u unknowledge
PROCESS\u SYSTEM\u DPI\u AWARE
PROCESS\u PER\u MONITOR\u DPI\u AWARE

因为我自己的程序是
PROCESS\u PER\u MONITOR\u DPI\u AWARE
,所以我传递给
SetWindowPos()
的坐标是物理坐标。我现在想做的是逻辑坐标中将客户区域调整为特定大小

我想做的是

  • 获取窗口所在监视器的DPI,显示为
    屏幕DPI
  • 将目标窗口的DPI获取为
    windowDPI
  • 获取
    scaleFactor
    作为
    screenDPI/windowDPI
  • scaleFactor
  • 通过从窗口矩形大小中减去当前客户端矩形大小,计算窗口框架的额外大小
  • 这在很大程度上是可行的,但当我使用两个屏幕的显示比例不同时

    • 如果我将窗口从一个屏幕移动到下一个屏幕,则窗口框架大小的计算将关闭
    • 当窗口位于辅助屏幕上时,如果应用程序使用
      PROCESS\u SYSTEM\u DPI\u AWARE
      (与主屏幕使用120 DPI相比,主屏幕使用96 DPI),则此操作将失败。这与窗口框的大小无关,我还不确定它到底为什么会失败,但目标
      x
      y
      坐标被放大,以便将窗口移到屏幕外
    • 如果由于调整大小,窗口的中心改变了屏幕,会发生什么情况?然后
      屏幕dpi
      将不再正确,对吗?我怎么处理那个案子
    我知道还有一个函数
    AdjustWindowRectExForDpi
    ,但不知怎的,我无法让它正常工作。我应该传递给它的
    dpi
    值是多少?目标屏幕的dpi、目标窗口的dpi或我自己程序的dpi?此外,此功能仅在Windows 10以后的版本中可用,因此如何在较旧的Windows客户端上处理它

    如果能帮上忙,我将不胜感激。谢谢

    我应该传递给它的dpi值是多少?目标屏幕的dpi、目标窗口的dpi或我自己程序的dpi

    需要从一个屏幕移动到下一个屏幕的窗口DPI

    代码示例:

    #include <Windows.h>
    
    LRESULT CALLBACK startup_window_procedure(HWND window, UINT message, WPARAM w_param, LPARAM l_param)
    {
        switch (message)
        {
        case WM_DESTROY:
        {
            PostQuitMessage(0);
            return 0;
        }
    
        case WM_DPICHANGED:
        {
            // Resize the window
            RECT* new_rect = reinterpret_cast<RECT*>(l_param);
    
            if (!SetWindowPos(window, nullptr, new_rect->left, new_rect->top, new_rect->right - new_rect->left, new_rect->bottom - new_rect->top, SWP_NOZORDER | SWP_NOACTIVATE))
            {
                return 1;
            }
    
            return 0;
        }
        }
    
        return DefWindowProcW(window, message, w_param, l_param);
    }
    
    int CALLBACK wWinMain(HINSTANCE instance, HINSTANCE prev_instance, PWSTR cmd_line, int cmd_show)
    {
        constexpr auto window_class_name = L"example_dialog";
        constexpr auto window_style = WS_OVERLAPPEDWINDOW;
    
        // Enable per-monitor DPI-awareness version 2
        if (!SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
        {
            return 1;
        }
    
        // Create the window
        WNDCLASSEXW window_class;
        window_class.cbSize = sizeof(window_class);
        window_class.style = CS_HREDRAW | CS_VREDRAW;
        window_class.lpfnWndProc = startup_window_procedure;
        window_class.cbClsExtra = 0;
        window_class.cbWndExtra = 0;
        window_class.hInstance = instance;
        window_class.hIcon = nullptr;
        window_class.hCursor = nullptr;
        window_class.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
        window_class.lpszMenuName = nullptr;
        window_class.lpszClassName = window_class_name;
        window_class.hIconSm = nullptr;
    
        if (!RegisterClassExW(&window_class))
        {
            return 1;
        }
    
        HWND window = CreateWindowExW(0, window_class_name, L"Example window", window_style, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, nullptr, nullptr, instance, nullptr);
    
        if (!window)
        {
            return 1;
        }
    
        UINT dpi = GetDpiForWindow(window);
        float scaling_factor = static_cast<float>(dpi) / 96;
        // Actually set the appropriate window size
        RECT scale;
        scale.left = 0;
        scale.top = 0;
        scale.right = static_cast<LONG>(300 * scaling_factor);
        scale.bottom = static_cast<LONG>(150 * scaling_factor);
    
        if (!AdjustWindowRectExForDpi(&scale, window_style, false, 0, dpi))
        {
            return 1;
        }
    
        if (!SetWindowPos(window, nullptr, 0, 0, scale.right - scale.left, scale.bottom - scale.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE))
        {
            return 1;
        }
    
        ShowWindow(window, SW_SHOWNORMAL);
    
        // Message loop
        MSG message;
        int result;
    
        while ((result = GetMessageW(&message, nullptr, 0, 0)) != 0)
        {
            if (result == -1)
            {
                return 1;
            }
            else
            {
                TranslateMessage(&message);
                DispatchMessageW(&message);
            }
        }
    
        return static_cast<int>(message.wParam);
    }
    
    #包括
    LRESULT回调启动\u窗口\u过程(HWND窗口、UINT消息、WPARAM w_参数、LPARAM l_参数)
    {
    开关(信息)
    {
    案例WM_销毁:
    {
    PostQuitMessage(0);
    返回0;
    }
    案例WM_dpichange:
    {
    //调整窗口大小
    RECT*new_RECT=重新解释强制转换(l_参数);
    如果(!SetWindowPos(窗口,nullptr,新建->左侧,新建->顶部,新建->右侧-新建->左侧,新建->底部-新建->顶部,SWP\u NOZORDER | SWP\u NOACTIVATE))
    {
    返回1;
    }
    返回0;
    }
    }
    返回DefWindowProcW(窗口、消息、w_参数、l_参数);
    }
    int CALLBACK wWinMain(HINSTANCE实例、HINSTANCE prev_实例、PWSTR cmd_行、int cmd_show)
    {
    constexpr自动窗口类名称=L“示例对话框”;
    constexpr auto window_style=WS_overlapped window;
    //启用每监视器DPI感知版本2
    if(!SetProcessDpiAwarenessContext(DPI\U感知\U上下文\U每\U监视器\U感知\U V2))
    {
    返回1;
    }
    //创建窗口
    WNDCLASSXW窗口类;
    window_class.cbSize=sizeof(window_class);
    window_class.style=CS_HREDRAW | CS_VREDRAW;
    window\u class.lpfnWndProc=启动\u window\u程序;
    window_class.cbClsExtra=0;
    window_class.cbWndExtra=0;
    window_class.hInstance=实例;
    window_class.hIcon=nullptr;
    window_class.hCursor=nullptr;
    window_class.hbrBackground=重新解释投影(颜色窗口+1);
    window_class.lpszMenuName=nullptr;
    window_class.lpszClassName=window_class_name;
    window_class.hIconSm=nullptr;
    如果(!RegisterClassesXW(&window_类))
    {
    返回1;
    }
    HWND window=CreateWindowExW(0,窗口类名称,L“示例窗口”,窗口样式,CW_USEDEFAULT,CW_USEDEFAULT,0,0,nullptr,nullptr,实例,nullptr);
    如果(!窗口)
    {
    返回1;
    }
    UINT dpi=GetDpiForWindow(窗口);
    浮动比例系数=静态比例系数(dpi)/96;
    //实际设置适当的窗口大小
    直尺;
    比例左=0;
    scale.top=0;
    scale.right=静态投影(300*缩放因子);
    scale.bottom=静态投影(150*缩放系数);
    if(!AdjustWindowRectExForDpi(&scale,窗口样式,false,0,dpi))
    {
    返回1;
    }
    如果(!SetWindowPos(窗口,nullptr,0,0,scale.right-scale.left,scale.bottom-scale.top,SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE))
    {
    返回1;
    }
    ShowWindow(窗口,SW_SHOWNORMAL);
    //消息循环
    消息;
    int结果;
    while((result=GetMessageW(&message,nullptr,0,0))!=0)
    {
    如果(结果==-1)
    {
    返回1;
    }
    其他的
    {
    翻译消息(和消息);
    DispatchMessageW(&message);
    }
    }
    返回静态_cast(message.wParam);
    }
    

    窗口可以从一个屏幕移动到下一个屏幕,并成功地重新计算窗口大小。

    太棒了,谢谢。但是,如果我将窗口从屏幕A移动到B,并且窗口的dpi在屏幕B上不同,那么我是否必须使用未来的dpi来调整窗口矩形?不,您不必这样做。当您移动到具有新dpi的屏幕时,该窗口还将获得
    WM\u DPICHANGED
    消息和重新计算的窗口大小。