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

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

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 5 页
字号:
WndProc proc hwnd:DWORD,message:DWORD,wParam :DWORD,lParam :DWORD
		
	LOCAL hdc 				:HDC
   LOCAL x,y			   :DWORD
	LOCAL ps  				:PAINTSTRUCT 
	LOCAL point				:POINT
	LOCAL	rect				:RECT
	LOCAL xcx,ycy,x1cx,y1cy:DWORD

	.if message == WM_SIZE
		 mov		eax,lParam	;cxBlock = LOWORD (lParam) / DIVISIONS 
		 shl		eax,16
		 shr		eax,16
		 mov		ecx,DIVISIONS
		 div		ecx
		 mov		cxBlock,eax
		
		 xor		edx,edx			 
		 mov		eax,lParam	 ;cyBlock = HIWORD (lParam) / DIVISIONS
		 shr		eax,16
 	 	 mov		ecx,DIVISIONS
		 div		ecx
		 mov		cyBlock,eax
		 mov		ebx,eax		 
		 
       ret
   .elseif message == WM_SETFOCUS
       invoke	ShowCursor,TRUE
		 ret
	.elseif message == WM_KILLFOCUS
		 invoke  ShowCursor,FALSE
		 ret
   .elseif message == WM_KEYDOWN 
       invoke  GetCursorPos,addr point
       invoke	ScreenToClient,hwnd, addr point
      
;x = max (0, min (DIVISIONS - 1, point.x / cxBlock))
;y = max (0, min (DIVISIONS - 1, point.y / cyBlock))
		 lea		esi,point
		 mov		eax,[esi]
		 mov		ecx,cxBlock
		 xor		edx,edx
		 div		ecx
		 cmp		eax,DIVISIONS - 1  
		 jl		@f
		 mov		eax,DIVISIONS - 1 
	@@:	 
		 cmp		eax,0
		 jg		@f
		 xor		eax,eax
	@@:	 
		 mov		x,eax
		 
		 mov		eax,[esi+4]
		 mov		ecx,cyBlock
		 xor		edx,edx
		 div		ecx
		 cmp		eax,DIVISIONS - 1  
		 jl		@f
		 mov		eax,DIVISIONS - 1 
	@@:	 
		 cmp		eax,0
		 jg		@f
		 xor		eax,eax
	@@:	 
		 mov		y,eax


  		 mov		eax,wParam
		 .if		eax == VK_UP
		 			dec	y
		 .elseif	eax == VK_DOWN
		 			inc	y
     	 .elseif eax == VK_LEFT
     	 			dec	x
 		 .elseif eax ==  VK_RIGHT
 		 			inc	x
 		 .elseif eax ==  VK_HOME
 		 			xor	eax,eax
 		 			mov	x,eax
 		 			mov	y,eax
 		 .elseif eax ==  VK_END
 		 			mov	eax,DIVISIONS - 1 
 		 			mov	x,eax
 		 			mov	y,eax
 		 .elseif (eax == VK_RETURN) || (eax == VK_SPACE)
 		 	;MAKELONG宏可以将两个16位的无符号数组合成一个32位的无符号数
 		 			mov	eax,xcx
 		 			shl	eax,16
 		 			add	eax,ycy
 		 			invoke SendMessage,hwnd, WM_LBUTTONDOWN, MK_LBUTTON,eax
		.endif
		 mov		eax,x
		 add		eax,DIVISIONS
		 xor		edx,edx
		 mov		ecx,DIVISIONS
		 div		ecx
		 mov		x,edx

		 mov		eax,y
		 add		eax,DIVISIONS
		 xor		edx,edx
		 mov		ecx,DIVISIONS
		 div		ecx
		 mov		y,edx		

;point.x = x * cxBlock + cxBlock / 2 
;point.y = y * cyBlock + cyBlock / 2 

		 mov		eax,x
		 mov		ecx,cxBlock
		 mul		ecx
		 mov		xcx,eax

		 mov		eax,y
		 mov		ecx,cyBlock
		 mul		ecx
		 mov		ycy,eax
		 
	 
		 lea		esi,point
		 
		 mov		eax,cxBlock
		 shr		eax,1
		 add		eax,xcx
		 mov		[esi],eax
		 
		 mov		eax,cyBlock
		 shr		eax,1
		 add		eax,ycy
		 mov		[esi+4],eax
	 ; invoke wsprintf,addr szBuffer,CTEXT("[%d] [%d]"),xcx,ycy
  ;invoke MessageBox,hwnd, addr szBuffer, NULL, NULL		 
	;ClientToScreen (hwnd, &point)
	;SetCursorPos (point.x, point.y)
		 invoke	ClientToScreen,hwnd,addr point
		 lea		esi,point
		 mov		eax,[esi]
		 mov		ebx,[esi+4]
		 invoke	SetCursorPos,eax,ebx

   .elseif message == WM_LBUTTONDOWN
   	 xor		edx,edx
		 mov		eax,lParam
		 shl		eax,16
		 shr		eax,16
		 mov		ecx,cxBlock
		 div		ecx
		 mov		x,eax
		 
		 xor		edx,edx
		 mov		eax,lParam
		 shr		eax,16
		 mov		ecx,cyBlock
		 div		ecx
		 mov		y,eax
		 
		 mov		eax,x
		 mov		ebx,y
		 lea		esi,fState
	 
		 .if		(eax<DIVISIONS)&&(ebx<DIVISIONS)
	 	
		 mov		eax,y
		 mov		ecx,DIVISIONS
		 mul		ecx
		 add		esi,eax
		 add		esi,x
		 xor		BYTE ptr [esi],1
		 
