SDK05- 控件

一、常用控件


标签和单选框、复选框简介

控件名称:参数:返回值:样式:
标签:Static Text作用:提示

image.png |
| 复选框:Check Box | wParam 必须为0 | 返回控件状态:

  • 选中
  • 未选中
  • 三态(额外)
    | |
    | | lParam 必须为0 | | |
    | 单选框:Radio Box | | | |
    | | | | |

获取控件文本的五种方式

检索指定对话框中控件的句柄。GetDlgItem
SendMessage(hEdt, EM_GETLINE, 0, (LPARAM)szBuf)
WM_GETTEXT专门拿窗口上的文本SendMessage(hEdt, WM_GETTEXT, sizeof(szBuf), (LPARAM)szBuf);
专门给指定的控件发消息(推荐)SendDlgItemMessage(hwndDlg, ID_TEXT, WM_GETTEXT, sizeof(szBuf), (LPARAM)szBuf);
专门获取句柄上的文本GetWindowText(hwndDlg, szBuf, sizeof(szBuf));
获取控件文本GetDlgItemText(hwndDlg, ID_TEXT, szBuf, sizeof(szBuf));
控件文本转整形UINT val = GetDlgItemInt(hwndDlg, ID_TEXT, NULL, NULL);

1. 单选框

** 说明**
多个单选框在创建的时候属于用一个组,只能选择其中的一个。
在这里插入图片描述

单选框分组是通过属性“ 组 ”来分开的 (当前组和下一个组中间的作为一组)
在这里插入图片描述

CTRL + D 可以改变控件 焦点 的顺序,可以实现 不同一行的作为一组
image.png
也可以通过修改 .rc 文件 来改变 焦点顺序
image.png

特征:上一个单选框属性组为True 到下一个 单选框属性为True 为一组。
image.png

2. 复选框

BM_GETCHECK消息
消息含义:向控件发送该消息以检查复选框或则单选按钮复选状态
参数:

  • wParam 必须为0
  • lParam 必须为0

消息代码:

SendDlgItemMessage (对话框句柄,控件ID,消息,00)

