我正在使用Delphi XE7来测试使应用程序DPI识别的问题。
其中一项任务是响应WM_DPICHANGE消息,该消息应在窗口移动到具有不同DPI值的监视器时生成。我没有设置多显示器,因此我编写了一个非常简单的测试程序来生成此消息,但是在Windows 8.1平台上没有收到。它在Windows 7上运行正常。以下程序演示了这一点:
unit Main;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
const
WM_DPICHANGED = 736; // 0x02E0
type
TMyForm = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure DPIChanged(var Message: TMessage); message WM_DPICHANGED;
public
{ Public declarations }
end;
var
MyForm: TMyForm;
implementation
{$R *.dfm}
procedure TMyForm.Button1Click(Sender: TObject);
begin
PostMessage(Self.Handle,WM_DPICHANGED,0,0);
end;
procedure TMyForm.DPIChanged(var Message: TMessage);
begin
ShowMessage('Message WM_DPICHANGED Received');
end;
end.
在Windows 8.1下运行时,不会显示ShowMessage。在信息到达我的程序之前是否有东西在吃东西?
答案 0 :(得分:2)
WM_DPICHANGED
。
当您说您的代码在Windows 7上运行时,它实际上是以点击按钮的方式发布消息到您的窗口并且您正在捕获该消息。另一方面,它与实际的DPI变化无关。在Windows 7 WM_DPICHANGED
被视为已发送一些自定义消息。
在Windows 8.1和更新版WM_DPICHANGED
上是Windows API定义的消息。使用PostMessage
发送该邮件失败,错误代码为1159 ERROR_MESSAGE_SYNC_ONLY
该错误意味着您无法异步发送该特定消息。此处的问题在于此处的第二个参数,即在Windows API中定义的RECT
消息的情况下指向WM_DPICHANGED
结构的指针。
- wParam - wParam的HIWORD包含窗口新dpi的Y轴值。 wParam的LOWORD包含 窗口的新DPI的X轴值。例如,96,120,144, 或192.X轴和Y轴的值相同 Windows应用程序。
- lParam - 一个指针到一个RECT结构,它提供了为新的缩放的当前窗口的建议大小和位置 DPI。期望是应用程序将重新定位和调整窗口大小 根据lParam在处理时提供的建议 消息。
如果您将WM_USER以下范围内的消息发送到异步 消息函数(PostMessage,SendNotifyMessage和 SendMessageCallback),其消息参数不能包含指针。 否则,操作将失败。函数将在之前返回 接收线程有机会处理消息和 发件人在使用之前会释放内存。
如果您将代码中的PostMessage
更改为SendMessage
,您的按钮点击也适用于Windows 8.1+。
当然,如果您已正确设置应用程序DPI感知,它通常也会处理Windows发送的WM_DPICHANGED
消息。