;RECT STRUCT
;  left    dd      ?
;  top     dd      ?
;  right   dd      ?
;  bottom  dd      ?
;RECT ENDS

		 lea		esi,rect
		 
		 mov		eax,x
		 mov		ecx,cxBlock
		 mul		ecx
		 mov		[esi],eax

		 mov		eax,y
		 mov		ecx,cyBlock
		 mul		ecx
		 mov		[esi+4],eax

		 mov		eax,x
		 inc		eax
		 mov		ecx,cxBlock
		 mul		ecx
		 mov		[esi+8],eax

		 mov		eax,y
		 inc		eax
		 mov		ecx,cyBlock
		 mul		ecx
		 mov		[esi+12],eax
		 
		 invoke	InvalidateRect,hwnd,addr rect,FALSE
		 .elseif
		 invoke	MessageBeep,0	
		 .endif
		 ret    	
		.elseif message == WM_PAINT
		invoke	BeginPaint,hwnd,addr ps
		mov		hdc,eax
      
		xor		eax,eax
		mov		x,eax
	Loopx:
		xor		eax,eax
		mov		y,eax
	  Loopy:
	   mov		eax,y
	   inc		eax
	   mov		ecx,cyBlock
	   mul		ecx
	   mov		y1cy,eax
	   push		eax
	   
	   mov		eax,x
	   inc		eax
	   mov		ecx,cxBlock
	   mul		ecx
	   mov		x1cx,eax
	   push		eax
	   
	   mov		eax,y
	   mov		ecx,cyBlock
	   mul		ecx
	   mov		ycy,eax
	   push		eax

	   mov		eax,x
	   mov		ecx,cxBlock
	   mul		ecx
	   mov		xcx,eax
	   push		eax
	   
	   push		hdc
		call		Rectangle
		

		lea		esi,fState
  	 	mov		eax,y
		mov		ecx,DIVISIONS
		mul		ecx
		add		esi,eax
		add		esi,x
		mov		al,[esi]
		.if		(al!=0)
	;invoke	wsprintf,addr szBuffer,CTEXT("[%d][%d][%d][%d]") ,x,y,ecx,ebx
	;invoke	MessageBox,hwnd,addr szBuffer,NULL,NULL					
			invoke	MoveToEx,hdc,xcx,ycy,NULL
			invoke	LineTo,hdc,x1cx,y1cy
			invoke	MoveToEx,hdc,xcx,y1cy,NULL
			invoke	LineTo,hdc,x1cx,ycy
		.endif
		
	  	inc		y
	  	mov		eax,y
	  	cmp		eax,DIVISIONS
	  	jb			Loopy
	  	
		inc		x
	   mov		eax,x
	   cmp		eax,DIVISIONS
	   jb			Loopx
		
      invoke	EndPaint,hwnd, addr ps
        
      ret
	.elseif message == WM_DESTROY
		invoke PostQuitMessage,NULL		
	.endif
UseDefWindowProc:
	invoke DefWindowProc,hwnd, message, wParam, lParam
	ret
WndProc endp

END START

CHECKER2中的WM_KEYDOWN的处理方式决定光标的位置(用GetCursorPos),把屏幕坐标转换为显示区域坐标(用ScreenToClient),并用矩形方块的宽度和高度来除这个坐标。这会产生指示矩形位置的x和y值(5×5数组)。当按下一个键时,鼠标光标可能在或不在显示区域中,所以x和y必须经过min和max宏处理以保证它们的范围是0到4之间。

对方向键,CHECKER2近似地增加或减少x和y。如果是Enter键或Spacebar键,那么CHECKER2使用SendMessage把WM_LBUTTONDOWN消息发送给它自身。这种技术类似于前面一章中把键盘接口加到窗口滚动条时所使用的方法。WM_KEYDOWN的处理方式是通过计算指向矩形中心的显示区域坐标,再用ClientToScreen转换成屏幕坐标,然后用SetCursorPos设定光标位置来实作的。

将子窗口用于命中测试


有些程序(例如,Windows的「画图」程序),把显示区域划分为几个小的逻辑区域。「画图」程序在其左边有一个由图示组成的工具菜单区,在底部有颜色菜单区。在这两个区做命中测试的时候,「画图」必须在使用者选中菜单项之前记住菜单的位置。

不过,也可能不需要这么做。实际上,画风经由使用子窗口简化了菜单的绘制和命中测试。子窗口把整个矩形区域划分为几个更小的矩形区,每个子窗口有自己的窗口句柄、窗口消息处理程序和显示区域,每个窗口消息处理程序接收只适用于它的子窗口的鼠标消息。鼠标消息中的lParam参数含有相当于该子窗口显示区域左上角的坐标,而不是其父窗口(那是「画图」的主应用程序窗口)显示区域左上角的坐标。

以这种方式使用子窗口有助于程序的结构化和模块化。如果子窗口使用不同的窗口类别,那么每个子窗口都有它自己的窗口消息处理程序。不同的窗口也可以定义不同的背景颜色和不同的内定光标。在第九章中,我将看到「子窗口控件」-滚动条、按钮和编辑方块等预先定义的子窗口。现在,我们说明在CHECKER程序中是如何使用子窗口的。

CHECKER中的子窗口


程序7-4所示的CHECKER3程序,这一版本建立了25个处理鼠标单击的子窗口。它没有键盘接口,但是可以按本章后面的范例的方法添加。

程序7-4 CHECKER3 

        
CHECKER3.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		"Checker3",0
	szChildClass DB	"Checker3_Child",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

⌨️ 快捷键说明

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