6

我的任务是为配置菜单中的每个项目分配工具提示。我已完成将工具提示“添加”到页面上的每个控件,但有时工具提示似乎会显示,有时则不会,具体取决于屏幕上控件的位置。

为了工具提示,我首先

EnableToolTips(TRUE);

在每个 CPropertyPage 的 OnInitDialog 方法中。然后我添加通知地图

ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnToolTipText)

随着功能 OnToolTipText 看起来像这样

BOOL CCfgPrefPage::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
    TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
    UINT nID = pNMHDR->idFrom;

    if (pTTT->uFlags & TTF_IDISHWND)
    {
        nID = ::GetDlgCtrlID((HWND)nID);
        if(nID)
        {
            if( nID == GetDlgItem(IDC_PICKDIST_EDIT)->GetDlgCtrlID())  
                _tcsncpy_s(pTTT->szText, _T("Tool Tip Text"), _TRUNCATE);
            else if( nID == GetDlgItem(IDC_ENDPTTOL_EDIT)->GetDlgCtrlID())  
                _tcsncpy_s(pTTT->szText, _T("Tool Tip Text"), _TRUNCATE);

            pTTT->lpszText = pTTT->szText; // Sanity Check
            pTTT->hinst = AfxGetResourceHandle(); // Don't think this is needed at all
            return TRUE;
        }
    }
    return FALSE;
}

对于我的某些控件,似乎不会显示工具提示。对于大多数复选框控件,工具提示会显示,但对于少数人来说,它们只是不显示。没有其他控件覆盖它们,它们没有被禁用。

另一件事,如果我使用非标准光标窗口反复闪烁工具提示,以至于在某些情况下不可读。我怎样才能解决这个问题?这在 CEdit 控件上不是问题,那么为什么在其他地方会出现问题呢?

编辑:更新,多年来一直在页面上的控件似乎显示了工具提示。我现在/今天尝试添加的任何控件都不会显示工具提示。无论位置、控件类型、设置如何,我都无法在新插入的控件上显示单个工具提示。

4

2 回答 2

6

如果您不想使用我建议的辅助类,请修复代码中的问题。首先,在映射偶数处理程序时使用 ON_NOTIFY_EX_RANGE 宏,如下所示(这将涵盖所有 ID):

ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)

接下来,您需要修复您的功能。我在这里看到了一些问题。首先,在测试 TTF_IDISHWND 标志时,您只需要重新初始化 nID。您不需要将其应用于整个函数。其次,在所有操作之后,您的 nID 将是实际的对话 ID。不需要 GetDlgItem() 函数

BOOL CCfgPrefPage::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
    TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
    UINT nID = pNMHDR->idFrom;

    if (pTTT->uFlags & TTF_IDISHWND)
    {
        nID = ::GetDlgCtrlID((HWND)nID);
    }
    if(nID)
    {
        if( nID == IDC_PICKDIST_EDIT)  
            _tcsncpy_s(pTTT->szText, _T("Tool Tip Text"), _TRUNCATE);
        else if( nID == IDC_ENDPTTOL_EDIT)  
            _tcsncpy_s(pTTT->szText, _T("Tool Tip Text"), _TRUNCATE);

        //pTTT->lpszText = pTTT->szText; // Sanity Check
        *pResult = 0;
        return TRUE;
    }
    return FALSE;
}
于 2013-03-28T00:39:05.713 回答
0

使用从旧 MFC 应用程序的菜单中重复某些菜单项的工具栏,我已经处理了这个工具提示问题以及 (1) 修改工具栏位图以包含其他图标和 (2) 提供有关当前的用户反馈应用状态。我的问题是我必须手动完成大部分操作,而不是使用各种向导和工具。

我所做的是(1)向 CView 派生类添加新成员以处理附加消息,(2)修改工具栏位图以使用 MS Paint 和资源编辑器添加附加图标,以及(3)添加CView 派生类的消息映射的新事件 ID 和事件处理程序。

我在更改工具栏位图时遇到的一个问题是,由于我要插入一个图标,因此我必须将位图中的现有图标向右移动。我的第一次尝试导致移动图标在应用程序工具栏上显示为空白。然后我意识到我需要在工具栏位图的长度上增加一点。在工具栏位图中的最后一个图标添加几列以使其成为标准像素宽度后,图标正确显示。

对于工具提示,我在消息映射中添加了以下内容:

ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnToolTipText)

然后我在我的类中添加了以下方法来处理我的菜单项的通知。附带说明一下,这似乎是类和类中OnToolTipText()使用的标准方法,但是派生自它,所以我怀疑它对方法的命名有什么影响。CFrameWndCMDIChildWndCViewCWndCFrameWnd

