3

アプリケーションがいつWM_SETTINGCHANGEメッセージを受信したかを知る必要があります (以前は と呼ばれていましたWM_WININICHANGE)。

問題は、TApplicationのメッセージ ポンプがメッセージをブラック ホール (デフォルト ハンドラ) に送信してから、それを確認できるようになることです。

procedure TApplication.WndProc(var Message: TMessage);
...
begin
   Message.Result := 0;

   for I := 0 to FWindowHooks.Count - 1 do
      if TWindowHook(FWindowHooks[I]^)(Message) then Exit;

   CheckIniChange(Message);

   with Message do
      case Msg of
      WM_SETTINGCHANGE:
         begin
            Mouse.SettingChanged(wParam);
            Default;   <----------------------*poof* down the sink hole
         end;
      ...
      end;
      ...
end;

プロシージャCheckIniChange()は、処理できるイベントをスローしませんMouse.SettingChanged()

そして、コード パスが に達するDefaultと、排水口に送られDefWindowProc、二度と見られることはありません (WndProc が最初に行うことは、Message.Resultをゼロに設定するためです。

私はハンドラーを TApplicationEvents.OnMessage イベントに割り当てたいと思っていました:

procedure TdmGlobal.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
begin
   case Msg.message of
   WM_SETTINGCHANGE:
      begin
         // Code
      end;
   end;
end;

ただし、OnMessage イベントは、メッセージ ポンプを介して受信したメッセージに対してのみスローされます。WM_SETTINGCHANGEメッセージは「処理」されるため、

PeekMessage
TranslateMessage
DispatchMessage

システム。

Windowsブロードキャストに応答するにはどうすればよいWM_SETTINGCHANGEですか?

4

3 に答える 3

9

Edit2: 古いバージョンでは、通常のメッセージ インターセプトが機能するはずです...

[...]
  private
    procedure WMSettingChange(var Message: TWMSettingChange); message WM_SETTINGCHANGE;
[...]
procedure TForm1.WMSettingChange(var Message: TWMSettingChange);
begin
  showMessage('SettingChange message intercept');
end;

編集:おっと!D5用とは思えませんでした。以下はD2007+のものです。

アプリケーションで OnSettingChange を使用します。

procedure TApplication.SettingChange(var Message: TWMSettingChange);
begin
  if Assigned(FOnSettingChange) then
    with Message do
      FOnSettingChange(Self, Flag, Section, Result);
end;

このコードでテストできます。タスクバーの高さまたはドッキング側を変更してみてください...

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnSettingChange := MySettingChange;
end;

procedure TForm1.MySettingChange(Sender: TObject; Flag: Integer;
  const Section: string; var Result: Integer);
begin
  showMessage('setting changed');
end;
于 2010-05-12T19:33:05.637 に答える
2

他のメッセージと同じように処理します。TApplication のメッセージ ハンドラを設定すると、TApplication のデフォルト ハンドラによって正しくルーティングされます。

// interface
type
  TYourMainForm = class(TForm)
    // other stuff
  private
    procedure WMSettingChange(var Msg: TWMSettingChange); message WM_SETTINGCHANGE;
  end;

// implementation
procedure TYourMainForm.WMSettingChange(var Msg: TWMSettingChange); message WM_SETTINGCHANGE;
begin
  // Whatever handling here. TWMSettingChange is defined in Messages.pas
end;
于 2010-05-12T19:53:14.810 に答える
2

答えは私の質問にありました。危険で、文書化されていない、次の使用ですHookMainWindow

procedure TdmGlobal.DataModuleCreate(Sender: TObject);
begin
   ...
   Application.HookMainWindow(SettingChangeHook);
end;

procedure TdmGlobal.DataModuleDestroy(Sender: TObject);
begin
   Application.UnhookMainWindow(SettingChangeHook);
end;

function TdmGlobal.SettingChangeHook(var Message: TMessage): Boolean;
begin
   case Message.Msg of
   WM_SETTINGCHANGE:
      begin
         //Handler code
      end;
   end;

   Result := False; //continue processing
end;
于 2010-05-12T19:29:29.920 に答える