使用从旧 MFC 应用程序的菜单中重复某些菜单项的工具栏,我已经处理了这个工具提示问题以及 (1) 修改工具栏位图以包含其他图标和 (2) 提供有关当前的用户反馈应用状态。我的问题是我必须手动完成大部分操作,而不是使用各种向导和工具。
我所做的是(1)向 CView 派生类添加新成员以处理附加消息,(2)修改工具栏位图以使用 MS Paint 和资源编辑器添加附加图标,以及(3)添加CView 派生类的消息映射的新事件 ID 和事件处理程序。
我在更改工具栏位图时遇到的一个问题是,由于我要插入一个图标,因此我必须将位图中的现有图标向右移动。我的第一次尝试导致移动图标在应用程序工具栏上显示为空白。然后我意识到我需要在工具栏位图的长度上增加一点。在工具栏位图中的最后一个图标添加几列以使其成为标准像素宽度后,图标正确显示。
对于工具提示,我在消息映射中添加了以下内容:
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnToolTipText)
然后我在我的类中添加了以下方法来处理我的菜单项的通知。附带说明一下,这似乎是类和类中OnToolTipText()
使用的标准方法,但是派生自它,所以我怀疑它对方法的命名有什么影响。CFrameWnd
CMDIChildWnd
CView
CWnd
CFrameWnd
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 是工具的标识符。