⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 见招拆招《windows程序设计》(八) .txt

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 5 页
字号:
	        push		eax
	        push		cyChar
	        
	        mov		eax,cxChar
	        mov		ecx,24
	        mul		ecx
	        push		eax
	        push		hdc
	        call		TextOut
        

	        ;TextOut (hdc, 24 * cxChar, cyChar, szUnd, lstrlen (szUnd)) ;
	        invoke		lstrlen,addr szUnd
	        push		eax
	        lea		eax,szUnd
	        push		eax
	        push		cyChar
	        
	        mov		eax,cxChar
	        mov		ecx,24
	        mul		ecx
	        push		eax
	        push		hdc
	        call		TextOut        
	        
	        invoke		EndPaint,hwnd, addr ps
	        
	        xor			eax,eax
	        ret
	.elseif uMsg == WM_DRAWITEM 
		  jmp			@f
	.elseif uMsg == WM_COMMAND
	@@:
		mov		ebx,cyChar
		neg		ebx
		invoke	ScrollWindow ,hwnd, 0, ebx, addr rect, addr rect
         	invoke	GetDC,hwnd
         	mov		hdc,eax

		invoke	GetStockObject, SYSTEM_FIXED_FONT
		invoke	SelectObject ,hdc, eax
         
	        mov		eax,lParam	;LOWORD (lParam)
	        and		eax,0FFFFh
	        push		eax
	        
	        mov		eax,lParam	;HIWORD (lParam)
	        shr		eax,16
	        push		eax
	        
	        mov		eax,wParam	;LOWORD (wParam)
	        and		eax,0FFFFh
	        push		eax
	        
	        mov		eax,wParam	;HIWORD (wParam)
	        shr		eax,16
	        push		eax
        
		.if		uMsg == WM_DRAWITEM
			lea	eax,szDraw
		.else
			lea	eax,szCom
		.endif	
		push	eax
		lea	eax,szFormat
		push	eax
			
		lea	eax,szBuffer
		push	eax
		call	wsprintf
		push	eax
			
		lea	eax,szBuffer
		push	eax
			
		xor	edx,edx
		mov	eax,rect.bottom
		mov	ecx,cyChar
		div	ecx
		dec	eax
		mov	ecx,cyChar
		mul	ecx
		push	eax
			
		mov	eax,cxChar
		mov	ecx,24
		mul	ecx
		push	eax
			
		push	hdc
		call	TextOut
			
         	invoke   ReleaseDC,hwnd, hdc
         	invoke   ValidateRect ,hwnd, addr rect
        
         	jmp	@f

	.elseif uMsg == WM_DESTROY
		invoke PostQuitMessage,NULL
		xor	eax,eax
		ret
	.endif
   @@:		
		invoke DefWindowProc,hwnd,uMsg,wParam,lParam
	ret
WndProc endp

END START
        
单击按钮时,按钮就给父窗口消息处理程序发送一个WM_COMMAND消息,也就是我们所熟悉的WndProc。BTNLOOK的WndProc将该消息的wParam参数和lParam参数显示在显示区域的右边,如图9-1所示。

具有BS_OWNERDRAW样式的按钮在窗口上显示为一个背景阴影,因为这种样式的按钮是由程序来负责绘制的。该按钮表示它需要由包含lParam消息参数的WM_DRAWITEM消息来绘制,而lParam消息参数是一个指向DRAWITEMSTRUCT型态结构的指针。在BTNLOOK中,这些消息也同样被显示。我将在本章的后面更详细地讨论这种拥有者绘制(owner draw)按钮。


 



图9-1 BTNLOOK的屏幕显示
 

建立子窗口


BTNLOOK定义了一个叫做button的结构,它包括了按钮窗口样式和描述性字符串,它们对应于10个按钮型态,所有按钮窗口样式都以字母「BS」开头,它表示「按钮样式」。10个按钮子窗口是在WndProc中处理WM_CREATE消息的过程中使用一个for循环建立的。CreateWindow呼叫使用下面这些参数:

Class name(类别名称)
Window text(窗口文字)

Window style(窗口样式)

x position(x位置)

y position(y位置)

Width(宽度)

Height(高度)

Parent window(父窗口)

Child window ID(子窗口ID)

Instance handle(执行实体句柄)

Extra parameters(附加参数)
 TEXT ("button")
button[i].szText

WS_CHILD | WS_VISIBLE | button[i].iStyle

cxChar

cyChar * (1 + 2 * i)

20 * xChar

7 * yChar / 4

hwnd

(HMENU) i

((LPCREATESTRUCT) lParam) -> hInstance

NULL
 

