0
点赞
收藏
分享

微信扫一扫

C++win32控件,组合框的封装

辰鑫chenxin 2022-03-27 阅读 70

组合框时程序的重要功能,几乎所有的软件都有组合框,使得软件更加人性化。下面我封装了一个简单的类,实现创建组合框,更改组合框选项。
运用一个简单的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)
在这里插入图片描述

举报

相关推荐

0 条评论