代码之家  ›  专栏  ›  技术社区  ›  Ian Boyd

Delphi:如何响应wm_settingchange/wm_wininichange?

  •  3
  • Ian Boyd  · 技术社区  · 14 年前

    我需要知道我的申请何时收到 WM_SETTINGCHANGE 消息(以前称为 WM_WININICHANGE )

    问题是信息泵入 应用程序 将其发送到黑洞(默认处理程序),然后我才能看到它:

    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_设置更改 消息是“已处理”的,它从未看到

    PeekMessage
    TranslateMessage
    DispatchMessage
    

    系统。

    我如何回应Windows广播 wm_设置更改 ?

    3 回复  |  直到 14 年前
        1
  •  9
  •   Francesca    14 年前

    edit2:对于旧版本,通常的消息截获应该可以工作…

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

    编辑:OOOPS!没看到是D5的。 以下是2007+版。

    在应用程序中使用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;
    
        2
  •  2
  •   Ian Boyd    14 年前

    答案就在我的问题中,危险的,无证的,使用 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;
    
        3
  •  2
  •   Ken White    14 年前

    你处理它就像处理其他信息一样。如果为应用程序设置了消息处理程序,则应用程序的默认处理程序将正确路由它:

    // 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;