类别名称参数是预先定义的名字。窗口样式使用WS_CHILD、WS_VISIBLE以及在button结构中定义的10个按钮样式之一(BS_PUSHBUTTON、BS_DEFPUSHBUTTON等等)。窗口文字参数(对于普通窗口来说,它是显示在标题列中的文字)将在每个按钮上显示出来。我简单地使用标识按钮样式文字的x位置和y位置参数,说明子窗口左上角相对于父窗口显示区域左上角的位置。宽度和高度参数规定了每个子窗口的宽度和高度。请注意,我用的是GetDialogBaseUnits函数来获得内定字体字符的宽度和高度。这是对话框用来获得文字尺寸的函数。此函数传回一个32位的值,其中低字组表示宽度,高字组表示高度。由于GetDialogBaseUnits传回的值与从GetTextMetrics获得的值大致上相同,但GetDialogBaseUnits有时使用起来会更方便些,而且能够与对话框控件更好地保持一致。

对每个子窗口,它的子窗口ID参数应该各不相同。在处理来自子窗口的WM_COMMAND消息时,ID帮助您的窗口消息处理程序识别出相应的子窗口。注意子窗口ID是作为CreateWindow的一个参数传递的,该参数通常用于指定程序的菜单,因此子窗口ID必须被强制转换为HMENU。

CreateWindow呼叫的执行实体句柄看起来有点奇怪,但是它利用了如下的事实,亦即在处理WM_CREATE消息的过程中,lParam实际上是指向CREATESTRUCT (「建立结构」)结构的指针,该结构有一个hInstance成员。所以将lParam转换成指向CREATESTRUCT结构的一个指针,并取出hInstance。

(有些Windows程序使用名为hInst的整体变量,使窗口消息处理程序能存取WinMain中的执行实体句柄。在WinMain中,您只需在建立主窗口之前设定:

hInst = hInstance ;
        
在前几期的CHECKER3程序中,我们曾用GetWindowLong取得执行实体句柄:

GetWindowLong (hwnd, GWL_HINSTANCE)
        
这几种方法都是正确的。)

在呼叫CreateWindow之后,我们不必再为这些子窗口做任何事情,由Windows中的按钮窗口消息处理程序负责维护它们,并处理所有的重画工作(BS_OWNERDRAW样式的按钮例外,它要求程序绘制它,这些将在后面加以讨论)。在程序终止时,如果父窗口已经被清除,那么Windows将清除这些子窗口。

子窗口向父窗口发消息


当您执行BTNLOOK时,将看到在显示区域的左边会显示出不同的按钮型态。我在前面已经提到过,用鼠标单击按钮时,子窗口控件就向其父窗口发送一个WM_COMMAND消息。BTNLOOK拦截WM_COMMAND消息并显示wParam和lParam的值,它们的含义如下:

LOWORD (wParam)
HIWORD (wParam)

lParam
 子窗口ID
通知码

子窗口句柄
 

如果您正在移植16位Windows程序,那么要注意改变这些消息参数以容纳32位的句柄。

子窗口ID是在建立子窗口时传递给CreateWindow的值。在BTNLOOK中,这些ID被显示在显示区域中,并使用0到9分别标识10个按钮。子窗口句柄是Windows从CreateWindow传回的值。

通知码更详细表示了消息的含义。按钮通知码的可能值在Windows表头文件中定义如下:

表9-1
 


按钮通知码标识符
 
BN_CLICKED 0 
BN_PAINT 1 
BN_HILITE or BN_PUSHED 2 
BN_UNHILITE or BN_UNPUSHED 3 
BN_DISABLE 4 
BN_DOUBLECLICKED or BN_DBLCLK 5 
BN_SETFOCUS 6 
BN_KILLFOCUS 7 

实际上,您不会看到这些按钮值中的大多数。从1到4的通知码是用于一种叫做BS_USERBUTTON的已不再使用的按钮的(它已经由BS_OWNERDRAW和另一种不同的通知方式所替换)。通知码6到7只有当按钮样式包括标识BS_NOTIFY才发送。通知码5只对BS_RADIOBUTTON、BS_AUTORADIOBUTTON和BS_OWNERDRAW按钮发送,或者当按钮样式中包括BS_NOTIFY时,也为其它按钮发送。

您会注意到,在用鼠标单击按钮时,该按钮文字的周围会有虚线。这表示该按钮拥有了输入焦点,所有键盘输入都将传送给子窗口按钮控件,而不是传送给主窗口。但是,当该按钮控件拥有输入焦点时,它将忽略所有的键盘输入,除了Spacebar键例外,此时Spacebar键与鼠标具有相同的效果。

父窗口向子窗口发送消息