返回控件状态:
![image.png](https://img-blog.csdnimg.cn/img_convert/09ca201fd33729535aafcdf9da0be12b.png#clientId=ucf1f4be2-e32f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=660&id=u1634240f&margin=[object Object]&name=image.png&originHeight=759&originWidth=1402&originalType=binary&ratio=1&rotation=0&showTitle=false&size=675638&status=done&style=none&taskId=uf3fc8aa0-1fea-4ffb-924e-b542913cea0&title=&width=1219.1304600576827#averageHue=#bbb9b4&height=292&id=D8gyC&originHeight=759&originWidth=1402&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=&width=539.0119018554688)

  • 选中
  • 未选中
  • 三态

判断复选框是否被选中 SendDlgItemMessage API BM_GETCHECK
![image.png](https://img-blog.csdnimg.cn/img_convert/f3dc509fe597390d5401da02a285457d.png#clientId=ucf1f4be2-e32f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=93&id=u08a829ec&margin=[object Object]&name=image.png&originHeight=107&originWidth=537&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9400&status=done&style=none&taskId=u293fb96d-5ca7-417d-bf35-a6a9ceb3969&title=&width=466.9565314200968#averageHue=#d7d6d4&id=LPKat&originHeight=107&originWidth=537&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
**参数 : **
:::success
**句柄 **
复选框ID
**获取选中函数API **
**0 **
**0 **
:::

测试代码:

#include <windows.h>
#include "resource.h"
enum GenderType//复选框不能用枚举,枚举只能多个里面选择一个
{
	GT_NAN,
	GT_WOMAN,
	GT_UN,
	GT_OTH
};
GenderType g_nGender = GT_NAN;

//处理消息封装函数一般都是以On开头的,On表示正在处理
void OnGetRadioButton(HWND hwndDlg)
{
	if (SendDlgItemMessage(hwndDlg, CHK_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "写代码", "提示", MB_OK);
	}
	if (SendDlgItemMessage(hwndDlg, CHK_WRITE_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "改代码", "提示", MB_OK);
	}
	if (SendDlgItemMessage(hwndDlg, CHK_COPY_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "抄代码", "提示", MB_OK);
	}
	switch (g_nGender)
	{
	case GT_NAN:
		MessageBox(hwndDlg, "男", "提示", MB_OK);
		break;
	case GT_WOMAN:
		MessageBox(hwndDlg, "女", "提示", MB_OK);
		break;
	case GT_UN:
		MessageBox(hwndDlg, "未知", "提示", MB_OK);
		break;
	case GT_OTH:
		MessageBox(hwndDlg, "其他", "提示", MB_OK);
		break;
	default:
		break;
	}
}
INT_PTR CALLBACK TestDialogProc(
	HWND hwndDlg,  // handle to dialog box
	UINT uMsg,     // message  
	WPARAM wParam, // first message parameter
	LPARAM lParam  // second message parameter
)
{
	switch (uMsg)
	{
	case WM_COMMAND:
	{ 
		WORD wCtrlId = LOWORD(wParam);  //控件的ID
		WORD wNotiCode = HIWORD(wParam);//通告码
		HWND hCtrl = (HWND)lParam;//控件的窗口句柄
		switch (wNotiCode)
		{
		case BN_CLICKED:
			switch (wCtrlId)
			{
				case BTN_GET:
					OnGetRadioButton(hwndDlg);
					break;
				case RDB_MAN:
					g_nGender = GT_NAN;
					break;
				case RDB_WOMAN:
					g_nGender = GT_WOMAN;
					break;
				case RDB_UNKWNOW:
					g_nGender = GT_UN;
					break;
				case RDB_OTHER:
					g_nGender = GT_OTH;
					break;
				default:
					break;
			}
		}
		break;
	}
	case WM_CLOSE:
	{
		EndDialog(hwndDlg, 0);
		break;
	}
	default:
		return FALSE;
		break;
	}


	return TRUE;
}
int WINAPI WinMain( _In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPSTR lpCmdLine,
	_In_ int nShowCmd )
{


	return DialogBox(hInstance,MAKEINTRESOURCE(DLG_TEST),NULL, TestDialogProc);
}

使用SetWindowLong 优化全局变量
优化:
——怎么存:
**SetWindowLong **把数据存到窗口中(可以相当于自己在窗口里面定义了一个全局变量)
![image.png](https://img-blog.csdnimg.cn/img_convert/6b5fa916b8321b78afd83e7bcee285c3.png#clientId=ucf1f4be2-e32f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=72&id=Rqoca&margin=[object Object]&name=image.png&originHeight=83&originWidth=431&originalType=binary&ratio=1&rotation=0&showTitle=false&size=6429&status=done&style=none&taskId=u0694c7a0-ddc6-4174-aec8-b778a28e2bb&title=&width=374.78261646566426#averageHue=#dbd9d7&id=M96pW&originHeight=83&originWidth=431&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
属性分析:
窗口句柄;
索引值:其实有表,窗口的各种属性,这里我们只关注对话框的索引,DWL_USER //对话框索引,当索引值使用DWL_USER 其实就是存入我们自己的四个字节,
eg:SetWindowLong(hWndDlg, DWL_USER, (LONG)new DlgInfo{ GT_NAN });
——怎么取:
**GetWindowLong **从窗口中取出数据
![image.png](https://img-blog.csdnimg.cn/img_convert/7022df63027cc7729fbf918ac0c15774.png#clientId=ucf1f4be2-e32f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=57&id=Xuttn&margin=[object Object]&name=image.png&originHeight=66&originWidth=630&originalType=binary&ratio=1&rotation=0&showTitle=false&size=5391&status=done&style=none&taskId=ud857fdcd-780b-4ae4-beeb-a96a2fab9b2&title=&width=547.82609831408#averageHue=#dbdad9&id=V9AdU&originHeight=66&originWidth=630&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
参数分析:窗口句柄,索引值;
DWL_USER //对话框索引
eg:GetWindowLong(hWndDlg, DWL_USER);
Tip:调试下断点问题,新增一个
![image.png](https://img-blog.csdnimg.cn/img_convert/c50a6aa2773652edec8c4e65425633cb.png#clientId=ucf1f4be2-e32f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=843&id=jt4kO&margin=[object Object]&name=image.png&originHeight=970&originWidth=1250&originalType=binary&ratio=1&rotation=0&showTitle=false&size=498639&status=done&style=none&taskId=uaefd800e-cbde-4014-a3dc-63651fc5cc1&title=&width=1086.9565442739683#averageHue=#b3b4b1&id=iT51y&originHeight=970&originWidth=1250&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
优化后的代码:

#include <windows.h>
#include "resource.h"
enum GenderType//复选框不能用枚举,枚举只能多个里面选择一个
{
	GT_NAN,
	GT_WOMAN,
	GT_UN,
	GT_OTH
};
//GenderType g_nGender = GT_NAN;
struct DlgInfo
{
	GenderType m_nGender;
};
//处理消息封装函数一般都是以On开头的,On表示正在处理
void OnGetRadioButton(HWND hwndDlg)
{
	if (SendDlgItemMessage(hwndDlg, CHK_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "写代码", "提示", MB_OK);
	}
	if (SendDlgItemMessage(hwndDlg, CHK_WRITE_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "改代码", "提示", MB_OK);
	}
	if (SendDlgItemMessage(hwndDlg, CHK_COPY_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "抄代码", "提示", MB_OK);
	}
	DlgInfo* pDi = (DlgInfo*)GetWindowLong(hwndDlg, DWL_USER);
	switch (pDi->m_nGender)
	{
	case GT_NAN:
		MessageBox(hwndDlg, "男", "提示", MB_OK);
		break;
	case GT_WOMAN:
		MessageBox(hwndDlg, "女", "提示", MB_OK);
		break;
	case GT_UN:
		MessageBox(hwndDlg, "未知", "提示", MB_OK);
		break;
	case GT_OTH:
		MessageBox(hwndDlg, "其他", "提示", MB_OK);
		break;
	default:
		break;
	}
	/*switch (g_nGender)
	{
	case GT_NAN:
		MessageBox(hwndDlg, "男", "提示", MB_OK);
		break;
	case GT_WOMAN:
		MessageBox(hwndDlg, "女", "提示", MB_OK);
		break;
	case GT_UN:
		MessageBox(hwndDlg, "未知", "提示", MB_OK);
		break;
	case GT_OTH:
		MessageBox(hwndDlg, "其他", "提示", MB_OK);
		break;
	default:
		break;
	}*/
}
INT_PTR CALLBACK TestDialogProc(
	HWND hwndDlg,  // handle to dialog box
	UINT uMsg,     // message  
	WPARAM wParam, // first message parameter
	LPARAM lParam  // second message parameter
)
{
	switch (uMsg)
	{
	case WM_INITDIALOG:
	{
		SetWindowLong(hwndDlg, DWL_USER, (LONG)new DlgInfo{ GT_NAN });
		//设置默认,默认选中男
		SendDlgItemMessage(hwndDlg, RDB_MAN, BM_SETCHECK, BST_CHECKED, 0);
		return TRUE;
	}
	case WM_COMMAND:
	{ 
		WORD wCtrlId = LOWORD(wParam);  //控件的ID
		WORD wNotiCode = HIWORD(wParam);//通告码
		HWND hCtrl = (HWND)lParam;//控件的窗口句柄
		DlgInfo* pDi = (DlgInfo*)GetWindowLong(hwndDlg, DWL_USER);
		switch (wNotiCode)
		{
		case BN_CLICKED:
			switch (wCtrlId)
			{
				case BTN_GET:
					OnGetRadioButton(hwndDlg);
					break;
				case RDB_MAN:
					pDi->m_nGender = GT_NAN;
					break;
				case RDB_WOMAN:
					pDi->m_nGender = GT_WOMAN;
					break;
				case RDB_UNKWNOW:
					pDi->m_nGender = GT_UN;
					break;
				case RDB_OTHER:
					pDi->m_nGender = GT_OTH;
					break;
				/*case RDB_MAN:
					g_nGender = GT_NAN;
					break;
				case RDB_WOMAN:
					g_nGender = GT_WOMAN;
					break;
				case RDB_UNKWNOW:
					g_nGender = GT_UN;
					break;
				case RDB_OTHER:
					g_nGender = GT_OTH;
					break;*/
				default:
					break;
			}
		}
		break;
	}
	case WM_CLOSE:
	{
		EndDialog(hwndDlg, 0);
		break;
	}
	default:
		return FALSE;
		break;
	}


	return TRUE;
}
int WINAPI WinMain( _In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPSTR lpCmdLine,
	_In_ int nShowCmd )
{


	return DialogBox(hInstance,MAKEINTRESOURCE(DLG_TEST),NULL, TestDialogProc);
}

3. Combobox 下拉选框

1、类型

image.png
image.png

simple是在下面框里全部显示
dropdwown是点击右边选择按钮后显示所有 (可编辑选中的)
下拉列表是点击右边选择按钮后显示所有 (不可编辑选中的)

2、选框操作

添加选项 CB_ADDSTRING
//初始化Combobox
		list<string> lstCmb({ "北京","北海","深圳","浙江" });
		for (auto val:lstCmb)
		{
			SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_ADDSTRING, 0, (LPARAM)val.c_str());
		}
获取选框的索引值

int nSelIdx = SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETCURSEL, 0, 0);

获取选中的文本值

//获取Combobox选中信息
					int nSelIdx = SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETCURSEL, 0, 0);
					TCHAR szBuff[MAXBYTE] = { 0 };
					SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETLBTEXT, nSelIdx, (LPARAM)szBuff);
					MessageBox(hwndDlg, szBuff, "提示", MB_OK);
清除 CB_RESETCONTENT

SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_RESETCONTENT, nSelIdx, NULL);

实例代码:
#include <windows.h>
#include <list>
#include "resource.h"
#include <string>

using namespace std;
enum GenderType//复选框不能用枚举,枚举只能多个里面选择一个
{
	GT_NAN,
	GT_WOMAN,
	GT_UN,
	GT_OTH
};
//GenderType g_nGender = GT_NAN;
struct DlgInfo
{
	GenderType m_nGender;
};
//处理消息封装函数一般都是以On开头的,On表示正在处理
void OnGetRadioButton(HWND hwndDlg)
{
	if (SendDlgItemMessage(hwndDlg, CHK_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "写代码", "提示", MB_OK);
	}
	if (SendDlgItemMessage(hwndDlg, CHK_WRITE_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "改代码", "提示", MB_OK);
	}
	if (SendDlgItemMessage(hwndDlg, CHK_COPY_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "抄代码", "提示", MB_OK);
	}
	DlgInfo* pDi = (DlgInfo*)GetWindowLong(hwndDlg, DWL_USER);
	switch (pDi->m_nGender)
	{
	case GT_NAN:
		MessageBox(hwndDlg, "男", "提示", MB_OK);
		break;
	case GT_WOMAN:
		MessageBox(hwndDlg, "女", "提示", MB_OK);
		break;
	case GT_UN:
		//MessageBox(hwndDlg, "未知", "提示", MB_OK);
		break;
	case GT_OTH:
		//MessageBox(hwndDlg, "其他", "提示", MB_OK);
		break;
	default:
		break;
	}
	/*switch (g_nGender)
	{
	case GT_NAN:
		MessageBox(hwndDlg, "男", "提示", MB_OK);
		break;
	case GT_WOMAN:
		MessageBox(hwndDlg, "女", "提示", MB_OK);
		break;
	case GT_UN:
		MessageBox(hwndDlg, "未知", "提示", MB_OK);
		break;
	case GT_OTH:
		MessageBox(hwndDlg, "其他", "提示", MB_OK);
		break;
	default:
		break;
	}*/
}
INT_PTR CALLBACK TestDialogProc(
	HWND hwndDlg,  // handle to dialog box
	UINT uMsg,     // message  
	WPARAM wParam, // first message parameter
	LPARAM lParam  // second message parameter
)
{
	switch (uMsg)
	{
	case WM_INITDIALOG:
	{
		SetWindowLong(hwndDlg, DWL_USER, (LONG)new DlgInfo{ GT_NAN });
		//设置默认值,默认选中男
		SendDlgItemMessage(hwndDlg, RDB_MAN, BM_SETCHECK, BST_CHECKED, 0);
		
		
		//初始化Combobox
		list<string> lstCmb({ "北京","北海","深圳","浙江" });
		int n = 0x1001;
		for (auto val:lstCmb)
		{
			int nIdx = SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_ADDSTRING, 0, (LPARAM)val.c_str());
			//存入自定义数据
			SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_SETITEMDATA, nIdx, n++);
		}
		//设置默认值,默认选中北京
		SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_SETCURSEL, 0, 0);
		return TRUE;
	}
	case WM_COMMAND:
	{ 
		WORD wCtrlId = LOWORD(wParam);  //控件的ID
		WORD wNotiCode = HIWORD(wParam);//通告码
		HWND hCtrl = (HWND)lParam;//控件的窗口句柄
		DlgInfo* pDi = (DlgInfo*)GetWindowLong(hwndDlg, DWL_USER);
		switch (wNotiCode)
		{
		case BN_CLICKED:
			switch (wCtrlId)
			{
				case BTN_GET:
				{
					//获取Combobox选中信息
					//索引
					int nSelIdx = SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETCURSEL, 0, 0);
					
					//文本
					TCHAR szBuff[MAXBYTE] = { 0 };
					SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETLBTEXT, nSelIdx, (LPARAM)szBuff);
					

					//自定义数据
					int nData = SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETITEMDATA, nSelIdx, NULL);
					
					TCHAR szFmt[MAXBYTE] = {};
					wsprintf(szFmt, "%04X:%s",nData,szBuff);
					
					MessageBox(hwndDlg, szFmt, "提示", MB_OK);

					//获取复选框信息
					OnGetRadioButton(hwndDlg);
					break;					
				}
				case BTN_DELETE:
				{
					int nSelIdx = SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETCURSEL, 0, 0);
					//删除选择的信息
					//SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_DELETESTRING, nSelIdx, NULL);
					
					//删除所有的信息
					SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_RESETCONTENT, nSelIdx, NULL);
					break;
				}
				//获取单选框信息
				case RDB_MAN:
					pDi->m_nGender = GT_NAN;
					break;
				case RDB_WOMAN:
					pDi->m_nGender = GT_WOMAN;
					break;
				case RDB_UNKWNOW:
					pDi->m_nGender = GT_UN;
					break;
				case RDB_OTHER:
					pDi->m_nGender = GT_OTH;
					break;
				/*case RDB_MAN:
					g_nGender = GT_NAN;
					break;
				case RDB_WOMAN:
					g_nGender = GT_WOMAN;
					break;
				case RDB_UNKWNOW:
					g_nGender = GT_UN;
					break;
				case RDB_OTHER:
					g_nGender = GT_OTH;
					break;*/
				default:
					break;
			}
		}
		break;
	}
	case WM_CLOSE:
	{
		EndDialog(hwndDlg, 0);
		break;
	}
	default:
		return FALSE;
		break;
	}
	return TRUE;
}
int WINAPI WinMain( _In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPSTR lpCmdLine,
	_In_ int nShowCmd )
{


	return DialogBox(hInstance,MAKEINTRESOURCE(DLG_TEST),NULL, TestDialogProc);
}

4、listbox完整代码

LB_GETSELCOUNT

检索多选列表框中所选项目的总数
image.png
image.png

If the list box is a single-selection list box, the return value is **LB_ERR. **

#include <windows.h>
#include <list>
#include "resource.h"
#include <string>

