【问题标题】:How to ignore system messages on application level? (WM_SettingChange / WM_WinIniChange)如何忽略应用程序级别的系统消息? (WM_SettingChange / WM_WinIniChange)
【发布时间】:2014-07-11 04:22:33
【问题描述】:

当用户更改其 Windows 区域设置中的日期格式时,我们有一个应用程序行为异常。 (是的,解决方案是解决不当行为——不是重点。)

更改设置会向所有应用程序广播WM_SETTINGCHANGE 消息。我们试图通过忽略此消息来避免我们的问题,并保持日期格式不变(目前,作为修补程序)。

无论我做什么,TMonthCalendar 组件仍会更改其格式,TDateTimePicker 使用TMonthCalendar 作为其弹出窗口。

我试过了(结果都一样):

  • 覆盖TForm::WndProc()

    void __fastcall TfrmMainWindow::WndProc( TMessage & msg )
    {
      if( msg.Msg == WM_SETTINGCHANGE )  return;  // ignore
    
      TForm::WndProc( msg );
    }
    
  • 使用Application->HookMainWindow( hookWindowsMessage ); 设置挂钩
  • 设置TApplication.UpdateFormatSettings = false;
  • 设置Application->OnEvent = onApplicationEvent; 以捕获所有事件...但不幸的是,此特定情况属于“OnMessage 仅接收发布到消息队列的消息,而不是直接使用 Windows API SendMessage 函数发送的消息”。规则。

似乎覆盖WndProc() 几乎是一个好主意,只是它只影响那个窗口,而不是整个应用程序。我以为这就是 Application->HookMainWindow() 的用途,但显然不是。

有人知道如何解决或规避这个问题吗?

【问题讨论】:

  • WM_SETTINGCHANGE 消息未请求更改设置的权限;这只是一个礼貌的通知。忽略该消息不会阻止更改发生。它与不处理消息相同。任何使用 Windows API 函数的控件都将开始获得与新设置相对应的行为。没有办法解决这个问题。
  • @CodyGray 非常正确,很遗憾。我可以阻止我的应用程序处理更改(见下文)。但是,我没有意识到 TMonthCalendar 实际上正在使用忽略我的应用程序设置的 Win32 API 日历。没办法。
  • 仅供参考,HookMainWindow() 仅拦截专门发送/发送到TApplication 窗口的消息。这不是拦截整个应用程序作为一个整体的消息的包罗万象。如果需要,请改用SetWindowsHookEx()

标签: windows c++builder


【解决方案1】:

正如 Cody Gray 在上面的评论中所说,问题不在于消息处理,而是 TMonthCalendar 组件使用 Win32 API 日历,因此应用程序上下文之外工作。

但是,对于所有其他组件(即TDateTimePicker 的行编辑)和内部全局变量(如ShortDateFormat 等),可以忽略格式更改,如下所示:

class TfrmMainWindow : public TForm
{
public:
  __fastcall TfrmMainWindow( TComponent * Owner )
    : TForm( Owner )
    {
      Application->HookMainWindow( hookWindowsMessage );
    }

  __fastcall ~TfrmMainWindow()
    {
      Application->UnhookMainWindow( hookWindowsMessage );
    }

private:
  bool __fastcall hookWindowsMessage( TMessage & msg )
    {
      if( msg.Msg == WM_SETTINGCHANGE )
      {
        String sLParam( (char *)msg.LParam );

        // Check for Region Settings change (not Desktop background etc.)
        if( sLParam.LowerCase() == "intl" )
        {
          return true;  // ignore message
        }
      }

      return false;  // handle message as usual
    }
};

来源:
"Trapping Messages Sent to an Application"

"TMonthCalendar displays dates according to the system locale (ignoring the BiDiMode setting)."

"The Win32 API provides a control used to select dates on a colorful calendar. The dates used and the way they display are based on the Regional Settings of the Control Panel."

【讨论】:

  • 哦,对于我的特殊情况,Application.UpdateFormatSettings = false; 实际上就像一个魅力。 :-)
猜你喜欢
  • 2011-02-18
  • 2016-04-05
  • 1970-01-01
  • 1970-01-01
  • 2011-07-30
  • 2014-12-07
  • 2012-02-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多