📄 lion-tut-c18.htm
字号:
<HTML>
<head>
<link rel="stylesheet" href="../../asm.css">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Iczelion's win32 asm tutorial</title>
</head>
<body bgcolor="#FFFFFF" background="../../images/back01.jpg">
<P align=center><FONT color=#0000ff size=4>第十八课 通用控件</FONT></P>
<HR SIZE=1>
<STRONG></STRONG>本课中我们将学习什么是通用控件和如何使用它们。
<H3><FONT
color=#ff0000>理论:</FONT></H3>WIN95相对于WIN3X有几个加强的用户界面控件。其实在WIN95正式发行前这些控件就在使用,譬如:状态条、工具条等。以前程序员要自己去编程使用它们,现在微软已经把它们包含到了WIN9X和WINNT中了。
<UL>
<LI>Toolbar ---工具条
<LI>Tooltip ---提示文本
<LI>Status bar ---状态条
<LI>Property sheet ---属性页单
<LI>Property page ---属性页
<LI>Tree view ---树型视图
<LI>List view ---列表视图
<LI>Animation ---动画
<LI>Drag list ---能够处理Drag-Drop的列表框
<LI>Header ---
<LI>Hot-key ---热键
<LI>Image list ---图象链表
<LI>Progress bar ---进程状态条
<LI>Right edit ---
<LI>Tab ---跳格表
<LI>Trackbar ---跟踪条
<LI>Up-down ---滚动条
</LI></UL>因为通用控件的数量非常多,把它们全部装入内存并注册它们是非常浪费内存的。除了“RTF文本编辑”控件外其他控件的可执行代码都放在comctl32.dll中,这样其他的应用程序就可以使用它们了。“RTF文本编辑”控件在richedXX.dll中,由于该控件非常的复杂,所以也比其它控件大。
<BR>要加载comctl32.dll可以在您的应用程序中调用函数InitCommonControls。InitCommonControls函数是动态链接库comctl32.dll中的一个函数,只要在您的程序中的任意地方引用了该函数就、会使得WINDOWS的程序加载器PE
Loader加载该库。函数InitCommonControls其实只有一条指令“ret”,它的唯一目的是为了使得在调用了个该函数的应用程序的可执行文件的PE头中的“引入”段中包含有comctl32.dll,这样无论什么时候该应用程序都会为您加载该库。所以真正初始化的工作是在该库的入口点处做的,在这里会注册所有的通用控件类,然后所有的通用控件就可以在这些类上进行创建,这就象创建其它的子窗口控件一样。<BR>RTF文本编辑控件则不同。如果您要使用它,就必须调用LoadLibrary函数来动态加载,并调用FreeLibrary来动态地卸载。<BR>现在我们学习如何创建这些通用控件。您可以用资源编辑器把它们放到一个对话框中,或者您也可以自己调用相关的函数来手动创建它们。几乎所有的通用控件都是调用函数CreateWindowEx或CreateWindow来创建的,您只要在其中传递通用控件的类名即可。有一些通用控件有一些特别的创建函数,但是其实这些函数在内部都调用了CreateWindowEx,只是包装后的函数更方便使用而已。经过包装的函数有:
<UL>
<LI>CreateToolbarEx
<LI>CreateStatusWindow
<LI>CreatePropertySheetPage
<LI>PropertySheet
<LI>ImageList_Create </LI></UL>为了创建通用控件您必须要知道它们的类名,我们把类名列于如下:<BR>
<CENTER>
<TABLE border=1 width="62%">
<TBODY>
<TR bgColor=#3366ff>
<TD>
<CENTER>类名 </CENTER></TD>
<TD>
<CENTER>通用控件 </CENTER></TD></TR>
<TR>
<TD>ToolbarWindow32</TD>
<TD>Toolbar</TD></TR>
<TR>
<TD>tooltips_class32</TD>
<TD>Tooltip</TD></TR>
<TR>
<TD>msctls_statusbar32</TD>
<TD>Status bar</TD></TR>
<TR>
<TD>SysTreeView32</TD>
<TD>Tree view</TD></TR>
<TR>
<TD>SysListView32</TD>
<TD>List view</TD></TR>
<TR>
<TD>SysAnimate32</TD>
<TD>Animation</TD></TR>
<TR>
<TD>SysHeader32</TD>
<TD>Header</TD></TR>
<TR>
<TD>msctls_hotkey32</TD>
<TD>Hot-key</TD></TR>
<TR>
<TD>msctls_progress32</TD>
<TD>Progress bar</TD></TR>
<TR>
<TD>RICHEDIT</TD>
<TD>Rich edit</TD></TR>
<TR>
<TD>msctls_updown32</TD>
<TD>Up-down</TD></TR>
<TR>
<TD>SysTabControl32</TD>
<TD>Tab</TD></TR></TBODY></TABLE>
<P> </P>
<P>Property sheets、property pages和image list控件有它们自己的创建函数。Drag
list其实是可以伸缩的listbox控件,所以它没有自己的类名。上面的类名是VC++的资源编辑器提供的,它们和Borland公司的WIN32
API指南中提出的不一样,和Petzold的书《Programming Windows 95》也不一样。可以肯定的是我们上面列出的类名绝对准确。
这些通用控件可以有通用的窗口类的一些风格,譬如WS_CHILD等。它们当然还有其他的特殊风格,譬如树型视图控件就有TVS_XXXXX风格,列表控件就有LVS_xxxx风格。具体的最好查找有关的WIN32
API函数指南。
既然我们已经知道了如何创建一个通用控件,我们就可以讨论这些通用控件之间以及和它们的父窗口之间是如何通讯的了。不象子窗口控件,通用控件在某些状态发生变化时不是通过发送WM_COMMAND而是发送WM_NOTIFY消息和父窗口通讯的。父窗口可以通过发送消息来控制子窗口的行为。对于那些新的通用控件,还有一些新的消息类型。您可以参考您的WIN32
API手册。</P>
<P>在下面的例子中我们将要实验一下进度条和状态条。</P></CENTER>
<H4><FONT color=#ff0000>例子代码:</FONT></H4><B>.386</B> <BR><B>.model
flat,stdcall</B> <BR><B>option casemap:none</B> <BR><B>include
\masm32\include\windows.inc</B> <BR><B>include \masm32\include\user32.inc</B>
<BR><B>include \masm32\include\kernel32.inc</B> <BR><B>include
\masm32\include\comctl32.inc</B> <BR><B>includelib \masm32\lib\comctl32.lib</B>
<BR><B>includelib \masm32\lib\user32.lib</B> <BR><B>includelib
\masm32\lib\kernel32.lib</B>
<P><B>WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD</B>
<P><B>.const</B> <BR><B>IDC_PROGRESS equ
1 ; control
IDs</B> <BR><B>IDC_STATUS equ 2</B> <BR><B>IDC_TIMER equ 3</B>
<P><B>.data</B> <BR><B>ClassName db "CommonControlWinClass",0</B>
<BR><B>AppName db "Common Control Demo",0</B>
<BR><B>ProgressClass db
"msctls_progress32",0 ; the class name of
the progress bar</B> <BR><B>Message db "Finished!",0</B>
<BR><B>TimerID dd 0</B>
<P><B>.data?</B> <BR><B>hInstance HINSTANCE ?</B> <BR><B>hwndProgress dd
?</B> <BR><B>hwndStatus dd ?</B> <BR><B>CurrentStep dd ?</B> <BR><B>.code</B>
<BR><B>start:</B> <BR><B> invoke GetModuleHandle, NULL</B>
<BR><B> mov hInstance,eax</B>
<BR><B> invoke WinMain, hInstance,NULL,NULL,
SW_SHOWDEFAULT</B> <BR><B> invoke ExitProcess,eax</B>
<BR><B> invoke InitCommonControls</B>
<P><B>WinMain proc
hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD</B>
<BR><B> LOCAL wc:WNDCLASSEX</B> <BR><B>
LOCAL msg:MSG</B> <BR><B> LOCAL hwnd:HWND</B>
<P><B> mov wc.cbSize,SIZEOF WNDCLASSEX</B>
<BR><B> mov wc.style, CS_HREDRAW or CS_VREDRAW</B>
<BR><B> mov wc.lpfnWndProc, OFFSET WndProc</B>
<BR><B> mov wc.cbClsExtra,NULL</B>
<BR><B> mov wc.cbWndExtra,NULL</B>
<BR><B> push hInst</B> <BR><B>
pop wc.hInstance</B> <BR><B> mov
wc.hbrBackground,COLOR_APPWORKSPACE</B> <BR><B>
mov wc.lpszMenuName,NULL</B> <BR><B>
mov wc.lpszClassName,OFFSET ClassName</B> <BR><B>
invoke LoadIcon,NULL,IDI_APPLICATION</B> <BR><B>
mov wc.hIcon,eax</B> <BR><B> mov
wc.hIconSm,eax</B> <BR><B> invoke
LoadCursor,NULL,IDC_ARROW</B> <BR><B> mov
wc.hCursor,eax</B> <BR><B> invoke RegisterClassEx, addr wc</B>
<BR><B> invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR
ClassName,ADDR AppName,\</B>
<BR><B>WS_OVERLAPPED+WS_CAPTION+WS_SYSMENU+WS_MINIMIZEBOX+WS_MAXIMIZEBOX+WS_VISIBLE,CW_USEDEFAULT,\</B>
<BR><B>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -