程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> Win32開發入門(12) 使用控件——單選按鈕

Win32開發入門(12) 使用控件——單選按鈕

編輯:關於C++

今天,咱們還是接著玩“控件斗地主”,這是我原創的超級游戲,有益身心健康,玩一朝,十年少 。

哦,對,腦細胞極速運動了一下,想起了一個問題,這個破問題雖然網上有很多種解決方案 ,但是,並沒有讓所有人都解決問題。

不知道大家有沒有調用過LoadIconMetric函數,這個函 數在靜態庫Comctl32.lib中有定義(當然,動態庫也有),不過,創建項目的時候,默認並沒有引用它 的,於是,大家知道,解決調用的方法就是在代碼中加上:

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

我一般習慣這種方法,這樣不必去修改項目屬性。但是, 很多朋友說過,在Win 7以後的系統,依然沒有成功,我也嘗到了調用失敗的“甜頭”,我一直在想, 這是為什麼呢?

於是,我又試了另一種方法,就是用LoadLibrary加載Comctl32.dll,然後通過 函數指針去調用它:

typedef LRESULT (WINAPI * pLoadICMT)(.......);

但結果還是沒 成功,GetProcAddress返回的地址為0,又一次嘗到了失敗帶來的“刺激”感。

直到某一天,我 在寫某程序時,從上一文中大家都看到,那個按鈕的視覺風格和Win9x/2000差不多,似乎沒有XP那種充 滿美學水准的效果。其實,這是因為我們的程序沒有啟用視覺效果,默認情況下,使用版本5中的控件 ,而要有XP以上的風格,是在版本6的控件內庫中才有。

當然方法可以很多人都知道,就是定義 一個用於視覺效果的清單文件,本質是XML格式。不過我用的開發工具是VS 2005之後的版本,就不用弄 個XML文件那麼麻煩了,直接到MSDN上復制粘貼這段代碼放到你的代碼文件(.cpp)中,就是這個,直 接抄過來就行了,適當的時候,要巧用MSDN上的資源。

// 開啟視覺效果 Copy from MSDN     
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

version是版本號,要有好看的效果,記得要6,不要寫用低版本的。processorArchitecture是處理 器平台,x86或amd64,用*號最好,通殺。

真是巧啊,原來這麼一來,噗,LoadIconMetric也能 調用了。總的來說,就是在代碼文件加上以下內容:

#include <CommCtrl.h> //包含頭文件     
// 導入靜態庫     
#pragma comment(lib, "Comctl32.lib")     
// 開啟視覺效果 Copy from MSDN     
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

這問題干掉了,開始今天的吹牛大行動。

單選按鈕,是的,在WinForm裡面你肯定知道, RadioButto,復選框就是CheckBox。不過那個時候.NET還沒那麼猛,那個時代,就是玩VB6,所以我知 道VB裡面,單選按鈕叫Option吧。

然後找遍了Win32的控件庫,怎麼沒見Radio和CheckBox,於 是,我陷入了萬分痛苦之中。不久後閱讀MSDN文檔,我就明白了,其實這兩個玩意兒都是BUTTON類的, 只是應用了不同的style罷了。

好的,咱們先來弄一個單選的吧。

case WM_CREATE:   

  
    {     
        CreateWindow(L"Button",L"這玩意兒好",     
            BS_RADIOBUTTON | WS_CHILD | WS_VISIBLE,     
            10,10,150,28,     
            hwnd, (HMENU)IDC_RADBTN1,      
            (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE),     
            NULL);     
    }     
    return 0;

應用BS_RADIOBUTTON樣式,就可以使按鈕變成單選按鈕,不過,別忘了 WS_CHILD | WS_VISIBLE。

運行一下。

不過,當你點擊它的時候,會發現它並不會選中,那是因為BS_RADIOBUTTON樣式不會自動讓 它選上。我們換一種可以自動處理的樣式,帶AUTO打頭的。

就是用 BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE,如下圖的預覽結果。

接下來,我們多創建幾個吧。

