--------------------------------------------------------------------------------
有关工具栏和状态栏
工具栏和状态栏也是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 来处理。