现在的位置: 首页 > 综合 > 正文

Win32汇编–通用控件 Progress Bar 的使用

2018年06月06日 ⁄ 综合 ⁄ 共 5648字 ⁄ 字号 评论关闭

  这几天在学通用控件的时候遇到了一些小问题,经过一段时间的折腾终于把这部分给搞定了~

  网络上对win32汇编中Progress Bar的使用没有什么特别详细的教程或者说明,虽然Progress Bar也是通用控件的一种,而对于通用控件而言使用方法也基本一致,但是对于特定的控件在使用方法上还是有一些细微的差别,于是本文将以Progress Bar为实例详细的介绍其使用方法。

  本文实例实现功能很简单:窗口中有一个进度条,进度条满了之后自动退出窗口。

   

  使用Progress Bar的一般步骤如下:

  1.调用InitCommonControls 函数进行一些初始化工作(调用该函数仅仅是为了在我们程序的可执行文件的PE头中的引入段中放入引用了comctl32.dll的信息),当然还得引入相应的头文件    comctl32.inc 、    comctl32.lib

  2.用常规方式创建父窗口--(RegisterClassEx-->CreateWindowEx-->ShowWindow-->UpdateWindow-->消息循环-->窗口过程)

  3.窗口过程中要实现以下步骤:(1)在消息WM_CREATE中创建通用控件Progress Bar、用SetTimer设置定时器。(2)在消息WM_TIMER中处理定时器发送的消息。(3)在消息WM_CLOSE中退出定时器

下面是源代码:

  .386
 .model flat,stdcall
 option casemap:none
  
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  
; Include 文件定义
  
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  
include         windows.inc
include         gdi32.inc
includelib      gdi32.lib
include         user32.inc
includelib      user32.lib
include         kernel32.inc
includelib      kernel32.lib
include        comctl32.inc
includelib     comctl32.lib
  
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  
; 数据段
  
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  
 .data?
hInstance       dd      ?
hWinMain        dd      ?
hProgressB   dd ?
TimerID  dd ?
CurrentStep  dd ? 
 
 
 .const
szClassName     db      'MyClass',0
progressBClassName db 'msctls_progress32',0
ID_TIMER equ 1
ID_PROGRESSBAR equ 2
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  
; 代码段
  
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  
 .code
  
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  
; 窗口过程
  
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  
_ProcWinMain    proc uses ebx edi esi, hWnd, uMsg, wParam, lParam
  
                local @stPs:PAINTSTRUCT
                local @stRect:RECT
                local @hDc
 
                mov eax,uMsg
  
;*************************************************************************
                .if eax==WM_CREATE
                
                      invoke     CreateWindowEx, WS_EX_CLIENTEDGE, \
  
                        offset progressBClassName, NULL, \
                        LVS_REPORT or WS_CHILD or WS_VISIBLE or WS_BORDER, \               ;通用窗口必须有WS_CHILD属性
                        150, 150, 250, 25, \
                        hWnd,  ID_PROGRESSBAR, hInstance, NULL   ;要传hWnd不能传hWinMain
                        
                        mov hProgressB,eax
                        
                        mov eax,100              ; the lParam of PBM_SETRANGE message contains the range 
                        mov CurrentStep,eax 
                        shl eax,16                   ; the high range is in the high word 
                       invoke SendMessage,hProgressB,PBM_SETRANGE,0,eax         ;lParam的高16位才是最大值!!

                    ;   invoke SendMessage,hProgressB,PBM_SETRANGE,0,100    ;设置范围  最小值和最大值(这样是错误的!)   
                       
                       invoke SendMessage,hProgressB,PBM_SETSTEP,10,0         ;设置步长,后一个一定要设为0
                       
                       invoke SetTimer, hWnd,0,1000,NULL     ;要用hWnd
                        mov TimerID,eax 

                       
                       
                .elseif    eax==WM_TIMER
                
                       invoke SendMessage,hProgressB,PBM_STEPIT,0,0   ;两参数都为0 return previous position
                       sub CurrentStep,10
                       
                       .if  CurrentStep==0
                         invoke PostMessage,hWnd,WM_CLOSE,NULL,NULL
                       .endif
                	
                
                .elseif     eax == WM_PAINT
  
                        invoke     BeginPaint,hWnd,addr @stPs
                        mov     @hDc,eax
   
                        invoke GetClientRect,hWnd,addr @stRect
                        invoke    DrawText,@hDc,NULL,-1, 
                        addr @stRect, 
                        DT_SINGLELINE or DT_CENTER or DT_VCENTER
                        invoke     EndPaint, hWnd, addr @stPs
  
;***************************************************************************
  
                .elseif eax == WM_CLOSE
  
                        invoke     DestroyWindow,hWinMain
                        invoke     PostQuitMessage,NULL
                        invoke KillTimer,hWnd,TimerID
  
;***************************************************************************
  
                .else
  
                        invoke     DefWindowProc,hWnd,uMsg,wParam,lParam
                        ret
  
                .endif
  
;***************************************************************************
  
                xor     eax,eax
                ret
  
_ProcWinMain    endp
  
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  
_WinMain        proc
  
                local   @stWndClass:WNDCLASSEX
                local   @stMsg:MSG
                invoke     GetModuleHandle,NULL
                mov     hInstance,eax
                invoke     RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
  
;**************************************************************************
  
; 注册窗口类
  
;**************************************************************************
  
                invoke     LoadCursor,0,IDC_ARROW
                mov     @stWndClass.hCursor,eax
                push    hInstance
                pop     @stWndClass.hInstance
                mov     @stWndClass.cbSize, sizeof WNDCLASSEX
                mov     @stWndClass.style, CS_HREDRAW or CS_VREDRAW
                mov     @stWndClass.lpfnWndProc, offset _ProcWinMain
                mov     @stWndClass.hbrBackground,COLOR_WINDOW + 1
                mov     @stWndClass.lpszClassName, offset szClassName
                invoke     RegisterClassEx, addr @stWndClass
  
;***************************************************************************
  
; 建立并显示窗口
  
;***************************************************************************
  
                invoke     CreateWindowEx, WS_EX_CLIENTEDGE, \
  
                        offset szClassName, NULL, \
                        WS_OVERLAPPED+WS_CAPTION+WS_SYSMENU+WS_MINIMIZEBOX+WS_MAXIMIZEBOX+WS_VISIBLE,\
                        ;WS_OVERLAPPEDWINDOW, \
                        200, 200, 600, 400, \
                        NULL, NULL, hInstance, NULL
  
                mov     hWinMain,eax
  
                invoke     ShowWindow,hWinMain,SW_SHOWNORMAL
                invoke     UpdateWindow,hWinMain
  
;**************************************************************************
  
; 消息循环
  
;**************************************************************************
  
                .while TRUE
  
                        invoke     GetMessage, addr @stMsg, NULL, 0, 0
                        .break     .if eax == 0
                        invoke     TranslateMessage, addr @stMsg
                        invoke     DispatchMessage, addr @stMsg
  
                .endw
                ret
  
_WinMain        endp
  
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  
start:
               invoke InitCommonControls 

                call    _WinMain
  
                invoke ExitProcess, NULL
  
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  
end start

特别要注意的几点:

   1.在用CreateWindowEx创建通用控件的时候要指定WS_CHILD和WS_VISIBLE属性,其父窗口是第一次调用CreateWindowExt时创建的窗口;父窗口的句柄为进入过程时传入的参数hWnd

   2.针对Progress Bar控件的消息主要有3个(1)PBM_SETRANGE  此消息是设置进度条的范围。看以下几句代码:
        mov eax,100  ; the lParam of PBM_SETRANGE message contains the range 
        mov CurrentStep,eax 
        shl eax,16    ; the high range is in the high word 
        invoke SendMessage,hProgressB,PBM_SETRANGE,0,eax         ;lParam的高16位才是最大值!!

      lParam是一个32位的数,其高16位为最大值(默认为100),低16位为最小值(最小为0)、wParam字段必须设置为0
     看MSDN里里对此消息的说明便知:
        
wParam 
   Must be zero. 
lParam 
  The LOWORD specifies the minimum range value, and the HIWORD specifies the maximum range value. The minimum range value must not be negative. By default, the minimum value is zero. The maximum range value must be greater than the minimum range value. By default,
the maximum range value is 100

(2)第二个消息是PBM_SETSTEP 此消息是用来设置步长 与上一个消息相反,其lParam字段必须设为0,wParam字段为增加的步长

(3)第三个消息是PBM_STEPIT 此消息用来更新Progress Bar使其前进一个步长 。其lParam和wParam字段都要设置为0

 

抱歉!评论已关闭.