Winapi Windows 10上的Win32 API窗口应用程序视网膜高DPI屏幕问题 主题:简单C++基于Win32 API的单窗口应用程序。请参阅下面的代码。 计算机是MacBook Retina,本机安装了Windows 10
问题:在鼠标悬停事件中,标题栏(窗口的非客户端区域)中的最小化/最大化/关闭按钮的行为不正确。每个按钮仅在鼠标光标移动时高亮显示,而按钮应一直高亮显示,直到鼠标指针离开按钮区域 问题:问题出在哪里?Win10清单 代码:Winapi Windows 10上的Win32 API窗口应用程序视网膜高DPI屏幕问题 主题:简单C++基于Win32 API的单窗口应用程序。请参阅下面的代码。 计算机是MacBook Retina,本机安装了Windows 10,winapi,windows-10,retina-display,win32gui,highdpi,Winapi,Windows 10,Retina Display,Win32gui,Highdpi,问题:在鼠标悬停事件中,标题栏(窗口的非客户端区域)中的最小化/最大化/关闭按钮的行为不正确。每个按钮仅在鼠标光标移动时高亮显示,而按钮应一直高亮显示,直到鼠标指针离开按钮区域 问题:问题出在哪里?Win10清单 代码: #include <Windows.h> #include <tchar.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
#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;
}
#包括
#包括
LRESULT回调WndProc(HWND HWND,UINT消息,WPARAM WPARAM,LPARAM LPARAM)
{
PAINTSTRUCT-ps;
HDC-HDC;
TCHAR msgGreeting[]=“来自MyWindowsApp的你好世界!”;
开关(信息)
{
案例WM_油漆:
hdc=开始喷漆(hWnd和ps);
文本输出(hdc,10,10,msgGreeting,(int)tcsclen(msgGreeting));
端漆(hWnd和ps);
打破
案例WM_销毁:
PostQuitMessage(0);
打破
违约:
返回DefWindowProc(hWnd、message、wParam、lParam);
打破
}
返回0;
}
int回调WinMain(HINSTANCE HINSTANCE、HINSTANCE hPrevInstance、LPSTR lpCmdLine、int nCmdShow)
{
//1.初始化应用程序
//2.显示主窗口
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=加载图标(wndClassWindowMain.hInstance,IDI_应用程序);
wndClassWindowMain.hCursor=LoadCursor(空,IDC_箭头);
wndClassWindowMain.hbrBackground=(HBRUSH)(彩色窗口);
wndClassWindowMain.lpszMenuame=NULL;
wndClassWindowMain.lpszClassName=文本(“MyMainWindowClass”);
wndClassWindowMain.hIconSm=加载图标(wndClassWindowMain.hInstance,IDI_应用程序);
if(0==RegisterClassEx(&wndClassWindowMain))
{
消息框(空)
,_T(“调用RegisterClassEx失败!”)
,_T(“MyWindowsApplication”)
,MB_i错误| MB_正常);
返回FALSE;
}
HWND hwndWindowMain=CreateWindowEx(WS_EX_APPWINDOW
,_T(“MyMainWindowClass”)
,_T(“我的窗口”)
,WS_重叠窗口
, 100, 100
, 640, 480
无效的
无效的
,hInstance
,空);
如果(NULL==hwndWindowMain)
{
消息框(空)
,\u T(“调用CreateWindowEx失败!”)
,_T(“MyWindowsApplication”)
,MB_i错误| MB_正常);
返回FALSE;
}
ShowWindow(hwndWindowMain、SW_SHOWDEFAULT);
更新窗口(hwndWindowMain);
//3.转到消息检索和调度循环
味精;
布尔布雷特;
while((bRet=GetMessage(&msg,NULL,0,0))!=0)
{
如果(bRet==-1)
{
//处理错误并可能退出
返回FALSE;
}
其他的
{
翻译信息(&msg);
发送消息(&msg);
}
}
返回(int)msg.wParam;
}
解决方案:
#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)兼容,需要执行以下步骤:
#包括
#pragma comment(lib,“Shcore.lib”)
WinMain
中添加以下调用SetProcessDpiAwareness(PROCESS\u PER\u MONITOR\u DPI\u AWARE)代码>
进一步阅读如下:解决方案:
#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)兼容,需要执行以下步骤:
#包括
#pragma comment(lib,“Shcore.lib”)
WinMain
中添加以下调用SetProcessDpiAwareness(PROCESS\u PER\u MONITOR\u DPI\u AWARE)代码>
<> P>进一步阅读如下:C和C++是不同的语言。请使用相关的标签。@ KayLUM对于这个案例没有区别,因为情况是关于平台而不是语言。@ KayLUM,我展示的代码是C++,但是很容易移植到C和C++程序员使用的WiAPI中,所以有两个标签将有助于目标受众找到这个线程。顺便说一句,我已经找到了解决办法。请欣赏.KayLUM:代码是有效的C和有效C++。它不是有效的Pascal、Delphi、Rust、Go或Python。为什么通过C++任意选择C来限制可发现性的范围,反之亦然?这将如何使这个问答更容易被发现?你对此有令人信服的答案吗?语言与问题无关。这是一个关于winapi的问题。最好给它贴上这样的标签。一个知道WiAPI的Delphi程序员也可以作为C或C++程序员来回答。C和C++是不同的语言。请使用相关的标签。@ KayLUM在这种情况下没有区别,因为情况是关于平台而不是语言。@ KayLUM,我展示的代码是C++,但是很容易移植到C和C++程序员使用的C.WiAPI,所以两个标签都会有。