CMap应用场景和例子

news2025/6/7 16:15:21

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()
实际应用场景
  1. 缓存机制:存储计算结果,避免重复计算
  2. 数据映射:将 ID 映射到对应的对象或数据
  3. 配置管理:存储键值对形式的配置信息
  4. 事件处理:将事件 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;  // 下一个可用ID

public:
    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 实现一个简单的联系人管理器:

  1. 数据结构设计

    • 定义了 ContactInfo 结构体存储联系人信息
    • 使用 CMap<int, int, ContactInfo, ContactInfo&> 存储联系人数据
  2. 核心功能

    • 添加联系人:使用 SetAt() 方法将新联系人添加到映射表
    • 查找联系人:使用 Lookup() 方法根据 ID 查找联系人
    • 更新联系人:先查找,然后修改信息并重新设置
    • 删除联系人:使用 RemoveKey() 方法删除指定 ID 的联系人
    • 遍历所有联系人:使用 GetStartPosition() 和 GetNextAssoc() 方法
  3. 内存管理

    • CMap 自动管理存储的对象,不需要手动释放
    • 析构函数中调用 RemoveAll() 确保所有资源被释放

使用 CMap 的注意事项

  1. 键类型要求

    • 键类型必须支持 == 运算符(用于比较)
    • 如果使用自定义类作为键,需要重载 == 运算符
  2. 内存管理

    • 对于值类型为指针的情况,需要手动管理指针指向的对象
    • 建议在删除元素前先释放指针指向的内存
  3. 遍历操作

    • 遍历过程中不要修改映射表结构(添加或删除元素)
    • 如果需要修改,应使用 GetNextAssoc() 返回的 POSITION 进行操作
  4. 性能考虑

    • 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 window

class 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_MSG
    void 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

/
// CLineColorListCtrl

CLineColorListCtrl::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_MAP
    ON_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 painting

    CRect 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类中用于:

  1. SetItemColorSetAllItemColor方法中设置特定列表项的颜色
  2. OnNMCustomdraw方法中查找并应用颜色设置
  3. ClearColor方法中清除所有颜色设置

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2401245.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kafka 如何保证顺序消费

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

【算法题】算法一本通

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

Modbus转Ethernet IP赋能挤出吹塑机智能监控

在现代工业自动化领域&#xff0c;小疆智控Modbus转Ethernet IP网关GW-EIP-001与挤出吹塑机的应用越来越广泛。这篇文章将为您详细解读这两者的结合是如何提高生产效率&#xff0c;降低维护成本的。首先了解什么是Modbus和Ethernet IP。Modbus是一种串行通信协议&#xff0c;它…

什么是终端安全管理系统(终端安全管理软件2024科普)

在当今数字化迅速发展的时代&#xff0c;企业面临着越来越多的信息安全威胁。为了应对这些挑战&#xff0c;保障公司数据的安全性和完整性&#xff0c;终端安全管理系统&#xff08;Endpoint Security Management System&#xff09;应运而生。 本文将为您深入浅出地科普2024年…

【JVM】Java类加载机制

【JVM】Java类加载机制 什么是类加载&#xff1f; 在 Java 的世界里&#xff0c;每一个类或接口在经过编译后&#xff0c;都会生成对应的 .class 字节码文件。 所谓类加载机制&#xff0c;就是 JVM 将这些 .class 文件中的二进制数据加载到内存中&#xff0c;并对其进行校验…

《C++初阶之入门基础》【C++的前世今生】

【C的前世今生】目录 前言&#xff1a;---------------起源---------------一、历史背景二、横空出世---------------发展---------------三、标准立世C98&#xff1a;首个国际标准版本C03&#xff1a;小修订版本 四、现代进化C11&#xff1a;现代C的开端C14&#xff1a;对C11的…

Apache APISIX

目录 Apache APISIX是什么&#xff1f; Lua Lua 的主要特点&#xff1a; Lua 的常见应用&#xff1a; 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作为一种轻量级的数据交换格式&#xff0c;在Web服务和应用程序中广泛使用。 JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人阅读…

《T/CI 404-2024 医疗大数据智能采集及管理技术规范》全面解读与实施分析

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

国产三维CAD皇冠CAD在「金属压力容器制造」建模教程:蒸汽锅炉

面对蒸汽锅炉设计中复杂的曲面封头、密集的管板开孔、多变的支撑结构以及严格的强度与安全规范&#xff08;如GB150、ASME等&#xff09;&#xff0c;传统二维设计手段往往捉襟见肘&#xff0c;易出错、效率低、协同难。国产三维CAD皇冠CAD&#xff08;CrownCAD&#xff09;凭借…

C++中单例模式详解

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

舆情监控系统爬虫技术解析

之前我已经详细解释过爬虫在系统中的角色和技术要点&#xff0c;这次需要更聚焦“如何实现”这个动作。 我注意到上次回复偏重架构设计&#xff0c;这次应该拆解为更具体的操作步骤&#xff1a;从目标定义到数据落地的完整流水线。尤其要强调动态调度这个容易被忽视的环节——…

Vue3中Ant-design-vue的使用-附完整代码

前言 首先介绍一下什么是Ant-design-vue Ant Design Vue 是基于 Vue 3 的企业级 UI 组件库&#xff08;同时兼容 Vue 2&#xff09;&#xff0c;是蚂蚁金服开源项目 Ant Design 的 Vue 实现版本。它遵循 Ant Design 的设计规范&#xff0c;提供丰富的组件和高质量的设计体系&…

Redis Sorted Set 深度解析:从原理到实战应用

Redis Sorted Set 深度解析&#xff1a;从原理到实战应用 在 Redis 丰富的数据结构家族中&#xff0c;Sorted Set&#xff08;有序集合&#xff09;凭借独特的设计和强大的功能&#xff0c;成为处理有序数据场景的得力工具。无论是构建实时排行榜&#xff0c;还是实现基于时间的…

若依框架修改模板,添加通过excel导入数据功能

版本&#xff1a;我后端使用的是RuoYi-Vue-fast版本&#xff0c;前端是RuoYi-Vue3 需求: 我需要每个侧边栏功能都需要具有导入excel功能&#xff0c;但是若依只有用户才具备&#xff0c;我需要代码生成的每个功能都拥有导入功能。​ 每次生成一个一个改实在是太麻烦了。索性…

web全栈开发学习-01html基础

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

多线程环境中,如果多个线程同时尝试向同一个TCP客户端发送数据,添加同步机制

原代码 public async Task SendToClientAsync(TcpClient targetClient, byte[] data, int offset, int length) {try{// 1. 检查客户端是否有效if (targetClient null || !targetClient.Connected){Console.WriteLine("Cannot send: client is not connected");ret…

【含文档+PPT+源码】基于微信小程序的旅游论坛系统的设计与实现

项目介绍 本课程演示的是一款基于微信小程序的旅游论坛系统的设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系统 …

贝叶斯优化+LSTM+时序预测=Nature子刊!

贝叶斯优化与LSTM的融合在时间序列预测领域取得了显著成效&#xff0c;特别是在处理那些涉及众多超参数调整的复杂问题时。 1.这种结合不仅极大提高了预测的精确度&#xff0c;还优化了模型训练流程&#xff0c;提升了效率和成本效益。超参数优化的新篇章&#xff1a;LSTM因其…