【问题标题】:Delphi: How to respond to WM_SettingChange/WM_WinIniChange?Delphi:如何响应 WM_SettingChange/WM_WinIniChange?
【发布时间】:2011-02-18 19:16:17
【问题描述】:

我需要知道我的应用程序何时收到WM_SETTINGCHANGE 消息(以前称为WM_WININICHANGE)。

问题是 TApplication 中的消息泵在我有机会看到它之前将其发送到黑洞(默认处理程序):

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_SETTINGCHANGE 消息已“处理”,因此它永远不会看到

PeekMessage
TranslateMessage
DispatchMessage

系统。

如何回复windows广播WM_SETTINGCHANGE

【问题讨论】:

    标签: windows delphi winapi messages delphi-5


    【解决方案1】:

    Edit2:对于旧版本,通常的消息拦截应该可以工作...

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

    编辑:哎呀!没看到它是为 D5 准备的。 以下是 D2007+。

    在您的应用程序中使用 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;
    

    【讨论】:

    • Application.OnSettingChange 在 D7 中为我工作。我无法让通常的...message WM_SETTINGCHANGE; 工作。
    【解决方案2】:

    您可以像处理任何其他消息一样处理它。如果您为其设置消息处理程序,TApplication 的默认处理程序将正确路由它:

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

    【讨论】:

    • 我不明白该消息被广播到我所有的表单这一事实 - 我认为它只进入应用程序的主消息循环。
    【解决方案3】:

    答案在我的问题中,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;
    

    【讨论】:

    猜你喜欢
    • 2014-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多