2016-05-04 49 views
0

私は、アプリケーションDPIに対応している問題をテストするためにDelphi XE7を使用しています。WM_DPICHANGEメッセージを受信しませんでした

タスクの1つは、ウィンドウが異なるDPI値を持つモニターに移動されたときに生成されるWM_DPICHANGEメッセージに応答することです。私はマルチモニタを設定していないので、このメッセージを生成する非常に簡単なテストプログラムを作成しましたが、Windows 8.1プラットフォームでは受信されません。これは、次のプログラムがこれを証明するのWindows 7上で動作しますOK:

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

複数のモニタなしで何かを達成するチャンスはありません –

+1

これは何も成し遂げません。あなたがメッセージをキャッチすることができたとしても、異なるDPI設定を持つ2台目のモニターを持たなくても、どのように応答するかをテストする方法はありません。それは、Androidデバイスやシミュレータを持たずにAndroidアプリを書くようなものです。あなたがすることは単純な推測であり、失敗することになります。 –

+1

また、[このドキュメントは(https://msdn.microsoft.com/en-us/library/windows/desktop/dn312083%28v=vs.85%29.aspx)を読むと、このメッセージは'PROCESS_PER_MONITOR_DPI_AWARE'に登録されているアプリケーションによって受信される可能性があります。 –

答えて

2

WM_DPICHANGEDは、Windows 8.1以降でのみサポートされています。

コードがWindows 7で動作すると言えば、ボタンをクリックするとウィンドウにメッセージがポストされ、そのメッセージがキャプチャされます。一方、実際のDPIの変更には関係ありません。 Windows 7では、カスタムメッセージを送信したように、WM_DPICHANGEDが処理されます。

Windows 8.1以降では、WM_DPICHANGEDはWindows API定義メッセージです。 PostMessageを使用してメッセージを送信するとエラーコード1159 ERROR_MESSAGE_SYNC_ONLY

このエラーは、その特定のメッセージを非同期に送信できないことを意味します。 Windows APIで定義されているWM_DPICHANGEDメッセージの場合、RECT構造体へのポインタである第2パラメータに問題があります。

WM_DPICHANGED

  • のwParam - のwParamのHIWORDは、ウィンドウの新しいDPIのY軸値を含みます。 wParamのLOWORDには、ウィンドウの新しいDPIのX軸値 が含まれています。たとえば、96,120,144, または192です.X軸とY軸の値は、Windowsアプリケーションの場合は と同じです。
  • lParamに - 推奨サイズと新しい DPIのためのスケーリングされた現在のウィンドウの位置を提供するRECT構造体へのポインタ。この メッセージを処理するとき、lParamが提供する提案に基づいて、アプリケーションはウィンドウの位置を変更し、ウィンドウのサイズを変更することが予想されます。

PostMessage

あなたは非同期 メッセージ機能(のPostMessage、SendNotifyMessage、および SendMessageCallback)にWM_USER以下の範囲でメッセージを送信した場合、そのメッセージのパラメータは、ポインタを含めることはできません。 それ以外の場合、操作は失敗します。関数は受信スレッドがメッセージを処理する機会を持っていた の前に返され、 送信者は使用前にメモリを解放します。

コードのPostMessageSendMessageに変更した場合、ボタンのクリックはWindows 8.1以降でも有効になります。

もちろん、アプリケーションのDPI認識を適切に設定していれば、通常はWindowsによって送信されるメッセージも処理されます(WM_DPICHANGED)。

+0

説明をありがとう。私は、DPIがマニフェストを持っていることを認識していた私のウィンドウは、デルファイがやっていたものだったのでメッセージを受け取っていないと心配していました。私は自分自身をマルチモニターテストプラットフォームにする必要があります。 – kaj66

+0

*「Windowsは、システムによって直接送信されないWM_DPICHANGEDメッセージを受信キューから保護しています。」*疑わしいと思われる*送信*メッセージはキューに入れられません。通常はキューに表示されないメッセージを監視することは、リソースの無駄になります。しかし、私は何もテスト/検証できません。 –

+0

@SertacAkyuz私は、メッセージがメッセージキューに送られる 'PostMessage'に対してそのコメントをしました。そして、期待通りにウィンドウに渡されないことは明らかです。正確に何が起きているのか分かりませんし、正確な詳細を知るにはMS開発者でなければなりません。 'SendMessage'は私が書いたように動作が異なります。 –

関連する問題