如何使用 WTL 跟踪多个 TrackBar 之间的焦点变化?

发布于 2025-01-02 06:26:10 字数 398 浏览 1 评论 0原文

我正在尝试使用 WTL 跟踪多个 TrackBar(又名滑块,全部在同一窗口内)之间的焦点变化。

到目前为止我已经尝试过 MESSAGE_HANDLER(WM_SETFOCUS,函数) 还有一个 COMMAND_HANDLER(IDC_SLIDERn, WM_SETFOCUS, func) 对于每个滑块都没有成功。

msdn 上关于轨迹栏控件的页面显示:“WM_SETFOCUS 重新绘制轨迹栏窗口。” ..

编辑: 现在,我从自己的类中派生了滑块,在该类中,我使用 MESSAGE_HANDLER 处理 WM_SETFOCUS,并通过使用 m_hWnd 作为 lParam 将消息发布到父窗口来通知父窗口,这样我就可以在父窗口中检查哪个滑块获得焦点。

这可行,但是有没有更优雅的方法来做到这一点?

I'm trying to track focus changes between several TrackBars (aka sliders, all within the same window) using WTL.

So far I've tried a
MESSAGE_HANDLER(WM_SETFOCUS, func)
as well as one
COMMAND_HANDLER(IDC_SLIDERn, WM_SETFOCUS, func)
for each slider without success.

The about trackbar controls page on msdn says: "WM_SETFOCUS Repaints the trackbar window." ..

edit:
I now have derived the sliders from my own class where I handle WM_SETFOCUS with MESSAGE_HANDLER and notify the parent window by posting the message to it with m_hWnd as lParam so I can check in the parent which slider gained focus.

This works, but is there a more elegant way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

把人绕傻吧 2025-01-09 06:26:10

正如您所发现的,WM_SETFOCUS 被发送到获得焦点的特定窗口,而不是发送到父窗口。

但是,您可以使用另一种技术来避免子类化;大多数控件(特别是“通用控件”,包括滑块)会在发生某些事件时向其父控件发送 WM_NOTIFY,从而允许父控件为子控件集合处理这些事件。

在您的情况下,尝试在父窗口中侦听 WM_NOTIFY 消息,特别检查通知 ID 为 NM_SETFOCUS - 来自 MSDN:

通知控件的父窗口该控件已收到输入焦点。该通知代码以 WM_NOTIFY 消息的形式发送。

...这听起来像是您正在寻找的东西。显然,ATL 使用 NOTIFY_HANDLER,类似于:

NOTIFY_HANDLER(IDC_SLIDERn, NM_SETFOCUS, func)

请注意,这有效,因为 Win32 公共控件支持这种通知转发;如果您要使用其他自定义控件,您可能不会收到这些通知,并且必须诉诸子类化。但对于通用控件来说,这是最简单的方法。

WM_SETFOCUS is sent to the specific window that gets focus, not to the parent, as you've discovered.

However, there's an alternate tecnique that you can use to avoid subclassing; most controls (specifically the 'common controls', which includes sliders) will send a WM_NOTIFY to their parent when certain events happen, allowing the parent to handle these events for a collection of children.

In your case, try listening for WM_NOTIFY message at the parent window, specifically checking for the case where the notification ID is NM_SETFOCUS - from MSDN:

Notifies a control's parent window that the control has received the input focus. This notification code is sent in the form of a WM_NOTIFY message.

...which sounds like what you are looking for. Apparently ATL supports these in the message map using NOTIFY_HANDLER, something like:

NOTIFY_HANDLER(IDC_SLIDERn, NM_SETFOCUS, func)

Note that this works because the Win32 Common Controls support this sort of notification forwarding; if you were to use some other custom control instead, you may not get these notifications and would have to resort to subclassing. But for the common controls, this is the simplest way of doing it.

池木 2025-01-09 06:26:10

您不需要派生类,使用 CContainedWindowT 进行子类化就可以了。

BEGIN_MSG_MAP_EX(CDialog)
// ...
ALT_MSG_MAP(IDC_TRACKBAR)
    MSG_WM_SETFOCUS(OnControlSetFocus)
    MSG_WM_KILLFOCUS(OnControlKillFocus)
END_MSG_MAP()
// ...
CContainedWindowT<CTrackBarCtrl> m_TrackBar;
// ...
CDialog() :
    m_TitleListView(this, IDC_TRACKBAR)
// ...
LRESULT OnInitDialog(HWND, LPARAM)
{
    // ...
    ATLVERIFY(m_TrackBar.SubclassWindow(GetDlgItem(IDC_TRACKBAR)));
    // ...
// ...  
LRESULT OnControlSetFocus(...) { }
LRESULT OnControlKillFocus(...) { }

You don't need to derive your class, subclassing with CContainedWindowT is just fine.

BEGIN_MSG_MAP_EX(CDialog)
// ...
ALT_MSG_MAP(IDC_TRACKBAR)
    MSG_WM_SETFOCUS(OnControlSetFocus)
    MSG_WM_KILLFOCUS(OnControlKillFocus)
END_MSG_MAP()
// ...
CContainedWindowT<CTrackBarCtrl> m_TrackBar;
// ...
CDialog() :
    m_TitleListView(this, IDC_TRACKBAR)
// ...
LRESULT OnInitDialog(HWND, LPARAM)
{
    // ...
    ATLVERIFY(m_TrackBar.SubclassWindow(GetDlgItem(IDC_TRACKBAR)));
    // ...
// ...  
LRESULT OnControlSetFocus(...) { }
LRESULT OnControlKillFocus(...) { }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文