Добавление подсказок к модальным диалоговым окнам
Вы, вероятно, видели диалоги с подсказками для каждого элемента управления на них. Это очень удобно, если предназначение элемента неочевидно из контекста. Статья Q141758 в базе знаний (Knowledge Base) подробно описывает, как реализовать подсказки в MFC-диалогах, поэтому здесь я лишь кратко перечислю основные пункты. Для MFC версии 4.0 и выше, вам придется выполнить следующие шаги (предполагаем, что диалоговое окно в вашем приложении уже существует):
• Добавить private или protected переменную типа CToolTipCtrl в класс вашего диалога.
• Добавить в класс управляющую переменную (control member variable), для каждого элемента, у которого будет подсказка. Это можно сделать с помощью ClassWizard (на закладке Member Variable).
• Переопределить CDialog::OnInitDialog и вызвать в нем CToolTipCtrclass="underline" :Create. Затем вызвать CToolTipCtrclass="underline" :AddTool для каждого элемента с подсказкой, передавая адрес управляющей переменной и текст подсказки в качестве параметров.
• Переопределить CDialog::PreTranslateMessage и вызвать в ней CToolTipCtrclass="underline" :RelayEvent для каждого сообщения, передаваемого в функцию. Это нужно для того, чтобы элемент ToolTip получал все необходимые сообщения мыши.
В MFC версий ниже 4.0 из CDialog::DoModal не вызывается CDialog::PreTranslateMessage, поэтому придется выполнить дополнительные действия для передачи сообщений мыши элементу ToolTip. Нужно переопределить CWinApp::ProcessMessageFilter и в нем передавать сообщения элементу ToolTip. CWinApp::ProcessMessageFilter вызывается хуковой функцией MFC для реакции на определенные сообщения Windows. За деталями, а также рабочими примерами, обратитесь к статье в базе знаний.
Добавление подсказок к Web-страницам
Демонстрационный проект WebButton
Как и в приложениях, подсказки на Web-страницах могут быть очень полезны. Подсказки могут быть использованы в двух очевидных случаях: для картинок и элементов ActiveX. Я написал пример элемента "кнопка", чтобы продемонстрировать, как просто добавлять подсказки к элементам ActiveX. На рис.3 показаны и элемент ActiveX – кнопка с улыбающейся рожицей, и картинка – небольшое "художество" прямо под кнопкой.
Рис.3. Подсказки на Web-странице
Добавить подсказку к картинке проще простого, потому что эта функциональность встроена в язык HTML (см. рис.4). Эта строка:
<img src="Image.gif" height=48 width=48 alt="Image ToolTip" >
задает имя и размер картинки. Подстрока "Image ToolTip" и есть текст подсказки, которая появляется при подведении курсора мыши к картинке. Также возможно задать для картинки несколько "активных зон" (HotSpots) и определить несколько подсказок, но это выходит за рамки статьи. Я только хочу показать, насколько просто добавлять подсказки на языке HTML.
Рис.4. HTML-код для подсказки
<OBJECT ID="WebButton1" WIDTH=31 HEIGHT=28 CLASSID="CLSID:381C5023-2FDA-11D0-8BC1-444553540000">
<PARAM NAME="_Version" VALUE="65536">
<PARAM NAME="_ExtentX" VALUE="786">
<PARAM NAME="_ExtentY" VALUE="731">
<PARAM NAME="_StockProps" VALUE="0">
<PARAM NAME="ToolTipText" VALUE="WebButton ToolTip Test">
</OBJECT>
</P>
<br><img src="Image.gif" height=48 width=48 alt="Image ToolTip" >
<SCRIPT LANGUAGE="VBScript">
<!-–
Sub WebButton1_Click()
MsgBox "WebButton was clicked"
end sub
-->
</SCRIPT>
Элемент ActiveX представляет собой кнопку с подсказкой. Для чего мне возиться с созданием кнопки, когда можно добавить на Web-страницу трехмерную картинку, которая будет выглядеть как кнопка? На это есть две причины. Во-первых, кнопка выглядит реалистичнее – она нажимается и отжимается по щелчку пользователя, как и положено настоящей кнопке. Во-вторых, я хотел показать добавление подсказок к элементам ActiveX, а кнопка – это простейший элемент, который я мог использовать в демонстрационных целях.
Для генерации кода я использовал AppWizard. Я установил флажок "Activate when visible" и отключил все остальные флажки. В опции "Which window class, if any, should this control subclass?" я выбрал BUTTON. AppWizard генерирует массу дополнительного кода, не относящегося к данной статье. В основном, я остановлюсь на коде, добавленном мной в класс CWebButtonCtrl (см. рис.5). Давайте для начала взглянем на пару переменных класса. CWebButtonCtrclass="underline" :m_bToolTipEnabled устанавливается в TRUE, если подсказки разрешены. В CWebButtonCtrclass="underline" :m_strToolTipText хранится текст подсказки. Я добавил обе переменные через ClassWizard и они представляют OLE-свойства, автоматические обновляемые библиотекой MFC при их изменении.
Рис.5. CWebButtonCtrl
// WebButtonCtl.cpp : Implementation of the CWebButtonCtrl OLE control class.
/////////////////////////////////////////////////////////////////////////////
// CWebButtonCtrclass="underline" :RelayToolTipEvent – Pass mouse messages to ToolTip
void CWebButtonCtrclass="underline" :RelayToolTipEvent(const MSG* pMsg) {
MSG MsgCopy;
::memcpy(&MsgCopy, pMsg, sizeof(MSG));
FilterToolTipMessage(&MsgCopy);
}
int CWebButtonCtrclass="underline" :OnToolHitTest(CPoint point, TOOLINFO* pTI) const {
if (m_bToolTipEnabled && pTI != NULL && pTI->cbSize >= sizeof(TOOLINFO)) {
// setup the TOOLINFO structure
pTI->hwnd = m_hWnd;
pTI->uId = 0;
pTI->uFlags = 0;
GetClientRect(&(pTI->rect));
pTI->lpszText = LPSTR_TEXTCALLBACK;
}
return (m_bToolTipEnabled ? 1 : –1);
}
/////////////////////////////////////////////////////////////////////////////
// CWebButtonCtrl message handlers
int CWebButtonCtrclass="underline" :OnCreate(LPCREATESTRUCT lpCreateStruct) {
if (COleControclass="underline" :OnCreate(lpCreateStruct) == –1) {
return –1;
}
if (m_Bitmap.LoadBitmap(IDB_WEBBUTTON)) {
SendMessage(BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)m_Bitmap.GetSafeHandle());
} else {
TRACE("Unable to load bitmap for button.");
}
EnableToolTips(TRUE);
return 0;
}
void CWebButtonCtrclass="underline" :OnMouseMove(UINT nFlags, CPoint point) {
RelayToolTipEvent(GetCurrentMessage());
COleControclass="underline" :OnMouseMove(nFlags, point);
}
void CWebButtonCtrclass="underline" :OnLButtonDown(UINT nFlags, CPoint point) {
RelayToolTipEvent(GetCurrentMessage());
COleControclass="underline" :OnLButtonDown(nFlags, point);
}
void CWebButtonCtrclass="underline" :OnLButtonUp(UINT nFlags, CPoint point) {
RelayToolTipEvent(GetCurrentMessage());