| 站点地图 | 联系我
| www.asm32.net | 2006版 | 资料中心 | linux | asm/asm32 | C/C++ | VC++ | java | 书签 | ASP.Net书签 | 上善若水 厚德载物
 现在位置 :: 主页 >> 资料中心 >> ROOT / CODE / ASM/ASM32 / Win32汇编编程 /
 

[资料 from asm.yeah.net] 用汇编编写屏幕保护程序

来源(Iczelion 的 Win32asm 教程)

[资料 from asm.yeah.net] 用汇编编写屏幕保护程序

作者:罗云彬·发布日期:2000-8-8·阅读次数:13243

Win32汇编编程

屏幕保护程序是什么,相信大家都用过,但对于它的结构也许就不那么熟悉了。屏幕保护程序是一种特使的 .exe 文件,实际上它是一个标准的 PE 文件,除了有扩展名 .scr,当然这个扩展名也是用连接程序产生的 .exe 文件改名得到的。但在编程中,屏幕保护程序又有它的特殊的地方,说穿了就是它的编程规范。

屏幕保护程序有以下特点:

1.屏幕保护程序是Win32 API 支持一种特殊的应用程序并由系统自动激活。其机制是当条件满足时,系统向当前活动窗口发出字参数 wParam 值为 SC_SCREENSAVE 的 WM_SYSCOMMAND 消息,然后由当前活动窗口执行 SYSTEM.INI 文件中 [boot] 区指定的屏幕保护程序。
2.屏幕保护程序激活的条件是:在规定时间内没有鼠标或键盘输入、当前的活动窗口是标准的 WINDOWS 应用程序。因为非 WINDOWS 应用,不会理睬 WM_SYSCOMMAND 消息。显然,如果当前活动的程序接管了字参数 wParam 值为 SC_SCREENSAVE 的 WM_SYSCOMMAND 消息并且不传递到 DefWindowProc 函数就可以禁止屏幕保护程序。这对某些运行中不愿意被打断的程序如视频播放,光盘刻录程序特别有用。
3.可以在控制面板的显示器中选择需要的屏幕保护程序,并可以配置屏幕保护程序的参数。配置的对话框由屏幕保护程序提供。

下面是编写屏幕保护程序的要点:

屏幕保护程序的编写由静态链接库 SCRNSAVE.LIB 支持,它包含了建立屏幕保护程序的主程序和缺省功能,如建立一个缺省的大小为全屏幕的窗口供用户使用,并提供缺省的消息处理程序,它对下面消息的缺省处理是:

WM_SETCURSOR -- 将光标设置为无
WM_PAINT -- 画屏幕背景
WM_LBUTTONDOWN、WM_MBUTTONDOWN、WM_RBUTTONDOWN、WM_KEYDOWN、WM_MOUSEMOVE -- 终止执行
WM_ACTIVATE -- 如果 wParam 是 FALSE,则终止执行

程序的入口代码已经包括在 scrnsave.lib 中,名称为 WinMain,所以程序尾包括 end WinMain 即可。
用户只需编写三个基本函数必须名为 ScreenSaverConfigureDialog、ScreenSaverProc 和 RegisterDialogClasses,这 3 个函数必须在.DEF 文件中指定 export

1.ScreenSaverProc - 主过程,也就是自动建立的主窗口的窗口过程,所有对屏幕的处理就是由它完成的。可以把未处理的消息传递到 DefScreenSaverProc函数,由系统处理上面说到的缺省处理。缺省 DefScreenSaverProc 过程处理 WM_LBUTTONDOWN、WM_MBUTTONDOWN ; WM_RBUTTONDOWN、WM_KEYDOWN、WM_MOUSEMOVE 消息并结束程序,如果在这些消息时不想退出,可以自行处理,不要传递到 DefScreenSaverProc。

2.ScreenSaverConfigureDialog - 处理屏幕保护程序配置对话框过程,这个过程并不是由主程序调用的,而是由控制面板的显示器设置程序调用。用户输入的配置数据应该输出到.INI 或注册表中。

3.RegisterDialogClasses - 登记屏幕保护程序配置对话框的窗口类,如果使用标准的对话框,可以简单地返回 TRUE。

在 ScreenSaverProc 窗口过程中,有个专用消息 WM_ERASEBKGND -- 可以在这时擦除背景,如果把这个消息传到 DefScreenSaverProc,会得到一个全黑的背景。

使用时必须将编译完成的 .exe 文件改名为 .scr 文件,然后拷贝到 Windows 或 Windows\System 目录下。

为使控制面板能够识别,屏幕保护程序的图标(ICON)在资源文件中必须定义为 100,资源文件中必须包含一描述字符串。该字符串用于控制面板显示屏幕保护程序的名字。它必须位于字符串表的首位,ID 为 100。资源文件中屏幕保护程序配置对话框的 ID 必须为2003。
综上所述,屏幕保护程序的两个部分即窗口过程和设置对话框过程是在不同的地方被执行的,所以在编程中要注意不要在两个过程中传递变量,这就意味着屏幕保护程序的设置要被输出到 .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 消息的处理,也就是说对动画的处理,如果就把上面的程序编译,那么你就会得到一个最简单的“黑屏”屏保。

Link: http://www.asm32.net/article_details.aspx?id=2620


浏览次数 317 发布时间 2007/2/22 23:27:41 从属分类 Win32汇编编程 【评论】【 】【打印】【关闭
 
| www.asm32.net | 2006版 | 资料中心 | linux | asm/asm32 | C/C++ | VC++ | java | 书签 | ASP.Net书签 | 京ICP备09029108号-1