using namespace std;
enum GenderType//复选框不能用枚举,枚举只能多个里面选择一个
{
	GT_NAN,
	GT_WOMAN,
	GT_UN,
	GT_OTH
};
//GenderType g_nGender = GT_NAN;
struct DlgInfo
{
	GenderType m_nGender;
};
//处理消息封装函数一般都是以On开头的,On表示正在处理
void OnGetRadioButton(HWND hwndDlg)
{
	if (SendDlgItemMessage(hwndDlg, CHK_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "写代码", "提示", MB_OK);
	}
	if (SendDlgItemMessage(hwndDlg, CHK_WRITE_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "改代码", "提示", MB_OK);
	}
	if (SendDlgItemMessage(hwndDlg, CHK_COPY_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "抄代码", "提示", MB_OK);
	}
	DlgInfo* pDi = (DlgInfo*)GetWindowLong(hwndDlg, DWL_USER);
	switch (pDi->m_nGender)
	{
	case GT_NAN:
		MessageBox(hwndDlg, "男", "提示", MB_OK);
		break;
	case GT_WOMAN:
		MessageBox(hwndDlg, "女", "提示", MB_OK);
		break;
	case GT_UN:
		//MessageBox(hwndDlg, "未知", "提示", MB_OK);
		break;
	case GT_OTH:
		//MessageBox(hwndDlg, "其他", "提示", MB_OK);
		break;
	default:
		break;
	}
	/*switch (g_nGender)
	{
	case GT_NAN:
		MessageBox(hwndDlg, "男", "提示", MB_OK);
		break;
	case GT_WOMAN:
		MessageBox(hwndDlg, "女", "提示", MB_OK);
		break;
	case GT_UN:
		MessageBox(hwndDlg, "未知", "提示", MB_OK);
		break;
	case GT_OTH:
		MessageBox(hwndDlg, "其他", "提示", MB_OK);
		break;
	default:
		break;
	}*/
	
}
INT_PTR CALLBACK TestDialogProc(
	HWND hwndDlg,  // handle to dialog box
	UINT uMsg,     // message  
	WPARAM wParam, // first message parameter
	LPARAM lParam  // second message parameter
)
{
	switch (uMsg)
	{
	case WM_INITDIALOG:
	{
		SetWindowLong(hwndDlg, DWL_USER, (LONG)new DlgInfo{ GT_NAN });
		//设置默认值,默认选中男
		SendDlgItemMessage(hwndDlg, RDB_MAN, BM_SETCHECK, BST_CHECKED, 0);
				
		//初始化Combobox
		list<string> lstCmb({ "北京","北海","深圳","浙江" });
		int n = 0x1001;
		for (auto val:lstCmb)
		{
			int nIdx = SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_ADDSTRING, 0, (LPARAM)val.c_str());
			//存入自定义数据
			SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_SETITEMDATA, nIdx, n++);
		}
		//设置默认值,默认选中北京
		SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_SETCURSEL, 0, 0);
		
		//初始化listbox
		list<string> lstLib({ "小春","晓春","小纯","晓纯","小淳","小椿" });
		for (auto val : lstLib)
		{	
			SendDlgItemMessage(hwndDlg, LB_NAME, LB_ADDSTRING, 0, (LPARAM)val.c_str());
		}
		return TRUE;
	}
	case WM_COMMAND:
	{ 
		WORD wCtrlId = LOWORD(wParam);  //控件的ID
		WORD wNotiCode = HIWORD(wParam);//通告码
		HWND hCtrl = (HWND)lParam;//控件的窗口句柄
		DlgInfo* pDi = (DlgInfo*)GetWindowLong(hwndDlg, DWL_USER);
		switch (wNotiCode)
		{
		case BN_CLICKED:
			switch (wCtrlId)
			{
				case BTN_GET:
				{
					//获取Combobox选中信息
					//索引
					int nSelIdx = SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETCURSEL, 0, 0);
					
					//文本
					TCHAR szBuff[MAXBYTE] = { 0 };
					SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETLBTEXT, nSelIdx, (LPARAM)szBuff);
					

					//自定义数据
					int nData = SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETITEMDATA, nSelIdx, NULL);
					
					TCHAR szFmt[MAXBYTE] = {};
					wsprintf(szFmt, "%04X:%s",nData,szBuff);
					
					MessageBox(hwndDlg, szFmt, "提示", MB_OK);

					//获取listbox多选框的值   
					//获取选中个数 
					UINT nCnt = SendDlgItemMessage(hwndDlg, LB_NAME, LB_GETSELCOUNT, 0, 0);

					//将所有选中的索引(就是第几行的)
					UINT aryIdxs[MAXBYTE] = {};
					SendDlgItemMessage(hwndDlg, LB_NAME, LB_GETSELITEMS,
						sizeof(aryIdxs) / sizeof(aryIdxs[0]), (LPARAM)aryIdxs);

					//遍历所有选中的,根据选框索引获取选框的值
					for (UINT nIdx = 0; nIdx < nCnt; nIdx++)
					{
						char szBuff[MAXBYTE] = {};
						//根据选框索引获取对应的值
						SendDlgItemMessage(hwndDlg, LB_NAME, LB_GETTEXT, aryIdxs[nIdx], (LPARAM)szBuff);
						MessageBox(hwndDlg, szBuff, "提示", MB_OK);
					}
					//获取复选框信息
					OnGetRadioButton(hwndDlg);
					break;					
				}
				case BTN_DELETE:
				{
					int nSelIdx = SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETCURSEL, 0, 0);
					//删除选择的信息
					//SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_DELETESTRING, nSelIdx, NULL);
					
					//删除所有的信息
					SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_RESETCONTENT, nSelIdx, NULL);
					break;
				}
				//获取单选框信息
				case RDB_MAN:
					pDi->m_nGender = GT_NAN;
					break;
				case RDB_WOMAN:
					pDi->m_nGender = GT_WOMAN;
					break;
				case RDB_UNKWNOW:
					pDi->m_nGender = GT_UN;
					break;
				case RDB_OTHER:
					pDi->m_nGender = GT_OTH;
					break;
				/*case RDB_MAN:
					g_nGender = GT_NAN;
					break;
				case RDB_WOMAN:
					g_nGender = GT_WOMAN;
					break;
				case RDB_UNKWNOW:
					g_nGender = GT_UN;
					break;
				case RDB_OTHER:
					g_nGender = GT_OTH;
					break;*/
				default:
					break;
			}
		}
		break;
	}
	case WM_CLOSE:
	{
		EndDialog(hwndDlg, 0);
		break;
	}
	default:
		return FALSE;
		break;
	}
	return TRUE;
}
int WINAPI WinMain( _In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPSTR lpCmdLine,
	_In_ int nShowCmd )
{


	return DialogBox(hInstance,MAKEINTRESOURCE(DLG_TEST),NULL, TestDialogProc);
}

效果:

二. List Control

image.png
image.png
列表框可以选择多个视图,相当于文件夹内显示文件信息一样,有大图标,小图标,列表等。

插入列属性:

LVM_INSERTCOLUMN 消息
消息含义:添加列表控件列表模式的属性值。该值通常在初始化的时候添加。该消息的发送还需要定义列表属性结构体。
image.png
属性结构体定义:

typedef struct _LVCOLUMN {
UINT mask;            	//说明此结构中哪些成员是有效的(枚举值见MSDN的列举) 掩码
int fmt;           		//列的对齐方式
int cx;            		//列的初始宽度
LPTSTR pszText; 		//列的标题
int cchTextMax;   		//pszText所指向的缓冲区的大小
int iSubItem;      		//与列关联的子项的索引值,从0开始,很多人都不用这个值,没关系
int iImage;           	//与列关联的图像列表中指定图像的索引值
int iOrder;           	//第几列,0代表最左一列
} LVCOLUMN, FAR *LPLVCOLUMN;

消息代码:

    LVCOLUMN lvc;
    lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;   //成员启用
    lvc.fmt = LVCFMT_LEFT;
    lvc.cx = 60;
    lvc.pszText = szText;
    lvc.cchTextMax = nLen;
    SendDlgItemMessage(hDlg, dwCtrId, LVM_INSERTCOLUMN, dwColIdx, (LPARAM)&lvc);

插入行

列表的插入不能一次性插入一整行内容,需要发送消息LVM_INSERTITEM先添加一行,然后再通过LVM_SETITEMTEXT消息设置其他列的数据。其中添加行适包含第一列的数据。

LVM_INSERTITEM 消息
消息含义:向控件发送该消息,以添加一行,注意的是,该消息需要发送行的索引,行必须递增,否则添加失败。

LV_ITEM结构体定义:

typedef struct _LVITEM {  
UINT mask;               //说明LVITEM结构中哪些成员有效  
int iItem;               //项目的索引值(可以视为行号)从0开始  
int iSubItem;            //子项的索引值(可以视为列号)从0开始  
UINT state;              //子项的状态  
UINT stateMask;          //状态有效的屏蔽位  
LPTSTR pszText;          //主项或子项的名称  
int cchTextMax;          //pszText所指向的缓冲区大小  
int iImage;              //关联图像列表中指定图像的索引值  
LPARAM lParam;           //程序定义的32位参数  
int iIndent;             //表示图像位置缩进的单位  
} LVITEM, FAR *LPLVITEM;</SPAN>  

消息发送示例:

LVITEM lvi = {};    //注意:必须初始化,否则不会添加成功。
    lvi.mask = LVIF_TEXT;
    lvi.iItem = dwRowIdx;
    lvi.pszText = szText;
    lvi.cchTextMax = nLen;
    SendDlgItemMessage(hDlg, dwCtrId, LVM_INSERTITEM, dwRowIdx, (LPARAM)&lvi);

设置列文本

LVM_SETITEMTEXT 消息
消息含义:发送该消息,通过结构体设置索引行和索引列的数据值。需要LVITEM结构体。结构体必须初始化。
消息发送:

LVITEM lvi = {};    //注意:必须初始化,否则不会添加成功。
    lvi.mask = LVIF_TEXT;
    lvi.iItem = dwRowIdx;
    lvi.pszText = szText;
    lvi.cchTextMax = nLen;
    SendDlgItemMessage(hDlg, dwCtrId, LVM_INSERTITEM, dwRowIdx, (LPARAM)&lvi);

获取列的值

LVM_GETITEM 检索列表视图项的部分或全部属性
image.png

删除所选行

