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

📄 见招拆招windows程序设计(六) .txt

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 5 页
字号:
	mov wndclass.cbWndExtra,0
	
	push hInst
	pop wndclass.hInstance
	
	invoke LoadIcon,NULL,IDI_APPLICATION
	mov wndclass.hIcon,eax	
	
	invoke LoadCursor,NULL,IDC_ARROW
	mov wndclass.hCursor,eax	
	
	invoke GetStockObject,WHITE_BRUSH
	mov wndclass.hbrBackground,EAX
	
	mov wndclass.lpszMenuName,NULL
	mov wndclass.lpszClassName,offset szAppName

	mov wndclass.hIconSm,0
	
	invoke RegisterClassEx, ADDR wndclass
	.if (EAX==0)
		 invoke MessageBox,NULL,CTXT("This program requires Windows NT!"),addr szAppName,MB_ICONERROR 		
		 ret
	.endif

   mov wndclass.lpfnWndProc,offset ChildWndProc    
   mov wndclass.cbWndExtra,sizeof (LONG) 
   mov wndclass.hIcon,NULL
	mov wndclass.lpszClassName,offset szChildClass
	invoke RegisterClassEx, ADDR wndclass

	invoke CreateWindowEx,
					NULL,
					ADDR szAppName, 	;window class name
					CTXT("Checker3 Mouse Hit-Test Demo"), ;window caption
					WS_OVERLAPPEDWINDOW,	;window style
					CW_USEDEFAULT,	;initial x position
					CW_USEDEFAULT,	;initial y position
					CW_USEDEFAULT, 	;initial x size
					CW_USEDEFAULT,	;initial y size
					NULL,	;parent window handle
					NULL,	;window menu handle
					hInstance,	;program instance handle
					NULL	;creation parameters
	mov hWnd,eax
	
	invoke ShowWindow,hWnd,iCmdShow
	invoke UpdateWindow,hWnd
	

	StartLoop:
		invoke GetMessage,ADDR msg,NULL,0,0
			cmp eax, 0
			je ExitLoop
				invoke TranslateMessage, ADDR msg
				invoke DispatchMessage,  ADDR msg
			jmp StartLoop
	ExitLoop:
	
	mov eax,msg.wParam
	ret
WinMain endp

WndProc proc hwnd:DWORD,message:DWORD,wParam :DWORD,lParam :DWORD
		
	LOCAL hdc 				:HDC
   LOCAL x,y,cxBlock,cyBlock :DWORD
	LOCAL xcx,ycy:DWORD   
	.if	  message == WM_CREATE

     	 lea		esi,hwndChild
       xor		eax,eax
       mov		x,eax
     loop1x:
     	 xor		eax,eax
     	 mov		y,eax
     	loop1y:
     	 invoke	GetWindowLong,hwnd,GWL_HINSTANCE
     	 mov		ecx,eax
	;invoke	wsprintf,addr szBuffer,CTXT("%d"),sizeof (LONG) 
	;invoke	MessageBox,hwnd,addr szBuffer,NULL,NULL	     	 
     	 mov		ebx,y
     	 shl		ebx,8
     	 or		ebx,x
		 invoke	CreateWindowEx,NULL,offset szChildClass,NULL,
		 				WS_CHILDWINDOW or WS_VISIBLE,
		 				0, 0, 0, 0,
		 				hwnd,ebx,ecx,NULL
		 mov		[esi],eax
		 add		esi,4
	 
     	 inc		y
     	 mov		eax,y
     	 cmp		eax,DIVISIONS
     	 jb		loop1y
     	 
     	 inc		x
     	 mov		eax,x
     	 cmp		eax,DIVISIONS
     	 jb		loop1x
		     	 
		 ret
	.elseif message == WM_SIZE
		 mov		eax,lParam	;cxBlock = LOWORD (lParam) / DIVISIONS 
		 shl		eax,16
		 shr		eax,16
		 mov		ecx,DIVISIONS
		 xor		edx,edx
		 div		ecx
		 mov		cxBlock,eax
		
		 mov		eax,lParam	 ;cyBlock = HIWORD (lParam) / DIVISIONS
		 shr		eax,16
 	 	 mov		ecx,DIVISIONS
 	 	 xor		edx,edx
		 div		ecx
		 mov		cyBlock,eax

		 lea		esi,hwndChild                                                   
       xor		eax,eax
       mov		x,eax
     loop2x:
     	 xor		eax,eax
     	 mov		y,eax
     	loop2y:
		 mov		eax,x
		 mov		ecx,cxBlock
		 mul		ecx
		 mov		xcx,eax
		 
		 mov		eax,y
		 mov		ecx,cyBlock
		 mul		ecx
		 mov		ycy,eax
