组合框时程序的重要功能,几乎所有的软件都有组合框,使得软件更加人性化。下面我封装了一个简单的类,实现创建组合框,更改组合框选项。
运用一个简单的win32对话框程序,使用我封装的类CComBox,创建了三个组合框显示在窗口左上角。(第三个组合框没有成功创建)
效果如下:
废话少说,上代码:
1、定义CComBox类的头文件:CComBox.h
#pragma once
#include <windows.h>
#include<vector>
#include<iostream>
#include <string> // string
class CComBox
{
public:
CComBox(int NumOfComBox):LimitNumForComBox(NumOfComBox) {}//构造函数传参,确定一个类对象可以最多建立多少个组合框
~CComBox()
{
for (auto itr = Myhwnd.begin(); itr != Myhwnd.end(); ++itr)
{
DestroyWindow(*itr);
}
}
/*
* HWND hWnd, 组合框所从属的父窗口句柄
*HINSTANCE g_hInst,应用程序识别符
*INT PosX,左上角X坐标
*INT PosY,左上角Y坐标
*INT Width,组合框的宽度
*INT Height,组合框的高度
*INT ComBoxID组合框的识别符,在没有使用资源预先创建组合框的情况下,没有定义资源、没有资源ID的情况下ComBoxID就是资源ID
*/
HWND OnCreate(HWND hWnd, HINSTANCE g_hInst,INT PosX,INT PosY,INT Width,INT Height,INT ComBoxID)
{
if (Myhwnd.size() >= LimitNumForComBox)
{
char tmp[124];
wsprintfA(tmp, "CComBox类实例化对象设定只能建立%d个组合框,建立的组合框数量超过了设定的值", LimitNumForComBox);
MessageBoxA(NULL, tmp, "建立这么多组合框干么啊!", MB_OK);
return 0;
}
//组合框的创建:窗口类名称是 COMBOBOX, 使用CreateWindow创建, 创建时要注意窗口高度(弹出的列表).
//1.1 简单组合框 CBS_SIMPLE,简单组合框的创建
//CreateWindowW(L"COMBOBOX", L"SIMPLE", WS_CHILD | WS_VISIBLE | CBS_SIMPLE, 50, 50, 120, 300, hWnd, (HMENU)1001, g_hInst, NULL);
1.2 下拉式组合框 CBS_DROPDOWN 能输入或者从下拉列表中选择,下拉式组合框的创建
//CreateWindowW(L"COMBOBOX", L"DROPDOWN", WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWN, 200, 50, 120, 300, hWnd, (HMENU)1002, g_hInst, NULL);
//1.3 下拉列表式组合框 CBS_DROPDOWNLIST只能从下拉列表中选择,下拉列表式组合框的创建
HWND hwnd = 0;
hwnd=CreateWindowA("COMBOBOX", "hWComBoxList", WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST, PosX, PosY, Width, Height, hWnd, (HMENU)ComBoxID, g_hInst, NULL);
Myhwnd.push_back(hwnd);//保存建立的组合框子窗口句柄
return hwnd;
}
/*
* 给组合框添加选项
* HWND hWComBox ,组合框的子窗口句柄
*std::vector<std::string>SelectionsOfComBox 组合框的选项
*/
void AddSelectionsForComBox(HWND hWComBox ,std::vector<std::string>SelectionsOfComBox)
{
for (auto itr = SelectionsOfComBox.begin(); itr != SelectionsOfComBox.end(); ++itr)
{
SendMessageA(hWComBox, CB_ADDSTRING, 0, (LPARAM)itr->c_str());
}
}
/*
此处应该是回调函数
*/
void OnSelect(HWND hWnd,INT ComBoxID)
{
//2.4 选择
// CB_GETCURSEL 获取被选择项
// CB_SETCURSEL 设置当前的选择项
// CB_SELECTSTRING 设置选择指定的字符串所对应的项
//获取COMBOBOX窗口句柄
HWND hDropList = GetDlgItem(hWnd, ComBoxID);//没有定义资源、没有资源ID的情况下这样用
//获取和设置选择项
//2.6 获取选项或者被选择字符串
// CB_GETLBTEXT 获取选项的字符串
// WM_GETTEXT 获取被选择到窗口的字符串
LRESULT nSel = SendMessage(hDropList, CB_GETCURSEL, 0, 0);//选中了组合框的第nSel项
//获取数据
LRESULT nValue = SendMessage(hDropList, CB_GETITEMDATA, nSel, 0);//第nSel项的内容是
WCHAR szInfo[260] = { 0 };
wsprintfW(szInfo, L"选中了组合框的第%d项,其内容是:%d", nSel,nValue);
MessageBox(NULL, szInfo, L"WinCombo", MB_OK);
//设置选择项
//SendMessage(hDropDown, CB_SETCURSEL, nSel, 0);
//CHAR szText[] = "ComboBox 5";
//SendMessage(hDropList, CB_SELECTSTRING, -1, (LPARAM)szText);
}
/*
** 更改组合框的选项
** HWND hWComBox, 所要改变选项的组合框(即该组合框子窗口句柄)
** std::vector<std::string>SelectionsOfComBox新的组合框选项
*/
void ChangeSelections(HWND hWComBox, std::vector<std::string>SelectionsOfComBox)
{
SendMessage(hWComBox, CB_RESETCONTENT, 0, 0);//清除旧的组合框的所有选项,然后重新加载选项
int i = 0;
//给合约组合框加载市场的合约数据
for (auto iter = SelectionsOfComBox.begin(); iter != SelectionsOfComBox.end(); ++iter)
{
if (i == 0)
{
SendMessageA(hWComBox, CB_ADDSTRING, i, (LPARAM)const_cast<char*>(iter->c_str()));//倒数第二个参数wparam应该是选项的序号,
}
else
{
SendMessageA(hWComBox, CB_INSERTSTRING, i, (LPARAM)const_cast<char*>(iter->c_str()));//倒数第二个参数wparam应该是选项的序号,
}
i++;
}
}
/*
** 获取选项的内容,对于有很多选项的组合框来说,逐一识别意义不是很大,只要能知道选项的内容即可
** HWND hWnd,父窗口句柄,在WM_COMMAND消息下面有实参
** INT ComBoxID组合框资源标识符
*/
char* GetSelectionStr(HWND hWnd, INT ComBoxID)
{
//2.4 选择
// CB_GETCURSEL 获取被选择项
// CB_SETCURSEL 设置当前的选择项
// CB_SELECTSTRING 设置选择指定的字符串所对应的项
//获取COMBOBOX窗口句柄
HWND hDropList = GetDlgItem(hWnd, ComBoxID);//没有定义资源、没有资源ID的情况下这样用
//获取和设置选择项
//2.6 获取选项或者被选择字符串
// CB_GETLBTEXT 获取选项的字符串
// WM_GETTEXT 获取被选择到窗口的字符串
LRESULT nSel = SendMessageA(hDropList, CB_GETCURSEL, 0, 0);//选中了组合框的第nSel项
char* szInfo=new char[124] ;
//获取数据
SendMessageA(hDropList, CB_GETLBTEXT, nSel, (LPARAM)szInfo);//第nSel项的内容是
//wsprintfA(szInfo, "选中了组合框的第%d项,其内容是:%s", nSel, szInfo);
//MessageBoxA(NULL, szInfo, "WinCombo", MB_OK);
return szInfo;
}
private:
int LimitNumForComBox = 0;//最多可以建立的组合框数量,构造函数传参确定
std::vector<HWND>Myhwnd;//把组合框子窗口句柄放在vector里面,方便操作
};
2、调用CComBox类的cpp文件:Win32ComboBox.cpp
#include <Windows.h>
#include "resource.h"
#include"CComBox.h"
/*此程序的目的就是检验CComBox类的使用方法*/
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
HWND hdlg;
HINSTANCE hgInst;
CComBox combox(2);// CComBox类的实例化对象,一个类对象combox可以建立2个CComBox控件
HWND hCBox_1;//第一个ComBox控件
HWND hCBox_2;//第二个ComBox控件
HWND hCBox_3;//第三个ComBox控件
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevApp, LPSTR lpCmd, int nShow)
{
hgInst = hInst;
//在资源文件中建立对话框,ID号:IDD_MY_DIALOG
//预先定义好对话框窗口过程函数DlgProc
hdlg = CreateDialogW(hInst, MAKEINTRESOURCE(IDD_MY_DIALOG), NULL, (DLGPROC)DlgProc);
if (!hdlg)
{
return 0;
}
ShowWindow(hdlg, SW_SHOW);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
//第一个ComBox控件,左上角的坐标点:P(10,10),宽为100,高为300,WM_COMMAND消息下控件的识别码1001
hCBox_1 = combox.OnCreate(hDlg, hgInst, 10, 10, 100, 300, 1001);
std::vector<std::string>SelectionsOfComBox = { "上海","郑州","大连","中金所","能源" };
combox.AddSelectionsForComBox(hCBox_1, SelectionsOfComBox);
SelectionsOfComBox.clear();
//第二个ComBox控件,左上角的坐标点:P(120,10),宽为100,高为300,WM_COMMAND消息下控件的识别码1002
hCBox_2 = combox.OnCreate(hDlg, hgInst, 120, 10, 100, 300, 1002);
//第三个ComBox控件,左上角的坐标点:P(230,10),宽为100,高为300,WM_COMMAND消息下控件的识别码1003
//第三个ComBox控件,是没有成功建立的,因为CComBox类的实例化对象 combox(2)参数为2,只能建立2个ComBox控件
hCBox_3 = combox.OnCreate(hDlg, hgInst, 230, 10, 50, 300, 1003);//会弹出MessageBox()提示框,显示没有成功创建
return (INT_PTR)TRUE;
}
break;
case WM_SYSCOMMAND:
{
if (wParam == SC_CLOSE)
{
DestroyWindow(hdlg);//销毁窗口
PostQuitMessage(0);//退出进程
}
return 0;
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))//WM_COMMAND消息低字节表示来源:来自窗口内部不同控件的点击消息
{
case IDOK:
{
DestroyWindow(hdlg);//销毁窗口
PostQuitMessage(0);//退出进程
return (INT_PTR)TRUE;
}
break;
case IDCANCEL:
{
DestroyWindow(hdlg);//销毁窗口
PostQuitMessage(0);//退出进程
return (INT_PTR)TRUE;
}
break;
case 1001://控件1hCBox_1创建时设定的标识符1001
{
if(HIWORD(wParam) == CBN_SELCHANGE)WM_COMMAND消息高字节表示控件内部不同选项被点击的点击消息
{
INT NumSelect = SendMessage(hCBox_1, CB_GETCURSEL, 0, 0);//结果正确,分别为0、1、2、3、4选项CB_GETLBTEXT
std::vector<std::string>vect_zhuli;//定义一个vector保存hCBox_2控件的选项
switch (NumSelect)
{
case 0://选项0,切换上海市场,合约组合框加载上海合约
{
SendMessageW(hCBox_1, CB_SETCURSEL, 0, 0);///交易所组合框默认0项被选中(上海),仅仅是界面上看看,并不代表实际的数据传递
vect_zhuli = { "上海1","上海2", "上海3", "上海4", "上海5", "上海6", "上海7", "上海8", "上海9", "上海10", "上海11", "上海12", "上海13", "上海14", "上海15" };
}
break;
case 1://选项1,切换郑州市场,合约组合框加载郑州合约
{
SendMessageW(hCBox_1, CB_SETCURSEL, 1, 0);///交易所组合框默认1项被选中(郑州),仅仅是界面上看看,并不代表实际的数据传递
vect_zhuli = { "郑州1","郑州2", "郑州3", "郑州4", "郑州5", "郑州6", "郑州7", "郑州8", "郑州9", "郑州10", "郑州11", "郑州12", "郑州13", "郑州14", "郑州15" };
}
break;
case 2://选项2,切换大连市场,合约组合框加载大连合约
{
SendMessageW(hCBox_1, CB_SETCURSEL, 2, 0);///交易所组合框默认2项被选中(大连),仅仅是界面上看看,并不代表实际的数据传递
vect_zhuli = { "大连1","大连2", "大连3", "大连4", "大连5", "大连6", "大连7", "大连8", "大连9", "大连10", "大连11", "大连12", "大连13", "大连14", "大连15" };
}
break;
case 3://选项3,切换中金所市场,合约组合框加载中金所合约
{
SendMessageW(hCBox_1, CB_SETCURSEL, 3, 0);///交易所组合框默认3项被选中(中金所),仅仅是界面上看看,并不代表实际的数据传递
vect_zhuli = { "中金所1","中金所2", "中金所3", "中金所4", "中金所5", "中金所6", "中金所7", "中金所8", "中金所9", "中金所10", "中金所11", "中金所12", "中金所13", "中金所14", "中金所15" };
}
break;
case 4://选项4,切换能源市场,合约组合框加载能源中心合约
{
SendMessageW(hCBox_1, CB_SETCURSEL, 4, 0);///交易所组合框默认4项被选中(能源),仅仅是界面上看看,并不代表实际的数据传递
vect_zhuli = { "能源1","能源2", "能源3", "能源4", "能源5", "能源6", "能源7", "能源8", "能源9", "能源10", "能源11", "能源12", "能源13", "能源14", "能源15" };
}
break;
default:
break;
}
combox.ChangeSelections(hCBox_2, vect_zhuli);//根据控件hCBox_1点击的不同选项,给hCBox_2加载相应的vect_zhuli选项
vect_zhuli.clear();
}
}
break;
case 1002://控件1hCBox_2创建时设定的标识符1002
{
if (HIWORD(wParam) == CBN_SELCHANGE)WM_COMMAND消息高字节表示控件内部不同选项被点击的点击消息
{
char* szInfo = new char[124];
szInfo = combox.GetSelectionStr(hDlg, 1002);
MessageBoxA(NULL, szInfo, "第二个组合框的选项", MB_OK);
delete[]szInfo;
}
}
break;
case 1003://控件1hCBox_3创建时设定的标识符1003
{
//这个控件从来就没有创建成功
//因为:第8行代码:
//CComBox combox(2);// CComBox类的实例化对象,一个类对象combox可以建立2个CComBox控件
}
break;
default:
break;
}
}
break;
}
return (INT_PTR)FALSE;
}
3、在资源视图下新建对话框,对话框ID号:IDD_MY_DIALOG,(为了与我的代码匹配,一定要把资源文件里的对话框设为ID设为IDD_MY_DIALOG)