未收到WM_DPICHANGE消息

时间:2016-05-04 15:42:04

标签: windows delphi dpi

我正在使用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。在信息到达我的程序之前是否有东西在吃东西?

1 个答案:

答案 0 :(得分:2)

仅在Windows 8.1及更高版本上支持

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结构的指针。

WM_DPICHANGED

  
      
  • wParam - wParam的HIWORD包含窗口新dpi的Y轴值。 wParam的LOWORD包含   窗口的新DPI的X轴值。例如,96,120,144,   或192.X轴和Y轴的值相同   Windows应用程序。
  •   
  • lParam - 一个指针到一个RECT结构,它提供了为新的缩放的当前窗口的建议大小和位置   DPI。期望是应用程序将重新定位和调整窗口大小   根据lParam在处理时提供的建议   消息。
  •   

PostMessage

  

如果您将WM_USER以下范围内的消息发送到异步   消息函数(PostMessage,SendNotifyMessage和   SendMessageCallback),其消息参数不能包含指针。   否则,操作将失败。函数将在之前返回   接收线程有机会处理消息和   发件人在使用之前会释放内存。

如果您将代码中的PostMessage更改为SendMessage,您的按钮点击也适用于Windows 8.1+。

当然,如果您已正确设置应用程序DPI感知,它通常也会处理Windows发送的WM_DPICHANGED消息。