;MoveWindow (  hwndChild[x][y],x * cxBlock, y * cyBlock,cxBlock, cyBlock, TRUE)		 
		 invoke	MoveWindow,[esi],xcx,ycy,cxBlock,cyBlock,TRUE

		 ;mov		[esi],eax
		 add		esi,4
		 
     	 inc		y
     	 mov		eax,y
     	 cmp		eax,DIVISIONS
     	 jb		loop2y
     	 
     	 
     	 inc		x
     	 mov		eax,x
     	 cmp		eax,DIVISIONS
     	 jb		loop2x
     	 
       ret

   .elseif message == WM_LBUTTONDOWN
       invoke	MessageBeep,0 
      ret
	.elseif message == WM_DESTROY
		invoke PostQuitMessage,NULL		
		ret
	.endif

	invoke DefWindowProc,hwnd, message, wParam, lParam
	ret
WndProc endp

ChildWndProc proc hwnd:DWORD,message:DWORD,wParam :DWORD,lParam :DWORD
	LOCAL hdc 				:HDC
	LOCAL ps  				:PAINTSTRUCT 
	LOCAL	rect				:RECT	
	.if	  message == WM_CREATE
      invoke	SetWindowLong,hwnd, 0, 0      ; on/off flag
      ret
   .elseif message == WM_LBUTTONDOWN
   	invoke	GetWindowLong,hwnd,0
   	xor		eax,1
      invoke	SetWindowLong ,hwnd, 0, eax
      invoke   InvalidateRect,hwnd, NULL, FALSE
		ret
	
		.elseif message == WM_PAINT
		invoke	BeginPaint,hwnd,addr ps
		mov		hdc,eax
      invoke    GetClientRect,hwnd, addr rect
      lea		esi,rect
      mov		eax,[esi+8]
      mov		ebx,[esi+12]
      invoke 	 Rectangle,hdc, 0, 0, eax,ebx
		
		invoke	GetWindowLong,hwnd,0
		.if	eax != 0
      	lea		esi,rect			                                      
			invoke	MoveToEx,hdc,0,0,NULL
			mov		ebx,[esi+8]	;Right
			mov		ecx,[esi+12];Buttom
			invoke	LineTo,hdc,ebx,ecx
			mov		ecx,[esi+12];Buttom			
			invoke	MoveToEx,hdc,0,ecx,NULL
			invoke	LineTo,hdc,ebx,0
		.endif	
		invoke	  EndPaint,hwnd,addr ps
		ret
	.endif
	invoke	DefWindowProc,hwnd, message, wParam, lParam
	ret
ChildWndProc endp
END START
        
CHECKER3有两个窗口消息处理程序WndProc和ChildWndProc。WndProc还是主(或父)窗口的窗口消息处理程序。ChildWndProc是针对25个子窗口的窗口消息处理程序。这两个窗口消息处理程序都必须定义为CALLBACK函数。

因为窗口消息处理程序与特定的窗口类别结构相关联,该窗口类别结构由Windows呼叫RegisterClass函数来注册,CHECKER3需要两个窗口类别。第一个窗口类别用于主窗口,名为「Checker3」。第二个窗口类别名为「Checker3_Child」。当然,您不必选择像这样有意义的名字。

