Delphi: Wie WM_SETTINGCHANGE / WM_WININICHANGE reagieren?
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?
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;