Win32 API window Windows 10 上的 Retina 高 DPI 屏幕应用程序问题
Win32 API window application Retina high DPI screen issues on Windows 10
主题: 简单的基于 C++ Win32 API 的单个 window 应用程序。请参阅下面的代码。
计算机是 MacBook Retina,本机安装 Windows 10。
问题: minimize/maximize/close 标题栏中的按钮(window 的非客户区)在鼠标悬停事件时表现不正确。每个按钮只有在鼠标光标移动时才会高亮,而按钮应该一直高亮直到鼠标指针离开按钮区域。
问题:问题是什么? Win10 清单?
代码:
#include <Windows.h>
#include <tchar.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
TCHAR msgGreeting[] = _T("Hello World from MyWindowsApp!");
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
TextOut(hdc, 10, 10, msgGreeting, (int)_tcsclen(msgGreeting));
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// 1. Initialize the application
// 2. Display the main window
WNDCLASSEX wndClassWindowMain;
wndClassWindowMain.cbSize = sizeof(WNDCLASSEX);
wndClassWindowMain.style = CS_VREDRAW | CS_HREDRAW;
wndClassWindowMain.lpfnWndProc = WndProc;
wndClassWindowMain.cbClsExtra = 0;
wndClassWindowMain.cbWndExtra = 0;
wndClassWindowMain.hInstance = hInstance;
wndClassWindowMain.hIcon = LoadIcon(wndClassWindowMain.hInstance, IDI_APPLICATION);
wndClassWindowMain.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClassWindowMain.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wndClassWindowMain.lpszMenuName = NULL;
wndClassWindowMain.lpszClassName = TEXT("MyMainWindowClass");
wndClassWindowMain.hIconSm = LoadIcon(wndClassWindowMain.hInstance, IDI_APPLICATION);
if (0 == RegisterClassEx(&wndClassWindowMain))
{
MessageBox(NULL
, _T("Call to RegisterClassEx failed!")
, _T("MyWindowsApplication")
, MB_ICONERROR | MB_OK);
return FALSE;
}
HWND hwndWindowMain = CreateWindowEx(WS_EX_APPWINDOW
, _T("MyMainWindowClass")
, _T("My Window")
, WS_OVERLAPPEDWINDOW
, 100, 100
, 640, 480
, NULL
, NULL
, hInstance
, NULL);
if (NULL == hwndWindowMain)
{
MessageBox(NULL
, _T("Call to CreateWindowEx failed!")
, _T("MyWindowsApplication")
, MB_ICONERROR | MB_OK);
return FALSE;
}
ShowWindow(hwndWindowMain, SW_SHOWDEFAULT);
UpdateWindow(hwndWindowMain);
// 3. Go to the message retrieval-and-dispatch loop
MSG msg;
BOOL bRet;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
return FALSE;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
解法:
问题在于上述示例中应用程序的 DPI(每英寸点数)感知。为了使您的本机 C++/Win32 API 代码与不同屏幕(包括 4K 和 Retina)兼容,您需要执行以下步骤:
- 包括适当的 header
#include <ShellScalingApi.h>
- 告诉链接器编译后的函数代码在哪里
#pragma comment(lib,"Shcore.lib")
- 最后在
WinMain
添加如下调用SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
瞧!
现在在 Retina 上我看到我的应用程序 window 适当缩放。 Minimize/Maximize/Close 按钮按预期工作。
进一步阅读在这里:https://msdn.microsoft.com/en-us/library/windows/desktop/dn302122(v=vs.85).aspx
主题: 简单的基于 C++ Win32 API 的单个 window 应用程序。请参阅下面的代码。 计算机是 MacBook Retina,本机安装 Windows 10。
问题: minimize/maximize/close 标题栏中的按钮(window 的非客户区)在鼠标悬停事件时表现不正确。每个按钮只有在鼠标光标移动时才会高亮,而按钮应该一直高亮直到鼠标指针离开按钮区域。
问题:问题是什么? Win10 清单?
代码:
#include <Windows.h>
#include <tchar.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
TCHAR msgGreeting[] = _T("Hello World from MyWindowsApp!");
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
TextOut(hdc, 10, 10, msgGreeting, (int)_tcsclen(msgGreeting));
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// 1. Initialize the application
// 2. Display the main window
WNDCLASSEX wndClassWindowMain;
wndClassWindowMain.cbSize = sizeof(WNDCLASSEX);
wndClassWindowMain.style = CS_VREDRAW | CS_HREDRAW;
wndClassWindowMain.lpfnWndProc = WndProc;
wndClassWindowMain.cbClsExtra = 0;
wndClassWindowMain.cbWndExtra = 0;
wndClassWindowMain.hInstance = hInstance;
wndClassWindowMain.hIcon = LoadIcon(wndClassWindowMain.hInstance, IDI_APPLICATION);
wndClassWindowMain.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClassWindowMain.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wndClassWindowMain.lpszMenuName = NULL;
wndClassWindowMain.lpszClassName = TEXT("MyMainWindowClass");
wndClassWindowMain.hIconSm = LoadIcon(wndClassWindowMain.hInstance, IDI_APPLICATION);
if (0 == RegisterClassEx(&wndClassWindowMain))
{
MessageBox(NULL
, _T("Call to RegisterClassEx failed!")
, _T("MyWindowsApplication")
, MB_ICONERROR | MB_OK);
return FALSE;
}
HWND hwndWindowMain = CreateWindowEx(WS_EX_APPWINDOW
, _T("MyMainWindowClass")
, _T("My Window")
, WS_OVERLAPPEDWINDOW
, 100, 100
, 640, 480
, NULL
, NULL
, hInstance
, NULL);
if (NULL == hwndWindowMain)
{
MessageBox(NULL
, _T("Call to CreateWindowEx failed!")
, _T("MyWindowsApplication")
, MB_ICONERROR | MB_OK);
return FALSE;
}
ShowWindow(hwndWindowMain, SW_SHOWDEFAULT);
UpdateWindow(hwndWindowMain);
// 3. Go to the message retrieval-and-dispatch loop
MSG msg;
BOOL bRet;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
return FALSE;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
解法:
问题在于上述示例中应用程序的 DPI(每英寸点数)感知。为了使您的本机 C++/Win32 API 代码与不同屏幕(包括 4K 和 Retina)兼容,您需要执行以下步骤:
- 包括适当的 header
#include <ShellScalingApi.h>
- 告诉链接器编译后的函数代码在哪里
#pragma comment(lib,"Shcore.lib")
- 最后在
WinMain
添加如下调用SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
瞧!
现在在 Retina 上我看到我的应用程序 window 适当缩放。 Minimize/Maximize/Close 按钮按预期工作。
进一步阅读在这里:https://msdn.microsoft.com/en-us/library/windows/desktop/dn302122(v=vs.85).aspx