CHECKER3在WinMain函数中注册了这两个窗口类别。注册完常规的窗口类别之后,CHECKER3只是简单地重新使用wndclass结构中的大多数的字段来注册Checker3_Child类别。无论如何,有四个字段根据子窗口类别而设定为不同的值: 

pfnWndProc字段设定为ChildWndProc,子窗口类别的窗口消息处理程序。
  
cbWndExtra字段设定为4字节,或者更确切地用sizeof (long)。该字段告诉Windows在其为依据此窗口类别的窗口保留的内部结构中,预留了4字节额外的空间。您能使用此空间来保存每个窗口的可能有所不同的信息。
  
因为像CHECKER3中的子窗口不需要图标,所以hIcon字段设定为NULL 。
  
pszClassName字段设定为「Checker3_Child」,是类别的名称。
  
通常,在WinMain中,CreateWindow呼叫建立依据Checker3类别的主窗口。然而,当WndProc收到WM_CREATE消息后,它呼叫CreateWindow 25次以建立25个Checker3_Child类别的子窗口。表7-3是在WinMain中CreateWindow呼叫的参数,与在建立25个子窗口的WndProc中CreateWindow呼叫的参数间的比较。

表7-3
 


参数
 主窗口
 子窗口
 
窗口类别 「Checker3」 「Checker3_Child」 
窗口标题 「Checker3...」 NULL 
窗口样式 WS_OVERLAPPEDWINDOW WS_CHILDWINDOW | WS_VISIBLE 
水平位置 CW_USEDEFAULT 0 
垂直位置 CW_USEDEFAULT 0 
宽度 CW_USEDEFAULT 0 
高度 CW_USEDEFAULT 0 
父窗口句柄 NULL hwnd 
菜单句柄/子ID NULL (HMENU) (y << 8 | x) 
执行实体句柄 hInstance (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE) 
额外参数 NULL NULL 

一般情况下,子窗口要求有关位置和大小的参数,但是在CHECKER3中的子窗口由WndProc确定位置和大小。对于主窗口,因为它本身就是父窗口,所以它的父窗口句柄是NULL。当使用CreateWindow呼叫来建立一个子窗口时,就需要父窗口句柄了。

主窗口没有菜单,因此参数是NULL。对于子窗口,相同位置的参数称为子ID(或子窗口ID)。这是唯一代表子窗口的数字。在处理对话框的子窗口控件时,子ID显得更为重要。对于CHECKER3来说,我只是简单地将子ID设定为一个数值,该数值是每个子窗口在5×5的主窗口中的x和y位置的组合。

CreateWindow函数需要一个执行实体句柄。在WinMain中,执行实体句柄可以很容易地取得,因为它是WinMain的一个参数。在建立子窗口时, CHECKER3必须用GetWindowLong来从Windows为窗口保留的结构中取得hInstance值(相对于GetWindowLong,我也能将hInstance的值保存到整体变量,并直接使用它)。

每一个子窗口都在hwndChild数组中保存了不同的窗口句柄。当WndProc接收到一个WM_SIZE消息后,它将为这25个子窗口呼叫MoveWindow。MoveWindow的参数表示子窗口左上角相对于父窗口显示区域的坐标、子窗口的宽度和高度以及子窗口是否需要重画。

现在让我们看一下ChildWndProc。此窗口消息处理程序为所有这25个子窗口处理消息。ChildWndProc的hwnd参数是子窗口接收消息的句柄。当ChildWndProc处理WM_CREATE消息时(因为有25个子窗口,所以要发生25次),它用SetWindowWord在窗口结构保留的额外区域中储存一个0值(通过在定义窗口类别时使用的cbWndExtra来保留的空间)。ChildWndProc用此值来恢复目前矩形的状态(有X或没有X)。在子窗口中单击时,WM_LBUTTONDOWN处理例程简单地修改这个整数值(从0到1,或从1到0),并使整个子窗口无效。此区域是被单击的矩形。WM_PAINT的处理很简单,因为它所绘制的矩形与显示区域一样大。