LVM_DELETEITEM 消息
**消息含义:**从列表视图控件中删除项。

  • _wParam _要删除的列表视图项的索引
  • _lParam _必须为零。

**返回值:**如果成功,则返回 TRUE ; 否则返回 FALSE

设置风格所选行高亮

LVM _ SETEXTENDEDLISTVIEWSTYLE 消息
**消息含义:**在列表视图控件中设置扩展样式。 可以显式发送此消息

  • wParam
  • lParam

LVM_GETEXTENDEDLISTVIEWSTYLE 消息
**消息含义:**获取当前用于给定列表视图控件的扩展样式。 可以显式发送此消息,

  • _wParam _必须为零。
  • _lParam _必须为零。

LVS_EX_FULLROWSELECT 消息
**消息含义:**高亮所选行,风格。
image.png

//设置选中高亮一行和添加网格线
int nOldStyle = SendDlgItemMessage(hwndDlg, LST_STUINFO, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
SendDlgItemMessage(hwndDlg, LST_STUINFO, LVM_SETEXTENDEDLISTVIEWSTYLE,0, nOldStyle | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

有非常多,需要哪种风格就去设置哪种。
Tips:列表属性结构体必须初始化,否则会出现不可预知的错误。

双击

**NM_DBLCLK **
用户用鼠标左键双击项目时,由列表视图控件发送。该通知消息以WM_NOTIFY消息的形式发送。

WM_NOTIFY
当事件发生或控件需要某些信息时,WM_NOTIFY消息由公共控件发送到其父窗口。

NMITEMACTIVATE
包含LVN_ITEMACTIVATE通知消息的信息

ntains information about an LVN_ITEMACTIVATE notification message. 
typedef struct tagNMITEMACTIVATE{
     NMHDR   hdr;
     int     iItem;
     int     iSubItem;
     UINT    uNewState;
     UINT    uOldState;
     UINT    uChanged;
     POINT   ptAction;
     LPARAM  lParam;
     UINT    uKeyFlags;
 } NMITEMACTIVATE, FAR *LPNMITEMACTIVATE;
 

小知识:

  1. 控件的对齐:工具栏 -> 等宽设置,垂直居中等等。
  2. 处理消息封装函数的时候,一般用On…来开头的函数命名,表示正在处理。
  3. SendMessage和SendDlgItemMessage 的区别在于,后者内部就获取了对话框上控件的句柄。
  4. 使用CTRL + D 来重新设置焦点顺序,依次点击重新设置顺序。

附录

Class All Code

#include <windows.h>
#include <list>
#include "resource.h"
#include <string>
#include <commctrl.h>

using namespace std;
enum GenderType//复选框不能用枚举,枚举只能多个里面选择一个
{
	GT_NAN,
	GT_WOMAN,
	GT_UN,
	GT_OTH
};
//GenderType g_nGender = GT_NAN;
struct DlgInfo
{
	GenderType m_nGender;
};
//处理消息封装函数一般都是以On开头的,On表示正在处理
void OnGetRadioButton(HWND hwndDlg)
{
	if (SendDlgItemMessage(hwndDlg, CHK_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "写代码", "提示", MB_OK);
	}
	if (SendDlgItemMessage(hwndDlg, CHK_WRITE_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "改代码", "提示", MB_OK);
	}
	if (SendDlgItemMessage(hwndDlg, CHK_COPY_CODE, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		MessageBox(hwndDlg, "抄代码", "提示", MB_OK);
	}
	DlgInfo* pDi = (DlgInfo*)GetWindowLong(hwndDlg, DWL_USER);
	switch (pDi->m_nGender)
	{
	case GT_NAN:
		MessageBox(hwndDlg, "男", "提示", MB_OK);
		break;
	case GT_WOMAN:
		MessageBox(hwndDlg, "女", "提示", MB_OK);
		break;
	case GT_UN:
		//MessageBox(hwndDlg, "未知", "提示", MB_OK);
		break;
	case GT_OTH:
		//MessageBox(hwndDlg, "其他", "提示", MB_OK);
		break;
	default:
		break;
	}
	/*switch (g_nGender)
	{
	case GT_NAN:
		MessageBox(hwndDlg, "男", "提示", MB_OK);
		break;
	case GT_WOMAN:
		MessageBox(hwndDlg, "女", "提示", MB_OK);
		break;
	case GT_UN:
		MessageBox(hwndDlg, "未知", "提示", MB_OK);
		break;
	case GT_OTH:
		MessageBox(hwndDlg, "其他", "提示", MB_OK);
		break;
	default:
		break;
	}*/
	
}
INT_PTR CALLBACK TestDialogProc(
	HWND hwndDlg,  // handle to dialog box
	UINT uMsg,     // message  
	WPARAM wParam, // first message parameter
	LPARAM lParam  // second message parameter
)
{
	switch (uMsg)
	{
	case WM_INITDIALOG:
	{
		SetWindowLong(hwndDlg, DWL_USER, (LONG)new DlgInfo{ GT_NAN });
		//设置默认值,默认选中男
		SendDlgItemMessage(hwndDlg, RDB_MAN, BM_SETCHECK, BST_CHECKED, 0);
				
		//初始化Combobox
		list<string> lstCmb({ "北京","北海","深圳","浙江" });
		int n = 0x1001;
		for (auto val:lstCmb)
		{
			int nIdx = SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_ADDSTRING, 0, (LPARAM)val.c_str());
			//存入自定义数据
			SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_SETITEMDATA, nIdx, n++);
		}
		//设置默认值,默认选中北京
		SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_SETCURSEL, 0, 0);
		
		//初始化listbox
		list<string> lstLib({ "小春","晓春","小纯","晓纯","小淳","小椿" });
		for (auto val : lstLib)
		{	
			SendDlgItemMessage(hwndDlg, LB_NAME, LB_ADDSTRING, 0, (LPARAM)val.c_str());
		}

		//初始化列表控件 list -control
		//添加表头
		list<string> lsHeaders({ "ID","姓名","性别"});
		int nColIdx = 0;//列索引
		for (auto str : lsHeaders)
		{
			LVCOLUMN lc = {};
			lc.mask = LVCF_WIDTH| LVCF_TEXT| LVCF_FMT;
			lc.fmt = LVCFMT_LEFT;
			lc.cx = 90;//列宽
			lc.pszText = (LPSTR)str.c_str();
			lc.cchTextMax = str.size();
			SendDlgItemMessage(hwndDlg, LST_STUINFO, LVM_INSERTCOLUMN, nColIdx++, (LPARAM)&lc);
		}
		//添加行
		list<string> lstCol0({ "1001","1002","1003" });
		int nRowIdx = 0;
		for (auto str:lstCol0)
		{
			LVITEM li = {};
			li.mask = LVIF_TEXT|LVIF_PARAM;	//文本和自定义数据
			li.iItem = nRowIdx++;		//行数
			li.iSubItem = 0;		//列数
			li.pszText = (LPSTR)str.c_str();
			li.cchTextMax = str.size();
			li.lParam = 0x10001 + nRowIdx;

			SendDlgItemMessage(hwndDlg, LST_STUINFO, LVM_INSERTITEM, 0, (LPARAM)&li);
		}

		list<string> lstCol1({ "小椿","大纯","小淳" });
		nRowIdx = 0;
		for (auto str : lstCol1)
		{
			LVITEM li = {};
			li.mask = LVIF_TEXT;	//文本
			li.iItem = nRowIdx;		//行数
			li.iSubItem = 1;		//列数
			li.pszText = (LPSTR)str.c_str();
			li.cchTextMax = str.size();

			SendDlgItemMessage(hwndDlg, LST_STUINFO, LVM_SETITEMTEXT, nRowIdx++, (LPARAM)&li);
		}
		list<string> lstCol2({ "男","女","女" });
		nRowIdx = 0;
		for (auto str : lstCol2)
		{
			LVITEM li = {};
			li.mask = LVIF_TEXT;	//文本
			li.iItem = 0;		//行数
			li.iSubItem = 2;		//列数
			li.pszText = (LPSTR)str.c_str();
			li.cchTextMax = str.size();

			SendDlgItemMessage(hwndDlg, LST_STUINFO, LVM_SETITEMTEXT, nRowIdx++, (LPARAM)&li);
		}

		//设置选中高亮一行和添加网格线
		int nOldStyle = SendDlgItemMessage(hwndDlg, LST_STUINFO, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
		SendDlgItemMessage(hwndDlg, LST_STUINFO, LVM_SETEXTENDEDLISTVIEWSTYLE,0, nOldStyle | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
	
		
		return TRUE;
	}
	case WM_NOTIFY:
	{
		LPNMHDR pnmh = (LPNMHDR)lParam;
		switch (pnmh->code)
		{
		case NM_DBLCLK:
		{
			LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;

			TCHAR szFmt[MAXBYTE] = {};
			wsprintf(szFmt, "被选中的行:%d", lpnmitem->iItem);
			MessageBox(hwndDlg, szFmt, "Tip", MB_OK);
			break;
		}
		default:
			break;
		}
		break;
	}
	case WM_COMMAND:
	{ 
		WORD wCtrlId = LOWORD(wParam);  //控件的ID
		WORD wNotiCode = HIWORD(wParam);//通告码
		HWND hCtrl = (HWND)lParam;//控件的窗口句柄
		DlgInfo* pDi = (DlgInfo*)GetWindowLong(hwndDlg, DWL_USER);
		switch (wNotiCode)
		{
		case BN_CLICKED:
			switch (wCtrlId)
			{
				case BTN_GET:
				{
					//获取Combobox选中信息
					//索引
					int nSelIdx = SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETCURSEL, 0, 0);
					
					//文本
					TCHAR szBuff[MAXBYTE] = { 0 };
					SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETLBTEXT, nSelIdx, (LPARAM)szBuff);
					

					//自定义数据
					int nData = SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETITEMDATA, nSelIdx, NULL);
					
					TCHAR szFmt[MAXBYTE] = {};
					wsprintf(szFmt, "%04X:%s",nData,szBuff);
					
					MessageBox(hwndDlg, szFmt, "提示", MB_OK);

					//获取listbox多选框的值   
					//获取选中个数 
					UINT nCnt = SendDlgItemMessage(hwndDlg, LB_NAME, LB_GETSELCOUNT, 0, 0);

					//将所有选中的索引(就是第几行的)
					UINT aryIdxs[MAXBYTE] = {};
					SendDlgItemMessage(hwndDlg, LB_NAME, LB_GETSELITEMS,
						sizeof(aryIdxs) / sizeof(aryIdxs[0]), (LPARAM)aryIdxs);

					//遍历所有选中的,根据选框索引获取选框的值
					for (UINT nIdx = 0; nIdx < nCnt; nIdx++)
					{
						char szBuff[MAXBYTE] = {};
						//根据选框索引获取对应的值
						SendDlgItemMessage(hwndDlg, LB_NAME, LB_GETTEXT, aryIdxs[nIdx], (LPARAM)szBuff);
						MessageBox(hwndDlg, szBuff, "提示", MB_OK);
					}
					//获取选中行数
					int nIdx = SendDlgItemMessage(hwndDlg, LST_STUINFO, LVM_GETSELECTIONMARK, 0, 0);

					//第一个列数据
					TCHAR szID[MAXBYTE] = { 0 };
					LVITEM li = {};
					li.mask = LVIF_PARAM | LVIF_TEXT;
					li.iItem = nIdx;//被选中的列
					li.iSubItem = 0;//第0列
					li.pszText = szID;
					li.cchTextMax = sizeof(szID);
					SendDlgItemMessage(hwndDlg, LST_STUINFO, LVM_GETITEM, 0, (LPARAM)&li);

					int nLCData = li.lParam;//自定义数据

					//第二列数据
					TCHAR szName[MAXBYTE] = {};
					li.mask = LVIF_TEXT;
					li.iItem = nIdx;//被选中的列
					li.iSubItem = 1;//第1列
					li.pszText = szName;
					li.cchTextMax = sizeof(szName);
					SendDlgItemMessage(hwndDlg, LST_STUINFO, LVM_GETITEM, 0, (LPARAM)&li);

					//第三列数据
					TCHAR szSex[MAXBYTE] = {};
					li.mask = LVIF_TEXT;
					li.iItem = nIdx;//被选中的列
					li.iSubItem = 2;//第2列
					li.pszText = szSex;
					li.cchTextMax = sizeof(szSex);
					SendDlgItemMessage(hwndDlg, LST_STUINFO, LVM_GETITEM, 0, (LPARAM)&li);

					TCHAR szLCFmt[MAXBYTE] = {0};
					wsprintf(szLCFmt, "data:%04X,id:%s name:%s sex:%s", nLCData, szID, szName, szSex);
					MessageBox(hwndDlg, szLCFmt, "提示", MB_OK);


					//获取复选框信息
					OnGetRadioButton(hwndDlg);
					break;					
				}
				case BTN_DELETE:
				{
					int nSelIdx = SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_GETCURSEL, 0, 0);
					//删除选择的信息
					//SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_DELETESTRING, nSelIdx, NULL);
					
					//删除所有的信息
					SendDlgItemMessage(hwndDlg, CMB_LOCATION, CB_RESETCONTENT, nSelIdx, NULL);
					break;
				}
				//获取单选框信息
				case RDB_MAN:
					pDi->m_nGender = GT_NAN;
					break;
				case RDB_WOMAN:
					pDi->m_nGender = GT_WOMAN;
					break;
				case RDB_UNKWNOW:
					pDi->m_nGender = GT_UN;
					break;
				case RDB_OTHER:
					pDi->m_nGender = GT_OTH;
					break;
				/*case RDB_MAN:
					g_nGender = GT_NAN;
					break;
				case RDB_WOMAN:
					g_nGender = GT_WOMAN;
					break;
				case RDB_UNKWNOW:
					g_nGender = GT_UN;
					break;
				case RDB_OTHER:
					g_nGender = GT_OTH;
					break;*/
				default:
					break;
			}
		}
		break;
	}
	case WM_CLOSE:
	{
		EndDialog(hwndDlg, 0);
		break;
	}
	default:
		return FALSE;
		break;
	}
	return TRUE;
}
int WINAPI WinMain( _In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPSTR lpCmdLine,
	_In_ int nShowCmd )
{


	return DialogBox(hInstance,MAKEINTRESOURCE(DLG_TEST),NULL, TestDialogProc);
}

