【Windows編程】系列第六篇:建立Toolbar與Statusbar

windows1

上一篇咱們學習瞭解瞭如何使用Windows GDI畫圖,該應用程序都是光光的靜態窗口,咱們使用Windows應用程序,但凡稍微複雜一點的程序都會有工具欄和狀態欄,工具欄主要用於一些快捷功能按鈕。好比典型的windows應用程序的上面是菜單欄,從菜單欄咱們能夠選擇應用程序提供的各類功能,可是有的功能比較經常使用,且不能放在第一級菜單,須要進入二級、三級甚至更多的菜單才能選擇。顯然這樣使用起來比較麻煩,因而這時候工具欄的做用就體現出來了,通常工具欄位於菜單欄的下面,可是位於客戶窗口的上面。下面就是windows的文本編輯器的工具欄:java

toolbar

Statusbar主要用於顯示應用程序的運行狀態,統計信息,操做信息等提示做用,通常是隻讀狀態。典型的狀態欄放在窗口的最下面,好比下面就是我正在使用的Word應用程序的狀態欄:程序員

statusbar

咱們此次要一塊兒學習的就是使用純Windows API函數建立基本的狀態欄和菜單欄。若是屬性MFC的朋友知道,若是用MFC來作工具欄和菜單欄很簡單。可是使用純API就麻煩一些了,固然帶來的感受是不同的,好比要動態建立,使用MFC的資源編輯器就無能爲力,可是對於咱們今天要使用的API建立方式來講,就顯示出他的強大了。編程

首先,前面咱們在講解Windows經常使用控件的建立時就知道,全部帶窗口的控件建立實際上都是調用Windows提供的CreateWindow或者CreateWindowEx(如下以CreateWindowEx爲例)這兩個函數,固然今天的菜單欄和狀態欄同樣須要這兩個函數來建立。因爲工具欄和狀態欄都是Windows的通用控件組中的控件,有默認的類名。建立工具欄時,類名爲TOOLBARCLASSNAME,建立狀態欄時,類名爲STATUSCLASSNAME,這兩個宏定義在commctrl.h文件中根據是否使用UNICODE編碼分別是「ToolbarWindow32」和「msctls_statusbar32」的寬字符版本和ANSI版本。windows

  • 建立工具欄數組

除了使用CreateWindowEx建立好工具欄後,做爲一個更好看一點,咱們還能夠給工具欄加上圖標以及功能提示。爲了加圖標,最方便的方法是使用一些列圖像列表API來加載和管理工具欄的圖片。ImageList_Create能夠建立一個圖片列表,它的原型爲:微信

HIMAGELIST ImageList_Create(int cx, int cy, UINT flags,  int cInitial, int cGrow);

 

該函數用法在MSDN上說的比較清楚。這個列表建立後並無圖片,只是一個列表管理的容器,還須要加載圖片集。加入圖片所需API以下:微信公衆平臺

int ImageList_AddMasked(HIMAGELIST himl, HBITMAP hbmImage, COLORREF crMask);

 

圖片加載後,還能夠設置圖片的顯示屬性,包括顯示圖片、文本以及信息提示功能。工具按鈕的響應是經過向窗口處理程序發送WM_COMMAND消息實現的,有用戶處理按鈕事件。工具欄的提示信息是經過WM_NOTIFY消息,由用戶設置,工具欄的建立實例請參看後面的應用實例。編輯器

  • 建立狀態欄函數

裝具狀態欄相比工具欄要簡單不少,用CreateWindowEx創建狀態欄後,默認狀況下,狀態欄只有一個顯示面板(panel),要建立多個面板,只要向狀態欄把配置好個面板的長度發送SB_SETPARTS消息便可,消息參數分別是面板個數和個面板的終點數組。好比:工具

int array[3]={120,120*2,-1};
SendMessage(hWndStatus,SB_SETPARTS,(WPARAM)3,(LPARAM)array);

 

表示將狀態欄面板分爲3各部分,第一部分到120像素爲止,第二部分到240像素爲止,剩下的(-1)所有分到第三部分中。

