📄 tut27.html
字号:
<br><b><tt> LOCAL ti:TOOLINFO</tt></b>
<br><b><tt> LOCAL id:DWORD</tt></b>
<br><b><tt> LOCAL rect:RECT</tt></b>
<br><b><tt> .if uMsg==WM_INITDIALOG</tt></b>
<br><b><tt> invoke InitCommonControls</tt></b>
<br><b><tt> invoke CreateWindowEx,NULL,ADDR
ToolTipsClassName,NULL,\</tt></b>
<br><b><tt>
TTS_ALWAYSTIP,CW_USEDEFAULT,\</tt></b>
<br><b><tt>
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\</tt></b>
<br><b><tt>
hInstance,NULL</tt></b>
<br><b><tt> mov hwndTool,eax</tt></b>
<br><b><tt> mov id,0</tt></b>
<br><b><tt> mov ti.cbSize,sizeof
TOOLINFO</tt></b>
<br><b><tt> mov ti.uFlags,TTF_SUBCLASS</tt></b>
<br><b><tt> push hDlg</tt></b>
<br><b><tt> pop ti.hWnd</tt></b>
<br><b><tt> invoke GetWindowRect,hDlg,addr
rect</tt></b>
<br><b><tt> invoke SetDlgToolArea,hDlg,addr
ti,addr MainDialogText1,id,addr rect</tt></b>
<br><b><tt> inc id</tt></b>
<br><b><tt> invoke SetDlgToolArea,hDlg,addr
ti,addr MainDialogText2,id,addr rect</tt></b>
<br><b><tt> inc id</tt></b>
<br><b><tt> invoke SetDlgToolArea,hDlg,addr
ti,addr MainDialogText3,id,addr rect</tt></b>
<br><b><tt> inc id</tt></b>
<br><b><tt> invoke SetDlgToolArea,hDlg,addr
ti,addr MainDialogText4,id,addr rect</tt></b>
<br><b><tt> invoke EnumChildWindows,hDlg,addr
EnumChild,addr ti</tt></b>
<br><b><tt> .elseif uMsg==WM_CLOSE</tt></b>
<br><b><tt> invoke EndDialog,hDlg,NULL</tt></b>
<br><b><tt> .else</tt></b>
<br><b><tt> mov eax,FALSE</tt></b>
<br><b><tt> ret</tt></b>
<br><b><tt> .endif</tt></b>
<br><b><tt> mov eax,TRUE</tt></b>
<br><b><tt> ret</tt></b>
<br><b><tt>DlgProc endp</tt></b><b><tt></tt></b>
<p><b><tt>EnumChild proc uses edi hwndChild:DWORD,lParam:DWORD</tt></b>
<br><b><tt> LOCAL buffer[256]:BYTE</tt></b>
<br><b><tt> mov edi,lParam</tt></b>
<br><b><tt> assume edi:ptr TOOLINFO</tt></b>
<br><b><tt> push hwndChild</tt></b>
<br><b><tt> pop [edi].uId</tt></b>
<br><b><tt> or [edi].uFlags,TTF_IDISHWND</tt></b>
<br><b><tt> invoke GetWindowText,hwndChild,addr buffer,255</tt></b>
<br><b><tt> lea eax,buffer</tt></b>
<br><b><tt> mov [edi].lpszText,eax</tt></b>
<br><b><tt> invoke SendMessage,hwndTool,TTM_ADDTOOL,NULL,edi</tt></b>
<br><b><tt> assume edi:nothing</tt></b>
<br><b><tt> ret</tt></b>
<br><b><tt>EnumChild endp</tt></b><b><tt></tt></b>
<p><b><tt>SetDlgToolArea proc uses edi esi hDlg:DWORD,lpti:DWORD,lpText:DWORD,id:DWORD,lprect:DWORD</tt></b>
<br><b><tt> mov edi,lpti</tt></b>
<br><b><tt> mov esi,lprect</tt></b>
<br><b><tt> assume esi:ptr RECT</tt></b>
<br><b><tt> assume edi:ptr TOOLINFO</tt></b>
<br><b><tt> .if id==0</tt></b>
<br><b><tt> mov [edi].rect.left,0</tt></b>
<br><b><tt> mov [edi].rect.top,0</tt></b>
<br><b><tt> mov eax,[esi].right</tt></b>
<br><b><tt> sub eax,[esi].left</tt></b>
<br><b><tt> shr eax,1</tt></b>
<br><b><tt> mov [edi].rect.right,eax</tt></b>
<br><b><tt> mov eax,[esi].bottom</tt></b>
<br><b><tt> sub eax,[esi].top</tt></b>
<br><b><tt> shr eax,1</tt></b>
<br><b><tt> mov [edi].rect.bottom,eax</tt></b>
<br><b><tt> .elseif id==1</tt></b>
<br><b><tt> mov eax,[esi].right</tt></b>
<br><b><tt> sub eax,[esi].left</tt></b>
<br><b><tt> shr eax,1</tt></b>
<br><b><tt> inc eax</tt></b>
<br><b><tt> mov [edi].rect.left,eax</tt></b>
<br><b><tt> mov [edi].rect.top,0</tt></b>
<br><b><tt> mov eax,[esi].right</tt></b>
<br><b><tt> sub eax,[esi].left</tt></b>
<br><b><tt> mov [edi].rect.right,eax</tt></b>
<br><b><tt> mov eax,[esi].bottom</tt></b>
<br><b><tt> sub eax,[esi].top</tt></b>
<br><b><tt> mov [edi].rect.bottom,eax</tt></b>
<br><b><tt> .elseif id==2</tt></b>
<br><b><tt> mov [edi].rect.left,0</tt></b>
<br><b><tt> mov eax,[esi].bottom</tt></b>
<br><b><tt> sub eax,[esi].top</tt></b>
<br><b><tt> shr eax,1</tt></b>
<br><b><tt> inc eax</tt></b>
<br><b><tt> mov [edi].rect.top,eax</tt></b>
<br><b><tt> mov eax,[esi].right</tt></b>
<br><b><tt> sub eax,[esi].left</tt></b>
<br><b><tt> shr eax,1</tt></b>
<br><b><tt> mov [edi].rect.right,eax</tt></b>
<br><b><tt> mov eax,[esi].bottom</tt></b>
<br><b><tt> sub eax,[esi].top</tt></b>
<br><b><tt> mov [edi].rect.bottom,eax</tt></b>
<br><b><tt> .else</tt></b>
<br><b><tt> mov eax,[esi].right</tt></b>
<br><b><tt> sub eax,[esi].left</tt></b>
<br><b><tt> shr eax,1</tt></b>
<br><b><tt> inc eax</tt></b>
<br><b><tt> mov [edi].rect.left,eax</tt></b>
<br><b><tt> mov eax,[esi].bottom</tt></b>
<br><b><tt> sub eax,[esi].top</tt></b>
<br><b><tt> shr eax,1</tt></b>
<br><b><tt> inc eax</tt></b>
<br><b><tt> mov [edi].rect.top,eax</tt></b>
<br><b><tt> mov eax,[esi].right</tt></b>
<br><b><tt> sub eax,[esi].left</tt></b>
<br><b><tt> mov [edi].rect.right,eax</tt></b>
<br><b><tt> mov eax,[esi].bottom</tt></b>
<br><b><tt> sub eax,[esi].top</tt></b>
<br><b><tt> mov [edi].rect.bottom,eax</tt></b>
<br><b><tt> .endif</tt></b>
<br><b><tt> push lpText</tt></b>
<br><b><tt> pop [edi].lpszText</tt></b>
<br><b><tt> invoke SendMessage,hwndTool,TTM_ADDTOOL,NULL,lpti</tt></b>
<br><b><tt> assume edi:nothing</tt></b>
<br><b><tt> assume esi:nothing</tt></b>
<br><b><tt> ret</tt></b>
<br><b><tt>SetDlgToolArea endp</tt></b>
<br><b><tt>end start</tt></b></blockquote>
<h3>
<font face="Tahoma">Analysis:</font></h3>
<font face="Tahoma">After the main dialog window is created, we create
the tooltip control with CreateWindowEx.</font>
<blockquote><b><tt>invoke InitCommonControls</tt></b>
<br><b><tt>invoke CreateWindowEx,NULL,ADDR ToolTipsClassName,NULL,\</tt></b>
<br><b><tt> TTS_ALWAYSTIP,CW_USEDEFAULT,\</tt></b>
<br><b><tt> CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\</tt></b>
<br><b><tt> hInstance,NULL</tt></b>
<br><b><tt>mov hwndTool,eax</tt></b></blockquote>
<font face="Tahoma">After that, we proceed to define four tools for each
corner of the dialog box.</font><font face="Tahoma"></font>
<p><b><tt> mov id,0
<font color="#99FF99">; used as the tool ID</font></tt></b>
<br><b><tt> mov ti.cbSize,sizeof TOOLINFO</tt></b>
<br><b><tt> mov ti.uFlags,TTF_SUBCLASS <font color="#66FF99">
; tell the tooltip control to subclass the dialog window.</font></tt></b>
<br><b><tt> push hDlg</tt></b>
<br><b><tt> pop ti.hWnd <font color="#99FF99">;
handle to the window that contains the tool</font></tt></b>
<br><b><tt> invoke GetWindowRect,hDlg,addr rect <font color="#99FF99">
; obtain the dimension of the client area</font></tt></b>
<br><b><tt> invoke SetDlgToolArea,hDlg,addr ti,addr MainDialogText1,id,addr
rect</tt></b><font face="Tahoma"></font>
<p><font face="Tahoma">We initialize the members of <b><font color="#99FF99">TOOLINFO
</font></b>structure. Note that we want to divide the client area into
4 tools so we need to know the dimension of the client area. That's why
we call <b><font color="#FFFFCC">GetWindowRect</font></b>. We don't want
to relay mouse messages to the tooltip control ourselves so we specify
<b><font color="#99FF99">TIF_SUBCLASS </font></b>flag.</font>
<br><font face="Tahoma"><b><font color="#FFFFCC">SetDlgToolArea</font></b>
is a function that calculates the bounding rectangle of each tool and registers
the tool to the tooltip control. I won't go into gory detail on the calculation,
suffice to say that it divides the client area into 4 areas with the same
sizes. Then it sends <b><font color="#99FF99">TTM_ADDTOOL</font></b> message
to the tooltip control, passing the address of the <b><font color="#99FF99">TOOLINFO</font></b>
structure in the lParam parameter.</font><font face="Tahoma"></font>
<p><b><tt> invoke SendMessage,hwndTool,TTM_ADDTOOL,NULL,lpti</tt></b><font face="Tahoma"></font>
<p><font face="Tahoma">After all 4 tools are registered, we can go on to
the buttons on the dialog box. We can handle each button by its ID but
this is tedious. Instead, we will use <b><font color="#FFFFCC">EnumChildWindows</font></b>
API call to enumerate all controls on the dialog box and then registers
them to the tooltip control. <b><font color="#FFFFCC">EnumChildWindows</font></b>
has the following syntax:</font>
<blockquote><b><font face="Tahoma"><font color="#FFCC99">EnumChildWindows
proto hWnd:DWORD, lpEnumFunc:DWORD, lParam:DWORD</font></font></b></blockquote>
<font face="Tahoma">hWnd is the handle to the parent window. lpEnumFunc
is the address of the <b><font color="#FFFFCC">EnumChildProc</font></b>
function that will be called for each control enumerated. lParam is the
application-defined value that will be passed to the <b><font color="#FFFFCC">EnumChildProc</font></b>
function. The <b><font color="#FFFFCC">EnumChildProc</font></b> function
has the following definition:</font>
<blockquote><b><font face="Tahoma"><font color="#FFCC99">EnumChildProc
proto hwndChild:DWORD, lParam:DWORD</font></font></b></blockquote>
<font face="Tahoma">hwndChild is the handle to a control enumerated by<b><font color="#FFFFCC">
EnumChildWindows</font></b>. lParam is the same lParam value you pass to
<b><font color="#FFFFCC">EnumChildWindows</font></b>.</font>
<br><font face="Tahoma">In our example, we call<b><font color="#FFFFCC">
EnumChildWindows</font></b> like this:</font>
<blockquote><b><tt>invoke EnumChildWindows,hDlg,addr EnumChild,addr ti</tt></b></blockquote>
<font face="Tahoma">We pass the address of the <b><font color="#66FF99">TOOLINFO</font></b>
structure in the lParam parameter because we will register each child control
to the tooltip control in the <b><font color="#FFFFCC">EnumChild </font></b>function.
If we don't use this method, we need to declare <b><font color="#FFFFCC">ti
</font></b>as a global variable which can introduce bugs.</font>
<br><font face="Tahoma">When we call<b><font color="#FFFFCC"> EnumChildWindows</font></b>,
Windows will enumerate the child controls on our dialog box and call the
<b><font color="#FFFFCC">EnumChild</font></b> function once for each control
enumerated. Thus if our dialog box has two controls, <b><font color="#FFFFCC">EnumChild</font></b>
will be called twice.</font>
<br><font face="Tahoma">The EnumChild function fills the relevant members
of the TOOLINFO structure and then registers the tool with the tooltip
control.</font>
<blockquote><b><tt>EnumChild proc uses edi hwndChild:DWORD,lParam:DWORD</tt></b>
<br><b><tt> LOCAL buffer[256]:BYTE</tt></b>
<br><b><tt> mov edi,lParam</tt></b>
<br><b><tt> assume edi:ptr TOOLINFO</tt></b>
<br><b><tt> push hwndChild</tt></b>
<br><b><tt> pop [edi].uId <font color="#99FF99">
; we use the whole client area of the control as the tool</font></tt></b>
<br><b><tt> or [edi].uFlags,TTF_IDISHWND</tt></b>
<br><b><tt> invoke GetWindowText,hwndChild,addr buffer,255</tt></b>
<br><b><tt> lea eax,buffer <font color="#99FF99">
; use the window text as the tooltip text</font></tt></b>
<br><b><tt> mov [edi].lpszText,eax</tt></b>
<br><b><tt> invoke SendMessage,hwndTool,TTM_ADDTOOL,NULL,edi</tt></b>
<br><b><tt> assume edi:nothing</tt></b>
<br><b><tt> ret</tt></b>
<br><b><tt>EnumChild endp</tt></b></blockquote>
<font face="Tahoma">Note that in this case, we use a different type of
tool: one that covers the whole client area of the window. We thus need
to fill the <b><font color="#FFFFCC">uID</font></b> field with the handle
to the window that contains the tool. Also we must specify <b><font color="#99FF99">TTF_IDISHWND</font></b>
flag in the <b><font color="#FFFFCC">uFlags</font></b> member.</font>
<br>
<hr WIDTH="100%">
<center><b>[<a href="http://win32asm.cjb.net">Iczelion's Win32 Assembly
Homepage</a>]</b></center>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -