Frage

Ich muss wissen, wenn meine Anwendung eine recieves WM_SETTINGCHANGE Nachricht (früher bekannt als WM_WININICHANGE ).

Das Problem ist, dass die Nachricht Pumpe in TApplication sendet es nach unten einem schwarzen Loch (Standard-Handler), bevor ich eine Chance bekommen, es zu sehen:

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;

Das Verfahren CheckIniChange() keine Veranstaltung werfen i umgehen kann, ebenso wenig wie Mouse.SettingChanged().

Und wenn der Codepfad erreicht Default wird auf der DefWindowProc Ablaufloch geschickt, nie wieder (da das erste, was zu sehen ist die WndProc nicht gesetzt wird, um die Message.Result auf Null zurück.

Ich habe gehofft, einen Handler zu einem TApplicationEvents.OnMessage Ereignisse zuweisen:

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

Aber das OnMessage Ereignis wird nur für Nachrichten ausgelöst, die durch die Nachricht Pumpe kommen. Da die WM_SETTINGCHANGE Meldung „behandelt“ wird, sieht es nie

PeekMessage
TranslateMessage
DispatchMessage

System.

Wie kann ich auf die Windows-Sendung WM_SETTINGCHANGE reagieren?

War es hilfreich?

Lösung

Edit2: Für ältere Versionen der übliche Nachricht abfangen soll ... arbeiten

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

Edit: Ooops! Sieht sie nicht für D5 sind. Das Folgende wurde in D2007 +.

Verwenden Sie einen OnSettingChange in Ihrer Anwendung:

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

Sie können mit diesem Code testen. Versuchen Sie, und die Höhe ändern oder Docking Seite des TaskBar ...

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;

Andere Tipps

Die Antwort war in meiner Frage, die gefährlich, ohne Papiere, die Verwendung von 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;

Sie behandeln es wie würden Sie jede andere Nachricht. TApplication der Standard-Handler leitet es richtig, wenn Sie einen Meldungshandler für sie einrichten:

// 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;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top