文章目录
CListCtrl类
CListCtrl是MFC中的一个控件类,用于显示列表数据。它继承自CWnd类,并提供了许多功能,如列标题、排序、多选等。下面是CListCtrl常用的函数方法和属性样式。
CListCtrl获取多个选中的方法:
a)GetFirstSelectedItemPosition和GetNextSelectItem。
b)while (++i < nCount) CListCtrl::GetItemState
c)CListCtrl::GetNextItem
CListCtrl::Create 创建一个列表控件并将它附加到 CListCtrl 对象。(不是用对话框资源拖入的)
CListCtrl::CreateEx:加强版的创建(扩展风格)
CListCtrl::DeleteAllItems:删除全部行数据(内部数据结构体是CArray)等价于RemoveAll
CListCtrl::DeleteItem:删除单行数据
CListCtrl::EditLabel:在项上显示一个编辑框
CListCtrl::GetEditControl:基于以上EditLabel
CListCtrl::GetBkColor和CListCtrl::SetBkColor:设置和获取背景色
CListCtrl::GetBkImage和CListCtrl::SetBkImage:背景图片
CListCtrl::GetCheck和CListCtrl::SetCheck:设置和获取打勾(需要设置扩展风格)
CListCtrl::GetExtendedStyle和CListCtrl::SetExtendedStyle:设置和获取扩展风格
GetFirstSelectedItemPosition:获取选中的多行数据,内部数据结构是单项链表
CListCtrl::GetNextSelectedItem:和以上函数配合形成循环获取所有选中项
CListCtrl::GetSelectedCount:选中的个数
CListCtrl::GetHeaderCtrl:获取表头控件,又是一个类CHeaderCtrl
CListCtrl::GetImageList和CListCtrl::SetImageList:设置和获取列表的图标
CListCtrl::GetItem和CListCtrl::SetItem:设置和获取完整项数据,包括图标,文字,选中状态,隐含数据等。
CListCtrl::GetItemCount和CListCtrl::SetItemCount:获取和设置数据的总行数。
CListCtrl::GetItemData和CListCtrl::GetItemData:获取项内隐含数据
CListCtrl::GetItemRect:获取项的位置(RECT)
CListCtrl::GetSubItemRect:获取某行列的小矩形
CListCtrl::SetItemText和CListCtrl::GetItemText:获取和设置某行列的文字
CListCtrl::SetItemState和CListCtrl::GetItemState:设置和获取项的状态。
CListCtrl::InsertItem:插入一项(包括文字和图标等)
CListCtrl::SortItems和CListCtrl::SortItemsEx:按照某列排序
#define WC_LISTVIEWA "SysListView32"
#define WC_LISTVIEWW L"SysListView32"
#ifdef UNICODE
#define WC_LISTVIEW WC_LISTVIEWW
#else
#define WC_LISTVIEW WC_LISTVIEWA
#endif
#else
#define WC_LISTVIEW "SysListView" LVS
#endif
// begin_r_commctrl
#define LVS_ICON 0x0000
#define LVS_REPORT 0x0001
#define LVS_SMALLICON 0x0002
#define LVS_LIST 0x0003
以上是视图格式:大图标,小图标,详细列表等。
#define LVS_TYPEMASK 0x0003
#define LVS_SINGLESEL 0x0004 单选
#define LVS_SHOWSELALWAYS 0x0008
#define LVS_SORTASCENDING 0x0010 正向排序(主要以列表项文字作为规则,多个列时最左测的)
#define LVS_SORTDESCENDING 0x0020 反向排序
#define LVS_SHAREIMAGELISTS 0x0040
#define LVS_NOLABELWRAP 0x0080
#define LVS_AUTOARRANGE 0x0100
#define LVS_EDITLABELS 0x0200 可以编辑的属性(主要以列表项文字作为规则,多个列时最左测的)
#define LVS_OWNERDATA 0x1000 海量列表的属性(当有几亿个数据插入都需要十几分钟)
#define LVS_NOSCROLL 0x2000
#define LVS_TYPESTYLEMASK 0xfc00
#define LVS_ALIGNTOP 0x0000
#define LVS_ALIGNLEFT 0x0800
#define LVS_ALIGNMASK 0x0c00
#define LVS_OWNERDRAWFIXED 0x0400 自绘(在第十章讲解)
#define LVS_NOCOLUMNHEADER 0x4000 在详细资料REPROT模式下多列却没有标头
#define LVS_NOSORTHEADER 0x8000 没有排序标头
CFile类
CFile类是MFC中的一个文件操作类,提供了对文件的读写、查找、定位等操作.
由于对开发的员工系统的数据需要进行本地保存,需要用到CFile类,下面是CFile类的基本方法和打开模式:
1、CFile类的重要方法:
CFile::Open 函数功能:打开一个文件并返回一个文件句柄。
BOOL Open(LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError = NULL);
参数说明:
lpszFileName:要打开的文件名。
nOpenFlags:打开文件的模式。可以是以下几个值之一:
CFile::modeRead:以只读方式打开文件。
CFile::modeWrite:以写入方式打开文件。如果文件不存在,则创建一个新文件;如果文件已存在,则截断文件长度为0。
CFile::modeReadWrite:以读写方式打开文件。如果文件不存在,则创建一个新文件;如果文件已存在,则保留原文件内容。
CFile::modeCreate:创建一个新文件并以写入方式打开它。如果文件已存在,则截断文件长度为0。
CFile::modeNoTruncate:不截断现有文件的长度。
CFile::shareCompat:允许其他进程打开文件。
CFile::shareExclusive:不允许其他进程打开文件。
pError:一个指向CFileException异常对象的指针,用于接收打开文件过程中可能出现的错误信息。
返回值:打开文件是否成功。CFile::Open:内部封装CreateFile产生句柄记录在m_hFile;
CFile::Close:内部CloseHandle 关闭文件
CFile::Read:内部ReadFile 函数功能:从文件中读取指定数量的字节,并将它们存储在缓冲区中。
UINT Read(void* lpBuf, UINT nCount);
参数说明:
lpBuf:指向接收数据的缓冲区的指针。
nCount:要读取的字节数。
返回值:实际读取的字节数。
CFile::Write:内部WriteFile 函数功能:将指定数量的字节从缓冲区写入文件中。
void Write(const void* lpBuf, UINT nCount);
参数说明:
lpBuf:指向要写入文件的数据的缓冲区的指针。
nCount:要写入的字节数。
CFile::Seek 函数功能:移动文件指针到指定位置。
LONG Seek(LONG lOff, UINT nFrom);
参数说明:
lOff:要移动的字节数。如果nFrom是CFile::begin,则此参数是从文件开头算起的字节数;如果nFrom是CFile::current,则此参数是相对于当前文件指针的字节数;如果nFrom是CFile::end,则此参数是从文件结尾算起的字节数。
nFrom:指定从哪个位置开始移动文件指针。可以是以下值之一:
CFile::begin:从文件开头计算。
CFile::current:从当前文件指针位置计算。
CFile::end:从文件结尾计算。
返回值:新的文件指针位置。
CFile打开模式:
以下打开模式可以通过按位或(|)的方式一起使用,来达到更灵活的文件操作效果。例如,可以使用
CFile::modeReadWrite | CFile::shareExclusive的方式打开一个文件,实现独占方式的读写操作。
//表示如果文件不存在则创建文件,如果文件存在则清空文件内容并写入新数据
modeCreate|modeWrite联合等价于fopen("wb")模式
modeRead :等价于"rb"模式
以下是打开的一些模式:
enum OpenFlags {
modeRead = (int) 0x00000, 以只读方式打开文件。
modeWrite = (int) 0x00001, 以只写方式打开文件。如果文件已经存在,将会清除文件内容,如果文件不存在,则会创建一个新的文件。
modeReadWrite = (int) 0x00002, 以读写方式打开文件。如果文件不存在,则会创建一个新的文件。
shareCompat = (int) 0x00000,
shareExclusive = (int) 0x00010, 独占方式打开文件,其他程序无法访问已经打开的文件
shareDenyWrite = (int) 0x00020, 拒绝其他程序读取已经打开的文件。
shareDenyRead = (int) 0x00030, 拒绝其他程序写入已经打开的文件。
shareDenyNone = (int) 0x00040, 允许其他程序读写已经打开的文件。
modeNoInherit = (int) 0x00080,
#ifdef _UNICODE
typeUnicode = (int) 0x00400, // used in derived classes (e.g. CStdioFile) only
#endif
modeCreate = (int) 0x01000, 创建一个新的文件。如果文件已经存在,则会清除文件内容。
modeNoTruncate = (int) 0x02000, 打开一个已经存在的文件,但不清除文件内容,可以在文件末尾追加新的数据。
typeText = (int) 0x04000, // used in derived classes (e.g. CStdioFile) only
typeBinary = (int) 0x08000, // used in derived classes (e.g. CStdioFile) only
osNoBuffer = (int) 0x10000,
osWriteThrough = (int) 0x20000,
osRandomAccess = (int) 0x40000,
osSequentialScan = (int) 0x80000,
};
提示:以下是本篇文章正文内容,下面案例可供参考
员工管理系统示例代码如下
Employer.h 应用主程序的头文件
#pragma once
#ifndef __AFXWIN_H__
#error "在包含此文件之前包含 'pch.h' 以生成 PCH"
#endif
#include "resource.h" // 主符号
class CEmployerApp : public CWinApp
{
public:
CEmployerApp();
public:
virtual BOOL InitInstance();
DECLARE_MESSAGE_MAP()
};
extern CEmployerApp theApp;
Employer.cpp
#include "pch.h"
#include "framework.h"
#include "Employer.h"
#include "EmployerDlg.h"
#include "CLogin.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
BEGIN_MESSAGE_MAP(CEmployerApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
CEmployerApp::CEmployerApp()
{
m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
}
CEmployerApp theApp;// 唯一的 CEmployerApp 对象
BOOL CEmployerApp::InitInstance()// CEmployerApp 初始化
{
CWinApp::InitInstance();
CLogin LogDlg;
if (IDCANCEL == LogDlg.DoModal())
return false;
CEmployerDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
return FALSE;
}
EmployerDlg.h: 头文件
#pragma once
struct SData
{
//CString sNumb;//指针变量 这里面存的是指针的地址,而不是内容 不能这样用
int nNumb;
TCHAR sName[20];
float fSalary;
TCHAR sDate[20];
};
class CEmployerDlg : public CDialogEx // CEmployerDlg 对话框
{
// 构造
public:
CEmployerDlg(CWnd* pParent = nullptr); // 标准构造函数
int CheckNumb(CString str);
void Load();
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_MAIN_DIG };// 对话框数据 类向导通过这个去关联
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnClickedAdd();
afx_msg void OnClickedDel();
afx_msg void OnClickedModeify();
afx_msg void OnBnClickedSave();
};
EmployerDlg.cpp: 实现文件
#include "pch.h"
#include "framework.h"
#include "Employer.h"
#include "EmployerDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CEmployerDlg 对话框 弹出对话框用的
CEmployerDlg::CEmployerDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_MAIN_DIG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CEmployerDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CEmployerDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_ADD, &CEmployerDlg::OnClickedAdd)
ON_BN_CLICKED(IDC_DEL, &CEmployerDlg::OnClickedDel)
ON_BN_CLICKED(IDC_MODEIFY, &CEmployerDlg::OnClickedModeify)
ON_BN_CLICKED(IDC_SAVE, &CEmployerDlg::OnBnClickedSave)
END_MESSAGE_MAP()
// CEmployerDlg 消息处理程序
BOOL CEmployerDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
auto pList = (CListCtrl*)GetDlgItem(IDC_LIST);
pList->InsertColumn(0, L"工号", LVCFMT_CENTER, 120);
pList->InsertColumn(1, L"姓名", LVCFMT_CENTER, 120);
pList->InsertColumn(2, L"工资", LVCFMT_CENTER, 130);
pList->InsertColumn(3, L"入职日期", LVCFMT_CENTER, 180);
pList->SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT); //Extended List-View Styles列表控件的额外样式
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
Load();
// TODO: 在此添加额外的初始化代码
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CEmployerDlg::OnPaint()
{
CPaintDC dc(this); // 用于绘制的设备上下文
}
int CEmployerDlg::CheckNumb(CString str)
{
auto pList = (CListCtrl*)GetDlgItem(IDC_LIST);
int nCount = pList->GetItemCount();
while (nCount--)
{
if (pList->GetItemText(nCount, 0) == str)
return nCount; //0代表第一个 3 代表第四个
}
return -1; //代表不存在
}
void CEmployerDlg::OnClickedAdd() //首先获取列表控件 对编辑框中的文字进行获取 插入到列表控件
{//通过GetItemCount来获取当前列表视图控件项的数目 依次排序
auto pList = (CListCtrl*)GetDlgItem(IDC_LIST);
CString str;
GetDlgItemText(IDC_NUMB, str);
int nIndex = CheckNumb(str);
if (nIndex >= 0)
{
MessageBox(L"你输入的工号已存在,请重新输入", L"提示");
return;
}
int nCount = pList->GetItemCount();
pList->InsertItem(nCount,str);
GetDlgItemText(IDC_NAME, str);
pList->SetItemText(nCount, 1, str);
GetDlgItemText(IDC_SALARY, str);
pList->SetItemText(nCount, 2, str);
GetDlgItemText(IDC_DATETIME, str);
pList->SetItemText(nCount, 3, str);
OnBnClickedSave();
}
void CEmployerDlg::OnClickedDel()
{
auto pList = (CListCtrl*)GetDlgItem(IDC_LIST);
int nCount = pList->GetSelectedCount();
if (nCount<=0)
{//::MessageBox 加了::就是强制指定全局变量和函数的用法 参数全部添上
// 不加::的话默认靠this这个句柄来
MessageBox(L"请先选中一行再进行删除");
return;
}
auto pos = pList->GetFirstSelectedItemPosition();
while (pos)
{
int nItem = pList->GetNextSelectedItem(pos);
CString str = pList->GetItemText(nItem, 0);
str += L" ";
str += pList->GetItemText(nItem, 1);
str += L" ";
str += pList->GetItemText(nItem, 2);
if (IDYES == MessageBox(str+ L"\r\n你确定要删除吗?", L"提示", MB_YESNO))
{
pList->DeleteItem(nItem);
}
}
OnBnClickedSave();
}
void CEmployerDlg::OnClickedModeify()
{
auto pList = (CListCtrl*)GetDlgItem(IDC_LIST);
auto pos = pList->GetFirstSelectedItemPosition();
if(!pos)
{
MessageBox(L"请先选中一行再进行修改");
return;
}
if (IDYES == MessageBox(L"\r\n你确定要修改吗?", L"提示", MB_YESNO))
{
CString str;
int nItem = pList->GetNextSelectedItem(pos);
GetDlgItemText(IDC_NUMB, str);
pList->SetItemText(nItem, 0, str);
GetDlgItemText(IDC_NAME, str);
pList->SetItemText(nItem, 1, str);
GetDlgItemText(IDC_SALARY, str);
pList->SetItemText(nItem, 2, str);
GetDlgItemText(IDC_DATETIME, str);
pList->SetItemText(nItem, 3, str);
}
OnBnClickedSave();
}
void CEmployerDlg::Load()
{
CFile file;
if (!file.Open(L"./Data.txt", CFile::modeRead))
{
MessageBox(L"打开文件失败");
return;
}
SData d;
CString str;
auto pList = (CListCtrl*)GetDlgItem(IDC_LIST);
pList->DeleteAllItems();
int i = 0;
while (file.Read(&d,sizeof(d)) ==sizeof(d))
{
str.Format(L"%d", d.nNumb);
pList->InsertItem(i, str);
pList->SetItemText(i, 1, d.sName);
str.Format(L"%g", d.fSalary);
pList->SetItemText(i, 2,str);
pList->SetItemText(i, 3, d.sDate);
++i;
}
file.Close();
}
void CEmployerDlg::OnBnClickedSave()
{
CFile file;
if (!file.Open(L"./Data.txt", CFile::modeCreate | CFile::modeWrite))
{
MessageBox(L"打开文件失败");
return;
}
auto pList = (CListCtrl*)GetDlgItem(IDC_LIST);
int i = -1, nCount = pList->GetItemCount();
SData d;
while (++i<nCount)
{
d.nNumb = _tstoi(pList->GetItemText(i, 0));//CString 的核心是WCAHR* pData; operatot LPCTSTR
wcscpy_s(d.sName,pList->GetItemText(i, 1));
d.fSalary = (float)_tstof(pList->GetItemText(i, 2));
wcscpy_s(d.sDate, pList->GetItemText(i, 3));
file.Write(&d, sizeof(d));
}
file.Close();//可以不用执行,因为有析构函数
}
CLogin.h: 实现文件
#pragma once
#include "afxdialogex.h"
class CLogin : public CDialogEx // CLogin 对话框
{
DECLARE_DYNAMIC(CLogin)
public:
CLogin(CWnd* pParent = nullptr); // 标准构造函数
virtual ~CLogin();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_LOGIN_DLG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedOk();
};
CLogin.cpp: 实现文件
#include "pch.h"
#include "Employer.h"
#include "afxdialogex.h"
#include "CLogin.h"
IMPLEMENT_DYNAMIC(CLogin, CDialogEx)
CLogin::CLogin(CWnd* pParent /*=nullptr*/) // CLogin 对话框
: CDialogEx(IDD_LOGIN_DLG, pParent)
{
}
CLogin::~CLogin()
{
}
void CLogin::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CLogin, CDialogEx)
ON_BN_CLICKED(IDOK, &CLogin::OnBnClickedOk)
END_MESSAGE_MAP()
void CLogin::OnBnClickedOk() // CLogin 消息处理程序
{
CString sName, sPass;
GetDlgItemText(IDC_USERNAME, sName);
GetDlgItemText(IDC_PASS, sPass);
if (sName=="abc"&&"123"==sPass)
{
EndDialog(IDOK);
return;
}
else
{
MessageBox(L"你的账号或者密码输入错误,请重新输入。");
SetDlgItemText(IDC_USERNAME, L"");
SetDlgItemText(IDC_PASS, L"");
GetDlgItem(IDC_USERNAME)->SetFocus();
}
//CDialogEx::OnOK();
}