windows sdk编程系列文章23 ---- 工具提示控件.doc_第1页
windows sdk编程系列文章23 ---- 工具提示控件.doc_第2页
windows sdk编程系列文章23 ---- 工具提示控件.doc_第3页
windows sdk编程系列文章23 ---- 工具提示控件.doc_第4页
windows sdk编程系列文章23 ---- 工具提示控件.doc_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

windows sdk编程系列文章 - 工具提示控件2008-04-24 23:21我们将学习工具提示控件:它是什么如何创建和使用.理论:工具提示是当鼠标在某特定区域上停留时显示的一个矩形窗口.工具提示窗口包含一些编程者想要显示的文本.在这点上,工具提示同状态栏的作用是一样的,所不同的是工具提示当单击或者远离指定区域的时候就会消逝,你可能熟悉与工具栏相关联的工具提示,那些提示是工具栏控件提供的便利.如果你想要在其它窗口、控件中显示工具提示的话,就不得不自己创建他们.既然已经了解了什么是工具提示,就让我们来看看如何创建他们.大致步骤如下:1. 用CreateWindowEx函数创建工具提示控件. 2. 定义一个工具提示控件将要监视鼠标移动的区域. 3. 将区域传递给工具提示控件 4. 将传递区域的鼠标消息转送给工具提示控件.(这步或许更早,具体依据转播消息的方法) 下面我们就来详细的讨论每一步. 工具提示控件的创建工具提示控件是一种通用控件.同样,要在源代码某处调用InitCommonControls以便vc能够将你的程序和comctl32.dll连接. 用CreateWindowEx创建工具提示控件,典型代码如下: InitCommonControls(); hwndTool = CreateWindowEx(NULL,ToolTipsClassName,NULL,TTS_ALWAYSTIP,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,g_hInstance,NULL);注意窗口风格:TIS_ALWAYSTIP指定了工具提示不管包含指定区域的窗口状态如何,当鼠标移过指定区域的时候,工具提示总是显示.简单的说就是,即使窗口处于非激活状态,鼠标移过工具提示指定区域的时候,工具提示也会出现. 你不必在CreateWindowEx中包括WS_POPUP 和 WS_EX_TOOLWINDOW风格,因为工具提示处理过程会自动加上,你也不必指定工具提示窗口的坐标和宽高,控件会依据要显示的文字自动调节.四个参数,均使用CW_USEDEFAULT ,其余的参数都不太重要. 指定工具工具提示控件创建了但还没有显示,我们想要当鼠标指针在某个区域之上时显示工具提示窗口.现在需要指定这个区域.我们称这样的区域为工具,“工具”就是工具提示控件监视鼠标指针是否移过的位于窗口客户区的一个方形区域.如果鼠标指针移过工具,工具提示窗口就显示.工具可覆盖整个客户区或者仅仅是它的一部分.因此我们把工具分成两种类型,一种是作为一个窗口,另一种则是某窗口客户区的一部分.两种各有所用.覆盖整个客户区的工具通常用于按钮、编辑控件等,你不必指定焦点域的坐标和大小:它被假定为窗口的整个客户区.仅覆盖窗口客户区一部分的工具在你想把窗口客户区分成几个部分但又不想使用子窗口时特别有用,但需要指定左上角的坐标和宽高.使用如下的 TOOLINFO 结构定义工具:typedef struct tagTOOLINFO UINT cbSize; UINT uFlags; HWND hwnd; UINT_PTR uId; RECT rect; HINSTANCE hinst; LPTSTR lpszText; #if (_WIN32_IE = 0x0300) LPARAM lParam;#endif TOOLINFO, NEAR *PTOOLINFO, *LPTOOLINFO; 域名说明cbSizeTOOLINFO结构的大小.必须填充, 如果这个区域不被正确填充Windows并不会报错,但你会得到不可预料的奇怪结果.uFlags指定焦点域的属性,可以是如下标志的联合: TTF_IDISHWND ID is hWnd.如果你指定了这个标志,就意味着你要使用覆盖整个客户区的工具 (上面第一种工具). 如果你使用了这个标志,你必须用你要使用的窗口句柄填充uId成员,如果你不指定这个成员,就意味着你要使用第二种工具、客户区窗口的一方形区域.在这种情况下,你就必须以方形区域的大小填充rect成员. TTF_CENTERTIP 通常工具提示窗口显示在鼠标的右下方,如果你指定了这个标志,不管鼠标的位置如何,工具提示总显示在焦点域总的中下方. TTF_RTLREADING .如果你的程序不是为阿拉伯或者希伯来语系统设计的,你完全可以不理它,它使得提示文本以从右至左的顺序显示,在其它系统中无效. TTF_SUBCLASS 如果你使用了这个标志,工具提示控件将子类化工具所在窗口以便截取发送给它的的鼠标消息,这个标志非常有用,否则你将不得不做更多的工作来向工具提示控件转发消息. hWnd包含工具的窗口句柄,如果你指定了TTF_IDISHWND标志,Windows将忽略该值,而使用uId成员的值作为窗口句柄.你需要填充这个域域如果: 你不使用 TTF_IDISHWND标志 (换句话说,你使用局部工具) 你在 lpszText 成员中指定了LPSTR_TEXTCALLBACK .这个值告诉工具提示控件当需要显示提示窗口时,必须向包含工具的窗口查询应该显示什么. 这是一种实时的控件文本更新.如果你需要动态改变提示文本,你应当在 lpszText成员中指定LPSTR_TEXTCALLBACK值,控件就会向hWnd指定的窗口发送TTN_NEEDTEXT 消息. uId这个域的值可能有两种含义,依 uFlags 是否包含TTF_IDISHWND. 如果TTF_IDISHWND标志没有被指定就代表应用程序定义的工具ID,由于这意味着你使用仅覆盖客户区一部分的工具,逻辑的推出一个客户区可能存在多个同样的焦点域(不存在交迭),Hwnd成员的一个窗口句柄就不够了,应用程序定义ID以区分他们因此而显得必要,只要唯一ID可以是任何值. 如果TTF_IDISHWND标志被指定就表示整个客户区都作为焦点域的窗口句柄,你或许会奇怪为什么不用上面提到的hWnd成员的值来储存窗口句柄.答案是:如果lpszText指定为LPSTR_TEXTCALLBACK,Hwnd 可能已经被填充了.还有提供提示文本的窗口和包含工具的窗口可能不是同一个!(你可以设计一个提供两种服务的窗口程序,但太严格了,在这点上,微软为我们提供了更大的自由,欢呼吧!) rect指定工具大小的rect结构.这个结构定义了一个以hWnd指定窗口客户区左上角为基点的方形大小,简言之,如果你想指定客户区的一部分作为工具就得填充这个结构,如果你指定了TTF_IDISHWND标志 ,控件就会忽略这个值.(你已经选择整个客户区作为工具)hInst如果lpszText指定了字符串资源的标识,包含将作为工具提文本字符串资源的实例句柄.听起来有点费解,阅读一下lpszText的说明就可以明白这个域是干什么用的了.若lpszText不包含字符串资源标识,控件会忽略这个域.lpszText这个域可以有如下几个值: 如果指定为LPSTR_TEXTCALLBACK, 工具提示控件就会向HWnd窗口发送TTN_NEEDTEXT消息以获得将要显示的字符串.提示文本的动态更新方法:每次显示提示窗口都改变提示文本. 如果在这个域中指定字符串资源标识,当控件要在提示窗口中显示提示文本时,就搜索hInst成员标识的实例的字符串资源列表.由于字符串资源列表标识总是16位值,这个域的高字节将永远为0,这种方法在你想移植程序时非常有用,由于字符串资源以脚本形式定义,你不必修改源代码.只需要修改字符串列表提示文本就会相应改变,而不必担心引进bugs. 如果这个域的值不是LPSTR_TEXTCALLBACK并且高字节不为零, 控件截取这个值作为提示文本的指针,这是最简单的方法但也最不稳定.通过检查高字节区分字符串资源标识. 总言之,你需要将TOOLINFO结构传递给工具提示控件之前填充填充好,它描述了你期望的工具属性.向工具提示控件注册工具填充完TOOLINFO结构后, 必须将其传递给控件 . 一个工具提示控件可以控制很多工具,因此不必为一个窗口创建很多控件,为了注册工具,向控件发送TTM_ADDTOOL消息 wParam不使用,lParam必须包含要注册的TOOLINFO结构的指针 SendMessage(hwndTool,TTM_ADDTOOL,NULL,(LPARAM)pTi);成功返回 TRUE,否则返回 FALSE. 发送 TTM_DELTOOL消息取消注册. 向工具提示控件转发鼠标消息以上步骤完毕之后,控件知道了应当监视那一块区域和应该在提示窗口显示什么.唯一缺乏的就是激发机制. 想想看:工具指定的其它窗口的客户区的区域.控件如何截取发送向该窗口的消息呢?实际中需要截取消息以便了解鼠标停留了多长时间,当指定时间流逝以后,控件显示提示窗口.有两种方法: 一种需要包含工具窗口的合作,另一种则不需要. 包含工具的窗口必须向控件发送 TTM_RELAYEVENT 以转发消息. lParam是指向要转发消息MSG的指针 控件仅处理如下鼠标消息 : o WM_LBUTTONDOWN o WM_MOUSEMOVE o WM_LBUTTONUP o WM_RBUTTONDOWN o WM_MBUTTONDOWN o WM_RBUTTONUP o WM_MBUTTONUP 其它消息全被忽略,因此包含工具的窗口的处理过程必须包含像这样的选择: LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if(uMsg = WM_CREATE) . else if(uMsg=WM_LBUTTONDOWN | uMsg=WM_MOUSEMOVE | uMsg=WM_LBUTTONUP | uMsg=WM_RBUTTONDOWN | uMsg=WM_MBUTTONDOWN | uMsg=WM_RBUTTONUP | uMsg=WM_MBUTTONUP) SendMessage(hwndTool,TTM_RELAYEVENT,NULL,&msg); . .你可以在TOOLINFO结构的uFlags成员指定 TTF_SUBCLASS标志。此标志告诉控件子类化包含工具的窗口以便无需窗口的协作便可捕获鼠标消息。由于除了控件自己处理截获的鼠标消息和指定TTF_SUBCLASS标志之外不用编写多余的代码,因此很易于使用。 就是这些了,到这步为止,控件已经全功能了.还有几个你应当知道的相关消息. TTM_ACTIVATE.如果你想动态的允许或者禁止工具提示控件,这个小消息就是为你而备.wParam值为TRUE,允许控件.若为FALSE,禁止控件.控件初始创建的时候无需发送消息激活他,便被自动设为允许状态. TTM_GETTOOLINFO and TTM_SETTOOLINFO. 如果你想在把TOOLINFO结构传递给控件之后获得或者改变其值,使用此消息.你需要用正确的uId and hWnd值指定要改变的工具.如果你只想改变rect成员的值,使用TTM_NEWTOOLRECT 消息,如果仅想改变提示文本,使用TTM_UPDATETIPTEXT消息. TTM_SETDELAYTIME. 使用此消息指定控件显示提示文本时的时间延迟. 例子:见光盘FirstWindow25例子是一个有两个按钮的对话框,对话框的客户区分为4部分:左上、右上、左下、右下.每个区域都指定为有自己提示文本的工具,两个按钮也有自己的提示文本.#include Windows.h#include tchar.h#include commctrl.h#pragma comment(lib,comctl32.lib)#define IDD_MAINDIALOG 101TCHAR ToolTipsClassName = _T(Tooltips_class32);TCHAR MainDialogText1 = _T(This is the upper left area of the dialog);TCHAR MainDialogText2 = _T(This is the upper right area of the dialog);TCHAR MainDialogText3 = _T(This is the lower left area of the dialog);TCHAR MainDialogText4 = _T(This is the lower right area of the dialog);HINSTANCE g_hInstance;HWND hwndTool;void SetDlgToolArea(HWND hDlg,LPTOOLINFO pTi,LPSTR lpText,DWORD id,RECT *lprect) if(id = 0) pTi-rect.left = 0; pTi-rect.top = 0; pTi-rect.right = (lprect-right - lprect-left)/2; pTi-rect.bottom = (lprect-bottom - lprect-top)/2; else if(id = 1) pTi-rect.left = (lprect-right - lprect-left)/2 + 1; pTi-rect.top = 0; pTi-rect.right = (lprect-right - lprect-left); pTi-rect.bottom = (lprect-bottom - lprect-top); else if(id = 2) pTi-rect.top = (lprect-bottom - lprect-top)/ 2 + 1; pTi-rect.left = 0; pTi-rect.right = (lprect-right - lprect-left)/2; pTi-rect.bottom = lprect-bottom - lprect-top; else pTi-rect.left = (lprect-right - lprect-left)/2 + 1; pTi-rect.top = (lprect-bottom - lprect-top)/2 + 1; pTi-rect.bottom = lprect-bottom - lprect-top; pTi-rect.right = lprect-right - lprect-left; pTi-lpszText = lpText; SendMessage(hwndTool,TTM_ADDTOOL,NULL,(LPARAM)pTi);BOOL CALLBACK EnumChild( HWND hwnd, LPARAM lParam) CHAR buffer256 = 0; LPTOOLINFO pTi = (LPTOOLINFO)lParam; pTi-uId = (UINT)hwnd; pTi-uFlags |= TTF_IDISHWND; GetWindowText(hwnd,buffer,255); pTi-lpszText = buffer; SendMessage(hwndTool,TTM_ADDTOOL,NULL,(LPARAM)pTi); return TRUE;INT_PTR CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) TOOLINFO ti; DWORD id; RECT rect; switch(uMsg) case WM_INITDIALOG: InitCommonControls(); hwndTool = CreateWindowEx(NULL,ToolTipsClassName,NULL,TTS_ALWAYSTIP,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,g_hInstance,NULL); id = 0; ti.cbSize = sizeof(TOOLINFO); ti.uFlags = TTF_SUBCLASS; ti.hwnd = hwndDlg; GetWindowRect(hwndDlg,&rect); SetDlgToolArea(hwndDlg,&ti,MainDialogText1,id,&rect); id+; SetDlgToolArea(hwndDlg,&ti,MainDialogText2,id,&rect); id+; SetDlgToolArea(hwndDlg,&ti,MainDialogText3,id,&rect); id+; SetDlgToolArea(hwndDlg,&ti,MainDialogText4,id,&rect); EnumChildWindows(hwndDlg,EnumChild,(LPARAM)&ti); break; case WM_CLOSE: EndDialog(hwndDlg,NULL); break; default: return FALSE; return TRUE;int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) g_hInstance = hInstance; return DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_MAINDIALOG),NULL,(DLGPROC)DialogProc,NULL);分析:创建主对话框窗口之后,使用CreateWindowEx创建工具提示控件. InitCommonControls(); hwndTool = CreateWindowEx(NULL,ToolTipsClassName,NULL,TTS_ALWAYSTIP,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,g_hInstance,NULL); 之后,我们继续定义对话框四个角作为焦点域. id = 0; ti.cbSize = sizeof(TOOLINFO); ti.uFlags = TTF_SUBCLASS; ti.hwnd = hwndDlg; GetWindowRect(hwndDlg,&rect); SetDlgToolArea(hwndDlg,&ti,MainDialogText1,id,&rect); id+; SetDlgToolArea(hwndDlg,&ti,MainDialogText2,id,&rect); id+; SetDlgToolArea(hwndDlg,&ti,MainDialogText3,id,&rect); id+; SetDlgToolArea(hwndDlg,&ti,MainDialogText4,id,&rect);我们初始化TOOLINFO结构. 注意我们要把客户区分成4个焦点域,因此我们需要知道客户区的大小,所以调用GetWindowRect.因为我们不想自己向控件转发消息,因此指定TIF_SUBCLASS 标志.SetDlgToolArea 是计算焦点域矩形范围的并向控件注册的函数,我不详细解释计算过程.只说明它把对话框分成4个焦点域.然后向控件发送TTM_ADDTOOL 消息, 在lParam参数中传递TOOLINFO结构的地址. SendMessage(hwndTool,TTM_ADDTOOL,NULL,(LPARAM)pTi); 在四个控件注册之后,我们来看看对话框的按钮,我们可以用ID来处理每个按钮,但是实在太乏味了.我们使用EnumChildWindows函数列举对话框上的所有控件并把他们注册给控件,EnumChildWindows原型如下:BOOL EnumChildWindows( HWND hWndParent, WNDENUMPROC lpEnumFunc,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论