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

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

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 5 页
字号:
					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			   :DWORD
	LOCAL ps  				:PAINTSTRUCT 
	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_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

        

        
图7-3是CHECKER1的显示。程序画的25个矩形的宽度和高度均相同。这些宽度和高度保存在cxBlock和cyBlock中,当显示区域大小发生改变时,将重新对这些值进行计算。WM_LBUTTONDOWN处理过程使用鼠标坐标来确定在哪个矩形中按下了键,它在fState数组中标志目前矩形的状态,并使该矩形区域失效,从而产生WM_PAINT消息。


 



图7-3 CHECKER1的屏幕显示
 

如果显示区域的宽度和高度不能被5整除,那么在显示区域的左边和下边将有一小条区域不能被矩形所覆盖。对于错误情况,CHECKER1通过呼叫MessageBeep响应此区域中的鼠标按键操作。

当CHECKER1收到WM_PAINT消息时,它通过GDI的Rectangle函数来重新绘制显示区域。如果设定了fState值,那么CHECKER1将使用MoveToEx和LineTo函数来绘制两条直线。在处理WM_PAINT期间,CHECKER1在重新绘制之前并不检查每个矩形区域的有效性,尽管它可以这样做。检查有效性的一种方法是在循环中为每个矩形块建立RECT结构(使用与WM_LBUTTONDOWN处理程序中相同的公式),并使用IntersectRect函数检查它是否与无效矩形(ps.rcPaint)相交。

使用键盘仿真鼠标


CHECKER1只能在装有鼠标情况下才可执行。下面我们在程序中加入键盘接口,就如同前面章节中对SYSMETS程序所做的那样。不过,即使在一个使用鼠标光标作为指向用途的程序中加入键盘接口,我们还是必须处理鼠标光标的移动和显示问题。

即使没有安装鼠标,Windows仍然可以显示一个鼠标光标。Windows为这个光标保存了一个「显示计数」。如果安装了鼠标,显示计数会被初始化为0;否则,显示计数会被初始化为-1。只有在显示计数非负时才显示鼠标光标。要增加显示计数,您可以呼叫:

ShowCursor (TRUE) ;
        
要减少显示计数,可以呼叫:

ShowCursor (FALSE) ;
        
您在使用ShowCursor之前,不需要确定是否安装了鼠标。如果您想显示鼠标光标,而不管鼠标存在与否,那么只需呼叫ShowCursor来增加显示计数。增加一次显示计数之后,如果没有安装鼠标则减少它以隐藏光标,如果安装了鼠标,则保留其显示。

即使没有安装鼠标,Windows也保留了鼠标目前的位置。如果没有安装鼠标,而您又显示鼠标光标,光标就可能出现在显示器的任意位置,直到您确实移动了它。要获得光标的位置,可以呼叫:

GetCursorPos (&pt) ;
        
其中pt是POINT结构。函数使用鼠标的x和y坐标来填入POINT字段。要设定光标位置,可以使用:

SetCursorPos (x, y) ;
        
在这两种情况下,x和y都是屏幕坐标,而不是显示区域坐标(这是很明显的,因为这些函数没有要求hwnd参数)。前面已经提到过,呼叫ScreenToClient和ClientToScreen就能做到屏幕坐标与客户坐标的相互转换。

如果您在处理鼠标消息并转换显示区域坐标时呼叫GetCursorPos ,这些坐标可能与鼠标消息的lParam参数中的坐标稍微有些不同。从GetCursorPos传回的坐标表示鼠标目前的位置。lParam中的坐标则是产生消息时鼠标的位置。

您或许想写一个键盘处理程序:使用键盘方向键来移动鼠标光标,使用Spacebar和Enter键来仿真鼠标按键。您肯定不希望每次按键只是将鼠标光标移动一个图素,如果这样做,当要把鼠标光标从显示器的一边移动到另一边时,会使用者在很长一段时间内都要按住同一个方向键。

如果您需要实作鼠标光标的键盘接口,并保持光标的精确定位能力,那么您可以采用下面的方式来处理按键消息:当按下方向键时,一开始鼠标光标移动较慢,但随后会加快。您也许还记得WM_KEYDOWN消息中的lParam参数标志着按键消息是否是重复活动的结果,这就是此参数的一个重要应用。

在CHECKER中加入键盘接口


程序7-3所示的CHECKER2程序,除了包括键盘接口外,和CHECKER1是一样的,您可以使用左、右、上和下方向键在25个矩形之间移动光标。Home键把光标移动到矩形的左上角, End键把光标移动到矩形的右下角。Spacebar和Enter键都能切换X标记。

程序7-3 CHECKER2 

        
CHECKER2.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		"Checker2",0
.DATA?
	hInstance	DD		?
	fState		DB		DIVISIONS*DIVISIONS dup (?)
	cxBlock		DD		?
	cyBlock 		DD		?

	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
        
	invoke CreateWindowEx,
					NULL,
					ADDR szAppName, 	;window class name
					CTXT("Checker2 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

⌨️ 快捷键说明

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