C++ MFC工具提示仅在特殊情况下显示

C++ MFC工具提示仅在特殊情况下显示,c++,windows,mfc,tooltip,C++,Windows,Mfc,Tooltip,我的任务是为配置菜单中的每个项目分配工具提示。我已经完成了向页面上的每个控件“添加”工具提示,但根据控件在屏幕上的位置,工具提示有时会显示,有时不会显示 若要使用工具提示,请先删除我创建的页面 EnableToolTips(TRUE); 在每个CPropertyPage的OnInitDialog方法中。 然后添加通知映射 ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnToolTipText) 函数OnToolTipText看起来就是这样 BOOL CCfgPrefPage:

我的任务是为配置菜单中的每个项目分配工具提示。我已经完成了向页面上的每个控件“添加”工具提示,但根据控件在屏幕上的位置,工具提示有时会显示,有时不会显示

若要使用工具提示,请先删除我创建的页面

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控制上不是问题,那么为什么在其他地方是问题呢


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

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

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


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

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

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

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

ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnToolTipText)
然后,我向类中添加了以下方法来处理菜单项的通知。作为旁注,似乎
ontoltitext()
CFrameWnd
类和
CMDIChildWnd
类中使用的标准方法,但是
CView
CFrameWnd
一样,都是从
CWnd
派生而来的,因此我怀疑它对该方法的命名有什么不同

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
MENUITEM "Export to SYLK file",         ID_TOGGLE_SYLK_EXPORT
菜单的特定部分使用相同的资源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
MENUITEM "Export to SYLK file",         ID_TOGGLE_SYLK_EXPORT
然后,要提供鼠标显示的状态栏文本,需要添加一个字符串表:

ID_TOGGLE_SYLK_EXPORT   "Toggle export of SYLK format report files for spreadsheets."
结构的
lpszText
成员在
TOOLINFO
struct的MSDN文档中描述为:

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

回顾这个问题的现有答案,我想知道
TTF_IDISHWND
标志的
if
语句检查。
TOOLINFO
struct的MSDN文档中有这样一句话:

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


我在Windows XP上遇到过类似的问题(仅在XP上,在Vista、7和8上没有问题)。我在模态对话框中有一个带有工具提示的按钮。当鼠标停在按钮上时,工具提示会在很短的延迟后弹出。到现在为止,一直都还不错。现在,只要满足以下两个条件之一,工具提示就会消失:1)用户将鼠标移出按钮,2)用户在4或5秒内不移动鼠标。如果工具提示因为第二种情况而消失,那么它将永远不会回到该对话框中,除非该对话框被关闭并再次打开。我也在使用windows XP机器。我没有