CMap应用场景和例子
CMap 详解
CMap
是 MFC (Microsoft Foundation Classes) 库中的一个模板类,用于实现键值对的映射关系(类似哈希表或字典)。它提供了高效的数据存储和检索功能,适用于需要通过键快速查找值的场景。
基本模板参数
cpp
运行
template<class KEY, // 键的类型class ARG_KEY, // 传递键的参数类型(通常是引用)class VALUE, // 值的类型class ARG_VALUE // 传递值的参数类型(通常是引用)
>
class CMap : public CObject
常用方法
- 添加元素:
SetAt(ARG_KEY key, ARG_VALUE newValue)
- 查找元素:
Lookup(ARG_KEY key, VALUE& rValue)
- 删除元素:
RemoveKey(ARG_KEY key)
- 删除所有元素:
RemoveAll()
- 获取元素数量:
GetCount()
- 检查是否为空:
IsEmpty()
实际应用场景
- 缓存机制:存储计算结果,避免重复计算
- 数据映射:将 ID 映射到对应的对象或数据
- 配置管理:存储键值对形式的配置信息
- 事件处理:将事件 ID 映射到处理函数
使用举例
下面是一个完整的示例,展示如何使用 CMap
实现一个简单的联系人管理器:
#pragma once
#include <afxtempl.h>// 联系人信息结构体
struct ContactInfo
{CString name;CString phone;CString email;ContactInfo() {}ContactInfo(const CString& n, const CString& p, const CString& e): name(n), phone(p), email(e) {}
};// 联系人管理器类
class CContactManager
{
private:// 使用CMap存储联系人信息,键为ID,值为ContactInfo结构体CMap<int, int, ContactInfo, ContactInfo&> m_contactMap;int m_nextId; // 下一个可用IDpublic:CContactManager() : m_nextId(1) {}~CContactManager() { m_contactMap.RemoveAll(); }// 添加联系人int AddContact(const CString& name, const CString& phone, const CString& email);// 根据ID查找联系人bool FindContact(int id, ContactInfo& info) const;// 更新联系人信息bool UpdateContact(int id, const CString& name, const CString& phone, const CString& email);// 删除联系人bool DeleteContact(int id);// 获取联系人数量int GetContactCount() const;// 显示所有联系人void DisplayAllContacts() const;
};
#include "stdafx.h"
#include "ContactManager.h"
#include <iostream>// 添加联系人
int CContactManager::AddContact(const CString& name, const CString& phone, const CString& email)
{int id = m_nextId++;ContactInfo info(name, phone, email);m_contactMap.SetAt(id, info);return id;
}// 根据ID查找联系人
bool CContactManager::FindContact(int id, ContactInfo& info) const
{return m_contactMap.Lookup(id, info);
}// 更新联系人信息
bool CContactManager::UpdateContact(int id, const CString& name, const CString& phone, const CString& email)
{ContactInfo info;if (m_contactMap.Lookup(id, info)){info.name = name;info.phone = phone;info.email = email;m_contactMap.SetAt(id, info);return true;}return false;
}// 删除联系人
bool CContactManager::DeleteContact(int id)
{return m_contactMap.RemoveKey(id) != 0;
}// 获取联系人数量
int CContactManager::GetContactCount() const
{return m_contactMap.GetCount();
}// 显示所有联系人
void CContactManager::DisplayAllContacts() const
{if (m_contactMap.IsEmpty()){std::cout << "没有联系人记录" << std::endl;return;}POSITION pos = m_contactMap.GetStartPosition();while (pos != NULL){int id;ContactInfo info;m_contactMap.GetNextAssoc(pos, id, info);// 转换CString为char*以便输出CStringA name(info.name);CStringA phone(info.phone);CStringA email(info.email);std::cout << "ID: " << id << std::endl;std::cout << " 姓名: " << name << std::endl;std::cout << " 电话: " << phone << std::endl;std::cout << " 邮箱: " << email << std::endl;std::cout << "------------------------" << std::endl;}
}
#include "stdafx.h"
#include "ContactManager.h"int main()
{CContactManager manager;// 添加联系人int id1 = manager.AddContact(_T("张三"), _T("13800138001"), _T("zhangsan@example.com"));int id2 = manager.AddContact(_T("李四"), _T("13900139001"), _T("lisi@example.com"));int id3 = manager.AddContact(_T("王五"), _T("13700137001"), _T("wangwu@example.com"));std::cout << "添加了 " << manager.GetContactCount() << " 个联系人" << std::endl;// 显示所有联系人std::cout << "\n所有联系人列表:" << std::endl;manager.DisplayAllContacts();// 查找联系人ContactInfo info;if (manager.FindContact(id2, info)){CStringA name(info.name);std::cout << "\n找到ID为 " << id2 << " 的联系人: " << name << std::endl;}// 更新联系人manager.UpdateContact(id2, _T("李四(更新)"), _T("13900139002"), _T("lisi_updated@example.com"));// 删除联系人manager.DeleteContact(id3);// 显示更新后的联系人列表std::cout << "\n更新后的联系人列表:" << std::endl;manager.DisplayAllContacts();return 0;
}
代码说明
上面的示例展示了如何使用 CMap
实现一个简单的联系人管理器:
-
数据结构设计:
- 定义了
ContactInfo
结构体存储联系人信息 - 使用
CMap<int, int, ContactInfo, ContactInfo&>
存储联系人数据
- 定义了
-
核心功能:
- 添加联系人:使用
SetAt()
方法将新联系人添加到映射表 - 查找联系人:使用
Lookup()
方法根据 ID 查找联系人 - 更新联系人:先查找,然后修改信息并重新设置
- 删除联系人:使用
RemoveKey()
方法删除指定 ID 的联系人 - 遍历所有联系人:使用
GetStartPosition()
和GetNextAssoc()
方法
- 添加联系人:使用
-
内存管理:
CMap
自动管理存储的对象,不需要手动释放- 析构函数中调用
RemoveAll()
确保所有资源被释放
使用 CMap 的注意事项
-
键类型要求:
- 键类型必须支持
==
运算符(用于比较) - 如果使用自定义类作为键,需要重载
==
运算符
- 键类型必须支持
-
内存管理:
- 对于值类型为指针的情况,需要手动管理指针指向的对象
- 建议在删除元素前先释放指针指向的内存
-
遍历操作:
- 遍历过程中不要修改映射表结构(添加或删除元素)
- 如果需要修改,应使用
GetNextAssoc()
返回的 POSITION 进行操作
-
性能考虑:
CMap
提供 O (1) 的平均查找时间- 但在最坏情况下可能退化为 O (n)
#if !defined(AFX_LINECOLORLISTCTRL_H__92EB1CD4_CD33_4E02_A098_367A8FEFF38E__INCLUDED_)
#define AFX_LINECOLORLISTCTRL_H__92EB1CD4_CD33_4E02_A098_367A8FEFF38E__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// LineColorListCtrl.h : header file
//#include <afxtempl.h>typedef struct
{COLORREF colText; //前景色COLORREF colTextBk;//背景色
} TEXT_BK;/
// CLineColorListCtrl windowclass CLineColorListCtrl : public CListCtrl
{
public:void SetItemColor(DWORD iItem, COLORREF TextColor, COLORREF TextBkColor); //设置某一行的前景色和背景色void SetAllItemColor(DWORD iItem, COLORREF TextColor, COLORREF TextBkColor);//指设置所有从第一行到iItem行的颜色。void ClearColor(); //清除颜色映射表 int m_iPopMenu;afx_msg void OnPaint();afx_msg BOOL OnEraseBkgnd(CDC* pDC);
// Construction
public:CLineColorListCtrl();// Attributes
public:CMap<DWORD, DWORD&, TEXT_BK, TEXT_BK&> MapItemColor;// Operations
public:// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CLineColorListCtrl)//}}AFX_VIRTUAL// Implementation
public:virtual ~CLineColorListCtrl();// Generated message map functions
protected://{{AFX_MSG(CLineColorListCtrl)// NOTE - the ClassWizard will add and remove member functions here.//}}AFX_MSGvoid CLineColorListCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult);DECLARE_MESSAGE_MAP()
};///{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_LINECOLORLISTCTRL_H__92EB1CD4_CD33_4E02_A098_367A8FEFF38E__INCLUDED_)
// LineColorListCtrl.cpp : implementation file
//#include "stdafx.h"
#include "LineColorListCtrl.h"#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif/
// CLineColorListCtrlCLineColorListCtrl::CLineColorListCtrl()
{m_iPopMenu = 0;
}CLineColorListCtrl::~CLineColorListCtrl()
{
}BEGIN_MESSAGE_MAP(CLineColorListCtrl, CListCtrl)//{{AFX_MSG_MAP(CLineColorListCtrl)// NOTE - the ClassWizard will add and remove mapping macros here.//}}AFX_MSG_MAPON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnNMCustomdraw)ON_WM_PAINT()ON_WM_ERASEBKGND()
END_MESSAGE_MAP()/
// CLineColorListCtrl message handlers
BOOL CLineColorListCtrl::OnEraseBkgnd(CDC* pDC)
{return false;return CListCtrl::OnEraseBkgnd(pDC);
}
//避免背景闪烁
void CLineColorListCtrl::OnPaint()
{//响应WM_PAINT消息CPaintDC dc(this); // device context for paintingCRect rect;CRect headerRect;CDC MenDC;//内存ID表CBitmap MemMap;GetClientRect(&rect);GetDlgItem(0)->GetWindowRect(&headerRect);MenDC.CreateCompatibleDC(&dc);MemMap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());MenDC.SelectObject(&MemMap);MenDC.FillSolidRect(&rect, RGB(228, 236, 243));//这一句是调用默认的OnPaint(),把图形画在内存DC表上DefWindowProc(WM_PAINT, (WPARAM)MenDC.m_hDC, (LPARAM)0);//输出dc.BitBlt(0, headerRect.Height(), rect.Width(), rect.Height(), &MenDC, 0, headerRect.Height(), SRCCOPY);MenDC.DeleteDC();MemMap.DeleteObject();}//自定义绘画颜色处理
void CLineColorListCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{*pResult = CDRF_DODEFAULT;NMLVCUSTOMDRAW * lplvdr = (NMLVCUSTOMDRAW*)pNMHDR;NMCUSTOMDRAW &nmcd = lplvdr->nmcd;switch(lplvdr->nmcd.dwDrawStage)//判断状态{case CDDS_PREPAINT:{*pResult = CDRF_NOTIFYITEMDRAW;break;}case CDDS_ITEMPREPAINT://如果为画ITEM之前就要进行颜色的改变{// 根据在 SetItemColor(DWORD iItem, COLORREF color) 设置的// ITEM号和COLORREF 在摸板中查找,然后进行颜色赋值。TEXT_BK tb;if(MapItemColor.Lookup(nmcd.dwItemSpec, tb)){lplvdr->clrText = tb.colText;lplvdr->clrTextBk = tb.colTextBk;*pResult = CDRF_DODEFAULT;}}break;}
}void CLineColorListCtrl::ClearColor()
{MapItemColor.RemoveAll();
}void CLineColorListCtrl::SetItemColor(DWORD iItem, COLORREF TextColor, COLORREF TextBkColor)
{TEXT_BK tb;tb.colText = TextColor;tb.colTextBk = TextBkColor;MapItemColor.SetAt(iItem, tb);//设置某行的颜色。this->RedrawItems(iItem, iItem);//重新染色this->SetFocus(); //设置焦点UpdateWindow();
}void CLineColorListCtrl::SetAllItemColor(DWORD iItem, COLORREF TextColor, COLORREF TextBkColor)
{TEXT_BK tb;tb.colText = TextColor;tb.colTextBk = TextBkColor;if(iItem > 0){for(DWORD numItem = 0; numItem < iItem ; numItem ++){MapItemColor.SetAt(numItem, tb);this->RedrawItems(numItem, numItem);}}
}
TEXT_BK 结构体和 MapItemColor 映射表
这部分代码定义了一个结构体和一个映射表,用于存储和管理列表项的颜色信息:
TEXT_BK 结构体
cpp
运行
typedef struct
{COLORREF colText; // 前景色(文本颜色)COLORREF colTextBk; // 背景色
} TEXT_BK;
这个结构体用于存储每个列表项的颜色属性:
colText
:文本颜色,使用 Windows API 的COLORREF
类型(通常是一个 32 位整数,表示 RGB 颜色值)colTextBk
:背景颜色
通过typedef
定义了这个结构体的别名TEXT_BK
,这样在代码中可以直接使用TEXT_BK
而不需要每次都写struct TEXT_BK
。
MapItemColor 映射表
cpp
运行
CMap<DWORD, DWORD&, TEXT_BK, TEXT_BK&> MapItemColor;
这行代码声明了一个 MFC 的CMap
模板类实例,用于存储列表项索引和颜色信息的映射关系:
- 第一个模板参数
DWORD
:键的类型,表示列表项的索引 - 第二个模板参数
DWORD&
:键的引用类型,用于高效传递参数 - 第三个模板参数
TEXT_BK
:值的类型,表示颜色信息 - 第四个模板参数
TEXT_BK&
:值的引用类型,用于高效传递参数
用途
这个映射表在CLineColorListCtrl
类中用于:
- 在
SetItemColor
和SetAllItemColor
方法中设置特定列表项的颜色 - 在
OnNMCustomdraw
方法中查找并应用颜色设置 - 在
ClearColor
方法中清除所有颜色设置
相关文章:
CMap应用场景和例子
CMap 详解 CMap 是 MFC (Microsoft Foundation Classes) 库中的一个模板类,用于实现键值对的映射关系(类似哈希表或字典)。它提供了高效的数据存储和检索功能,适用于需要通过键快速查找值的场景。 基本模板参数 cpp 运行 tem…...

Kafka 如何保证顺序消费
在消息队列的应用场景中,保证消息的顺序消费对于一些业务至关重要,例如金融交易中的订单处理、电商系统的库存变更等。Kafka 作为高性能的分布式消息队列系统,通过巧妙的设计和配置,能够实现消息的顺序消费。接下来,我…...

【算法题】算法一本通
每周更新至完结,建议关注收藏点赞。 目录 待整理文章已整理的文章方法论思想总结模版工具总结排序 数组与哈希表栈双指针(滑动窗口、二分查找、链表)树前缀树堆 优先队列(区间/间隔问题、贪心 )回溯图一维DP位操作数学…...

Modbus转Ethernet IP赋能挤出吹塑机智能监控
在现代工业自动化领域,小疆智控Modbus转Ethernet IP网关GW-EIP-001与挤出吹塑机的应用越来越广泛。这篇文章将为您详细解读这两者的结合是如何提高生产效率,降低维护成本的。首先了解什么是Modbus和Ethernet IP。Modbus是一种串行通信协议,它…...
C++中如何遍历map?
文章目录 1. 使用范围for循环(C11及以上)2. 使用迭代器3. 使用反向迭代器注意事项 在C中, std::map 是一种关联容器,它存储的是键值对(key-value pairs),并且按键的顺序进行排序。遍历 std::m…...

什么是终端安全管理系统(终端安全管理软件2024科普)
在当今数字化迅速发展的时代,企业面临着越来越多的信息安全威胁。为了应对这些挑战,保障公司数据的安全性和完整性,终端安全管理系统(Endpoint Security Management System)应运而生。 本文将为您深入浅出地科普2024年…...
书籍转圈打印矩阵(8)0604
题目 给定一个整型矩阵matrix,请按照转圈的方式打印它。 例如: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 打印结果为:1,2,3ÿ…...

【JVM】Java类加载机制
【JVM】Java类加载机制 什么是类加载? 在 Java 的世界里,每一个类或接口在经过编译后,都会生成对应的 .class 字节码文件。 所谓类加载机制,就是 JVM 将这些 .class 文件中的二进制数据加载到内存中,并对其进行校验…...
Elasticsearch中的自定义分析器(Custom Analyzer)介绍
在 Elasticsearch 中,自定义分析器(Custom Analyzer) 是一种可配置的文本处理组件,允许用户通过组合分词器(Tokenizer)、过滤器(Token Filter)和字符过滤器(Character Filter)来定义特定的文本分析逻辑。这使得 Elasticsearch 能够针对不同语言、业务场景或特殊需求,…...

《C++初阶之入门基础》【C++的前世今生】
【C的前世今生】目录 前言:---------------起源---------------一、历史背景二、横空出世---------------发展---------------三、标准立世C98:首个国际标准版本C03:小修订版本 四、现代进化C11:现代C的开端C14:对C11的…...

Apache APISIX
目录 Apache APISIX是什么? Lua Lua 的主要特点: Lua 的常见应用: CVE-2020-13945(Apache APISIX默认API Token导致远程Lua代码执行) 编辑Lua脚本解析 CVE-2021-45232(Apache APISIX Dashboard API权限绕过导致RCE) Apache …...

如何在 git dev 中创建合并请求
先将 自己的代码 推到 自己的远程的 分支上 在 创建 合并请求 根据提示 将 自己的远程的 源码 合并到 对应的分支上 然后 创建 合并请求 等待 对应的 人 来 进行合并就行...

基于nlohmann/json 实现 从C++对象转换成JSON数据格式
C对象的JSON序列化与反序列化 基于JsonCpp库实现C对象序列化与反序列化 JSON 介绍 JSON作为一种轻量级的数据交换格式,在Web服务和应用程序中广泛使用。 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读…...
Java枚举类映射MySQL的深度解析与实践指南
Java枚举类映射MySQL的深度解析与实践指南 一、枚举类型映射的四大核心策略 1. 序数映射法(ordinal映射) 实现原理:存储枚举值的下标顺序 public enum OrderStatus {PENDING, // 存储为0PROCESSING, // 存储为1SHIPPED, //…...
代码训练LeetCode(21)跳跃游戏2
代码训练(21)LeetCode之跳跃游戏2 Author: Once Day Date: 2025年6月4日 漫漫长路,才刚刚开始… 全系列文章可参考专栏: 十年代码训练_Once-Day的博客-CSDN博客 参考文章: 45. 跳跃游戏 II - 力扣(LeetCode)力扣 (LeetCode) 全球极客挚爱…...
【HarmonyOS 5】鸿蒙APP使用【团结引擎Unity】开发的案例教程
以下是基于团结引擎开发鸿蒙Unity应用的详细案例教程,整合环境配置、工程适配、跨语言通信等核心环节 一、环境配置(关键前置步骤) 1. 工具安装 工具版本要求作用团结引擎Hub≥1.2.3Unity鸿蒙项目构建管理DevEco Studio≥…...

《T/CI 404-2024 医疗大数据智能采集及管理技术规范》全面解读与实施分析
规范背景与详细信息 《T/CI 404-2024 医疗大数据智能采集及管理技术规范》是由中国国际科技促进会联合河南科技大学、河南科技大学第一附属医院、深圳市人民医院等十余家医疗机构与企业共同制定的团体标准,于2024年5月正式发布实施。该规范是我国医疗大数据领域的重要技术标准…...

国产三维CAD皇冠CAD在「金属压力容器制造」建模教程:蒸汽锅炉
面对蒸汽锅炉设计中复杂的曲面封头、密集的管板开孔、多变的支撑结构以及严格的强度与安全规范(如GB150、ASME等),传统二维设计手段往往捉襟见肘,易出错、效率低、协同难。国产三维CAD皇冠CAD(CrownCAD)凭借…...
Mysql避免索引失效
1. 在索引列上使用函数或表达式 问题描述 SELECT * FROM users WHERE YEAR(create_time) 2023; 如果create_time列上有索引,上述查询会导致索引失效,因为MySQL无法直接利用索引的B树结构。 解决方法 将函数应用于条件值,而不是列&#…...
python爬虫:Ruia的详细使用(一个基于asyncio和aiohttp的异步爬虫框架)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Ruia概述1.1 Ruia介绍1.2 Ruia特点1.3 安装Ruia1.4 使用案例二、基本使用2.1 Request 请求2.2 Response - 响应2.3 Item - 数据提取2.4 Field 提取数据2.5 Spider - 爬虫类2.6 Middleware - 中间件三、高级功能3.1 …...

C++中单例模式详解
在C中,单例模式 (Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。这在需要一个全局对象来协调整个系统行为的场景中非常有用。 为什么要有单例模式? 在许多项目中,某些类从逻辑上讲只需要一个实…...

舆情监控系统爬虫技术解析
之前我已经详细解释过爬虫在系统中的角色和技术要点,这次需要更聚焦“如何实现”这个动作。 我注意到上次回复偏重架构设计,这次应该拆解为更具体的操作步骤:从目标定义到数据落地的完整流水线。尤其要强调动态调度这个容易被忽视的环节——…...
Windows上用FFmpeg采集摄像头推流 → MediaMTX服务器转发流 → WSL2上拉流播放
1. Windows上 FFmpeg 推流(摄像头采集) 设备名称可用 ffmpeg -list_devices true -f dshow -i dummy 查询,假设为Integrated Camera 采集推流示例(推RTMP到MediaMTX): ffmpeg -rtbufsize 100M -f dshow …...
cpp多线程学习
1.thread std::thread是 C11 引入的跨平台线程管理类,封装了操作系统的线程 API(如 pthread、Windows 线程),提供统一的线程操作接口。线程的生命周期由join()和detach()控制。 thread在创建时就开始执行 join():阻…...

Vue3中Ant-design-vue的使用-附完整代码
前言 首先介绍一下什么是Ant-design-vue Ant Design Vue 是基于 Vue 3 的企业级 UI 组件库(同时兼容 Vue 2),是蚂蚁金服开源项目 Ant Design 的 Vue 实现版本。它遵循 Ant Design 的设计规范,提供丰富的组件和高质量的设计体系&…...
k8s热更新-subPath 不支持热更新
文章目录 k8s热更新-subPath 不支持热更新背景subPath 不支持热更新1. 为什么 subPath 不支持热更新?2. 挂载整个目录为何支持热更新?使用demo举例:挂载整个目录(不使用 subPath) k8s热更新-subPath 不支持热更新 背景…...

Redis Sorted Set 深度解析:从原理到实战应用
Redis Sorted Set 深度解析:从原理到实战应用 在 Redis 丰富的数据结构家族中,Sorted Set(有序集合)凭借独特的设计和强大的功能,成为处理有序数据场景的得力工具。无论是构建实时排行榜,还是实现基于时间的…...
docker中组合这几个命令来排查 import 模块失败 的问题
pwd ls echo $PYTHONPATH这三个命令是你在 Linux 或 Docker 容器中常用来「查看环境状态」的基础命令。 ✅ 1. echo $PYTHONPATH 🔍 含义 这是在查看当前的 Python 模块搜索路径。 🧠 分解解释: echo:打印某个变量的值&#x…...

若依框架修改模板,添加通过excel导入数据功能
版本:我后端使用的是RuoYi-Vue-fast版本,前端是RuoYi-Vue3 需求: 我需要每个侧边栏功能都需要具有导入excel功能,但是若依只有用户才具备,我需要代码生成的每个功能都拥有导入功能。 每次生成一个一个改实在是太麻烦了。索性…...

web全栈开发学习-01html基础
背景 最近在付费网站学习web全栈开发,记录一下阶段性学习。今天刚好学完html基础,跟着教程画了个基础的网站。 样品展示: 开发工具 vscode Visual Studio Code - Code Editing. Redefined 常用插件 Prettier:格式优化 Live Sever:实时调…...