新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → WIN32汇编 启动画面 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 3139 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: WIN32汇编 启动画面 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 WIN32汇编 启动画面

    lpTimerFunc 处理该定时器消息的函数所在的地址.如果你用NULL作为该参数,那么定时器的消息会被送给 hWnd 参数所指定的窗口.

    SetTimer 如果成功则返回定时器的 ID 否则返回 NULL. 所以最好不要把定时器的ID设为0(Pheadnius:NULL代表0, 记得吗?).

    你可以用2种方法创建定时器:
    如果你有一个窗口并且定时器把消息传给这个窗口.那么你需要把所有的4个参数都传送给 Settimer 函数 (lpTimerFunc参数必须为NULL).
    如果你没有窗口或者你不想让窗口处理定时器的消息,那么你必须在窗口句柄中传送一个NULL.同时你要指定用于处理定时器消息的函数的地址.
    在这个例子中我们要使用第一种方法.
    当你设定的时间到了, 与定时器相连的窗口会收到 WM_TIMER 消息.例如,你指定 uElapse 的值为 1000, 你的窗口每过一秒都会收到 WM_TIMER 消息.
    等到你再也不需要这个定时器了,就用 KillTimer 来去除定时器.
    KillTimer proto hWnd:DWORD, TimerID:DWORD
    例子:
    ;-----------------------------------------------------------------------
    ; 主程序
    ;-----------------------------------------------------------------------
    .386
    .model flat,stdcall
    option casemap:none
    include \masm32\include\windows.inc
    include \masm32\include\user32.inc
    include \masm32\include\kernel32.inc
    includelib \masm32\lib\user32.lib
    includelib \masm32\lib\kernel32.lib
    WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

    .data
    ClassName db "SplashDemoWinClass",0
    AppName db "Splash Screen Example",0
    Libname db "splash.dll",0

    .data?
    hInstance HINSTANCE ?
    CommandLine LPSTR ?
    .code
    start:
    invoke LoadLibrary,addr Libname
    .if eax!=NULL
    invoke FreeLibrary,eax
    .endif
    invoke GetModuleHandle, NULL
    mov hInstance,eax
    invoke GetCommandLine
    mov CommandLine,eax
    invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
    invoke ExitProcess,eax

    WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
    LOCAL wc:WNDCLASSEX
    LOCAL msg:MSG
    LOCAL hwnd:HWND
    mov wc.cbSize,SIZEOF WNDCLASSEX
    mov wc.style, CS_HREDRAW or CS_VREDRAW
    mov wc.lpfnWndProc, OFFSET WndProc
    mov wc.cbClsExtra,NULL
    mov wc.cbWndExtra,NULL
    push hInstance
    pop wc.hInstance
    mov wc.hbrBackground,COLOR_WINDOW+1
    mov wc.lpszMenuName,NULL
    mov wc.lpszClassName,OFFSET ClassName
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov wc.hIcon,eax
    mov wc.hIconSm,eax
    invoke LoadCursor,NULL,IDC_ARROW
    mov wc.hCursor,eax
    invoke RegisterClassEx, addr wc
    INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
    WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
    CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
    hInst,NULL
    mov hwnd,eax
    invoke ShowWindow, hwnd,SW_SHOWNORMAL
    invoke UpdateWindow, hwnd
    .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
    WinMain endp

    WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    .IF uMsg==WM_DESTROY
    invoke PostQuitMessage,NULL
    .ELSE
    invoke DefWindowProc,hWnd,uMsg,wParam,lParam
    ret
    .ENDIF
    xor eax,eax
    ret
    WndProc endp
    end start

    ;--------------------------------------------------------------------
    ; 位图 DLL
    ;--------------------------------------------------------------------
    .386
    .model flat, stdcall
    include \masm32\include\windows.inc
    include \masm32\include\user32.inc
    include \masm32\include\kernel32.inc
    include \masm32\include\gdi32.inc
    includelib \masm32\lib\user32.lib
    includelib \masm32\lib\kernel32.lib
    includelib \masm32\lib\gdi32.lib
    .data
    BitmapName db "MySplashBMP",0
    ClassName db "SplashWndClass",0
    hBitMap dd 0
    TimerID dd 0

    .data
    hInstance dd ?

    .code

    DllEntry proc hInst:DWORD, reason:DWORD, reserved1:DWORD
    .if reason==DLL_PROCESS_ATTACH ; When the dll is loaded
    push hInst
    pop hInstance
    call ShowBitMap
    .endif
    mov eax,TRUE
    ret
    DllEntry Endp
    ShowBitMap proc
    LOCAL wc:WNDCLASSEX
    LOCAL msg:MSG
    LOCAL hwnd:HWND
    mov wc.cbSize,SIZEOF WNDCLASSEX
    mov wc.style, CS_HREDRAW or CS_VREDRAW
    mov wc.lpfnWndProc, OFFSET WndProc
    mov wc.cbClsExtra,NULL
    mov wc.cbWndExtra,NULL
    push hInstance
    pop wc.hInstance
    mov wc.hbrBackground,COLOR_WINDOW+1
    mov wc.lpszMenuName,NULL
    mov wc.lpszClassName,OFFSET ClassName
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov wc.hIcon,eax
    mov wc.hIconSm,0
    invoke LoadCursor,NULL,IDC_ARROW
    mov wc.hCursor,eax
    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 把控制权还给主程序.


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/8/29 11:07:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/22 23:59:30

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    62.500ms