封装的List Control操作类

CListControl.h

#pragma once
#include <windows.h>
#include <commctrl.h>
class CListControl
{
public: 
    //插入列属性,通常只插入一次
    void InsertColum(HWND hDlg, DWORD dwCtrId, LPTSTR szText, int nLen, DWORD dwColIdx);

    //插入一行,包好第一列元素
    void InsertItem(HWND hDlg, DWORD dwCtrId, LPTSTR szText, int nLen, DWORD dwRowIdx);
    
    //设置一列,通常与插入一行一起使用
    void SetItemText(HWND hDlg, DWORD dwCtrId, LPTSTR szText, int nLen, DWORD dwRowIdx, DWORD dwColIdx);
   
    //获取选中行信息
    void GetItemText(HWND hDlg, DWORD dwCtrId, LPTSTR szText, int nLen, DWORD dwRowIdx, DWORD dwColIdx);
   
    //设置整行高亮
    void SetFull(HWND hDlg, DWORD dwCtrId);
    
    //删除选中行
    void DeleItem(HWND hDlg, DWORD dwCtrId);
    
    //删除所有行
    void DeleALLItem(HWND hDlg, DWORD dwCtrId);
    
    //插入一整行信息
    
    

public:
    int GetRow() const { return nRow; }
    void SetRow(int val) { nRow = val; }


private:
    int nRow;
    int nCol;
};


