按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
tf文件和不带格式的txt文件,由于该控件非常复杂,代码的规模比较大,单独一个Richedit控件的代码规模就和ctl32。dll中全部代码的规模相当,所以Windows系统将Richedit控件单独放到另一个dll文件中,有关Richedit控件的情况将在9。4节中详细介绍。
图9。1 常见的通用控件
9。1。2 使用通用控件
1.库初始化
通用控件的数量非常多,平时把它们全部装入并注册是非常浪费内存的,所以在默认状态下ctl32。dll并不会被装入内存,因此,在使用通用控件之前必须将通用控件库装入内存,专用函数InitmonControls可以用来完成这个工作,调用这个函数的惟一目的是保证系统加载ctl32。dll库文件。
当库文件被装入的时候,库的入口函数会注册所有的通用控件类,然后用户程序就可以使用这些预定义的类来创建各种类型的通用控件窗口,这就像创建其他的子窗口控件一样。InitmonControls函数没有参数,也没有定义返回值,它的使用方法是:
invoke InitmonControls
InitmonControls函数仅注册表9。1中所列的通用控件类,并不注册表9。2中的扩展通用控件。如果需要使用扩展通用控件,那么需要使用InitmonControlsEx函数来进行装入和注册的工作:
invoke InitmonControlsEx,lpInitCtrls
lpInitCtrls参数指向一个INITMONCONTROLSEX结构:
INITMONCONTROLSEX STRUCT
dwSize dd ? ;结构长度
dwICC dd ? ;需要初始化的类
INITMONCONTROLSEX ENDS
结构中的dwICC字段指定了需要注册的扩展通用控件类,与InitmonControls注册所有它支持的通用控件类不同,InitmonControlsEx函数只注册dwICC字段指明的扩展通用控件类,字段可以是下面取值的组合:
● ICC_BAR_CLASSES——注册工具栏、状态栏、Trackbar和Tooltip类。
● ICC_COOL_CLASSES——注册Rebar类。
● ICC_DATE_CLASSES——注册Date and Time Picker类。
● ICC_HOTKEY_CLASS——注册Hot Key类。
● ICC_INTERNET_CLASSES——注册IP Address Picker类。
● ICC_LISTVIEW_CLASSES——注册ListView和Header类。
● ICC_PAGESCROLLER_CLASS——注册Pager类。
● ICC_PROGRESS_CLASS——注册Progress Bar类。
● ICC_TAB_CLASSES——注册Tab和Tooltip类。
● ICC_TREEVIEW_CLASSES——注册TreeView和Tooltip类。
● ICC_UPDOWN_CLASS——注册Up…Down类。
● ICC_USEREX_CLASSES——注册boBoxEx类。
● ICC_WIN95_CLASSES——注册InitmonControls函数注册的所有类。
InitmonControlsEx函数是InitmonControls函数的扩充,使用它也可以注册InitmonControls函数能够注册的所有类(也可以仅注册其中的一部分),如果只用到通用控件,两个初始化函数都可以使用,但若用到扩展通用控件,那就只能使用InitmonControlsEx函数来进行初始化了。
创建通用控件的代码一般放在主窗口的WM_CREATE消息中,所以InitmonControls和InitmonControlsEx函数的调用需要在此之前完成,一般在程序一开始的地方就调用它们。
来源:电子工业出版社 作者:罗云彬 上一页 回书目 下一页
上一页 回书目 下一页
第9章 通用控件
9。1 通用控件简介(2)
2。 创建通用控件
大部分的通用控件都以窗口类的方法实现(惟一的例外是图像列表),所以创建通用控件窗口的方法和使用自定义窗口类建立窗口的方法是一样的,只要在CreateWindowEx函数中使用通用控件的类名就可以了。如果要在对话框中使用通用控件,也可以在资源文件中用定义子窗口控件同样的方法来定义通用控件(见5。4。4小节)。
在建立通用控件的时候,可以使用WS_CHILD等通用的窗口风格,除此之外,不同的通用控件也有自己的特殊风格,如树型视图控件有TVS_XXXXX风格、列表控件有LVS_xxxx风格等,表9。1和表9。2中列出了一些特殊风格的前缀,这些风格的具体含义可以参考Win32 API函数指南。
可以在对话框资源定义中如下定义一个列表视图控件:
CONTROL 〃〃; IDC_LISTVIEW; 〃SysListView32〃;
LVS_REPORT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP;
11; 13; 216; 82; WS_EX_CLIENTEDGE
也可以在程序中使用CreateWindowsEx函数如下创建:
szClass db 〃SysListView32〃;0
。。。
invoke CreateWindowEx;WS_EX_CLIENTEDGE;offset szClass;NULL;
LVS_REPORT or WS_CHILD or WS_VISIBLE or WS_BORDER;
11;13;216;82;
hWinMain;IDC_LISTVIEW;hInstance;NULL
上述两种方法的使用效果是一样的,程序代码中的WS_CHILD等以WS开头的风格是窗口的通用风格,而LVS_REPORT风格是列表视图控件的特有风格。由于大多数时候通用控件都是当做子窗口创建的,所以窗口风格中必须包括WS_CHILD风格。另外,使用CreateWindowEx创建的时候必须指定WS_VISIBLE风格,否则控件不会被显示;而在对话框资源中定义的时候,系统总是默认加上WS_VISIBLE风格,所以有没有WS_VISIBLE是无所谓的。
除了调用CreateWindowEx或CreateWindow函数来创建通用控件外,某些通用控件的创建可以使用一些专用的函数,这些函数其实在内部都调用了CreateWindowEx,只是由于包装后的函数是量身定做的,使用起来更方便而已。经过包装的函数有:
● CreateToolbarEx函数——用来创建工具栏。
● CreateStatusWindow函数——用来创建状态栏。
● CreateUpDownControl函数——用来创建滚动条控件。
另外,有些通用控件并没有自己的窗口类名称,或者说根本就不是窗口类,比如属性表格和属性页控件是基于项目列表控件(Table Control)的,DragList控件是基于下拉式列表框的,它们是其他控件的扩展;而图像列表控件本身是一幅图像而不是窗口类。创建这些控件的时候,由于无法用类名来指定它们,所以无法使用CreateWindowEx函数来创建,必须使用下面这些专用的创建函数:
● PropertySheet函数——用来创建属性表格。
● CreatePropertySheetPage函数——用来创建属性页。
● ImageList_Create函数——用来创建图像列表。
● MakeDragList函数——用来创建DragList控件。
在使用控件时要牢记的是:大部分的控件是窗口,它们是特殊的窗口,所以所有适用于窗口的概念都可以使用在控件上,包括创建与使用的方法,和父窗口的通信方式及内部的工作原理等。
3。 通用控件和父窗口之间的通信
当在对话框中使用子窗口控件时,父窗口通过SendMessage函数发送控制消息来管理子窗口控件,而子窗口控件通过发送WM_MAND或WM_NOTIFY消息来将用户的动作通知父窗口。
通用控件的通信方法和子窗口控件使用的方法是一样的——父窗口发送控制消息来管理通用控件,不同类型的通用控件使用不同的控制消息,如状态栏的控制消息都是以SB_开头的(Status Bar的缩写);TreeView控件的控制消息是以TVM_开头的(Tree View Message的缩写);ListView控件的控制消息是以LVM_开头的(List View Message的缩写)。不同的消息都有特定的用法和参数,在使用时需要查阅Win32函数手册。
通用控件也通过发送通知消息来和父窗口通信,不同通用控件使用的通知消息可能有所不同,归纳起来情况如下:
● 工具栏控件使用WM_MAND消息将按钮动作通知父窗口,这是为了便于和菜单、加速键使用同一份代码来处理用户按下工具栏按钮的动作。
● 滚动条控件使用WM_VSCROLL或者WM_HSCROLL消息通知父窗口,和窗口自身滚动条使用的消息名称保持一致可以便于使用已经存在的滚动条消息处理代码。
● 除了上面这两种特殊情况外,大部分通用控件使用WM_NOTIFY消息通知父窗口。这样可以避免和菜单或加速键等使用的WM_MAND消息相混淆。
当父窗口收到WM_NOTIFY消息时,wParam参数的内容是通用控件的ID,也就是使用CreateWindowEx函数创建控件时使用的第10个参数,通过这个参数可以判别WM_NOTIFY消息是由哪个通用控件发送的;消息的lParam参数指向一个NMHDR结构:
NMHDR STRUCT
hwndFrom DWORD ? ;发送WM_NOTIFY的通用控件的窗口句柄
idFrom DWORD ? ;发送WM_NOTIFY的通用控件的ID
code DWORD ? ;通知码
NMHDR ends
通过NMHDR结构中的hwndFrom字段和idFrom字段也可以判别发送WM_NOTIFY消息的控件,由于使用CreateWindowEx函数创建多个通用控件的时候可以使用同样的ID值,所以有时候使用ID并不能惟一确定控件,只有在创建的时候对不同的控件使用了不同的ID值,才能用ID值来惟一确定控件。而系统中每个窗口的窗口句柄是惟一的,所以使用hwndFrom字段是肯定能惟一确定控件的。
结构中的code字段是通知码,通过这个字段可以了解到控件上发生的动作,每种控件都有自己独特的通知码集合,但下面的通知码是大部分控件都使用的:
● NM_CLICK——用户在控件上按下了鼠标左键。
● NM_DBLCLK——用户在控件上双击鼠标左键。
● NM_KILLFOCUS——控件失去了键盘输入焦点。
● NM_OUTOFMEMORY——控件在运行中内存耗尽。
● NM_RCLICK——用户在控件上按下了鼠标右键。
● NM_RDBLCLK——用户在控件上双击鼠标右键。
● NM_RETURN——用户在控件上按下了回车键。
● NM_SETFOCUS——控件得到了键盘输入焦点。
来源:电子工业出版社 作者:罗云彬 上一页 回书目 下一页
上一页 回书目 下一页
第9章 通用控件
9。2 使用状态栏(1)
状态栏一般位于主窗口的底部(当然,如果愿意的话,也可以把它放在主窗口的上方,不过几乎没有人这样做),用来显示程序运行中的一些状态信息。本节中的例子程序创建了一个带状态栏的对话框,运行界面如图9。2的左边窗口所示。状态栏中分别显示了时间、编辑器中的总字节数和插入状态等3栏内容,随着时间的改变和字符的输入,这些信息会随时被更新。状态栏的另一个重要应用是显示菜单项的说明信息。在例子程序中,随着鼠标移到不同的菜单项上,状态栏上的说明信息也随之改变,如图9。2的右边窗口所示。
图9。2 状态栏示例
一般来说,状态栏仅用于输出信息,并不用来输入信息,但有时也会使用状态栏来获取有限功能的输入,如在例子程序中状态栏的第3栏上单击鼠标,文字会在“插入”和“改写”之间切换,一些文本编辑软件就是用这种办法来改变文字输入方式的。
本节提供的例子位于所附光盘的Chapter09StatusBar目录中,包括StatusBar。asm文件和StatusBar。rc文件。StatusBar。asm文件的内容如下:
。386
。model flat; stdcall
option casemap :none
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; Include 文件定义
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
include windows。inc
include user32。inc
includelib user32。lib
include kernel32。inc
includelib kernel32。lib
include ctl32。inc
includelib ctl32。lib
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; Equ 等值定义
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
ICO_MAIN equ 1000
DLG_MAIN equ 1000
IDM_MAIN equ 1000
IDM_EXIT equ 1104
IDM_MENUHELP equ 1300
ID_STATUSBAR equ 1
ID_EDIT equ 2
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 数据段
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
。data?
hInstance dd ?
hWinMain dd ?
hWinStatus dd ?
hWinEdit dd ?
lpsz1 dd ?
lpsz2 dd ?
nst
szClass db 'EDIT';0
szFormat0 db '%02d:%02d:%02d';0
szFormat1 db '字节数:%d';0
sz1 db '插入';0
sz2 db '改写';0
dwStatusWidth dd 60;140;172;…1
dwMenuHelp dd 0;IDM_MENUHELP;0;0
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 代码段
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
de
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
_Resize proc
local @stRect:RECT;@stRect1:RECT
invoke MoveWindow;hWinStatus;0;0;0;0;TRUE
invoke GetWindowRect;hWinStatus;addr @stRect
invoke GetClientRect;hWinMain;addr @stRect1
mov ecx;@stRect1。right
sub ecx;@stRect1。left
mov eax;@stRect1。bottom
sub eax;@stRect1。top
sub eax;@stRect。bottom
add eax;@stRect。top
invoke MoveWindow;hWinEdit;0;0;ecx;eax;TRUE
ret
_Resize endp
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
_ProcDlgMain proc uses ebx edi esi hWnd;wMsg;wParam;lParam
local @szBuffer'128':byte
local @stST:SYSTEMTIME
local @stPoint:POINT;@stRect:RECT
mov eax;wMsg
;********************************************************************
。if eax WM_TIMER
invoke GetLocalTime;addr @stST
movzx eax;@stST。wHour
movzx ebx;@stST。wMinute
movzx ecx;@stST。wSecond
invoke wsprintf;addr @szBuffer;addr szFormat0;
eax;ebx;ecx
invoke SendMessage;hWinStatus;SB_SETTEXT;
0;addr @szBuffer
;********************************************************************
。elseif eax WM_CLOSE
invoke KillTimer;hWnd;1