因为CHECKER3的C原始码文件和.EXE文件比CHECKER1的大(更不用说程序的说明了),我不会试着告诉你说CHECKER3比CHECKER1更简单。但请注意,我们没有做任何的鼠标命中测试!我们所要的,就是知道CHECKER3中是否有个子窗口得到了命中窗口的WM_LBUTTONDOWN消息。

子窗口和键盘

为CHECKER3添加键盘接口就像CHECKER系列构想中的最后一步。但在这样做的时候,可能有更适当的做法。在CHECKER2中,鼠标光标的位置决定按下Spacebar键时哪个区域将获得标记符号。当我们处理子窗口时,我们能从对话框功能中获得提示。在对话框中,带有闪烁的插入符号或点划的矩形的子窗口表示它有输入焦点(当然也可以用键盘进行定位)。

我们不需要把Windows内部已有的对话框处理方式重新写过,我只是要告诉您大致上应该如何在应用程序中仿真对话框。研究过程中,您会发现这样一件事:父窗口和子窗口可能要共享同键盘消息处理。按下Spacebar键和Enter键时,子窗口将锁定复选标记。按下方向键时,父窗口将在子窗口之间移动输入焦点。实际上,当您在子窗口上单击时,情况会有些复杂,这时是父窗口而不是子窗口获得输入焦点。

CHECKER4.C如程序7-5所示。


程序7-5 CHECKER4 

        
CHECKER4.ASM

;MASMPlus 代码模板 - 普通的 Windows 程序代码

.386
.Model Flat, StdCall
Option Casemap :None

Include windows.inc
Include user32.inc
Include kernel32.inc
Include gdi32.inc
Include libc.inc

includelib gdi32.lib
IncludeLib user32.lib
IncludeLib kernel32.lib
IncludeLib msvcrt.lib
include macro.asm
	
	WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
	WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
	
DIVISIONS equ	5

.DATA
	szAppName	DB		"Checker4",0
	szChildClass DB	"Checker4_Child",0
	idFocus 		DD		0
.DATA?
	hInstance	DD		?
	hwndChild	DD		DIVISIONS*DIVISIONS dup (?)
	

	szBuffer		db		100 dup (?)

.CODE

START:   ;从这里开始执行
	invoke   GetModuleHandle,NULL
	mov 		hInstance,eax
	invoke   WinMain,hInstance,NULL,NULL,SW_SHOWDEFAULT
	invoke   ExitProcess,0

WinMain proc hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,iCmdShow:DWORD
	LOCAL wndclass :WNDCLASSEX
	LOCAL msg  		:MSG
	local hWnd 		:HWND
	mov wndclass.cbSize,sizeof WNDCLASSEX	
	mov wndclass.style,CS_HREDRAW or CS_VREDRAW	
	mov wndclass.lpfnWndProc,offset WndProc

	mov wndclass.cbClsExtra,0
	mov wndclass.cbWndExtra,0
	
	push hInst
	pop wndclass.hInstance
	
	invoke LoadIcon,NULL,IDI_APPLICATION
	mov wndclass.hIcon,eax	
	
	invoke LoadCursor,NULL,IDC_ARROW
	mov wndclass.hCursor,eax	
	
	invoke GetStockObject,WHITE_BRUSH
	mov wndclass.hbrBackground,EAX
	
	mov wndclass.lpszMenuName,NULL
	mov wndclass.lpszClassName,offset szAppName

	mov wndclass.hIconSm,0
	
	invoke RegisterClassEx, ADDR wndclass
	.if (EAX==0)
		 invoke MessageBox,NULL,CTXT("This program requires Windows NT!"),addr szAppName,MB_ICONERROR 		
		 ret
	.endif

   mov wndclass.lpfnWndProc,offset ChildWndProc    
   mov wndclass.cbWndExtra,sizeof (LONG) 
   mov wndclass.hIcon,NULL
	mov wndclass.lpszClassName,offset szChildClass
	invoke RegisterClassEx, ADDR wndclass

	invoke CreateWindowEx,
					NULL,
					ADDR szAppName, 	;window class name
					CTXT("Checker3 Mouse Hit-Test Demo"), ;windo

⌨️ 快捷键说明

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