CListControl.cpp

#include "CListControl.h"

void CListControl::InsertColum(HWND hDlg, DWORD dwCtrId, LPTSTR szText, int nLen, DWORD dwColIdx)
{
    LVCOLUMN lvc;
    lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;   //成员启用
    lvc.fmt = LVCFMT_LEFT;
    lvc.cx = 60;
    lvc.pszText = szText;
    lvc.cchTextMax = nLen;
    SendDlgItemMessage(hDlg, dwCtrId, LVM_INSERTCOLUMN, dwColIdx, (LPARAM)&lvc);
}

void CListControl::InsertItem(HWND hDlg, DWORD dwCtrId, LPTSTR szText, int nLen, DWORD dwRowIdx)
{
    LVITEM lvi = {};    //注意:必须初始化,否则不会添加成功。
    lvi.mask = LVIF_TEXT;
    lvi.iItem = dwRowIdx;
    lvi.pszText = szText;
    lvi.cchTextMax = nLen;
    SendDlgItemMessage(hDlg, dwCtrId, LVM_INSERTITEM, dwRowIdx, (LPARAM)&lvi);
}

void CListControl::SetItemText(HWND hDlg, DWORD dwCtrId, LPTSTR szText, int nLen, DWORD dwRowIdx, DWORD dwColIdx)
{
    /*  注意:
    *       1. 需要设置行和列,由于插入行的时候,第一列已经有了,所以列要++ncol
    *       2. 不同于插入行,只用设置行,这还需要设置列。
    *       3. 消息不同,LVM_SETITEMTEXT,指明插入哪行,而不是列
    */
    LVITEM lviText = {};    //注意:必须初始化,否则不会添加成功。
    lviText.mask = LVIF_TEXT;
    lviText.iItem = dwRowIdx;
    lviText.iSubItem = dwColIdx;
    lviText.pszText = szText;
    lviText.cchTextMax = nLen;
    SendDlgItemMessage(hDlg, dwCtrId, LVM_SETITEMTEXT, dwRowIdx, (LPARAM)&lviText);
}

void CListControl::GetItemText(HWND hDlg, DWORD dwCtrId, LPTSTR szText, int nLen, DWORD dwRowIdx, DWORD dwColIdx)
{
    LVITEM lviText = {};    //注意:必须初始化,否则不会添加成功。
    lviText.mask = LVIF_TEXT;
    lviText.iItem = dwRowIdx;
    lviText.iSubItem = dwColIdx;
    lviText.pszText = szText;
    lviText.cchTextMax = nLen;
    SendDlgItemMessage(hDlg, dwCtrId, LVM_GETITEMTEXT, dwRowIdx, (LPARAM)&lviText);
}

