发新话题
打印

[转载]Win32汇编教程6-工具栏和状态栏的使用

[转载]Win32汇编教程6-工具栏和状态栏的使用

作者:罗云彬


有关工具栏和状态栏

   工具栏和状态栏也是Windows标准界面的组成部分,工具栏一般位于菜单栏的下方,上面是一些系统定义的或自己定义的图片,可以通俗地显示这个按钮的作用。状态栏一般位于窗口的最下方,用来显示程序运行中的一些信息。工具栏和状态栏是Windows系统的两个通用的控件,你可以通过两个专用的 API 或者利用 CreateWindowEx 再使用制定的已经由系统定义的类来创建它们。这两个 API 分别是 CreateToolbarEx 和 CreateStatusWindow。下面将一下它们的用法。
   CreateToolbarEx 的声明为:

HWND CreateToolbarEx(

   HWND hwnd,
   DWORD ws,
   UINT wID,
   int nBitmaps,
   HINSTANCE hBMInst,
   UINT wBMID,
   LPCTBBUTTON lpButtons,
   int iNumButtons,
   int dxButton,
   int dyButton,
   int dxBitmap,
   int dyBitmap,
   UINT uStructSize}

它的参数中 hwnd 是父窗口(也就是我们的主窗口)的句柄,ws 是工具栏的风格,可以由几项合成,如 WS_VISIBLE 是创建是可见,TBSTYLE_FLAT表示平面按钮,WS_BORDER表示有边线等,具体可以见手册。wID 是工具栏的标识,nBitmaps 是定义按钮的图片个数,因为如果你要使用自己的图片,所有图片是要放在同一行中的,然后就由你自己指定中间的个数, hBMInst 是包含已定义系统图片的资源句柄,在你不想自己画图,使用内定的标准图片时使用,一般包含这些图片的 hInstance 已经在 Widnows.inc 中定义为 HINST_COMMCTRL,同样 wBMID 一般是 IDB_STD_SMALL_COLOR,表示使用大图片还是小图片等等。接下来是定义按钮的数据结构,中间定义了各个按钮的命令号,图片号及其他属性,结构如下:

TBBUTTON STRUCT
  iBitmap DWORD ?
  idCommand DWORD ?
  fsState BYTE ?
  fsStyle BYTE ?
  bReserved BYTE 2 dup(?)
  dwData DWORD ?
  iString DWORD ?
TBBUTTON ENDS

其中,每个结构定义一个按钮,数据结构中iBitmap 是图片ID,idCommand 是按钮的命令号,这个命令号当你按下按钮的时候会出现在 WM_COMMAND 消息的 wParam 中,你就可以知道哪个按钮被按下了。fsState 是按钮的初始状态,如 TBSTATE_PRESSED 是已经按下的,详细见手册,fsStyle 是风格。
   而建立状态栏的 CreateStatusWindow 的声明如下:

HWND CreateStatusWindow(

   LONG style,
   LPCTSTR lpszText,
   HWND hwndParent,
   UINT wID
   );

style 是状态栏的风格,lpszText 指向初始化是要显示在状态栏的文本,你可以指向 NULL。hwndParent 是父窗口的句柄。wID 是窗口 ID。

使用工具栏和状态栏的源程序

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;  是否包括调试代码
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DEBUG    =  1
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;  Programmed by 罗云彬, bigluo@telekbird.com.cn
;  Website: http://asm.yeah.net
;  LuoYunBin's Win32 ASM page (罗云彬的编程乐园)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;  版本信息
;  工具栏和状态栏演示程序 Ver 1.0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    .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

includelib  user32.lib
includelib  kernel32.lib
includelib  comctl32.lib
includelib  comdlg32.lib
includelib  gdi32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;  Equ 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

IDI_MAIN  equ    1000    ;icon

IDM_MAIN  equ    4000    ;menu
IDM_TOOLBAR  equ    4001
IDM_STATUSBAR  equ    4002
IDM_EXIT  equ    4003
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;  数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    .data?

