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
windowDPI
scaleFactor
作为screenDPI/windowDPI
scaleFactor
- 如果我将窗口从一个屏幕移动到下一个屏幕,则窗口框架大小的计算将关闭
- 当窗口位于辅助屏幕上时,如果应用程序使用
(与主屏幕使用120 DPI相比,主屏幕使用96 DPI),则此操作将失败。这与窗口框的大小无关,我还不确定它到底为什么会失败,但目标PROCESS\u SYSTEM\u DPI\u AWARE
和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
消息和重新计算的窗口大小。