void CListControl::SetFull(HWND hDlg, DWORD dwCtrId)
{
    //设置列表控件整行高亮
    DWORD dwStyle = SendDlgItemMessage(hDlg, dwCtrId, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
    dwStyle = dwStyle | LVS_EX_FULLROWSELECT;
    SendDlgItemMessage(hDlg, dwCtrId, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
}

void CListControl::DeleItem(HWND hDlg, DWORD dwCtrId)
{
    //获取选中索引
    DWORD dwSel = SendDlgItemMessage(hDlg, dwCtrId, LVM_GETSELECTIONMARK, 0, 0);
    SendDlgItemMessage(hDlg, dwCtrId, LVM_DELETEITEM, dwSel, 0);
    //删除后行号索引需要--,否则再次添加将失败。
}

void CListControl::DeleALLItem(HWND hDlg, DWORD dwCtrId)
{
    SendDlgItemMessage(hDlg, dwCtrId, LVM_DELETEALLITEMS, 0, 0);
    //删除后需要清空行号
}

List Control 课堂代码


#include <windows.h>
#include "resource.h"
#include "CListControl.h"

struct tagRowCol
{
    int nRow = 0;
    int nCol = 0;
}RowCol;

//对话框过程函数
INT_PTR CALLBACK DialogProc(HWND hwndDlg,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam
);

BOOL OnProc(HWND hwndDlg,WORD wCtrlID)
{
    switch (LOWORD(wCtrlID))
    {
        //检测复选框勾选状态
    case IDC_BUTTON1:
    {
        BOOL RetCheck1 = SendDlgItemMessage(hwndDlg, IDC_CHECK1, BM_GETCHECK, 0, 0);
        BOOL RetCheck2 = SendDlgItemMessage(hwndDlg, IDC_CHECK2, BM_GETCHECK, 0, 0);
        BOOL RetCheck3 = SendDlgItemMessage(hwndDlg, IDC_CHECK3, BM_GETCHECK, 0, 0);

        if (RetCheck1)
        {
            MessageBox(hwndDlg, "已勾选记住密码", "检测提示", NULL);
        }
        if (RetCheck2)
        {
            MessageBox(hwndDlg, "已勾选自动登录", "检测提示", NULL);
        }
        if (RetCheck3)
        {
            MessageBox(hwndDlg, "已勾选自动填充", "检测提示", NULL);
        }
    }
    break;
    case IDC_BUTTON2:
    {
        BOOL RetRaiod1 = SendDlgItemMessage(hwndDlg, IDC_RADIO1, BM_GETCHECK, 0, 0);
        BOOL RetRaiod2 = SendDlgItemMessage(hwndDlg, IDC_RADIO2, BM_GETCHECK, 0, 0);
        BOOL RetRaiod3 = SendDlgItemMessage(hwndDlg, IDC_RADIO3, BM_GETCHECK, 0, 0);

        if (RetRaiod1)
        {
            MessageBox(hwndDlg, "Radio1", "检测提示", NULL);
        }
        if (RetRaiod2)
        {
            MessageBox(hwndDlg, "Radio2", "检测提示", NULL);
        }
        if (RetRaiod3)
        {
            MessageBox(hwndDlg, "Radio3", "检测提示", NULL);
        }
    }
    break;
    case IDC_BUTTON3:
    {

        //第一行
        RowCol.nCol = 0;
        char szId1[] = { "1001" };
        CListControl cls;
        cls.InsertItem(hwndDlg, IDC_LIST2, szId1, sizeof(szId1), RowCol.nRow);
        //InsertItem(hwndDlg, IDC_LIST2, szId1, sizeof(szId1),RowCol.nRow);
        char szName1[] = { "张三" };
        cls.SetItemText(hwndDlg, IDC_LIST2, szName1, sizeof(szName1), RowCol.nRow, ++RowCol.nCol);
        //SetItemText(hwndDlg, IDC_LIST2, szName1, sizeof(szName1), RowCol.nRow, ++RowCol.nCol);
        char szGen1[] = { "男" };
        cls.SetItemText(hwndDlg, IDC_LIST2, szGen1, sizeof(szGen1), RowCol.nRow++, ++RowCol.nCol);
        //SetItemText(hwndDlg, IDC_LIST2, szGen1, sizeof(szGen1), RowCol.nRow++, ++RowCol.nCol);

        //第二行
        RowCol.nCol = 0;    //注意,每次添加都要将行号给清0
        char szId2[] = { "10021" };
        //InsertItem(hwndDlg, IDC_LIST2, szId2, sizeof(szId2), RowCol.nRow);
        char szName2[] = { "李四123" };
        //SetItemText(hwndDlg, IDC_LIST2, szName2, sizeof(szName2), RowCol.nRow, ++RowCol.nCol);
        char szGen2[] = { "男" };
        //SetItemText(hwndDlg, IDC_LIST2, szGen2, sizeof(szGen2), RowCol.nRow++, ++RowCol.nCol);

        //第三行
        RowCol.nCol = 0;    
        char szId3[] = { "1003" };
        //InsertItem(hwndDlg, IDC_LIST2, szId3, sizeof(szId3), RowCol.nRow);
        char szName3[] = { "王舞" };
        //SetItemText(hwndDlg, IDC_LIST2, szName3, sizeof(szName3), RowCol.nRow, ++RowCol.nCol);
        char szGen3[] = { "女" };
        //SetItemText(hwndDlg, IDC_LIST2, szGen3, sizeof(szGen3), RowCol.nRow++, ++RowCol.nCol);


#if 0

#if 0
        LVCOLUMN lvc;
        char szId[] = { "学生ID" };
        lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;   //成员启用
        lvc.fmt = LVCFMT_LEFT;
        lvc.cx = 60;
        lvc.pszText = szId;
        lvc.cchTextMax = sizeof(szId);
        SendDlgItemMessage(hwndDlg, IDC_LIST2, LVM_INSERTCOLUMN, 0, (LPARAM)&lvc);
#endif // 

        //设置列属性
        char szId[] = { "学生ID" };
        InsertColum(hwndDlg, IDC_LIST2, szId, sizeof(szId), 0);
        char szName[] = { "姓名" };
        InsertColum(hwndDlg, IDC_LIST2, szName, sizeof(szName), 1);
        char szGender[] = { "性别" };
        InsertColum(hwndDlg, IDC_LIST2, szGender, sizeof(szGender), 2);

        //插入行
#if 0

        int nRow = 0;
        LVITEM lvi = {};    //注意:必须初始化,否则不会添加成功。
        char szId1[] = { "1001" };
        lvi.mask = LVIF_TEXT;
        lvi.iItem = nRow;
        lvi.pszText = szId1;
        lvi.cchTextMax = sizeof(szId1);
        SendDlgItemMessage(hwndDlg, IDC_LIST2, LVM_INSERTITEM, 0, (LPARAM)&lvi);
#endif // 0

        char szId1[] = { "1001" };
        InsertItem(hwndDlg, IDC_LIST2, szId1, 0);

        //设置列

        /*  注意:
        *       1. 需要设置行和列,由于插入行的时候,第一列已经有了,所以列要++ncol
        *       2. 不同于插入行,只用设置行,这还需要设置列。
        *       3. 消息不同,LVM_SETITEMTEXT,指明插入哪行,而不是列
        */
#if 0

        LVITEM lviText = {};    //注意:必须初始化,否则不会添加成功。
        lviText.mask = LVIF_TEXT;
        lviText.iItem = nRow;
        lviText.iSubItem = ++nCol;
        lviText.pszText = szName1;
        lviText.cchTextMax = sizeof(szName1);
        SendDlgItemMessage(hwndDlg, IDC_LIST2, LVM_SETITEMTEXT, nRow, (LPARAM)&lviText);
#endif // 0


        int nRow = 0;
        int nCol = 0;
        char szName1[] = { "张三" };
        SetItemText(hwndDlg, IDC_LIST2, szName1, nRow, nCol);
#endif // 0

    }
    break;

    case IDC_BUTTON4:
    {
        //获取选中索引
        DWORD dwSel = SendDlgItemMessage(hwndDlg, IDC_LIST2, LVM_GETSELECTIONMARK, 0, 0);
        SendDlgItemMessage(hwndDlg, IDC_LIST2, LVM_DELETEITEM, dwSel, 0);
        RowCol.nRow--;
        //返回值,删除成功返回TRUE,删除失败返回false
        //直接删除后再添加,出现只有ID,空的情况

    }
    break;
    case IDC_BUTTON5:
    {
        //获取下标索引
        DWORD dwSel = SendDlgItemMessage(hwndDlg, IDC_LIST2, LVM_GETSELECTIONMARK, 0, 0);
        char szBuff[MAXBYTE] = {};

        CListControl cls;
        RowCol.nCol = 0;
        char szId[MAXBYTE] = {};
        cls.GetItemText(hwndDlg, IDC_LIST2, szId, sizeof(szId), dwSel, RowCol.nCol++);
        char szName[MAXBYTE] = {};
        cls.GetItemText(hwndDlg, IDC_LIST2, szName, sizeof(szId), dwSel, RowCol.nCol++);
        char szGend[MAXBYTE] = {};
        cls.GetItemText(hwndDlg, IDC_LIST2, szGend, sizeof(szGend), dwSel, RowCol.nCol++);

        wsprintf(szBuff, "ID:%s 姓名:%s  性别:%s", szId, szName, szGend);
        MessageBox(hwndDlg, szBuff, NULL, MB_OK);


    }
    case IDC_BUTTON6:
    {

        CListControl cls;

        cls.DeleALLItem(hwndDlg,IDC_LIST2);
        RowCol.nRow = 0;

        //获取选中列
        //DWORD dwSel = SendDlgItemMessage(hwndDlg, IDC_LIST2, LVM_GETSELECTEDCOLUMN, 0, 0);
        //SendDlgItemMessage(hwndDlg, IDC_LIST2, LVM_DELETECOLUMN, dwSel, 0);
    }
        break;
    default:
        break;
    }

    return TRUE;
}


int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
)
{
    //创建一个模态对话框
    DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL, DialogProc);
    return 0;
}


INT_PTR CALLBACK DialogProc(HWND hwndDlg,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam
)
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
    {
        //初始化
        CListControl cls;
       
        设置列属性
        char szId[] = { "学生ID" };
        cls.InsertColum(hwndDlg, IDC_LIST2, szId, sizeof(szId), 0);
        //InsertColum(hwndDlg, IDC_LIST2, szId, sizeof(szId), 0);
        char szName[] = { "姓名" };
        cls.InsertColum(hwndDlg, IDC_LIST2, szName, sizeof(szName), 1);
        //InsertColum(hwndDlg, IDC_LIST2, szName, sizeof(szName), 1);
        char szGender[] = { "性别" };
        cls.InsertColum(hwndDlg, IDC_LIST2, szGender, sizeof(szGender), 2);
        //InsertColum(hwndDlg, IDC_LIST2, szGender, sizeof(szGender), 2);



        //设置列表控件整行高亮
#if 0

        DWORD dwStyle = SendDlgItemMessage(hwndDlg, IDC_LIST2, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
        dwStyle = dwStyle | LVS_EX_FULLROWSELECT;
        SendDlgItemMessage(hwndDlg, IDC_LIST2, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);

#endif // 0

        cls.SetFull(hwndDlg, IDC_LIST2);


        

        return TRUE;
    }
    case WM_CLOSE:
        EndDialog(hwndDlg, IDCANCEL);
        return TRUE;

    case WM_COMMAND:
    {
        switch (HIWORD(wParam))
        {
        case BN_CLICKED:
        {
            OnProc(hwndDlg, wParam);
            return TRUE;
        }
        default:
            break;
        }

        return TRUE;
    }

    default:
        break;
    }

    return FALSE;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑桃鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值