3

我需要知道我的应用程序何时收到一条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

4

3 回答 3

9

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;
于 2010-05-12T19:33:05.637 回答
2

答案在我的问题中,危险的、无证的使用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;
于 2010-05-12T19:29:29.920 回答
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;
于 2010-05-12T19:53:14.810 回答