使用资源—对话框—在对话框中使用子窗口控件
子窗口控件是一些Windows预定义类,它们实际上就是一个个以对话框为父窗口的子窗口。对于程序员来说,在对话框中使用它们的时候并不需要手工去逐一创建,只需要在对话框中定义就可以了,“对话框管理器”会在初始化对话框的时候,根据定义语句自动建立所有的子窗口。
1、子窗口控件的定义
子窗口控件定义的一般语法是:
CONTROL 文本, ID, 类, 风格, x, y, 宽度, 高度 [, 扩展风格]
“文本”指控件的初始化值,“ID”是子窗口向对话框过程发送WM_COMMAND中用的ID值,“类”可以是按钮(Button)、静态(Static)、编辑(Edit)、滚动条(ScrollBar)、列表框(ListBox)和组合框(ComboBox),这些类都是Windows系统中已经预定义的,“对话框管理器”在初始化的时候把每一条控件定义语句转换成下面的CreateWindow命令:
invoke CreateWindow, 类名, 文本, 风格, x, y, 宽度, 高度, 对话框窗口句柄, ID,
hInstance, NULL
正因为如此,所有可以用CreateWindow建立的子窗口都可以在资源中定义,只要知道要使用的类和风格就可以了。所以除了上面这些基本的类之外,对话框中还可以使用一些通用控件,如“日期”(SysDateTimePick32)、“月历”(SysMonthCal32)、“热键”(msctls_hotkey32)和“列表”(SysListView32)等,括号内是它们的类名,只要把定义语句的“类”写成对应的名称就可以了。
基于同一个预定义类的控件根据风格属性的不同,外表可能完全不同,如单选钮、复选框和分组框使用的类都是Button类,文本、图标框、位图框和线条等都是Static类。使用CONTROL语句定义的时候可能不是很直观,所以Rc.exe资源编译器允许使用另一种语法来书写控件定义:
控件名称 [文本,] ID, x, y, 宽度, 高度 [, 风格] [, 扩展风格]
这里使用“控件名称”而不是“类”是因为这个名称只是Rc.exe使用的缩写,并不是真正的Windows类的名称,“控件名称”由Rc.exe解释成“类”名,同时为它使用了几种默认的风格,定义语句中风格属性实际上是附加在默认风格上的,表5.4列出了每种控件使用的类和默认属性,除了表中列出的默认属性外,每种控件还被默认定义了WS_CHILD和WS_VISIBLE属性。
资源脚本中使用的控件名称
控件名称
|
说明
|
基于的类
|
默认窗口风格
|
PUSHBUTTON
|
按钮
|
Button
|
BS_PUSHBUTTON, WS_TABSTOP
|
DEFPUSHBUTTON
|
默认按钮
|
Button
|
BS_DEFPUSHBUTTON, WS_TABSTOP
|
CHECKBOX
|
复选框
|
Button
|
BS_CHECKBOX, WS_TABSTOP
|
AUTOCHECKBOX
|
自动复选框
|
Button
|
BS_AUTOCHECKBOX, WS_TABSTOP
|
STATE3
|
3态复选框
|
Button
|
BS_3STATE, WS_TABSTOP
|
AUTO2STATE
|
自动3态复选框
|
Button
|
BS_AUTO3STATE, WS_TABSTOP
|
RADIOBUTTON
|
单选框
|
Button
|
BS_RADIOBUTTON, WS_TABSTOP
|
AUTORADIOBUTTON
|
自动单选框
|
Button
|
BS_AUTORADIOBUTTON, WS_TABSTOP
|
GROUPBOX
|
分组框
|
Button
|
BS_GROUPBOX
|
SCROLLBAR
|
滚动条
|
ScrollBar
|
SBS_HORZ
|
CTEXT
|
居中文本
|
Static
|
SS_CENTER, WS_GROUP
|
LTEXT
|
左对齐文本
|
Static
|
SS_LEFT, WS_GROUP
|
RTEXT
|
右对齐文本
|
Static
|
SS_RIGHT, WS_GROUP
|
ICON
|
图标框
|
Static
|
SS_ICON
|
EDITTEXT
|
文本编辑
|
Edit
|
ES_LEFT, WS_BORDER, WS_TABSTOP
|
COMBOBOX
|
组合框
|
ComboBox
|
CBS_SIMPLE, WS_TABSTOP
|
LISTBOX
|
列表框
|
ListBox
|
LBS_NOTIFY, WS_BORDER
|
看下面的例子:
GROUPBOX “选项”, -1, 55, 5, 120, 100
PUSHBUTTON “退出”, IDCANCEL, 255, 115, 50, 14
这两条语句和下面的语句编译后产生的二进制资源文件是一模一样的:
CONTROL “选项”, -1, “Button”, BS_GROUPBOX | WS_TABSTOP, 55, 5, 120, 100
CONTROL “退出”, IDCANCEL, “Button”, BS_PUSHBUTTON | WS_TABSTOP, 255, 115, 50, 14
第一种语句的用法比第二种语句不但要直观许多,而且不必书写默认的窗口风格。
当用到的控件没有缩写语法时,那就必须用CONTROL定义了,下面的两句分别定义了一条横线和一个图片框,它们并没有缩写的用法:
CONTROL “”, -1, “Static”, SS_ETCHEDHORZ | WS_CHILD | WS_VISIBLE, 60, 65, 110, 1
CONTROL BMP_ID, -1, “Static”, SS_BITMAP | WS_CHILD | WS_VISIBLE, 5, 5, 40, 95
下面以一个例子来演示各种子窗口控件的用法。
//Control.rc
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include <resource.h>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define ICO_MAIN 0x1000 //图标
#define DLG_MAIN 0x1
#define IDB_1 1
#define IDB_2 2
#define IDC_ONTOP 101
#define IDC_SHOWBMP 102
#define IDC_ALOW 103
#define IDC_MODALFRAME 104
#define IDC_THICKFRAME 105
#define IDC_TITLETEXT 106
#define IDC_CUSTOMTEXT 107
#define IDC_BMP 108
#define IDC_SCROLL 109
#define IDC_VALUE 110
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN ICON "Main.ico"
IDB_1 BITMAP "Picture1.bmp"
IDB_2 BITMAP "Picture2.bmp"
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DLG_MAIN DIALOG 193, 180, 310, 134
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "对话框子窗口控件示例"
FONT 9, "宋体"
{
GROUPBOX "选项", -1, 55, 5, 120, 100
AUTOCHECKBOX "总在最前面", IDC_ONTOP, 65, 20, 100, 12
AUTOCHECKBOX "显示图片", IDC_SHOWBMP, 65, 35, 100, 12
AUTOCHECKBOX "允许更换图片", IDC_ALOW, 65, 50, 100, 12
CONTROL "", -1, "Static", SS_ETCHEDHORZ | WS_CHILD | WS_VISIBLE, 60, 65, 110, 1
AUTORADIOBUTTON "模态边框(&Modal Frame)", IDC_MODALFRAME, 65, 70, 100, 12, WS_TABSTOP
AUTORADIOBUTTON "可变边框(&Thick Frame)", IDC_THICKFRAME, 65, 85, 100, 12, WS_TABSTOP
GROUPBOX "标题栏文字", -1, 180, 5, 125, 100, BS_GROUPBOX
COMBOBOX IDC_TITLETEXT, 190, 20, 105, 70, CBS_DROPDOWNLIST | WS_TABSTOP
LTEXT "自定义文字:", -1, 190, 40, 105, 10
EDITTEXT IDC_CUSTOMTEXT, 190, 55, 105, 12
LTEXT "请在此选择显示在标题栏上面的文字,或者选择“自定义”后自行输入", -1, 191, 73, 105, 26, WS_BORDER
CONTROL "", -1, "Static", SS_ETCHEDHORZ | WS_CHILD | WS_VISIBLE, 5, 110, 300, 1
DEFPUSHBUTTON "更换图片(&C)", IDOK, 200, 115, 50, 14
PUSHBUTTON "退出(&X)", IDCANCEL, 255, 115, 50, 14
CONTROL IDB_1, IDC_BMP, "Static", SS_BITMAP | WS_CHILD | WS_VISIBLE, 5, 5, 40, 95
SCROLLBAR IDC_SCROLL, 6, 118, 125, 10
LTEXT "0" IDC_VALUE, 138, 119, 50, 8
}
//Control.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 gdi32.inc
includelib gdi32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN equ 1000h
DLG_MAIN equ 1
IDB_1 equ 1
IDB_2 equ 2
IDC_ONTOP equ 101
IDC_SHOWBMP equ 102
IDC_ALOW equ 103
IDC_MODALFRAME equ 104
IDC_THICKFRAME equ 105
IDC_TITLETEXT equ 106
IDC_CUSTOMTEXT equ 107
IDC_BMP equ 108
IDC_SCROLL equ 109
IDC_VALUE equ 110
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstance dd ?
hBmp1 dd ?
hBmp2 dd ?
dwPos dd ?
.const
szText1 db 'Hello, World!', 0
szText2 db '嘿,你看到标题栏变了吗?', 0
szText3 db '自定义', 0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
_ProcDlgMain proc uses ebx edi esi hWnd, wMsg, wParam, lParam
local @szBuffer[128]:byte
mov eax, wMsg
.if eax == WM_CLOSE
invoke EndDialog, hWnd, NULL
invoke DeleteObject, hBmp1
invoke DeleteObject, hBmp2
.elseif eax == WM_INITDIALOG
;*******************************************************************************
; 设置标题栏图标
;*******************************************************************************
invoke LoadIcon, hInstance, ICO_MAIN
invoke SendMessage, hWnd, WM_SETICON, ICON_BIG, eax
;*******************************************************************************
; 初始化组合框
;*******************************************************************************
invoke SendDlgItemMessage, hWnd, IDC_TITLETEXT, CB_ADDSTRING, 0, addr szText1
invoke SendDlgItemMessage, hWnd, IDC_TITLETEXT, CB_ADDSTRING, 0, addr szText2
invoke SendDlgItemMessage, hWnd, IDC_TITLETEXT, CB_ADDSTRING, 0, addr szText3
invoke SendDlgItemMessage, hWnd, IDC_TITLETEXT, CB_SETCURSEL, 0, 0
invoke GetDlgItem, hWnd, IDC_CUSTOMTEXT
invoke EnableWindow, eax, FALSE
invoke LoadBitmap, hInstance, IDB_1
mov hBmp1, eax
invoke LoadBitmap, hInstance, IDB_2
mov hBmp2, eax
;*******************************************************************************
; 初始化单选钮和复选框
;*******************************************************************************
invoke CheckDlgButton, hWnd, IDC_SHOWBMP, BST_CHECKED
invoke CheckDlgButton, hWnd, IDC_ALOW, BST_CHECKED
invoke CheckDlgButton, hWnd, IDC_THICKFRAME, BST_CHECKED
;*******************************************************************************
; 初始化滚动条
;*******************************************************************************
invoke SendDlgItemMessage, hWnd, IDC_SCROLL, SBM_SETRANGE, 0, 100
;*******************************************************************************
.elseif eax == WM_COMMAND
mov eax, wParam
.if ax == IDCANCEL
invoke EndDialog, hWnd, NULL
invoke DeleteObject, hBmp1
invoke DeleteObject, hBmp2
;*******************************************************************************
; 更换图片
;*******************************************************************************
.elseif ax == IDOK
mov eax, hBmp1
xchg eax, hBmp2
mov hBmp1, eax
invoke SendDlgItemMessage, hWnd, IDC_BMP, STM_SETIMAGE, IMAGE_BITMAP, eax
;*******************************************************************************
; 设置是否“总在最前面”
;*******************************************************************************
.elseif ax == IDC_ONTOP
invoke IsDlgButtonChecked, hWnd, IDC_ONTOP
.if eax == BST_CHECKED
invoke SetWindowPos, hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE
.else
invoke SetWindowPos, hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE
.endif
;*******************************************************************************
; 演示隐藏和显示图片控件
;*******************************************************************************
.elseif ax == IDC_SHOWBMP
invoke GetDlgItem, hWnd, IDC_BMP
mov ebx, eax
invoke IsWindowVisible, ebx
.if eax
invoke ShowWindow, ebx, SW_HIDE
.else
invoke ShowWindow, ebx, SW_SHOW
.endif
;*******************************************************************************
; 演示允许和灰化“更换图片”按钮
;*******************************************************************************
.elseif ax == IDC_ALOW
invoke IsDlgButtonChecked, hWnd, IDC_ALOW
.if eax == BST_CHECKED
mov ebx, TRUE
.else
xor ebx, ebx
.endif
invoke GetDlgItem, hWnd, IDOK
invoke EnableWindow, eax, ebx
;*******************************************************************************
.elseif ax == IDC_MODALFRAME
invoke GetWindowLong, hWnd, GWL_STYLE
and eax, not WS_THICKFRAME
invoke SetWindowLong, hWnd, GWL_STYLE, eax
.elseif eax == IDC_THICKFRAME
invoke GetWindowLong, hWnd, GWL_STYLE
or eax, WS_THICKFRAME
invoke SetWindowLong, hWnd, GWL_STYLE, eax
;*******************************************************************************
; 演示处理下拉式组合框
;*******************************************************************************
.elseif ax == IDC_TITLETEXT
shr eax,16
;*******************************************************************************
.if ax == CBN_SELENDOK
invoke SendDlgItemMessage, hWnd, IDC_TITLETEXT, CB_GETCURSEL, 0, 0
.if eax == 2
invoke GetDlgItem, hWnd, IDC_CUSTOMTEXT
invoke EnableWindow, eax, TRUE
.else
mov ebx, eax
invoke SendDlgItemMessage, hWnd, IDC_TITLETEXT, CB_GETLBTEXT, ebx, addr @szBuffer
invoke SetWindowText, hWnd, addr @szBuffer
invoke GetDlgItem, hWnd, IDC_CUSTOMTEXT
invoke EnableWindow, eax, FALSE
.endif
.endif
;*******************************************************************************
; 在文本框中输入文字
;*******************************************************************************
.elseif ax == IDC_CUSTOMTEXT
invoke GetDlgItemText, hWnd, IDC_CUSTOMTEXT, addr @szBuffer, sizeof @szBuffer
invoke SetWindowText, hWnd, addr @szBuffer
.endif
;*******************************************************************************
; 处理滚动条消息
;*******************************************************************************
.elseif eax == WM_HSCROLL
mov eax, wParam
.if ax == SB_LINELEFT
dec dwPos
.elseif ax == SB_LINERIGHT
inc dwPos
.elseif ax == SB_PAGELEFT
sub dwPos, 10
.elseif ax == SB_PAGERIGHT
add dwPos, 10
.elseif ax == SB_THUMBPOSITION || ax == SB_THUMBTRACK
mov eax, wParam
shr eax,16
mov dwPos,eax
.else
mov eax,TRUE
ret
.endif
cmp dwPos, 0
jge @F
mov dwPos, 0
@@:
cmp dwPos,100
jle @F
mov dwPos,100
@@:
invoke SetDlgItemInt, hWnd, IDC_VALUE, dwPos, FALSE
invoke SendDlgItemMessage, hWnd, IDC_SCROLL, SBM_SETPOS, dwPos, TRUE
;*******************************************************************************
.else
mov eax, FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDlgMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke DialogBoxParam, hInstance, DLG_MAIN, NULL, offset _ProcDlgMain, NULL
invoke ExitProcess, NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start