用汇编编写屏幕保护程序
屏幕保护程序是什么,相信大家都用过,但对于它的结构也许就不那么熟悉了。屏幕保护程序是一种特使的 .exe 文件,实际上它是一个标准的 PE 文件,除了有扩展名 .scr,当然这个扩展名也是用连接程序产生的 .exe 文件改名得到的。但在编程中,屏幕保护程序又有它的特殊的地方,说穿了就是它的编程规范。
屏幕保护程序有以下特点:
下面是编写屏幕保护程序的要点:
综上所述,屏幕保护程序的两个部分即窗口过程和设置对话框过程是在不同的地方被执行的,所以在编程中要注意不要在两个过程中传递变量,这就意味着屏幕保护程序的设置要被输出到 .ini 或注册表中保存,在窗口过程中的 WM_CREATE 消息中再读入,因为你无法把它保留在内存中。同样窗口过程和设置对话框过程中的变量或资源的初始化也要分别进行,比如说两者都要用到同一个图片,那就在自己的 WM_CREATE 消息中分别 LoadBitmap,总之要时刻认为你是在编写两个“独立的程序”。
下面是一个屏幕保护程序的资源定义例子:
#include	<resource.h>
#define	ICO_MAIN		100
#define	DLG_SETUP		2003
ICO_MAIN	ICON		"Resource\Main.ico"
DLG_SETUP	DIALOG DISCARDABLE  0, 0, 300, 120
STYLE		DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION		"屏幕保护程序"
FONT		9, "宋体"
BEGIN
    ...
    ...
    DEFPUSHBUTTON   "确定(&O)",		IDOK,		240,10,50,14
    PUSHBUTTON      "取消(&C)",		IDCANCEL,	240,29,50,14
END
STRINGTABLE	DISCARDABLE
BEGIN
	100	"保护程序"
END
.def 文件例子:
EXPORTS
  ScreenSaverProc
  ScreenSaverConfigureDialog
  RegisterDialogClasses
源代码例子:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;	Programmed by 罗云彬, bigluo@telekbird.com.cn
;	Website: http://asm.yeah.net
;	LuoYunBin's Win32 ASM page (罗云彬的编程乐园)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;	版本信息
;	屏幕保护程序模板
;	Ver 1.0 - 2000.07.15
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
		.386
		.model flat, stdcall
		option casemap :none   ; case sensitive
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;	Include 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include		windows.inc
include		user32.inc
include		kernel32.inc
include		comctl32.inc
include		comdlg32.inc
include		gdi32.inc
include		advapi32.inc
include		shell32.inc
include		scrnsave.inc
includelib	user32.lib
includelib	kernel32.lib
includelib	comctl32.lib
includelib	comdlg32.lib
includelib	gdi32.lib
includelib	advapi32.lib
includelib	shell32.lib
includelib	scrnsave.lib
includelib	msvcrt.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;	Equ 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN	equ		100	;Must be 100
DLG_SETUP	equ		2003	;Must be 2003
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;	数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
		.data?
hInstance	dd		?
hWinMain	dd		?
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;	代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
		.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 设置对话框过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ScreenSaverConfigureDialog	proc	uses ebx edi esi, \
		hWnd:DWORD,wMsg:DWORD,wParam:DWORD,lParam:DWORD
		mov	eax,wMsg
;********************************************************************
		.elseif	eax == WM_CLOSE
			invoke	EndDialog,hWnd,NULL
;********************************************************************
		.elseif	eax == WM_COMMAND
			mov	eax,wParam
			.if	eax ==	IDOK
                ...
                在此保存设置
                ...
				invoke	EndDialog,hWnd,NULL
			.elseif eax ==	IDCANCEL
				invoke	EndDialog,hWnd,NULL
			.endif
		.else
			mov	eax,FALSE
			ret
		.endif		   
		mov	eax,TRUE
		ret
		
ScreenSaverConfigureDialog	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 主程序窗口过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ScreenSaverProc	proc	uses ebx edi esi, \
		hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
		mov	eax,uMsg
		.if	eax ==	WM_CREATE
   			invoke	GetModuleHandle,NULL
			mov	hInstance,eax
			mov	eax,hWnd
			mov	hWinMain,eax
            ...
            在此初始化,包括定义一个定时器
            ...
   			invoke	SetTimer,hWinMain,TIMER_MOON,100,NULL
		.elseif	eax ==	WM_DESTROY
			call	_Quit
;********************************************************************
		.elseif	eax ==	WM_TIMER
            ...
            在此画屏幕动画
            ...
			xor	eax,eax
			ret
;********************************************************************
;		.elseif	eax ==	WM_ERASEBKGND
;********************************************************************
; 以下黑屏的代码在 DefScreenSaverProc 中已经包括,如果自己要处理
; 屏幕,可以把它去掉。
;********************************************************************
;			invoke	GetDC,hWnd
;			mov	@hDc,eax
;			invoke	GetClientRect,hWnd,addr @stRc
;			invoke	GetStockObject,BLACK_BRUSH
;			invoke	FillRect,@hDc,addr @stRc,eax
;			invoke	ReleaseDC,hWnd,@hDc
;			xor	eax,eax
;			ret
		.endif
;********************************************************************
		invoke	DefScreenSaverProc,hWnd,uMsg,wParam,lParam
		ret
ScreenSaverProc	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 注册设置对话框窗口Class过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
RegisterDialogClasses	proc	uses ebx edi esi, hInst:DWORD
		mov	eax,TRUE
		ret
RegisterDialogClasses	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
		end	WinMain
以上是一个屏幕保护程序的框架结构,其实编写一个屏幕保护程序的大部分工作量在于 WM_TIMER 消息的处理,也就是说对动画的处理,如果就把上面的程序编译,那么你就会得到一个最简单的“黑屏”屏保。这里是我编写的一个屏保月下情人,是用 
Win32Asm 编写的。