設置面板文本內容,能夠給狀態欄發送SB_SETTEXT消息;要在狀態欄面板中增長小圖標,能夠給狀態發送SB_SETICON消息。

上面的工具欄和狀態欄只是介紹了最基本的狀況,更多的設置和消息處理均可以參考MSDN。本系列專一在基本編程和使用上,只是介紹常見的用法,不過這些用法也夠初學者編程使用。

  • 使用實例

下面咱們經過一個基本的實例程序說明如何採用純Windows API建立、使用工具欄和狀態欄。程序中建立的Toolbar有三個圖標,當程序正常顯示,鼠標在某個工具欄按鈕上移動,或者處於Disable狀態是,會有不一樣的圖片顯示,讀者能夠本身更換其餘本身喜歡的圖標。

#include <windows.h>
#include <commctrl.h>
#include <tchar.h>

#pragma comment(lib, "comctl32.lib")

// Windows XP sytle button
#pragma comment(linker,"\"/manifestdependency:type='win32' "\
						"name='Microsoft.Windows.Common-Controls' "\
						"version='6.0.0.0' processorArchitecture='*' "\
						"publicKeyToken='6595b64144ccf1df' language='*'\"")

#define IDC_TOOLBAR   1001
#define IDC_STATUSBAR 1002
//#define PIC_RESOURCE_USED

#ifdef PIC_RESOURCE_USED
#define IDB_NEW   110
#define IDB_OPEN  111
#define IDB_SAVE  112
#endif
#define ID_FOPEN  1111
#define ID_FCLOSE 1112
#define ID_FSAVE  1113

static TCHAR szAppName[] = TEXT("toolbar");
static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
     HWND     hWnd;
     MSG      msg;
     WNDCLASS wndclass;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW;
     wndclass.lpfnWndProc   = WndProc;
     wndclass.cbClsExtra    = 0;
     wndclass.cbWndExtra    = 0;
     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;
     }
     //初始化公共空間
     INITCOMMONCONTROLSEX icc;
     icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
     icc.dwICC = ICC_BAR_CLASSES;
     InitCommonControlsEx(&icc);
     hWnd = CreateWindow(szAppName,                  // window class name
                          szAppName,                 // window caption
                          WS_OVERLAPPEDWINDOW,        // window style
                          CW_USEDEFAULT,              // initial x position
                          CW_USEDEFAULT,              // initial y position
                          400,              // initial x size
                          300,              // 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;
}

HWND CreateToolbar(HWND hParentWnd)
{
    HWND hWndTB;
    TBBUTTON tbb[3];
    HIMAGELIST hImageList,hHotImageList,hDisableImageList;
    HBITMAP hBitmap;

    HINSTANCE hInst = GetModuleHandle(NULL);
    //建立Toolbar控件
    hWndTB = CreateWindowEx(0, TOOLBARCLASSNAME,TEXT(""),
							WS_CHILD|WS_VISIBLE|WS_BORDER|TBSTYLE_LIST|TBSTYLE_AUTOSIZE|TBSTYLE_TOOLTIPS,
							0,0,0,0,
							hParentWnd,
							(HMENU)IDC_TOOLBAR,
							hInst,
							NULL);
    if(!hWndTB)
    {
        return NULL;
    }
    SendMessage(hWndTB, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
    //下面建立三組24x24像素大小的位圖圖像列表,用於工具欄圖標
    hImageList = ImageList_Create(24,24,ILC_COLOR24|ILC_MASK,3,1);
#ifdef PIC_RESOURCE_USED
    hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_COLOR3));
