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

📄 026.txt

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 2 页
字号:
        invoke RegisterClassEx, addr wc 
        INVOKE CreateWindowEx,NULL,ADDR ClassName,NULL,\ 
           WS_POPUP,CW_USEDEFAULT,\ 
           CW_USEDEFAULT,250,250,NULL,NULL,\ 
           hInstance,NULL 
        mov   hwnd,eax 
        INVOKE ShowWindow, hwnd,SW_SHOWNORMAL 
        .WHILE TRUE 
                INVOKE GetMessage, ADDR msg,NULL,0,0 
                .BREAK .IF (!eax) 
                INVOKE TranslateMessage, ADDR msg 
                INVOKE DispatchMessage, ADDR msg 
        .ENDW 
        mov     eax,msg.wParam 
        ret 
ShowBitMap endp 
WndProc proc hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD 
        LOCAL ps:PAINTSTRUCT 
        LOCAL hdc:HDC 
        LOCAL hMemoryDC:HDC 
        LOCAL hOldBmp:DWORD 
        LOCAL bitmap:BITMAP 
        LOCAL DlgHeight:DWORD 
        LOCAL DlgWidth:DWORD 
        LOCAL DlgRect:RECT 
        LOCAL DesktopRect:RECT 

        .if uMsg==WM_DESTROY 
                .if hBitMap!=0 
                        invoke DeleteObject,hBitMap 
                .endif 
                invoke PostQuitMessage,NULL 
        .elseif uMsg==WM_CREATE 
                invoke GetWindowRect,hWnd,addr DlgRect 
                invoke GetDesktopWindow 
                mov ecx,eax 
                invoke GetWindowRect,ecx,addr DesktopRect 
                push  0 
                mov  eax,DlgRect.bottom 
                sub  eax,DlgRect.top 
                mov  DlgHeight,eax 
                push eax 
                mov  eax,DlgRect.right 
                sub  eax,DlgRect.left 
                mov  DlgWidth,eax 
                push eax 
                mov  eax,DesktopRect.bottom 
                sub  eax,DlgHeight 
                shr  eax,1 
                push eax 
                mov  eax,DesktopRect.right 
                sub  eax,DlgWidth 
                shr  eax,1 
                push eax 
                push hWnd 
                call MoveWindow 
                invoke LoadBitmap,hInstance,addr BitmapName 
                mov hBitMap,eax 
                invoke SetTimer,hWnd,1,2000,NULL 
                mov TimerID,eax 
        .elseif uMsg==WM_TIMER 
                invoke SendMessage,hWnd,WM_LBUTTONDOWN,NULL,NULL 
                invoke KillTimer,hWnd,TimerID 
        .elseif uMsg==WM_PAINT 
                invoke BeginPaint,hWnd,addr ps 
                mov hdc,eax 
                invoke CreateCompatibleDC,hdc 
                mov hMemoryDC,eax 
                invoke SelectObject,eax,hBitMap 
                mov hOldBmp,eax 
                invoke GetObject,hBitMap,sizeof BITMAP,addr bitmap 
                invoke StretchBlt,hdc,0,0,250,250,\ 
                       hMemoryDC,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY 
                invoke SelectObject,hMemoryDC,hOldBmp 
                invoke DeleteDC,hMemoryDC 
                invoke EndPaint,hWnd,addr ps 
        .elseif uMsg==WM_LBUTTONDOWN 
                invoke DestroyWindow,hWnd 
        .else 
                invoke DefWindowProc,hWnd,uMsg,wParam,lParam 
                ret 
        .endif 
        xor eax,eax 
        ret 
WndProc endp 

End DllEntry 

分析:
我们首先要再主程序中检验这段代码. 
 invoke LoadLibrary,addr Libname 
 .if eax!=NULL 
    invoke FreeLibrary,eax 
 .endif 
我们调用 LoadLibrary 读入名称为 "splash.dll" 的 DLL. 然后, 用 FreeLibrary 卸载. 一直到 DLL 完成初始化, LoadLibrary才会返回.
主程序的任务到此为止. 更有趣的部分再 DLL里. 
   .if reason==DLL_PROCESS_ATTACH  ; When the dll is loaded 
      push hInst 
      pop hInstance 
      call ShowBitMap 

DLL 被加载后, Windows 调用它的有 DLL_PROCESS_ATTACH 标记的入口函数. 我们借这个机会显示启动画面. 首先,我们保存 DLL 事例的句柄以供将来使用. 然后, 调用一个叫 ShowBitMap 的函数进行真正的工作. ShowBitMap 注册一个窗口, 创建这个窗口和显示它.就像我们以前创建窗口一样. 有趣的是这个 CreateWindowEx 调用: 

        INVOKE CreateWindowEx,NULL,ADDR ClassName,NULL,\ 
           WS_POPUP,CW_USEDEFAULT,\ 
           CW_USEDEFAULT,250,250,NULL,NULL,\ 
           hInstance,NULL 

注意, 这里的窗口风格仅仅使用了 WS_POPUP . 所以窗口即没有标题栏,也没有边界. 我们同时也限定窗口的宽高为 250x250个像素.
现在窗口创建好了. 在 WM_CREATE 的消息处理代码里我们把这个窗口移到屏幕的中央.代码如下: 

                invoke GetWindowRect,hWnd,addr DlgRect 
                invoke GetDesktopWindow 
                mov ecx,eax 
                invoke GetWindowRect,ecx,addr DesktopRect 
                push  0 
                mov  eax,DlgRect.bottom 
                sub  eax,DlgRect.top 
                mov  DlgHeight,eax 
                push eax 
                mov  eax,DlgRect.right 
                sub  eax,DlgRect.left 
                mov  DlgWidth,eax 
                push eax 
                mov  eax,DesktopRect.bottom 
                sub  eax,DlgHeight 
                shr  eax,1 
                push eax 
                mov  eax,DesktopRect.right 
                sub  eax,DlgWidth 
                shr  eax,1 
                push eax 
                push hWnd 
                call MoveWindow 

它先找到桌面和窗口的大小. 然后,计算出一个窗口左上角的坐标. 使这个窗口能位于屏幕中央. 

                invoke LoadBitmap,hInstance,addr BitmapName 
                mov hBitMap,eax 
                invoke SetTimer,hWnd,1,2000,NULL 
                mov TimerID,eax 

下一步,它用 LoadBitmap 从资源中读入位图并且创建一个定时器.定时器的 ID 为 1 时间间隔为 2 秒. 定时器将每 2 秒 向窗口发送 WM_TIMER 消息. 

        .elseif uMsg==WM_PAINT 
                invoke BeginPaint,hWnd,addr ps 
                mov hdc,eax 
                invoke CreateCompatibleDC,hdc 
                mov hMemoryDC,eax 
                invoke SelectObject,eax,hBitMap 
                mov hOldBmp,eax 
                invoke GetObject,hBitMap,sizeof BITMAP,addr bitmap 
                invoke StretchBlt,hdc,0,0,250,250,\ 
                       hMemoryDC,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY 
                invoke SelectObject,hMemoryDC,hOldBmp 
                invoke DeleteDC,hMemoryDC 
                invoke EndPaint,hWnd,addr ps 

当窗口收到 WM_PAINT 消息, 它创建一个内存DC(Pheadnius:还记得DC吗. 在win32编程中你会经常遇到DC这个词. 它是 Device Context 的缩写, 官方译为"设备描述表". 如果你研究过vc, 你应该对它不陌生. 不过如果你不明白它是什么也不要紧. 你可以把它看作一个句柄. 就是某个设备或某块内存的名称.),然后把位图选进内存DC. 再用 GetObject 函数获得位图的尺寸, 然后用 StretchBlt 把位图显示在窗口上. StretchBlt的作用和 BitBlt 一样,但它可以拉伸或压缩位图到我们希望的大小. 在这里我们希望位图能适合窗口的大小,所以我们 StretchBlt 代替 BitBlt. 之后我们删除内存DC. 

        .elseif uMsg==WM_LBUTTONDOWN 
                invoke DestroyWindow,hWnd 

如果你的程序的使用者每次都要看到启动画面消失才能用, 他们一定会厌烦. 我们可以为用户提供多一种选择. 当他单击启动画面, 它就会消失. 这就是为什么我们要在DLL里处理 WM_LBUTTONDOWN 消息. 收到这个消息后立即就用 DestroyWindow 关掉窗口. 

        .elseif uMsg==WM_TIMER 
                invoke SendMessage,hWnd,WM_LBUTTONDOWN,NULL,NULL 
                invoke KillTimer,hWnd,TimerID 

如果用户选择等待, 那么启动画面会在定时器到了指定的时间后消失. (在本例中, 是 2 秒). 我们可以通过处理 WM_TIMER 消息达到这一目的. 在收到这一消息后,我们可以对窗口传送 WM_LBUTTONDOWN 消息来关掉窗口. 这是为了避免代码重复. 现在, 我们不再需要这个定时器了,所以我们用 KillTimer 删除它. 
窗口关闭后,DLL 把控制权还给主程序. 


--------------------------------------------------------------------------------

⌨️ 快捷键说明

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