用汇编编写屏幕保护程序
屏幕保护程序是什么,相信大家都用过,但对于它的结构也许就不那么熟悉了。屏幕保护程序是一种特使的 .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 ...以上是一个屏幕保护程序的框架结构,其实编写一个屏幕保护程序的大部分工作量在于 WM_TIMER 消息的处理,也就是说对动画的处理,如果就把上面的程序编译,那么你就会得到一个最简单的“黑屏”屏保。这里是我编写的一个屏保月下情人,是用 Win32Asm 编写的。
在此保存设置
... 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