2010-05-12 23 views
2

J'ai besoin de savoir quand mon application reçoit un message WM_SETTINGCHANGE (anciennement connu sous le nom WM_WININICHANGE).Delphi: Comment répondre à WM_SettingChange/WM_WinIniChange?

Le problème est que la pompe de message dans TApplication 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 un événement 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 DefWindowProc, ne jamais être revu (depuis la première chose que l'WndProc fait est réglé le Message.Result à zéro.

j'espérais attribuer 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 Depuis le message WM_SETTINGCHANGE est « manipulé », il ne voit jamais le

PeekMessage 
TranslateMessage 
DispatchMessage 

système.

Comment puis-je répondre à la diffusion de Windows WM_SETTINGCHANGE?

Répondre

8

Edit2: Pour les anciennes versions l'interception habituelle message devrait fonctionner ...

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

Edit: Oups! Je n'ai pas vu c'était pour D5. Ce qui suit était en 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 le côté de la hauteur ou 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; 
+0

' Application.OnSettingChange' travaillé pour moi en D7. Je n'ai pas pu obtenir le message habituel «... message WM_SETTINGCHANGE; – Slashback

2

La réponse était dans 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; 
+2

, non documentée ... http://docwiki.embarcadero.com/VCL/en/Forms.TApplication.HookMainWindow –

1

Vous le manipulez comme vous le feriez pour tout autre message. Le gestionnaire par défaut de TApplication sera l'itinéraire correctement si vous configurez un gestionnaire de messages pour elle:

// 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; 
bien
+0

Je n'appréciais pas le fait que le message soit diffusé à tous mes formulaires - je supposais que cela ne concernait que la boucle principale du message de l'application. –