/*---------------------------------------

--------------------------*/ 
//控件ID     
#define IDC_RADBTN1     50001     
#define IDC_RADBTN2     50002     
#define IDC_RADBTN3     50003     
#define IDC_RADBTNBLUE      51001     
#define IDC_RADBTNRED       51002     
#define IDC_RADBTNGREEN     51003     
/*-----------------------------------------------------------------*/ 
// 消息處理函數     
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)     
{     
    switch(msg)     
    {     
    case WM_CREATE:     
        {     
            // 獲取當前實例句柄     
            HINSTANCE hthisapp = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE);     
            // 縱坐標,控件將以此作為基准,     
            // 排列時依次增加     
            int yLoc = 0;     
            // 用來顯示文本     
            yLoc += 10;     
            CreateWindow(L"Static",L"請問你的性別是:",     
                SS_SIMPLE | WS_CHILD | WS_VISIBLE,     
                10,yLoc,160,18,     
                hwnd, NULL,      
                hthisapp,     
                NULL);     
            // 第一組單選按鈕     
            yLoc += 22;     
            CreateWindow(L"Button",L"男",     
                WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_GROUP,      
                12, yLoc, 60, 16,     
                hwnd,     
                (HMENU)IDC_RADBTN1,     
                hthisapp,NULL);     
            yLoc += 20;     
            CreateWindow(L"Button",L"女",     
                WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,      
                12,yLoc, 60, 16,     
                hwnd,(HMENU)IDC_RADBTN2,hthisapp,NULL);     
            yLoc += 20;     
            CreateWindow(L"Button",L"人妖",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,     
                12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTN3,hthisapp,NULL);     
            // 顯示文本     
            yLoc += 38;     
            CreateWindow(L"Static",L"你喜歡哪一種顏色?",     
                WS_CHILD | WS_VISIBLE | SS_SIMPLE,     
                10,yLoc,150,18,hwnd,NULL,hthisapp,NULL);     
            //第二組單選按鈕     
            yLoc += 22;     
            CreateWindow(L"Button",L"藍色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | 

WS_GROUP,     
                12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNBLUE,hthisapp,NULL);     
            yLoc += 20;     
            CreateWindow(L"Button",L"紅色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,     
                12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNRED,hthisapp,NULL);     
            yLoc += 20;     
            CreateWindow(L"Button",L"綠色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,     
                12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNGREEN,hthisapp,NULL);     
        }     
        return 0;     
    case WM_DESTROY:     
        PostQuitMessage(0); //平安退出     
        return 0;     
    default:     
        return DefWindowProc(hwnd,msg,wParam,lParam);     
    }     
    return 0;     
}

在創建單選框中,為什麼有些加了WS_GROUP樣式,而有些未加呢?

其實是這樣的, 既然單選按鈕是單選的,那麼,任何一個單選按鈕都與其他的單選按鈕是互斥的關系。所以,在同一個 容器(本例是同一個窗口)中就需要把單選按鈕進行分組。

同一組中的單選按鈕相互排斥,他 的分組方法:

順序,以Tab鍵順序為參考,這個不用我介紹,你隨便打開一個窗口,然後多按幾 下Tab鍵你就懂了,如果不懂,那你真的無可救藥了。

凡是設置了WS_GROUP的單選框做為一組中 的首元素,隨後的所有單選按鈕都和它在同一組,直到下一個設置了WS_GROUP樣式的單選按鈕。用上面 的例子來說吧。

性別一組中,第一個應用了WS_GROUP的是“男”,隨後的“女”和“人妖”都 與“男”在同一組,因為後面一個“藍色”設置了WS_GROUP樣式。所以,

第一組為:男,女, 人妖;

第二組為:藍色,紅色,綠色。

顯然,用了BS_AUTORADIOBUTTON後,系統就會自 動處理選擇狀態了。

完整的代碼清單如下:

#include <Windows.h>     
#include <WindowsX.h>     
#include <CommCtrl.h> //包含頭文件     
// 導入靜態庫     
#pragma comment(lib, "Comctl32.lib")     
// 開啟視覺效果 Copy from MSDN     
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")     
         