#else
    hBitmap = (HBITMAP)LoadImage(NULL, TEXT("color24x3.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION); //加載一組圖片
#endif
    ImageList_AddMasked(hImageList, hBitmap, RGB(255,255,255));
    DeleteObject (hBitmap);
    SendMessage(hWndTB,TB_SETIMAGELIST,0,(LPARAM)hImageList); //正常顯示時的圖像列表

    hHotImageList = ImageList_Create(24,24,ILC_COLOR24|ILC_MASK,3,1);
#ifdef PIC_RESOURCE_USED
    hBitmap = LoadBitmap(hInst,MAKEINTRESOURCE(IDB_GREEN3));
#else
    hBitmap = (HBITMAP)LoadImage(NULL, TEXT("green24x3.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
#endif
    ImageList_AddMasked(hHotImageList,hBitmap, RGB(255,255,255));
    DeleteObject (hBitmap);
    SendMessage(hWndTB,TB_SETHOTIMAGELIST,0,(LPARAM)hHotImageList); //鼠標懸浮時的圖像列表

    hDisableImageList = ImageList_Create(24,24,ILC_COLOR24|ILC_MASK,3,1);
#ifdef PIC_RESOURCE_USED
    hBitmap = LoadBitmap(hInst,MAKEINTRESOURCE(IDB_GRAY3));
#else
    hBitmap = (HBITMAP)LoadImage(NULL, TEXT("gray24x3.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
#endif
    ImageList_AddMasked(hDisableImageList,hBitmap, RGB(255,255,255));
    DeleteObject (hBitmap);
    SendMessage(hWndTB,TB_SETDISABLEDIMAGELIST,0,(LPARAM)hDisableImageList); //當工具欄button失能是的圖像列表

    ZeroMemory(tbb, sizeof(tbb));
    tbb[0].iBitmap =MAKELONG(0,0) ;
    tbb[0].fsState = TBSTATE_ENABLED;
    tbb[0].fsStyle = TBSTYLE_BUTTON|BTNS_AUTOSIZE;
    tbb[0].idCommand = ID_FOPEN; 
    tbb[0].iString = (INT_PTR)TEXT("打開");
    tbb[1].iBitmap =MAKELONG(1,0);
    tbb[1].fsState = TBSTATE_ENABLED;
    tbb[1].fsStyle = TBSTYLE_BUTTON|BTNS_AUTOSIZE;
    tbb[1].idCommand = ID_FCLOSE; 
    tbb[1].iString = (INT_PTR)TEXT("關閉");
    tbb[2].iBitmap =MAKELONG(2,0);
    tbb[2].fsState = TBSTATE_ENABLED;
    tbb[2].fsStyle = TBSTYLE_BUTTON|BTNS_AUTOSIZE;
    tbb[2].idCommand = ID_FSAVE;
    tbb[2].iString = (INT_PTR)TEXT("保存");
    SendMessage(hWndTB, TB_ADDBUTTONS, sizeof(tbb)/sizeof(TBBUTTON), (LPARAM)&tbb); //配置工具欄按鈕信息
    SendMessage(hWndTB,WM_SIZE,0,0);

    return hWndTB;
}

HWND CreateStatusBar(HWND hParentWnd)
{
#define PANEL_NUM 3
    int array[PANEL_NUM]={120,120*2,-1};
    HINSTANCE hInst = GetModuleHandle(NULL);
    //建立Statusbar控件
    HWND hWndStatus = CreateWindowEx(0, STATUSCLASSNAME, TEXT(""), WS_CHILD|WS_BORDER|WS_VISIBLE, 0, 0, 0, 0, hParentWnd, (HMENU)IDC_STATUSBAR, hInst, NULL);
    if (hWndStatus)
    {
        SendMessage(hWndStatus,SB_SETPARTS,(WPARAM)PANEL_NUM,(LPARAM)array); //設置面板個數
        SendMessage(hWndStatus,SB_SETTEXT,(LPARAM)1,(WPARAM)TEXT("panel-1")); //設置第二個面板內容
        SendMessage(hWndStatus,SB_SETTEXT,(LPARAM)2,(WPARAM)TEXT("panel-2")); //設置第三個面板內容
    }
#undef PANEL_NUM

    return hWndStatus;
}

static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC         hDC;
    PAINTSTRUCT ps;
    static HWND hToolbar;
    static HWND hStatusbar;

    switch (message)
    {
    case WM_CREATE:
        hToolbar = CreateToolbar(hWnd);
        hStatusbar = CreateStatusBar(hWnd);
        return 0;
	
    case WM_COMMAND:
    {
        int wmId    = LOWORD(wParam);
        int wmEvent = HIWORD(wParam);

        // 分析菜單選擇:
        switch (wmId)
        {
        case ID_FOPEN:
            SendMessage(hToolbar, TB_ENABLEBUTTON, (WPARAM)ID_FOPEN, (LPARAM)MAKELONG(FALSE,0));
            SendMessage(hToolbar, TB_ENABLEBUTTON, (WPARAM)ID_FSAVE, (LPARAM)MAKELONG(TRUE,0));
            break;
        case ID_FSAVE:
            SendMessage(hToolbar, TB_ENABLEBUTTON, (WPARAM)ID_FSAVE, (LPARAM)MAKELONG(FALSE,0));
            SendMessage(hToolbar, TB_ENABLEBUTTON, (WPARAM)ID_FOPEN, (LPARAM)MAKELONG(TRUE,0));
            break;
        case ID_FCLOSE:
            MessageBox(hWnd, TEXT("click!"), TEXT("hint"), MB_OK);
            break;
        }
    }
    return 0;

    case WM_NOTIFY:
    {
        LPNMHDR lpnmhdr=(LPNMHDR)lParam;
        LPTOOLTIPTEXT lpttext;

        if(lpnmhdr->code==TTN_GETDISPINFO)  
        {
            //處理鼠標在工具欄上懸浮移動時的文本提示
            lpttext=(LPTOOLTIPTEXT)lParam;
            switch(lpttext->hdr.idFrom)
            {
            case ID_FOPEN:
                lpttext->lpszText=TEXT("打開文件");
                break;

            case ID_FCLOSE:
                lpttext->lpszText=TEXT("關閉文件");
                break;

            case ID_FSAVE:
                lpttext->lpszText=TEXT("保存爲文件");
                break;
            }
        }
    }
    return 0;

    case WM_SIZE:
    {
        SendMessage(hToolbar, TB_AUTOSIZE, 0, 0);
        SendMessage(hStatusbar, WM_SIZE, 0, 0); 
    }
    return 0;

    case WM_MOUSEMOVE:
    {
        TCHAR szBuf[MAX_PATH];
        _stprintf(szBuf,TEXT("Mouse(%d,%d)"),LOWORD(lParam),HIWORD(lParam));
        SendMessage(hStatusbar, SB_SETTEXT, 0, (LPARAM)(LPSTR)szBuf);
    }
    return 0;

    case WM_PAINT:
        hDC = BeginPaint(hWnd, &ps);
        ;
        EndPaint(hWnd, &ps);
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0 ;
    }
    return DefWindowProc (hWnd, message, wParam, lParam);
}

該實例程序後,結果顯示以下圖:

toolbar_statusbar

該程序的工具欄按下「打開」按鈕後,本身後變成Disable狀態,點擊「保存」後,「打開」按鈕會再次激活。能夠看到,在鼠標移到「保存」按鈕上時,出現提示「保存爲文件」的文本提示。

狀態欄一共有三個面板,後面兩個在建立時靜態賦字符串,第一個則實時捕獲鼠標在客戶區中的座標位置並顯示出來。

整體來講工具欄和狀態欄的基本用法仍是比較簡單,只是因爲這兩個控件屬於微軟的通用控件,建立以前須要調用InitCommonControlsEx初始化通用控件庫並設置須要使用的控件。本篇就寫到這裏,感興趣的讀者請繼續關注Windows編程基礎系列的後續文章。

  更多經驗交流能夠加入Windows編程討論QQ羣454398517


關注微信公衆平臺:程序員互動聯盟(coder_online),你能夠第一時間獲取原創技術文章,和(java/C/C++/Android/Windows/Linux)技術大牛作朋友,在線交流編程經驗,獲取編程基礎知識,解決編程問題。程序員互動聯盟,開發人員本身的家。

image010

轉載請註明出處,謝謝合做!

相關文章
相關標籤/搜索