显示嵌套在另一个控件中的控件的 MFC 工具提示
Showing MFC tooltips for controls nested inside another control
出于某些原因,我有一个 parent window。此 window 包含正常控件。但它也需要 child 控件,其中又包含控件。实际应用要复杂得多。在真实版本中,我还使用 WS_EX_CONTROLPARENT
允许在嵌套控件之间的对话框中导航。
为简单起见,我创建了一个对话框基础应用程序。其中有一个普通的编辑控件和一个带有编辑控件的静态控件。我刚刚在我的代码中创建了编辑控件。
我启用了工具提示。以正常的方式。显示按钮和普通编辑控件的工具提示。但是static里面的控件不显示tooltip
如何在我的处理程序中获取嵌套控件的工具提示?
这里是 CPP 的代码。
// ToolTipTestDlg.cpp : implementation file
#include "pch.h"
#include "framework.h"
#include "ToolTipTest.h"
#include "ToolTipTestDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CToolTipTestDlg dialog
CToolTipTestDlg::CToolTipTestDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_TOOLTIPTEST_DIALOG, pParent)
{
EnableToolTips();
}
void CToolTipTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CONTAINER, m_container);
}
BEGIN_MESSAGE_MAP(CToolTipTestDlg, CDialogEx)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
// CToolTipTestDlg message handlers
BOOL CToolTipTestDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
m_edit1.Create(WS_CHILD | WS_BORDER | WS_VISIBLE, CRect(10, 10, 110, 30), this, 1);
m_edit2.Create(WS_CHILD | WS_BORDER | WS_VISIBLE, CRect(10, 10, 110, 30), &m_container, 1);
return TRUE; // return TRUE unless you set the focus to a control
}
BOOL CToolTipTestDlg::OnToolTipText(UINT nId, NMHDR* pNMHDR, LRESULT* pResult)
{
// For all keyboard messages we need to know the target of the message
ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);
TOOLTIPTEXTW* pTTTW = reinterpret_cast<NMTTDISPINFO*>(pNMHDR);
CString strTipText = _T("Test");
wcsncpy_s(pTTTW->szText, _countof(pTTTW->szText), CT2W(strTipText), _countof(pTTTW->szText));
*pResult = 0;
return TRUE; // message was handled
}
头文件:
// ToolTipTestDlg.h : header file
#pragma once
// CToolTipTestDlg dialog
class CToolTipTestDlg : public CDialogEx
{
// Construction
public:
CToolTipTestDlg(CWnd* pParent = nullptr); // standard constructor
// Dialog Data
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_TOOLTIPTEST_DIALOG };
#endif
CEdit m_edit1, m_edit2;
CStatic m_container;
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
// Generated message map functions
virtual BOOL OnInitDialog();
DECLARE_MESSAGE_MAP()
afx_msg BOOL OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult);
};
以及包含容器的 RC 文件:
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_TOOLTIPTEST_DIALOG DIALOGEX 0, 0, 321, 96
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,79,75,50,14
PUSHBUTTON "Cancel",IDCANCEL,134,75,50,14
LTEXT " ",IDC_CONTAINER,7,39,168,25,SS_NOTIFY
END
我的调查显示此 MFC 工具提示实现仅适用于调用 EnabledToolTips
的控件的直接子控件。
我找到了一个有效的解决方案。它可能不是最好的,但很容易实现。
我使用自己的容器class(在我的真实代码中这个class已经存在)
class CStaticContainer : public CStatic
{
public:
DECLARE_MESSAGE_MAP()
afx_msg BOOL OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult);
};
我确保使用了这个容器 class 并继承了现有的 CStatic(这里是对话框 class 中示例的代码):
// In the dialog class
CStaticContainer m_container;
...
void CToolTipTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CONTAINER, m_container);
}
我也在 OnInitDialog
中为容器启用了工具提示。
m_container.EnableToolTips();
对于容器 class 我添加了一个 TTN_NEEDTEXT
处理程序。它只是将消息转发给外部父级。
BEGIN_MESSAGE_MAP(CStaticContainer, CStatic)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
BOOL CStaticContainer::OnToolTipText(UINT nId, NMHDR* pNMHDR, LRESULT* pResult)
{
GetParent()->SendMessage(WM_NOTIFY, nId, reinterpret_cast<LPARAM>(pNMHDR));
return TRUE; // message was handled
}
现在所有控件都显示工具提示。
出于某些原因,我有一个 parent window。此 window 包含正常控件。但它也需要 child 控件,其中又包含控件。实际应用要复杂得多。在真实版本中,我还使用 WS_EX_CONTROLPARENT
允许在嵌套控件之间的对话框中导航。
为简单起见,我创建了一个对话框基础应用程序。其中有一个普通的编辑控件和一个带有编辑控件的静态控件。我刚刚在我的代码中创建了编辑控件。
我启用了工具提示。以正常的方式。显示按钮和普通编辑控件的工具提示。但是static里面的控件不显示tooltip
如何在我的处理程序中获取嵌套控件的工具提示?
这里是 CPP 的代码。
// ToolTipTestDlg.cpp : implementation file
#include "pch.h"
#include "framework.h"
#include "ToolTipTest.h"
#include "ToolTipTestDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CToolTipTestDlg dialog
CToolTipTestDlg::CToolTipTestDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_TOOLTIPTEST_DIALOG, pParent)
{
EnableToolTips();
}
void CToolTipTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CONTAINER, m_container);
}
BEGIN_MESSAGE_MAP(CToolTipTestDlg, CDialogEx)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
// CToolTipTestDlg message handlers
BOOL CToolTipTestDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
m_edit1.Create(WS_CHILD | WS_BORDER | WS_VISIBLE, CRect(10, 10, 110, 30), this, 1);
m_edit2.Create(WS_CHILD | WS_BORDER | WS_VISIBLE, CRect(10, 10, 110, 30), &m_container, 1);
return TRUE; // return TRUE unless you set the focus to a control
}
BOOL CToolTipTestDlg::OnToolTipText(UINT nId, NMHDR* pNMHDR, LRESULT* pResult)
{
// For all keyboard messages we need to know the target of the message
ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);
TOOLTIPTEXTW* pTTTW = reinterpret_cast<NMTTDISPINFO*>(pNMHDR);
CString strTipText = _T("Test");
wcsncpy_s(pTTTW->szText, _countof(pTTTW->szText), CT2W(strTipText), _countof(pTTTW->szText));
*pResult = 0;
return TRUE; // message was handled
}
头文件:
// ToolTipTestDlg.h : header file
#pragma once
// CToolTipTestDlg dialog
class CToolTipTestDlg : public CDialogEx
{
// Construction
public:
CToolTipTestDlg(CWnd* pParent = nullptr); // standard constructor
// Dialog Data
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_TOOLTIPTEST_DIALOG };
#endif
CEdit m_edit1, m_edit2;
CStatic m_container;
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
// Generated message map functions
virtual BOOL OnInitDialog();
DECLARE_MESSAGE_MAP()
afx_msg BOOL OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult);
};
以及包含容器的 RC 文件:
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_TOOLTIPTEST_DIALOG DIALOGEX 0, 0, 321, 96
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,79,75,50,14
PUSHBUTTON "Cancel",IDCANCEL,134,75,50,14
LTEXT " ",IDC_CONTAINER,7,39,168,25,SS_NOTIFY
END
我的调查显示此 MFC 工具提示实现仅适用于调用 EnabledToolTips
的控件的直接子控件。
我找到了一个有效的解决方案。它可能不是最好的,但很容易实现。
我使用自己的容器class(在我的真实代码中这个class已经存在)
class CStaticContainer : public CStatic
{
public:
DECLARE_MESSAGE_MAP()
afx_msg BOOL OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult);
};
我确保使用了这个容器 class 并继承了现有的 CStatic(这里是对话框 class 中示例的代码):
// In the dialog class
CStaticContainer m_container;
...
void CToolTipTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CONTAINER, m_container);
}
我也在 OnInitDialog
中为容器启用了工具提示。
m_container.EnableToolTips();
对于容器 class 我添加了一个 TTN_NEEDTEXT
处理程序。它只是将消息转发给外部父级。
BEGIN_MESSAGE_MAP(CStaticContainer, CStatic)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
BOOL CStaticContainer::OnToolTipText(UINT nId, NMHDR* pNMHDR, LRESULT* pResult)
{
GetParent()->SendMessage(WM_NOTIFY, nId, reinterpret_cast<LPARAM>(pNMHDR));
return TRUE; // message was handled
}
现在所有控件都显示工具提示。