inline BOOL CPCSampleView::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
    static wchar_t toolTextToggleExportSylk [64] = L"Toggle SYLK export.";
    static wchar_t toolTextClearWindow [64] = L"Clear the log displayed.";
    static wchar_t toolTextConnectLan [64] = L"Log on the POS terminal through the LAN.";

    TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;

    switch (pNMHDR->idFrom) {
        case ID_TOGGLE_SYLK_EXPORT:
            pTTT->lpszText = toolTextToggleExportSylk;
            return TRUE;
        case ID_WINDOW_CLEAR:
            pTTT->lpszText = toolTextClearWindow;
            return TRUE;
        case ID_CONNECT_LAN_ON:
            pTTT->lpszText = toolTextConnectLan;
            return TRUE;
    }
    // if we do not handle the message then return FALSE to let someone else do it.
    return FALSE;
}

对于在执行报告时切换文件导出的菜单项的用户反馈,我提供了对消息映射的以下更改,然后实施了必要的方法。涉及两种类型的消息,因此我必须添加两个方法和两个新的消息映射条目:

// New message map entries to handle the menu item selection event
// and to update the menu item and the toolbar icon with state changes
ON_COMMAND(ID_TOGGLE_SYLK_EXPORT, OnToggleExportSylk)
ON_UPDATE_COMMAND_UI(ID_TOGGLE_SYLK_EXPORT, OnUpdateToggleExportSylk)


// New methods added to the CView derived class

// handle the menu selection event generated by either selecting the menu item
// from the menu or by clicking on the icon in the toolbar.
void CPCSampleView::OnToggleExportSylk()
{
    // Exclusive Or to toggle the indicator bit from 0 to 1 and 1 to 0.
    GetDocument()->ulReportOptionsMap ^= CPCSampleDoc::ulReportOptionsExportSylk;
}

// handle the request from the MFC framework to update the displayed state this
// not only does a check mark against the menu item it also causes the toolbar
// icon to appear depressed if click is set or non-depressed if click is not set
inline void CPCSampleView::OnUpdateToggleExportSylk (CCmdUI* pCmdUI) 
{
    if (GetDocument()->ulReportOptionsMap & CPCSampleDoc::ulReportOptionsExportSylk)
    {
        // SYLK export is turned on so indicate status to the user. This will
        // put a check mark beside the menu item and show the toolbar button depressed
        pCmdUI->SetCheck (1);
    }
    else
    {
        // SYLK export is turned off so indicate status to the user.  This will
        // remove the check mark beside the menu item and show the toolbar button as raised.
        pCmdUI->SetCheck (0);
    }
}

需要更改资源文件来为切换操作提供新按钮以及为切换操作添加新菜单项。我对几个不同的事物使用相同的资源 ID,因为它们都是独立的。因此,资源字符串的 id 与菜单项的 id 相同,工具栏按钮的 id 也相同,以简化我的生活并轻松找到所有特定的点点滴滴。

工具栏资源文件定义如下所示:

IDR_MAINFRAME TOOLBAR  16, 15
BEGIN
    BUTTON      ID_CONNECT_LAN_ON
    SEPARATOR
    BUTTON      ID_WINDOW_CLEAR
    SEPARATOR
    BUTTON      ID_TOGGLE_SYLK_EXPORT
    SEPARATOR
    BUTTON      ID_APP_ABOUT
END

菜单的特定部分使用相同的资源 ID 作为切换事件 ID,如下所示:

MENUITEM "Export to SYLK file",         ID_TOGGLE_SYLK_EXPORT

然后提供用鼠标显示的状态栏文本,添加了一个字符串表:

ID_TOGGLE_SYLK_EXPORT   "Toggle export of SYLK format report files for spreadsheets."

该结构的lpszText成员在该结构的 MSDN 文档中描述TOOLINFO为:

指向包含工具文本的缓冲区的指针,或包含文本的字符串资源的标识符。该成员有时用于返回值。如果需要检查返回值,必须指向一个足够大的有效缓冲区。否则,可以将其设置为 NULL。如果 lpszText 设置为 LPSTR_TEXTCALLBACK,则控件将 TTN_GETDISPINFO 通知代码发送到所有者窗口以检索文本。

回顾这个问题的现有答案,我想知道if检查TTF_IDISHWND标志的语句。该TOOLINFO结构的 MSDN 文档有这样的说法:

指示 uId 成员是工具的窗口句柄。如果未设置此标志,则 uId 是工具的标识符。

于 2015-08-08T18:43:24.210 回答