2012-01-05 9 views
4

私はいくつかのウィンドウ とアプリケーション メッセージに応答しようとしていますが、それらを複数回取得します。同じ種類の複数のウィンドウメッセージが表示されるのはなぜですか?

たとえば、WM_TIMECHANGEを使用してシステムの日付を変更したときにメッセージボックスを表示するために、次のコードを記述します。 WMTimeChangeは複数回実行され、倍数(ほとんどの場合2〜3回)のメッセージボックスが1つずつ表示されます。たぶん、私は何かを欠いている?

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs; 

type 
    TForm1 = class(TForm) 
    protected 
    procedure WMTimeChange(var Msg: TMessage) ; message WM_TIMECHANGE; 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

{ TForm1 } 

procedure TForm1.WMTimeChange(var Msg: TMessage); 
begin 
    showmessage('Date/Time has changed!'); 
end; 

end. 

Windows XPでのテスト。

EDIT:明確にするために、私の意図は理解されていますWHYこれは起こり、複数の呼び出しを回避する方法ではありません。とにかく、それに対する答えが不可能ならば、私は後で答えを受け入れるでしょう。

EDIT2:Delphiの問題ではないように、Delphiタグを削除しました。

+0

どのように時間を変更していますか?なぜ*メッセージは何回も送信されるべきではありませんか? –

+0

@RobKennedy時計をダブルクリックし、年を変更します(2012年から2013年まで)。「OK」ボタンをクリックします。今年は一度だけ変更したので、WM_TIMECHANGEは1つしか期待していません。 – EMBarbosa

+0

@EMBarbosa:オペレーティングシステム*は、時間が変更されるたびにメッセージが送信されることを保証します(最低1回)。しかし、私はそれが一度*送られたことを保証するとは思わない。結局のところ、おそらく技術的なレベルで説明したGUI操作は、システムの日付/時刻データの3つの変更に相当します。 –

答えて

3

コードは正しいです。 WindowsがWM_TIMECHANGEメッセージを何回か送信しているようです。

だから、あなただけのすなわち、多かれ少なかれ15分、あなたのメッセージは1日1回のみの1%あたりのトリガすることができるように小さな時間ヒステリシス比較を追加することができます。これは何を私のようなものである

type 
    TForm1 = class(TForm) 
    protected 
    FWMTimeChangeTimeStamp: TDateTime; 
    procedure WMTimeChange(var Msg: TMessage) ; message WM_TIMECHANGE; 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

{ TForm1 } 

procedure TForm1.WMTimeChange(var Msg: TMessage); 
begin 
    if Now-FWMTimeChangeTimeStamp>0.01 then 
    begin 
    showmessage('Date/Time has changed!'); 
    FWMTimeChangeTimeStamp := Now; 
    end; 
end; 
+1

私はちょうどメッセージをピックし、最後に送信されたものを処理します。 –

+2

@Sertac誰かが、第2のものが投稿される前に最初のものを処理できないと言っていますか? –

+0

@SertacAkyuz *いくつかのメッセージが送信されたようです。 'message WM_TIMECHANGE'イベントハンドラを使うと、すべてのメッセージを処理できます。私の答えで実装した15分の閾値は、最初のものだけを処理し、15分まで無視します。 15分が良くない場合は、0.01を0.001または0.0002に変更してください。 –

1

私の場合は、この行動に弾力を回復するために使用されています。しかし、コメントの中で述べたように、ユーザーがアプリケーションに答えるのに時間がかかる場合にのみ機能します。だから、Arnaud Bounchezは一般的な使い方の方が優れています。 FWMTimeChangeStampを現在のコンピュータクロックとは異なる値に初期化することを忘れないでください。

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs; 

type 
    TForm1 = class(TForm) 
    procedure FormCreate(Sender: TObject); 
    protected 
    procedure WMTimeChange(var Msg: TMessage) ; message WM_TIMECHANGE; 
    private 
    isTimeChangeEventShowing: Boolean; 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

{ TForm1 } 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    isTimeChangeEventShowing := false 
end; 

procedure TForm1.WMTimeChange(var Msg: TMessage); 
begin 
    if not isTimeChangeEventShowing then 
    begin 
    isTimeChangeEventShowing := true; 
    showmessage('Date/Time has changed!'); 
    isTimeChangeEventShowing := false; 
    end; 
end; 

end. 
関連する問題