工具欄
工具欄是一種位于父窗口頂部帶有按鈕的水平窗口,用戶可以通過選擇工具欄的按鈕來完成相應的命令。你可以通過調用CreateWindowEx或 CreateWindow函數來創(chuàng)建工具欄,還可以通過發(fā)送工具欄消息來增加、刪除及管理工具欄上的按鈕。如果你已經熟悉了MFC或Visual Basic中的狀態(tài)欄,那么你會發(fā)現Win32中的工具欄控件將會非常容易上手。如果你不熟悉工具欄,那么也不要失望——它們是非常容易實現的。圖2是一個帶有4個按鈕的工具欄,你會注意到頭三個按鈕(帶有數字的)是緊挨在一起的,另外的那個帶有門圖標(不管怎樣,假設它像個門吧)的按鈕則和它們相距有一點空間。這一空間叫做separator,它被用來實現狀態(tài)欄按鈕的邏輯分組。
圖2.簡單的工具欄示例
工具欄樣式及其默認行為
工具欄的窗口過程是默認設置它的位置和大小的。默認地,工具欄顯示在父窗口客戶區(qū)的頂部;不過,你也可以通過指定CCS_BOTTOM樣式來使之位于客戶區(qū)的底部。
工具欄獨有的唯一一個新樣式是TBSTYLE_TOOLTIPS,這一樣式使得工具欄能夠顯示工具提示(那種當你在工具欄按鈕上停留鼠標時顯示的小窗口)。系統(tǒng)將會在工具欄需要顯示彈出式文本的時候向它發(fā)送WM_NOTIFY消息,下面的示例代碼示范了工具提示特色的實現。
創(chuàng)建工具欄
如上所述,創(chuàng)建一個工具欄很簡單:你填充一個按鈕結構,創(chuàng)建一個包含按鈕的大位圖,然后調用CreateWindowEx函數,并指定 TOOLBARCLASSNAME窗口類。當工具欄創(chuàng)建了以后,你需要向它發(fā)送消息來添加按鈕和位圖。然后,如果你沒有什么特別的事情要做的話,那么就可以讓系統(tǒng)來處理工具欄了。以下的代碼創(chuàng)建了一個工具欄,裝載了位圖并向工具欄添加了一些按鈕。
// 填充描述工具欄按鈕的結構
TBBUTTON tbButtons[] = {
{ 0, IDM_OPT1, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
{ 1, IDM_OPT2, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
{ 2, IDM_OPT3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, -1},
{ 3, IDM_EXIT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}
};
// 如果在Win32之下,那么聲明一個位圖結構
TBADDBITMAP tbBitamps;
// 初始化成員
.
.
.
tbBitamps.hInst = hInstance; // 當前實例
tbBitmaps.nID = IDB_TOOLBAR; // 位圖資源的ID
.
.
.
// 創(chuàng)建一個Win32工具欄的函數
// 參數:
// HWND hWndParent - 父窗口句柄
// LONG lNumBitmaps - 工具欄的位圖數
// TBADDBITMAP tbBItmaps - Win32下的位圖結構
// LONG lNumButtons - 工具欄的按鈕數
// TBBUTON tbButtons - 按鈕結構的指針
// DWORD dwStyle - 指定工具欄窗口樣式,可以是若干公共控件樣式或工具欄特定樣式的組合
// int iToolBarID - 工具欄的ID
// 返回值:
// 如果成功則返回工具欄句柄,否則返回NULL
//
HWND MyCreateTooolBar(HWND hWndParent, LONG lNumBitmaps,
TBADDBITMAP tbBitmaps, LONG lNumButtons, TBBUTON tbButtons,
WORD wStyle, UINT uToolBarID)
{
HWND hWndToolBar;
// Create the toolbar control.
hWndToolBar = CreateWindowEx( 0L, // 無擴展樣式
TOOLBARCLASSNAME, // 工具欄窗口類
"", // 無默認文本
WS_CHILD | WS_BORDER | WS_VISIBLE | dwStyle, // 樣式及默認值
0, 0, 100, 30, // 標準工具欄尺寸和位置
hWndParent, // 工具欄父窗口
(HMENU)iToolBarID, // 工具欄ID
tbBitmaps->hInst, // 當前實例
NULL ); // 沒有類數據
if (hWndToolBar)
{
// 裝載工具欄位圖
if (SendMessage(hWndToolBar, TB_ADDBITMAP, lNumBitmaps,
(LONG) &tbBitmaps) == -1)
return (NULL);
// 添加按鈕
SendMessage(hWndToolBar, TB_ADDBUTTONS, lNumButtons, (LONG) &tbButtons);
// 成功創(chuàng)建工具欄,返回句柄
return (hWndToolBar);
}
// 創(chuàng)建失敗,返回NULL
return NULL;
}
創(chuàng)建狀態(tài)欄的另一種方法是調用CreateToolBarEx函數,這個函數的功能和上邊我編寫的MyCreateToolBar一樣。CreateToolBarEx函數帶有以下參數:
·HWND hwnd:工具欄的父窗口句柄。
·DWORD ws:工具欄的窗口樣式。
·WORD wID:工具欄的ID。
·int nBitmaps:由hBMInst和wBMID指定的位圖所包含的圖像數目。
·HINSTANCE hBMInst:包含位圖資源的可執(zhí)行文件模塊實例。
·WORD wBMID:位圖資源ID。如果hBMInst為NULL,那么這個值必須是一個有效的位圖句柄。
·LPCTTBBUTTON lpButtons:TBBUTTON結構的地址。
·int iNumButtons:向工具欄添加的按鈕數目。
·int dxButton, dyButton:按鈕的像素寬度和長度。
·int dxBitmap, dyBitmap:位圖的像素寬度和長度。
·UINT uStructSize:TBBUTTON結構的尺寸。
你可以通過指定TBSTYLE_TOOLTIPS樣式和在.rc文件中創(chuàng)建一個STRINGTABLE來向工具欄添加工具提示的支持。如果你這么做了,那么你就需要處理工具欄父窗口的WM_NOTIFY消息,如下代碼所示:
// 這是.RC文件的內容
STRINGTABLE
BEGIN
IDM_OPT1, "Option 1"
IDM_OPT2, "Option 2"
IDM_OPT3, "Option 3"
IDM_EXIT, "Exit Tool bar Sample"
END
// 這是.C文件的內容
TOOLINFO tbToolInfo;
// 捕獲WM_NOTIFY消息
case WM_NOTIFY:
lpToolTipText = (LPTOOLTIPTEXT)lParam;
if (lpToolTipText->hdr.co
{
// 如果系統(tǒng)需要文本,則從資源中進行裝載
LoadString (hInst,
lpToolTipText->hdr.idFrom, // 字符串ID == 命令ID
szBuf,
sizeof(szBuf));
// 將結構指向字符串
lpToolTipText->lpszText = szBuf;
}
break;
你可以點這里下載工程文件并運行TOOLBAR.EXE來看一下上邊這段代碼是如何工作的。
警告:工具欄的可執(zhí)行文件是使用Windows 95最初的開發(fā)包構建并測試的。這個可執(zhí)行文件只能運行在Windows 95之下,不能運行在Windows 3.1或Windows NT 3.5中。如果你的機器上裝有Windows 95,但是在運行這一實例的時候出現了問題,請將工程文件復制并重新進行構建,最后重新運行可執(zhí)行文件。
工具欄結構
本節(jié)描述了一些結構,你可以使用它們在Win32中創(chuàng)建和管理工具欄及其按鈕。你添加的每個按鈕都可以擁有下表中所列的某個樣式,這些按鈕樣式可以在TBBUTTON結構中組合使用。
表2.工具欄按鈕樣式
TBSTYLE_BUTTON 標準按鈕。
TBSTYLE_CHECK 類似于CheckBox擁有兩個狀態(tài)的選擇按鈕。
TBSTYLE_CHECKGROUP 類似于RadioBox的分組選擇按鈕。
TBSTYLE_GROUP 同上。
TBSTYLE_SEP separator,按鈕分組間的一點空間。
當你指定了你的工具欄及其按鈕之后,你可能會需要查詢工具欄按鈕的狀態(tài)信息。當前的狀態(tài)保存在一個TBBUTTON結構中,就像下面描述的那樣。如果你需要動態(tài)地決定按鈕的狀態(tài),那么你可以向工具欄發(fā)送TB_GETSTATE消息。
表3.工具欄按鈕狀態(tài)
TBSTATE_CHECKED 被選中。
TBSTATE_ENABLED 有效。
TBSTATE_HIDDEN 隱藏。
TBSTATE_INDETERMINATE 模糊。
TBSTATE_PRESSED 按下。
TBBUTTON
typedef struct tagTBBUTTON {
int idCommand; // 按鈕命令ID
BYTE fsState; // 按鈕狀態(tài)標志,見表3
BYTE fsStyle; // 按鈕樣式,見表2
DWORD dwData; // 應用程序定義的數據
int iString; // 按鈕幫助文本字符串索引
} TBBUTTON;
TBBUTTON結構包含了工具欄按鈕的信息,它包括以下成員:
·int iBitmap:0起始的索引,標識了位圖中按鈕圖像的位置。
·int idCommand:和按鈕關聯的命令標識符。當按鈕被按下時,這個標識符將會通過WM_COMMAND傳送。如果fsStyle成員是TBSTYLE_SEP,那么這一成員必須為0。
·BYTE fsState:按鈕狀態(tài)標志,它可以是表3中的值組合。
·BYTE fsStyle:按鈕樣式標志,它可以是表2中的值組合。
·DWORD dwData:由應用程序定義的數值。
·int iString:字串列表中按鈕的幫助文本索引。
ADJUSTINFO
typedef struct tagADJUSTINFO {
TBBUTTON tbButton; // 包含按鈕信息的結構
char szDescription[1]; // TBD
};
ADJUSTINFO結構包含了工具欄中由用戶自定義的按鈕的信息,它包括以下成員:
·TBBUTTON tbButton:包含按鈕信息的結構。
·char szDescription:這個成員的使用方法還未被決定。
TBADDBITMAP
typedef struct tagTBADDBITMAP {
HINSTANCE hInst; // 包含位圖的實例句柄
UINT nID; // 位圖的資源ID
} TBADDBITMAP;
TBADDBITMAP結構包含了向工具欄添加的位圖的信息,這一結構在編寫Win32應用程序的時候非常有用,它包括以下成員:
·HINSTANCE hInst:包含位圖的實例句柄。
·UINT nID:位圖的資源ID。
工具欄消息
系統(tǒng)和應用程序可以向工具欄發(fā)送消息,就像給其它窗口發(fā)送消息一樣。本節(jié)列出了能夠向工具欄空間發(fā)送的消息,以及每個消息的wParam和lParam值。
TB_ADDBITMAP
wParam = nButtons; // 位圖中按鈕的數目
lParam = (LPTBADDBITMAP)lptbab; // 位圖句柄
描述:TB_ADDBITMAP消息用來向工具欄中有效的圖像列表中添加一個新的位圖,這一消息只能夠在非Win32應用程序中使用。
參數:wParam表示位圖中的按鈕數量,lParam為一個TBADDBITMAP結構的指針。
返回值:低位字包含了第一個按鈕位圖的索引,如果函數調用成功,高位字不使用;如果調用不成功,低位字是-1。
TB_ADDBUTTONS
wParam = nButtons; // 按鈕數目
lParam = (LPTBBUTTON)lpButtons; // 按鈕結構數組地址
描述:TB_ADDBUTTONS消息用來向工具欄添加一個或多個按鈕。
參數:wParam表示要添加的按鈕數,lParam是一個TBBUTTON結構數組的指針,這個數組中包含著要添加的按鈕的信息。這個數組必須包含和wParam所指定的按鈕數目相同的元素。
返回值:成功返回TRUE,否則返回FALSE。
TB_ADDSTRING
wParam = (HINSTANCE)hInst; // 包含字符串的實例句柄
lParam = (MAKELONG)(idString, 0); // 字符串ID或字符串緩沖區(qū)
描述:TB_ADDSTRING消息用來向工具欄可用的字串列表中添加一個新的字符串。
參數:wParam為一個包含字符串資源的可執(zhí)行文件的模塊實例句柄——如果lParam指向一個或多個字符串,那么wParam應該為0。 lParam是一個字符串資源的資源ID,或者是一個要添加到字串列表的包含一個或多個空字符結尾的字符串的緩沖區(qū),字符串的個數由wParam指定。最后一個字符串必須由兩個NULL字符結尾。
返回值:如果成功則返回第一個新字符串的索引,否則返回-1。
TB_AUTOSIZE
wParam = 0; // 不使用
lParam = 0; // 不使用
描述:TB_AUTOSIZE消息用來使工具欄重新設置大小。應用程序在設置了按鈕或位圖的尺寸、添加了字符串之后可以發(fā)送這一條消息來改變工具欄的尺寸。
參數:wParam和lParam不使用。
返回值:無。
TB_BUTTONCOUNT
wParam = 0; // 不使用
lParam = 0; // 不使用
描述:TB_BUTTONCOUNT消息用來獲得工具欄當前的按鈕總數。
參數:wParam和lParam不使用。
返回值:工具欄的按鈕數。
TB_BUTTONSTRUCTSIZE
wParam = cb; // TBBUTTON結構的字節(jié)大小
lParam = 0; // 不使用
描述:TB_BUTTONSTRUCTSIZE用來指定TBBUTTON結構的大小,系統(tǒng)使用這個大小來決定當前的COMMCTRL.DLL版本。如果應用程序使用了CreateWindow來創(chuàng)建工具欄,那么它必須在添加所有按鈕之前發(fā)送這條消息。CreateToolBarEx函數自動發(fā)送這條消息,并且TBBUTTON結構作為這個函數的一個參數。
參數:wParam為TBBUTTON結構的字節(jié)大小,lParam不使用。
返回值:無。
TB_CHECKBUTTON
wParam = idButton; // 要選中的按鈕命令ID
lParam = MAKELONG(fCheck, 0); // 選定標記 - TRUE為添加,FALSE為移除
描述:TB_CHECKBUTTON消息用來選中或不選擇一個給定的按鈕。當一個按鈕被選定的時候,它的外觀是被按下的。
參數:wParam是要選定的按鈕命令ID。如果lParam為TRUE,則添加選定標記;如果lParam為FALSE,選定標記被移除了。
返回值:成功返回TRUE,否則返回FALSE。
wParam = idButton; // 按鈕命令ID
lParam = 0; // 不使用
描述:TB_COMMANDTOINDEX消息用來獲得由命令ID關聯的按鈕索引。
參數:wParam為和按鈕關聯的命令ID,lParam不使用。
返回值:按鈕的索引。
TB_CUSTOMIZE
wParam = 0; // 不使用
lParam = 0; // 不使用
描述:TB_CUSTOMIZE消息用來顯示自定義工具欄對話框。
參數:wParam和lParam不使用。
返回值:無。
TB_DELETEBUTTON
wParam = iButton; // 要刪除的按鈕的索引
lParam = 0; // 不使用
描述:TB_DELETEBUTTON消息用來從工具欄刪除一個按鈕。
參數:wParam是要刪除按鈕的索引,lParam不使用。
返回值:成功返回TRUE,否則FALSE。
TB_ENABLEBUTTON
wParam = idButton; // 按鈕的命令ID
lParam = MAKELONG(fEnable, 0); // 標記 - TRUE為生效,FALSE為失效
描述:TB_ENABLEBUTTON用來使指定的按鈕生效或失效。當按鈕生效后,它就可以被按下和選中了。
參數:wParam是要生效或失效的按鈕的命令ID。如果lParam為TRUE,按鈕就生效;如果lParam為FALSE,按鈕就失效。
返回值:成功返回TRUE,否則返回FALSE。
TB_GETBUTTON
wParam = iButton; // 要獲得的按鈕索引
lParam = (LPTBBUTTON)lpButton; // 接收按鈕信息的緩沖區(qū)
描述:TB_GETBUTTON消息用來接收給定按鈕的信息。
參數:wParam為要獲得信息的按鈕索引,lParam為一個用來接收按鈕信息的TBBUTTON結構的地址。
返回值:成功返回TRUE,否則返回FALSE。
TB_GETITEMRECT
wParam = iButton; // 按鈕的索引
lParam = (LPRECT)lprc; // 用來接收矩形值的數組
描述:TB_GETITEMRECT消息用來獲得工具欄按鈕的矩形范圍,它不能用于獲得擁有TBSTATE_HIDDEN狀態(tài)的按鈕矩形范圍。
參數:wParam為要獲得信息的按鈕索引,lParam為一個用來接收矩形范圍坐標的RECT結構指針。
返回值:成功返回TRUE,否則返回FALSE。
TB_GETSTATE
wParam = idButton; // 按鈕命令ID
lParam = 0; // 不使用
描述:TB_GETSTATE消息用來獲得按鈕的狀態(tài)信息,即按鈕是否生效、被壓下或選中。
參數:wParam為要獲得信息的按鈕命令ID,lParam不使用。
返回值:如果調用成功,則該消息返回按鈕的狀態(tài)信息(見表3)。如果調用失敗,則返回-1。
TB_HIDEBUTTON
wParam = idButton; // 按鈕的命令ID
lParam = MAKELONG(fShow, 0); // TRUE為隱藏,FALSE為顯示
描述:TB_HIDEBUTTON消息用來隱藏或顯示指定的按鈕。
參數:wParam為要隱藏或顯示的按鈕命令ID。如果lParam為TRUE,則隱藏按鈕;如果為FALSE,則顯示按鈕。
返回值:成功返回TRUE,否則返回FALSE。
TB_INDETERMINATE
wParam = idButton; // 按鈕的命令ID
lParam = MAKELONG(fIndeterminate, 0); // TRUE為設置,FALSE為清除
描述:TB_INDETERMINATE消息用來設置或清除指定按鈕的模糊狀態(tài)。
參數:wParam為要設置或清除狀態(tài)的按鈕命令ID。如果lParam為TRUE,則設置模糊狀態(tài);如果為FALSE,則清除此狀態(tài)。
返回值:成功返回TRUE,否則返回FALSE。
TB_INSERTBUTTON
wParam = iButton; // 按鈕的索引
lParam = (LPTBBUTTON)lpButton; // 按鈕信息結構
描述:TB_INSERTBUTTON消息用來向工具欄添加一個按鈕。
參數:wParam是按鈕的索引值,這個消息向wParam索引的按鈕之前插入新的按鈕。lParam為一個包含要插入按鈕的信息的TBBUTTON結構。
返回值:成功返回TRUE,否則返回FALSE。
TB_ISBUTTONCHECKED, TB_ISBUTTONENABLED, TB_ISBUTTONHIDDEN, TB_ISBUTTONINDETERMINATE, TB_ISBUTTONPRESSED
wParam = idButton; // 按鈕命令ID
lParam = 0; // 不使用
描述:這些消息決定給定的按鈕是否被選中、生效、隱藏或被壓下。
參數:wParam是按鈕的命令ID,lParam不使用。
返回值:如果狀態(tài)為真,那么返回非0值,否則返回0。
TB_PRESSBUTTON
wParam = idButton; // 按鈕命令ID
lParam = MAKELONG(fPress, 0); // TRUE為被壓下,FALSE為被釋放
描述:TB_PRESSBUTTON消息用來壓下或釋放給定的按鈕。
參數:wParam是要壓下或釋放的按鈕命令ID。lParam如果是TRUE,則按鈕被壓下;如果是FALSE,按鈕則被釋放。
返回值:成功返回TRUE,否則返回FALSE。
TB_SAVERESTORE
wParam = (BOOL)fSave; // TRUE為保存,FALSE為恢復
lParam = (LPSTR)lpszSectionFile; // 用于保存信息的字符串
描述:TB_SAVERESTORE消息用來保存或恢復工具欄的狀態(tài)。
參數:如果wParam為TRUE,則保存信息;否則,恢復信息。lParam為一個由兩個連續(xù)的零結尾字符串的地址。第一個字符串指定了一個初始化文件中的段名稱,第二個指定了初始化文件的文件名。如果第二個字符串為空,該消息使用默認值WIN.INI文件。
返回值:無。
TB_SETBITMAPSIZE
wParam = 0; // 不使用
lParam = MAKELONG(dxBitmap, dyBitmap); // 要設置的寬度和高度
描述:TB_SETBITMAPSIZE消息用來設置要添加到工具欄的位圖圖像的尺寸,這一尺寸必須在添加任何位圖之前設置。如果應用程序沒有顯式地設置位圖尺寸,那么這個尺寸會被設置為16×15像素。
參數:wParam不使用,lParam為位圖圖像的像素寬度和高度。
返回值:成功返回TRUE,否則返回FALSE。
TB_SETBUTTONSIZE
wParam = 0; // 不使用
lParam = MAKELONG(dxButton, dyButton); // 要設置的寬度和高度
描述:TB_SETBUTTONSIZE消息用來設置要添加到工具欄的按鈕尺寸,這一尺寸必須在添加任何按鈕之前設置。如果應用程序沒有顯式地設置按鈕尺寸,那么這個尺寸會被設置為24×22像素。
參數:wParam不使用,lParam為按鈕的像素寬度和高度。
返回值:成功返回TRUE,否則返回FALSE。
TB_SETSTATE
wParam = idButton; // 按鈕的命令ID
lParam = MAKELONG(fState, 0); // 要設置的狀態(tài)(見表3)
描述:TB_SETSTATE消息用來設置給定按鈕的狀態(tài)。
參數:wParam為按鈕的命令ID,lParam由表3中的狀態(tài)標志組成。
返回值:成功返回TRUE,否則返回FALSE。
工具欄通知消息
本節(jié)列出了Windows向工具欄窗口發(fā)送的通知消息,工具欄的父窗口通過WM_COMMAND來接收這些消息。除了另有說明之外,Windows忽略了這些消息的返回值。在所有的情況下,wParam包含了工具欄的ID。
表4.工具欄通知消息