// 先聲明一個WindowProc回調     
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);     
// 入口點     
int WINAPI wWinMain(HINSTANCE hTheApp, HINSTANCE hPrevApp, LPWSTR lpCmd, int nShow)     
{     
    PCWSTR cn = L"My"; // 窗口名     
    PCWSTR tt = L"應用程序"; // 窗口標題     
    // 設計窗口類     
    WNDCLASS wc = { sizeof(WNDCLASS) };     
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;     
    wc.lpfnWndProc = WindowProc;     
    wc.style = CS_HREDRAW | CS_VREDRAW;     
    LoadIconMetric(hTheApp, IDI_APPLICATION, LIM_SMALL, &wc.hIcon);     
    wc.lpszClassName = cn;     
    wc.hInstance = hTheApp;     
    RegisterClass(&wc); // 注冊窗口類     
    // 創建窗口     
    HWND hwnd = CreateWindow(cn, tt,WS_OVERLAPPEDWINDOW,     
        28,34,400,330,NULL,NULL,hTheApp,NULL);     
    if( !hwnd)     
    { /* 如果窗口創建失敗,    
         那繼續執行也沒有意義    
        長痛不如短痛,結束吧。     
      */ 
        return 0;     
    }     
    ShowWindow(hwnd,nShow); //顯示窗口     
    UpdateWindow(hwnd); //更新窗口     
    // 消息循環     
    MSG msg;     
    while(GetMessage(&msg,NULL,0,0))     
    {     
        TranslateMessage(&msg);     
        DispatchMessage(&msg); //調度消息到WindowProc回調     
    }     
    return 0;     
}     
         
/*-----------------------------------------------------------------*/ 
//控件ID     
#define IDC_RADBTN1         50001     
#define IDC_RADBTN2         50002     
#define IDC_RADBTN3         50003     
#define IDC_RADBTNBLUE      51001     
#define IDC_RADBTNRED       51002     
#define IDC_RADBTNGREEN     51003     
#define IDC_BTN_OK          1107 //確定按鈕ID     
/*-----------------------------------------------------------------*/ 
// 消息處理函數     
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)     
{     
    switch(msg)     
    {     
    case WM_CREATE:     
        {     
            // 獲取當前實例句柄     
            HINSTANCE hthisapp = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE);     
            // 縱坐標,控件將以此作為基准,     
            // 排列時依次增加     
            int yLoc = 0;     
            // 用來顯示文本     
            yLoc += 10;     
            CreateWindow(L"Static",L"請問你的性別是:",     
                SS_SIMPLE | WS_CHILD | WS_VISIBLE,     
                10,yLoc,160,18,     
                hwnd, NULL,      
                hthisapp,     
                NULL);     
            // 第一組單選按鈕     
            yLoc += 22;     
            CreateWindow(L"Button",L"男",     
                WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_GROUP,      
                12, yLoc, 60, 16,     
                hwnd,     
                (HMENU)IDC_RADBTN1,     
                hthisapp,NULL);     
            yLoc += 20;     
            CreateWindow(L"Button",L"女",     
                WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,      
                12,yLoc, 60, 16,     
                hwnd,(HMENU)IDC_RADBTN2,hthisapp,NULL);     
            yLoc += 20;     
            CreateWindow(L"Button",L"人妖",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,     
                12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTN3,hthisapp,NULL);     
            // 顯示文本     
            yLoc += 38;     
            CreateWindow(L"Static",L"你喜歡哪一種顏色?",     
                WS_CHILD | WS_VISIBLE | SS_SIMPLE,     
                10,yLoc,150,18,hwnd,NULL,hthisapp,NULL);     
            //第二組單選按鈕     
            yLoc += 22;     
            CreateWindow(L"Button",L"藍色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | 

WS_GROUP,     
                12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNBLUE,hthisapp,NULL);     
            yLoc += 20;     
            CreateWindow(L"Button",L"紅色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,     
                12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNRED,hthisapp,NULL);     
            yLoc += 20;     
            CreateWindow(L"Button",L"綠色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,     
                12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNGREEN,hthisapp,NULL);     
            // 創建一個確定按鈕     
            CreateWindow(L"Button",L"確定",WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,     
                230,180,80,27,hwnd,(HMENU)IDC_BTN_OK,hthisapp,NULL);     
        }     
        return 0;     
    case WM_DESTROY:     
        PostQuitMessage(0); //平安退出     
        return 0;     
    default:     
        return DefWindowProc(hwnd,msg,wParam,lParam);     
    }     
    return 0;     
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved