当前位置:首页 >> 编程开发 >> Visual C++ >> 内容

Win32开发入门(12) 使用控件——单选按钮

时间:2015/5/19 21:32:34 作者:平凡之路 来源:xuhantao.com 浏览:

今天,咱们还是接着玩“控件斗地主”,这是我原创的超级游戏,有益身心健康,玩一朝,十年少 。

哦,对,脑细胞极速运动了一下,想起了一个问题,这个破问题虽然网上有很多种解决方案 ,但是,并没有让所有人都解决问题。

不知道大家有没有调用过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;     
}

相关文章
  • 没有相关文章
  • 徐汉涛(www.xuhantao.com) © 2024 版权所有 All Rights Reserved.
  • 部分内容来自网络,如有侵权请联系站长尽快处理 站长QQ:965898558(广告及站内业务受理) 网站备案号:蒙ICP备15000590号-1