hInstance  dd    ?
hWinMain  dd    ?
hMenu    dd    ?
hIcon    dd    ?
hToolbar  dd    ?
hStatusbar  dd    ?

szBuffer  db  256 dup  (?)

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;  数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    .data

szClassName  db  "Toolbar Template",0
szCaptionMain  db  '工具栏和状态栏演示程序 - 罗云彬',0
dwFlag    dd  F_TOOLBAR or F_STATUSBAR
;********************************************************************
;  标志位定义
F_TOOLBAR  equ  00000001b
F_STATUSBAR  equ  00000010b
stToolbar  TBBUTTON  < STD_FILENEW,1,TBSTATE_ENABLED,TBSTYLE_BUTTON,2 dup(0),-1>
    TBBUTTON  <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,2 dup(0),-1>
    TBBUTTON  < STD_FILEOPEN,2,TBSTATE_ENABLED,TBSTYLE_BUTTON,2 dup(0),-1>
    TBBUTTON  < STD_FILESAVE,3,TBSTATE_ENABLED,TBSTYLE_BUTTON,2 dup(0),-1>
    TBBUTTON  <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,2 dup(0),-1>
    TBBUTTON  < STD_PRINT,4,TBSTATE_ENABLED,TBSTYLE_BUTTON,2 dup(0),-1>
    TBBUTTON  < STD_PRINTPRE,0,TBSTATE_ENABLED,TBSTYLE_SEP,2 dup(0),-1>
NUM_BUTTONS  EQU  7

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;  代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    .code

if    DEBUG
  include    Debug.asm
endif

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;  程序开始
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
    call  _WinMain
    invoke  ExitProcess,NULL

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;  主窗口程序
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WinMain  proc
    local  @stWcMain:WNDCLASSEX
    local  @stMsg:MSG

;********************************************************************
;  如果已经在运行,则激活已运行的进程
;********************************************************************
    invoke  FindWindow,offset szClassName,NULL
    .if  eax != NULL
      invoke  ShowWindow,eax,SW_SHOWNORMAL
      invoke  ExitProcess,NULL
    .endif

    invoke  InitCommonControls
    invoke  GetModuleHandle,NULL
    mov  hInstance,eax
    invoke  LoadIcon,hInstance,IDI_MAIN
    mov  hIcon,eax
    invoke  LoadMenu,hInstance,IDM_MAIN
    mov  hMenu,eax
;*************** 注册窗口类 *****************************************
    invoke  LoadCursor,0,IDC_ARROW
    mov  @stWcMain.hCursor,eax
    mov  @stWcMain.cbSize,sizeof WNDCLASSEX
    mov  @stWcMain.hIconSm,0
    mov  @stWcMain.style,CS_HREDRAW or CS_VREDRAW
    mov  @stWcMain.lpfnWndProc,offset WndMainProc
    mov  @stWcMain.cbClsExtra,0
    mov  @stWcMain.cbWndExtra,0
    mov  eax,hInstance
    mov  @stWcMain.hInstance,eax
    mov  @stWcMain.hIcon,0
    mov  @stWcMain.hbrBackground,COLOR_BTNFACE+1
    mov  @stWcMain.lpszClassName,offset szClassName
    mov  @stWcMain.lpszMenuName,0
    invoke  RegisterClassEx,addr @stWcMain
;*************** 建立输出窗口 ***************************************
    invoke  CreateWindowEx,NULL,\  ;WS_EX_CLIENTEDGE,\
      offset szClassName,offset szCaptionMain,\
      WS_OVERLAPPEDWINDOW,\  ; OR WS_VSCROLL OR WS_HSCROLL,\
      50,50,550,350,\
      NULL,hMenu,hInstance,NULL

    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
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
WndMainProc  proc  uses ebx edi esi, \
    hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

    mov  eax,uMsg
    .if  eax ==  WM_CREATE
      mov  eax,hWnd
      mov  hWinMain,eax
      call  _Init
;********************************************************************
    .elseif  eax ==  WM_SIZE
      invoke  SendMessage,hStatusbar,uMsg,wParam,lParam
      invoke  SendMessage,hToolbar,uMsg,wParam,lParam
;********************************************************************
    .elseif  eax ==  WM_COMMAND
      mov  eax,wParam
      movzx  eax,ax
      .if  eax ==  IDM_EXIT
        call  _Quit
      .elseif  eax ==  IDM_TOOLBAR
        xor  dwFlag,F_TOOLBAR
        call  _ArrangeWindow
      .elseif  eax ==  IDM_STATUSBAR
        xor  dwFlag,F_STATUSBAR
        call  _ArrangeWindow
      .else
        _Debug  "菜单和工具栏命令","命令ID",eax
      .endif
;********************************************************************
    .elseif  eax ==  WM_CLOSE
      call  _Quit
;********************************************************************
    .else
      invoke  DefWindowProc,hWnd,uMsg,wParam,lParam
      ret
    .endif
;********************************************************************
;  注意:WndProc 处理 Windows 消息后,必须在 Eax 中返回 0
;  但是由 DefWindowProc 处理后的返回值不能改变,否则窗口
;  将无法显示!
;********************************************************************
    xor  eax,eax
    ret

WndMainProc  endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;  主窗口控制子程序
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Init    proc

    invoke  SendMessage,hWinMain,WM_SETICON,ICON_SMALL,hIcon
    invoke  CreateToolbarEx,hWinMain,\
      WS_VISIBLE or WS_CHILD or TBSTYLE_FLAT or WS_BORDER,\
      1,0,HINST_COMMCTRL,IDB_STD_SMALL_COLOR,offset stToolbar,\
      NUM_BUTTONS,0,0,0,0,sizeof TBBUTTON
    mov  hToolbar,eax

    invoke  CreateStatusWindow,WS_CHILD or WS_VISIBLE,NULL,hWinMain,2
    mov  hStatusbar,eax
    call  _ArrangeWindow

    ret

_Init    endp
;********************************************************************
_Quit    proc

    invoke  DestroyWindow,hWinMain
    invoke  PostQuitMessage,NULL
    ret

_Quit    endp
;********************************************************************
_ArrangeWindow  proc
    local  @stRect:RECT
    local  @stRectTemp:RECT
    local  @dwWidth:DWORD

    test  dwFlag,F_TOOLBAR
    .if  ZERO?
      invoke  ShowWindow,hToolbar,SW_HIDE
      invoke  CheckMenuItem,hMenu,IDM_TOOLBAR,MF_UNCHECKED
    .else
      invoke  ShowWindow,hToolbar,SW_SHOW
      invoke  CheckMenuItem,hMenu,IDM_TOOLBAR,MF_CHECKED
    .endif
    test  dwFlag,F_STATUSBAR
    .if  ZERO?
      invoke  ShowWindow,hStatusbar,SW_HIDE
      invoke  CheckMenuItem,hMenu,IDM_STATUSBAR,MF_UNCHECKED
    .else
      invoke  ShowWindow,hStatusbar,SW_SHOW
      invoke  CheckMenuItem,hMenu,IDM_STATUSBAR,MF_CHECKED
    .endif

    ret

_ArrangeWindow  endp
;********************************************************************
    end  start


程序的分析和要点

   在工具栏和状态栏编程中,要注意的就是工具栏和状态栏并不会随父窗口的大小变化自己调整位置和大小,所以要在父窗口的 WM_SIZE 消息中来移动和调整它们,这可以简单的把 WM_SIZE 消息传给它们就行了。不必自己再去计算。

.elseif eax == WM_SIZE
invoke SendMessage,hStatusbar,uMsg,wParam,lParam
invoke SendMessage,hToolbar,uMsg,wParam,lParam
另外,工具栏和状态栏也是一种子窗口,所以如果想把它们隐藏或显示的话,可以用标准的 ShowWindow 来处理。

附件

源代码.rar (11 KB)

2006-1-5 02:53, 下载次数: 64

人情如冰六月寒,花做一份艳,为谁笑人间? 如果任何人发现我转载的有图像的文章中图像失效或者文章有问题,请及时短消息通知我。先谢谢。::)) coup de foudre

TOP

发新话题