虽然BTNLOOK中没有显示这一事实,但是父窗口消息处理程序也能向子窗口控件发送消息。这些消息包括以前缀WM开头的许多消息。另外,在WINUSER.H中还定义了8个按钮说明消息;前缀BM表示「按钮消息」。这些按钮消息如下表所示:

表9-2
 


按钮消息
 
BM_GETCHECK 0x00F0 
BM_SETCHECK 0x00F1 
BM_GETSTATE 0x00F2 
BM_SETSTATE 0x00F3 
BM_SETSTYLE 0x00F4 
BM_CLICK 0x00F5 
BM_GETIMAGE 0x00F6 
BM_SETIMAGE 0x00F7 

BM_GETCHECK和BM_SETCHECK消息由父窗口发送给子窗口控件,以取得或者设定复选框和单选按钮的选中标记。BM_GETSTATE和BM_SETSTATE消息表示按钮处于正常状态还是(鼠标或Spacebar键按下时的)「按下」状态。我们将在讨论按钮的每种型态时,看到这些消息是如何起作用的。BM_SETSTYLE消息允许您在按钮建立之后改变按钮样式。

每个子窗口控件都具有一个在其兄弟中唯一的窗口句柄和ID值。对于句柄和ID这两者,知道其中的一个您就可以获得另一个。如果您知道子窗口控件的窗口句柄,那么您可以用下面的叙述来获得ID:

id = GetWindowLong (hwndChild, GWL_ID) ;
        
第七章的CHECKER序3程曾用此函数(与SetWindowLong一起)来维护注册窗口类别时保留的特殊区域的数据。在建立子窗口时,Windows保留了GWL_ID标识符存取的数据。您也可以使用:

id = GetDlgCtrlID (hwndChild) ;
        
虽然函数中的「Dlg」部分指的是对话框,但实际上这是一个通用的函数。

知道ID和父窗口句柄,您就能获得子窗口句柄:

hwndChild = GetDlgItem (hwndParent, id) ;
        
按键


在BTNLOOK中显示的前两个按钮是「压入」按钮。按钮是一个矩形,包括了CreateWindow呼叫中窗口文字参数所指定的文字。该矩形占用了在CreateWindow或者MoveWindow呼叫中给出的全部高度和宽度,而文字在矩形的中心。

按键控件主要用来触发一个立即响应的动作,而不保留任何形式的开/关指示。两种型态的按钮控件有两种窗口样式,分别叫做BS_PUSHBUTTON和BS_DEFPUSHBUTTON,BS_DEFPUSHBUTTON中的「DEF」代表「内定」。当用来设计对话框时,BS_PUSHBUTTON控件和BS_DEFPUSHBUTTON控件的作用不同。但是当用作子窗口控件时,两种型态的按钮作用相同,尽管BS_DEFPUSHBUTTON的边框要粗一些。

当按钮的高度为文字字符高度的7/4倍时,按钮的外观看起来最好,其中文字字符由BTNLOOK使用;而按钮的宽度至少调节到文字的宽度再加上两个字符的宽度。

当鼠标光标在按钮中时,按下鼠标按键将使按钮用三维阴影重画自己,就好像真的被按下一样。放开鼠标按键时,就恢复按钮的原貌,并向父窗口发送一个WM_COMMAND消息和BN_CLICKED通知码。与其它按钮型态相似,当按钮拥有输入焦点时,在文字的周围就有虚线,按下及释放Spacebar键与按下及释放鼠标按键具有相同的效果。

您可以通过给窗口发送BM_SETSTATE消息来仿真按钮闪动。以下的操作将导致按钮被按下:

SendMessage (hwndButton, BM_SETSTATE, 1, 0) ;
        
下面的呼叫使按钮恢复正常:

SendMessage (hwndButton, BM_SETSTATE, 0, 0) ;
        
hwndButton窗口句柄是从CreateWindow呼叫传回的值。

您也可以向按键发送BM_GETSTATE消息,子窗口控件传回按钮目前的状态:如果按钮被按下,则传回TRUE;如果按钮处于正常状态,则传回FALSE。但是,绝大多数应用并不需要这一消息。因为按钮不保留任何开/关信息,所以BM_SETCHECK消息和BM_GETCHECK消息不会被用到。

复选框


复选框是一个文字方块,文字通常出现在复选框的右边(如果您在建立按钮时指定了BS_LEFTTEXT样式,那么文字会出现在左边;您也许将用BS_RIGHT直接调整文字来组合此样式)。复选框通常用于允许使用者对选项进行选择的应用程序中。复选框的常用功能如同一个开关:单击框一次将显示勾选标记,再次单击清除勾选标记。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -