创建一个工具栏
2个函数可以用,CreateToolbarEx或者CreateWindowEx.这里用后者。用CreateWindowEx需要指定窗口类为TOOLBARCLASSNAME,初始化为没有包含任何按钮。MSDN中也说了它属于公共控件(common control),需要使用InitCommonControlsEx初始化。可以用2个消息来增加按钮。分别是TB_ADDBUTTONS,TB_INSERTBUTTON.最后还需要发送TB_AUTOSIZE消息当你向工具栏中插入一些按钮或字符串等等之后导致工具栏需要重新估算一下它的大小的时候。
MSDN:
You can use two functions to create a toolbar—CreateToolbarEx or CreateWindowEx. The CreateToolbarEx function creates a toolbar and adds an initial set of buttons to it. You can also use CreateWindowEx, specifying the TOOLBARCLASSNAME window class to create a toolbar that initially contains no buttons. The TOOLBARCLASSNAME window class is registered when the common control DLL is loaded. To ensure that this DLL is loaded, use the InitCommonControlsEx function first. If you create an empty toolbar, you add buttons to it by using the TB_ADDBUTTONS or TB_INSERTBUTTON message. You must send the TB_AUTOSIZE message after all the items and strings have been inserted into the control to cause the toolbar to recalculate its size based on its content.
指定工具栏的大小跟位置
CCS_TOP,CCS_BOTTOM 决定工具栏是沿着客户区上面还是下面,缺省情况下带有CCS_TOP风格。
TB_STYLE_TOOLTIPS 工具栏创建并管理了一个tooltip控件,它是一个小的弹窗,包含了对这个工具栏上按钮的描述。起初它是隐藏的,当用户移动鼠标到某个工具栏按钮上大约1秒钟的时候。它显示在光标附近。当工具栏接受到WM_MOUSEMOVE消息的时候,发送一个通知消息给tooltip控件。notification message就是TTN_GETDISPINFO.
程序可以直接发送TB_GETTOOLTIPS消息从而获得这个tooltip控件的句柄。还可以用TB_SETTOOLTIPS消息替换一个tooltip控件用另一个tooltip控件。
另外还有很多其他风格,比如CCS_NORESIZE,CCS_NOPARENTALIGN.................and so on.
如果创建工具栏用的CreateToolbarEx,参数中可以指定工具栏的宽跟高(in pixels以像素为单位),用CreateWindowEx没有这个便利了,工具栏的窗口过程自动调整它的尺寸跟位置。高度基于在工具栏上按钮的高度,宽度跟客户区宽度一样。如果想试图改变自动设置,需要借助TB_SETBUTTONSIZE消息。
MSDN:
If you create a toolbar using CreateToolbarEx, the function enables you to specify in pixels the height and width of the toolbar. However, the CreateWindowEx function does not have parameters for specifying toolbar size. The toolbar window procedure automatically sets the size and position of the toolbar window. The height is based on the height of the buttons in the toolbar. The width is the same as the width of the parent window's client area. To change the automatic size settings, send a TB_SETBUTTONSIZE message. The CCS_TOP and CCS_BOTTOM common control styles determine whether the toolbar is positioned along the top or bottom of the client area. By default, a toolbar has the CCS_TOP style.
很重要的一点:工具栏窗口过程会自动调整它的尺寸当它接受到WM_SIZE或TB_AUTOSIZE消息的时候。
用位图来定义按钮图像
工具栏上的每个按钮都包含一个位图图像,工具栏用一个内部列表来存储这些图像信息。可以用TB_ADDBITMAP消息来增加图像。
每个图像都有一个基于0的索引,第一张图像0,往后依次递增。TB_ADDBITMAP消息增加图像到工具栏内部图像列表的末尾,返回添加的第一张图像的索引。你可以发送TB_ADDBUTTONS消息对某个图像跟某个按钮进行关联。
MSDN:
Each image has a zero-based index. The first image added to the internal list has an index of 0, the second image has an index of 1, and so on. TB_ADDBITMAP adds images to the end of the list and returns the index of the first new image that it added. To associate the image with a button, you must send a TB_ADDBUTTONS message and specify the image's index after you add bitmaps to the internal image list.
为按钮定义文本
每个按钮都能够显示一个字符串,工具栏内部维护的那个list同样包含了用于工具栏按钮上的所有字符串变量。你可以向list中增加字符串用TB_ADDSTRING消息。。。
然后实用TB_ADDSTRING并非唯一的添加字符串到工具栏的方式,还可以显示一个字符串通过一个字符串指针在TBBUTTON结构体中的iString域,这个结构体最终是要传递给TB_ADDBUTTONS的。另外,你能用TB_SETBUTTONINFO给工具栏按钮赋值。更多请查MSDN.
Each string has a zero-based index. The first string added to the internal list of strings has an index of 0, the second string has an index of 1, and so on. TB_ADDSTRING adds strings to the end of the list and returns the index of the first new string. You use a string's index to associate the string with a button.
Using TB_ADDSTRING is not the only way to add strings to a toolbar. You can display a string in a button by passing a string pointer in the iString field of the TBBUTTON structure that is passed to TB_ADDBUTTONS. Additionally, you can use TB_SETBUTTONINFO to assign text to a toolbar button. For more information, see Assigning text to a toolbar button.
工具栏上添加按钮
CreateToolbarEx的方式按要求填充TBBUTTON结构体数组就OK,CreateWindowEx创建的是空的工具栏,需要发送TB_ADDBUTTONS消息来填充。
If you use the CreateToolbarEx function to create a toolbar, you can add buttons to the toolbar by filling an array of TBBUTTON structures and specifying the address of the array in the function call. However, the CreateWindowEx function does not have a parameter for passing a TBBUTTON structure. CreateWindowEx creates an empty toolbar that you fill by sending a TB_ADDBUTTONS message, specifying the address of a TBBUTTON structure.
再补充1个消息:
TB_BUTTONSTRUCTSIZE
If an application uses the CreateWindowEx function to create the toolbar, the application must send this message to the toolbar before sending the TB_ADDBITMAP or TB_ADDBUTTONS message. The CreateToolbarEx function automatically sends TB_BUTTONSTRUCTSIZE, and the size of the TBBUTTON structure is a parameter of the function
下面该状态栏了
创建
2个函数CreateStatusWindow,CreateWindowEx+STATUSCLASSNAME的窗口类。同样是公共控件,需要InitCommonControls.
风格类型
缺省的状态栏沿着它的父窗口下面,但是可以指定CCS_TOP风格让其显示在客户区上面。
大小跟高度
The window procedure for the status bar automatically sets the initial size and position of the window, ignoring the values specified in the CreateWindowEx function. The width is the same as that of the parent window's client area. The height is based on the metrics of the font that is currently selected into the status bar's device context and on the width of the window's borders.
The window procedure automatically adjusts the size of the status bar whenever it receives a WM_SIZE message. Typically, when the size of the parent window changes, the parent sends a WM_SIZE message to the status bar.
状态栏分栏
可以用SB_SETPARTS消息分栏。最多256个分栏,可以得到分栏数目SB_GETPARTS消息。
向某栏写文本需要借助SB_SETTEXT消息,具体参照MSDN.
A status bar can have many different parts, each displaying a different line of text. You divide a status bar into parts by sending the window an SB_SETPARTS message, specifying the number of parts to create and the address of an integer array. The array contains one element for each part, and each element specifies the client coordinate of the right edge of a part.
A status bar can have a maximum of 256 parts, although applications typically use far fewer than that. You retrieve a count of the parts in a status bar, as well as the coordinate of the right edge of each part, by sending the window an SB_GETPARTS message.
代码:
/*------------------------------------------------------------
HELLOWIN.C -- Displays "Hello, Windows 98!" in client area
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
#include <commctrl.h>
#pragma comment(lib,"comctl32.lib")
#define BTN 1
#define IDC_MAIN_TOOL 1111
#define ID_FILE_NEW 1200
#define ID_FILE_OPEN 1201
#define ID_FILE_SAVEAS 1202
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK ButtonWndProc(HWND,UINT,WPARAM,LPARAM);
WNDPROC OldWndProc;
HWND hBtn;
HINSTANCE hInst;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("HelloWin") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
INITCOMMONCONTROLSEX InitCtrlEx;
InitCommonControlsEx(&InitCtrlEx);
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
hInst=wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, // window class name
TEXT ("The Hello Program"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK ButtonWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
return CallWindowProc(OldWndProc,hwnd,message,wParam,lParam);
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
TCHAR ButtonName[]=TEXT("我是按钮");
static HWND hWndStatus,hWndTool;
TCHAR szBuf[MAX_PATH];
int nCount=3;
int array[3]={250,500,-1};
static TBBUTTON tbb[3];
static TBADDBITMAP tbab;
LPNMHDR lpnmhdr;
LPTOOLTIPTEXT lpttext;
switch (message)
{
case WM_CREATE:
hWndStatus=CreateWindowEx(0,STATUSCLASSNAME,"",WS_CHILD|WS_BORDER|WS_VISIBLE,-100,-100,10,10,hwnd,(HMENU)100,hInst,NULL);
if(!hWndStatus)
MessageBox(hwnd,TEXT("can't create statusbar!"),TEXT("error_notify"),MB_OK);
SendMessage(hWndStatus,SB_SETPARTS,(WPARAM)nCount,(LPARAM)array);
SendMessage(hWndStatus,SB_SETTEXT,(LPARAM)1,(WPARAM)TEXT("I am status bar"));
SendMessage(hWndStatus,SB_SETTEXT,(LPARAM)2,(WPARAM)TEXT("by yiruirui"));
hWndTool=CreateWindowEx(0,TOOLBARCLASSNAME,NULL,WS_CHILD|WS_VISIBLE|TBSTYLE_TOOLTIPS,0,0,0,0,hwnd,(HMENU)1111,hInst,NULL);
SendMessage(hWndTool,TB_BUTTONSTRUCTSIZE,(WPARAM)sizeof(TBBUTTON),0);
tbab.hInst=HINST_COMMCTRL;
tbab.nID=IDB_STD_SMALL_COLOR;
if(SendMessage(hWndTool,TB_ADDBITMAP,1,(LPARAM)&tbab)==-1)
MessageBox(hwnd,TEXT("失败"),TEXT("创建"),0);
ZeroMemory(tbb,sizeof(tbb));
tbb[0].iBitmap=STD_FILENEW;
tbb[0].fsState=TBSTATE_ENABLED;
tbb[0].fsStyle=TBSTYLE_BUTTON;
tbb[0].idCommand=ID_FILE_NEW;
tbb[0].iString=(INT_PTR)"yi";
tbb[1].iBitmap=STD_FILEOPEN;
tbb[1].fsState=TBSTATE_ENABLED;
tbb[1].fsStyle=TBSTYLE_BUTTON;
tbb[1].idCommand=ID_FILE_OPEN;
tbb[1].iString=(INT_PTR)"rui";
tbb[2].iBitmap=STD_FILESAVE;
tbb[2].fsState=TBSTATE_ENABLED;
tbb[2].fsStyle=TBSTYLE_BUTTON;
tbb[2].idCommand=ID_FILE_SAVEAS;
tbb[2].iString=(INT_PTR)"rui";
SendMessage(hWndTool,TB_ADDBUTTONS,sizeof(tbb)/sizeof(TBBUTTON),(LPARAM)&tbb);
SendMessage(hWndTool,TB_SETBUTTONSIZE,0,(LPARAM)MAKELONG(35,35));
SendMessage(hWndTool,TB_AUTOSIZE,0,0);
return 0 ;
case WM_SIZE:
{
HWND hTool;
hTool=GetDlgItem(hwnd,IDC_MAIN_TOOL);
SendMessage(hTool,TB_AUTOSIZE,0,0);
MoveWindow(hWndStatus,0,0,0,0,TRUE);
}
break;
case WM_MOUSEMOVE:
wsprintf(szBuf,"Mouse position:%d,%d",LOWORD(lParam),HIWORD(lParam));
SendMessage(hWndStatus,SB_SETTEXT,0,(LPARAM)(LPSTR)szBuf);
break;
case WM_DRAWITEM:
{
}
break;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_NEW:
MessageBox(hwnd,TEXT("notify"),TEXT("file new"),0);
break;
case ID_FILE_OPEN:
MessageBox(hwnd,TEXT("notify"),TEXT("file open"),0);
break;
case ID_FILE_SAVEAS:
MessageBox(hwnd,TEXT("notify"),TEXT("file save as"),0);
break;
}
break;
case WM_NOTIFY:
lpnmhdr=(LPNMHDR)lParam;
if(lpnmhdr->code==TTN_GETDISPINFO)
{
lpttext=(LPTOOLTIPTEXT)lParam;
switch(lpttext->hdr.idFrom)
{
case ID_FILE_NEW:
lpttext->lpszText="新建";
break;
case ID_FILE_OPEN:
lpttext->lpszText="打开";
break;
case ID_FILE_SAVEAS:
lpttext->lpszText="保存为";
break;
}
}
break;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
只是一些相对简单的功能,更多复杂的还需要认真去读MSDN。
贴个运行示意图: