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

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

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 4 页
字号:
	  mov	stPrevious.wSecond,ax;
	  xor	eax,eax
		ret
	.elseif message == WM_PAINT
        invoke  BeginPaint, hwnd, ADDR ps

        mov	hdc,eax	 	; Get handle to device context
 
	  	  invoke  SetIsotropic, hdc,cxClient,cyClient

	  	  invoke  DrawClock, hdc; Draw the dial
        invoke  EndPaint, hwnd, ADDR ps
        xor	eax,eax
		ret
	.elseif message == WM_DESTROY
		invoke	KillTimer,hwnd,ID_TIMER
		invoke 	PostQuitMessage,NULL		
		ret	
	.endif	
	
	invoke DefWindowProc,hwnd, message, wParam, lParam
	ret
WndProc endp

;---------------------------------------------------------------;
; This routine finds new values for cartesian coordinates X & Y	;
; when the point is rotated by theta degrees	;
;;
; Enter: DS:SI points at a data block in the calling routine	;
;;
;	  [si] (real4) contains the rotation angle in degrees	;
;	[si+4] (real4) contains the math X coordinate;
;	[si+8] (real4) contains the math Y coordinate;     	   
;	[si+12](real4) will contain the new X coordinate	;
;	[si+16](real4) will contain the new Y coordinate	;
;;
; Note: I keep the orignal coords (as opposed to updating	;
;	so that a program can reuse the same values if required	;
;; 		  		;
;	X1 =  X * cos(theta)  +  Y * sin(theta) ;
;	Y1 = -X * sin(theta)  +  Y * cos(theta)	;
; ;
; Return:  New coords are updated in callers parameter block.	;  
;---------------------------------------------------------------;

.DATA
deg2rad		real4	1.7453292E-2	; 2 * pi / 360 (conversion factor for radians)

.CODE

angle	equ	dword ptr [esi]
X_Coord	equ 	dword ptr [esi+4]
Y_Coord	equ	dword ptr [esi+8]
New_X	equ	dword ptr [esi+12]
New_Y	equ	dword ptr [esi+16]  

rotate	PROC	 

	fld	angle	; Put the rotation in degrees into st(0)

	fmul	deg2rad	; st=radians
	fsincos; st=cos,   st(1)=sin

	fld	st	; st=cos,   st(1)=cos, st(2)=sin

	fmul	X_Coord	; st=X*cos, st(1)=cos, st(2)=sin

	fxch; st=cos,   st(1)=X*cos, st(2)=sin
	fmul	Y_Coord	; st=Y*cos, st(1)=X*cos, st(2)=sin

	fxch	st(2)	; st=sin,   st(1)=X*cos, st(2)=Y*cos

	fld	st	; st=sin, st1=sin, st2=X*cos, st3=Y*cos	;now X, X, Y*sin, Y*cos, cos, sin	

	fmul	X_Coord	; X*sin, sin,   X*cos, Y*cos

	fxch; sin,   X*sin, X*cos, Y*cos
	fmul	Y_Coord	; Y*sin, X*sin, X*cos, Y*cos
	fadd	st,st(2); Y*sin + X*cos, X*sin, X*cos, Y*cos

	fstp	New_X	; X*sin, X*cos, Y*cos ; Stored new X coord
 
	fxch	st(1)	; X*cos, X*sin, Y*cos
	fstp	st	; X*sin, Y*cos  
	fsub; -X*sin +Y*cos

	fstp	New_Y	; Stored new Y coord
	
	RET

rotate	ENDP
END START

        
CLOCK屏幕显示如图8-2。


 



图8-2 CLOCK的屏幕显示
 

等方向性(isotropic)映像对于这样的应用来说是理想的,CLOCK.C中的SetIsotropic函数负责设定此模式。在呼叫SetMapMode之后,SetIsotropic将窗口范围设定为1000,并将视端口范围设定为显示区域的一半宽度和显示区域的负的一半高度。视端口原点被设定为显示区域的中心。我在第五章中讨论过,这将建立一个笛卡儿坐标系,其点(0,0)位于显示区域的中心,在所有方向上的范围都是1000。

RotatePoint函数是用到三角函数的地方,此函式的三个参数分别是一个或者多个点的数组、数组中点的个数以及以度为单位的旋转角度。函式以原点为中心按顺时针方向(这对一个时钟正合适)旋转这些点。例如,如果传给函式的点是(0,100)-即12:00的位置-而角度为90度,那么该点将被变换为(100,0)-即3:00。它使用下列公式来做到这一点:

x' = x * cos (a) + y * sin (a)
        
y' = y * cos (a) - x * sin (a)
        
RotatePoint函数在绘制时钟表面的点和表针时都是有用的,我们将马上看到这一点。

DrawClock函数绘制60个时钟表面的点,从顶部(12:00)开始,其中每个点离原点900单位,因此第一个点位于(0,900),此后的每个点按顺时针依次增加6度。这些点中的l2个直径为100个单位;其余的为33个单位。使用Ellipse函数来画点。

DrawHands函数绘制时钟的时针、分针和秒针。定义表针轮廓(当它们垂直向上时的形状)的坐标存放在一个POINT结构的数组中。根据时间,这些坐标使用RotatePoint函数进行旋转,并用Windows的Polyline函数进行显示。注意时针和分针只有当传递给DrawHands的bChange参数为TRUE时才被显示。当程序更新时钟的表针时,大多数情况下时针和分针不需要重画。

现在让我们将注意力转到窗口消息处理程序。在WM_CREATE消息处理期间,窗口消息处理程序取得目前时间并将它存放在名为dtPrevious的变量中,这个变量将在以后被用于确定时针或者分针从上次更新以来是否改变过。

第一次绘制时钟是在第一个WM_PAINT消息处理期间,这只不过是依次呼叫SetIsotropic、DrawClock和DrawHands,后者的bChange参数被设定为TRUE。

在WM_TIMER消息处理期间,WndProc首先取得新的时间并确定是否需要重新绘制时针和分针。如果需要,则使用一个白色画笔和上一次时间绘制所有的表针,从而有效地擦除它们。否则,只对秒针使用白色画笔进行擦除,然后,再使用一个黑色画笔绘制所有的表针。

以定时器进行状态报告


本章的最后一个程序是我在第五章提到过的。它是一个使用GetPixel函数的好例子。

WHATCLR (见程序8-5)显示了鼠标光标下目前图素的RGB颜色。


程序8-5 WHATCLR 

        
WHATCLR.Asm 这个程序的源程序有一点问题,不知道为什么它要在每次取点之后画上一个黑色的点,这样会导致刚开始取色是
正常的,但是时间长一些,取出来的就是黑色了。下面的程序是我修改过的。
;MASMPlus 代码模板 - 普通的 Windows 程序代码

.386
.Model Flat, StdCall
Option Casemap :None

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

includelib gdi32.lib
IncludeLib user32.lib
IncludeLib kernel32.lib
include macro.asm
	
	WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
	WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
	FindWindowSize PROTO :DWORD,:DWORD

	ID_TIMER		equ	1
	
.DATA
	szAppName   db "WhatClr",0
	fFlipFlop	BOOL		FALSE
.DATA?
	hInstance	dd ?
	cr				COLORREF	?
	crLast		COLORREF	?
	hdcScreen	HDC	?
.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
	LOCAL cxWindow,cyWindow:DWORD
	
	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
   
   lea		eax,cyWindow
   push		eax
   lea		eax,cxWindow
   push		eax
   call		FindWindowSize
   
	invoke CreateWindowEx,
					NULL,
					ADDR szAppName, ;window class name
					CTXT("What Color"), ;window caption
					WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_BORDER,	;window style
					CW_USEDEFAULT,;initial x position
					CW_USEDEFAULT,;initial y position
					cxWindow, 	;initial x size
					cyWindow,	;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

FindWindowSize proc pcxWindow:DWORD,pcyWindow:DWORD
     	LOCAL   			hdcFindWin:HDC
     	LOCAL				tm:TEXTMETRIC

		invoke	CreateIC,CTEXT("DISPLAY"),NULL,NULL,NULL
		mov		hdcFindWin,eax
		invoke   GetTextMetrics,hdcFindWin,addr tm
     	invoke	DeleteDC,hdcFindWin
;* pcxWindow = 2 * 	GetSystemMetrics (SM_CXBORDER)+12 * tm.tmAveCharWidth ;     
      invoke	GetSystemMetrics,SM_CXBORDER
      shl		eax,1
      mov		ebx,eax
      mov		eax,tm.tmAveCharWidth
      mov		ecx,12
      mul		ecx
      add		eax,ebx
      mov		edi,pcxWindow
      mov		[edi],eax
      
; * pcyWindow = 2 * 	GetSystemMetrics (SM_CYBORDER)+GetSystemMetrics (SM_CYCAPTION) + 
;                         	    2 * tm.tmHeight ;
      invoke	GetSystemMetrics,SM_CYBORDER
      shl		eax,1
      mov		ebx,eax
      invoke	GetSystemMetrics,SM_CYCAPTION
      add		ebx,eax
      mov		eax,tm.tmHeight
      shl		eax,1
      add		ebx,eax
      mov		edi,pcyWindow
      mov		[edi],ebx
		ret
FindWindowSize Endp

WndProc proc hwnd:DWORD,message:DWORD,wParam :DWORD,lParam :DWORD
	LOCAL		hdc:HDC
	LOCAL		ps	:PAINTSTRUCT
	LOCAL		pt	:POINT
	LOCAL		rc	:RECT
	LOCAL		szBuffer[16]:TCHAR
	
		.if 	  message == WM_CREATE
			invoke	CreateDC,CTEXT("DISPLAY"),NULL,NULL,NULL
			mov		hdcScreen,eax
			invoke	SetTimer,hwnd,ID_TIMER,100,NULL
		   ret   	
		.elseif	message == WM_TIMER

		invoke	GetCursorPos,addr pt
		invoke	GetPixel,hdcScreen,pt.x,pt.y
		mov		cr,eax
		
;invoke	SetPixel,hdcScreen,pt.x,pt.y,0
		mov		eax,cr
		.if	(eax!=crLast)
					mov	eax,cr
					mov	crLast,eax
					invoke	InvalidateRect,hwnd,NULL,FALSE
		.endif	
		ret
	.elseif message == WM_PAINT
		invoke	BeginPaint,hwnd,addr ps
		mov		hdc,eax
		invoke	GetClientRect,hwnd,addr rc
		
		mov		eax,cr
		and		eax,0FFh
		push		eax

		mov		eax,cr
		and		eax,0FF00h
		shr		eax,8
		push		eax

		mov		eax,cr
		and		eax,0FF0000h
		shr		eax,16
		push		eax
		
		mov		eax,CTEXT(" [ %02X %02X %02X] ")
		push		eax
		lea		eax,szBuffer
		push		eax
		call		wsprintf
		invoke	DrawText,hdc,addr szBuffer,-1,addr rc,DT_SINGLELINE or DT_CENTER or DT_VCENTER
		
		invoke	EndPaint,hwnd,addr ps
		ret
	.elseif message == WM_DESTROY
		invoke	DeleteDC,hdcScreen
		invoke	KillTimer,hwnd,ID_TIMER
		invoke 	PostQuitMessage,NULL		
		ret	
	.endif	
	
	invoke DefWindowProc,hwnd, message, wParam, lParam
	ret
WndProc endp
END START
        
                                           

                                                 程序运行结果(可惜看不到鼠标)

WHATCLR在WinMain中做了一点与以往不同的事。因为WHATCLR的窗口只需要显示十六进制RGB值那么大,所以它在CreateWindow函数中使用WS_BORDER窗口样式建立了一个不能改变大小的窗口。要计算窗口的大小,WHATCLR通过先呼叫CreateIC再呼叫GetSystemMetrics以取得用于显示的设备内容信息。计算好的窗口宽度和高度值被传递给CreateWindow。

WHATCLR的窗口消息处理程序在处理WM_CREATE消息处理期间,呼叫CreateDC建立了用于整个视讯显示的设备内容。这个设备内容在程序的生命周期内都有效。在处理WM_TIMER消息处理期间,程序取得目前鼠标光标位置的图素。在处理WM_PAINT消息处理期间显示RGB颜色。

您可能想知道,从CreateDC函数中取得的设备内容句柄是否能让您在屏幕的任意位置显示一些东西,而不光只是取得图素颜色。答案是可以的,一般而言,让一个应用程序在另一个程控的画面区域上画图是不好的,但在某些特殊情况下,这可能会非常有用。比如,有一种“桌面破坏”的小游戏,你可以使用锤子电锯等等,破坏你的桌面。不喜欢的时候,按下一个键,马上又恢复为以前的桌面。



--------------------------------------------------------------------------------
<<<上一篇  欢迎访问AoGo汇编小站:http://www.aogosoft.com/ 下一篇>>>  

⌨️ 快捷键说明

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