Delphi: Comment répondre à WM_SETTINGCHANGE / WM_WININICHANGE?
Question
je dois savoir quand ma demande un recieves WM_SETTINGCHANGE
message (anciennement connu sous le nom WM_WININICHANGE
).
Le problème est que la pompe de message dans TApplication il envoie dans un trou noir (gestionnaire par défaut) avant que je puisse avoir une chance de le voir:
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;
La procédure CheckIniChange()
ne jette pas tout état de cause, je peux gérer, ni ne Mouse.SettingChanged()
.
Et une fois le chemin de code atteint Default
, il est envoyé dans le trou de vidange de DefWindowProc
, de ne jamais être revu (depuis la première chose que l'WndProc n'est réglé le Message.Result
à zéro.
i espérait affecter un gestionnaire à un événement TApplicationEvents.OnMessage:
procedure TdmGlobal.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
begin
case Msg.message of
WM_SETTINGCHANGE:
begin
// Code
end;
end;
end;
Mais l'événement ne OnMessage est jeté pour les messages qui passent par la pompe de message. Étant donné que le message WM_SETTINGCHANGE
est « manipulé », il ne voit jamais le
PeekMessage
TranslateMessage
DispatchMessage
système .
Comment puis-je répondre aux fenêtres WM_SETTINGCHANGE
de diffusion?
La solution
Edit2: Pour les anciennes versions de l'interception habituelle message doit travailler ...
[...]
private
procedure WMSettingChange(var Message: TWMSettingChange); message WM_SETTINGCHANGE;
[...]
procedure TForm1.WMSettingChange(var Message: TWMSettingChange);
begin
showMessage('SettingChange message intercept');
end;
Edit: Oups! N'a pas vu qu'il était pour D5. Ce qui suit était D2007 +.
Utilisez un OnSettingChange dans votre application:
procedure TApplication.SettingChange(var Message: TWMSettingChange);
begin
if Assigned(FOnSettingChange) then
with Message do
FOnSettingChange(Self, Flag, Section, Result);
end;
Vous pouvez tester avec ce code. Essayez de changer la hauteur ou le côté amarrage du ... 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;
Autres conseils
La réponse était à ma question, ce qui est dangereux, non documenté, l'utilisation de 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;
Vous le manipuler comme vous le feriez pour tout autre message. gestionnaire par défaut de TApplication volonté la route correctement si vous configurez un gestionnaire de messages pour lui:
// 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;