MFC学习笔记
个人财务管理软件设计中MFC控件的使用(List)
1.添加内容
//将添加的信息在列表中显示
CString sName, sDate, sPlace, sSalary, sBonus, sAlimony;
ifstream addfin("adduse.txt", ios::in);
string a1, a2, a3, a4, a5, a6;
while(addfin >> a1>> a2 >> a3 >> a4 >> a5 >> a6)
{
sName=a1.c_str();
sDate = a2.c_str();
sPlace = a3.c_str();
sSalary = a4.c_str();
sBonus = a5.c_str();
sAlimony = a6.c_str();
myList1.InsertItem(0, NULL);//插入一个行
myList1.SetItemText(0, 0, sName);//填充数据
myList1.SetItemText(0, 1, sDate);
myList1.SetItemText(0, 2, sPlace);
myList1.SetItemText(0, 3, sSalary);
myList1.SetItemText(0, 4, sBonus);
myList1.SetItemText(0, 5, sAlimony);
}
2.删除内容
//判断列表框中是否有记录
if (!myList1.GetItemCount()) {
MessageBox(L"暂无记录", L"警告", MB_OKCANCEL | MB_ICONEXCLAMATION);
return;
}
//判断是否选中一项,若选中则删除
POSITION ps;
int index = 0;
ps = myList1.GetFirstSelectedItemPosition();
index = myList1.GetNextSelectedItem(ps);//标记行号
if (-1 == index)
{
MessageBox(L"请选中一行数据", L"警告", MB_OKCANCEL | MB_ICONEXCLAMATION);
return;
}
else
{
if (IDOK == MessageBox(L"确定删除?", L"提示", MB_OKCANCEL | MB_ICONQUESTION))
{
myList1.DeleteItem(index);
}
}
3.修改内容
// 删除再添加
4.查询内容
CString str, cbsel;
int nIndex = myCombo.GetCurSel();
myCombo.GetLBText(nIndex, str);
GetDlgItemText(IDC_CBSEL, cbsel);
UpdateData(TRUE);
int i,flag = 0;
if (str == "姓名")
{
for (i = 0; i<myList1.GetItemCount(); ++i)
{
if (cbsel == myList1.GetItemText(i, 0))
{
myList2.InsertItem(0, NULL);
myList2.SetItemText(0, 0, myList1.GetItemText(i, 0));
myList2.SetItemText(0, 1, myList1.GetItemText(i, 1));
myList2.SetItemText(0, 2, myList1.GetItemText(i, 2));
myList2.SetItemText(0, 3, myList1.GetItemText(i, 3));
myList2.SetItemText(0, 4, myList1.GetItemText(i, 4));
myList2.SetItemText(0, 5, myList1.GetItemText(i, 5));
UpdateData(FALSE);
flag = 1;
}
}
}
else if (str == "...")//其他查询条件的实现方法基本相同,不再赘述
5.保存到文档
USES_CONVERSION;
char* save1;
ofstream savefile;
savefile.open("SAVEFILE.txt", ios::out);
for(int j=0;j<myList1.GetItemCount();++j)
{
save1 = W2A(myList1.GetItemText(j, 0));
savefile << save1 << " ";
save1 = W2A(myList1.GetItemText(j, 1));
savefile << save1 << " ";
save1 = W2A(myList1.GetItemText(j, 2));
savefile << save1 << " ";
save1 = W2A(myList1.GetItemText(j, 3));
savefile << save1 << " ";
save1 = W2A(myList1.GetItemText(j, 4));
savefile << save1 << " ";
save1 = W2A(myList1.GetItemText(j, 5));
savefile << save1 << " " << endl;
}
savefile.close();
MessageBox(L"保存成功", L"提示", MB_OKCANCEL);
这个里功能更全面:百度文库-MFC学生信息管理系统详解
list control控件的使用
1.设置listctrl 风格及扩展风格
LONG lStyle;
lStyle = GetWindowLong(m_list.m_hWnd, GWL_STYLE);//获取当前窗口style
lStyle &= ~LVS_TYPEMASK; //清除显示方式位
lStyle |= LVS_REPORT; //设置style
SetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle);//设置style
DWORD dwStyle = m_list.GetExtendedStyle();
dwStyle |= LVS_EX_FULLROWSELECT;//选中某行使整行高亮(只适用与report风格的listctrl)
dwStyle |= LVS_EX_GRIDLINES;//网格线(只适用与report风格的listctrl)
dwStyle |= LVS_EX_CHECKBOXES;//item前生成checkbox控件
m_list.SetExtendedStyle(dwStyle); //设置扩展风格
2.插入数据
m_list.InsertColumn( 0, "id", LVCFMT_LEFT, 40 );//插入列
m_list.InsertColumn( 1, "name", LVCFMT_LEFT, 50 );
int nRow = m_list.InsertItem(0, “”);//插入行
m_list.SetItemText(nRow, 0, “12138”);//设置数据,第1列
m_list.SetItemText(nRow, 1, “Jack”);//设置数据,第2列
3.选中和取消选中一行
int nIndex = 0;
//选中
m_list.SetItemState(nIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
//取消选中
m_list.SetItemState(nIndex, 0, LVIS_SELECTED|LVIS_FOCUSED);
4.得到listctrl中所有行的checkbox的状态
m_list.SetExtendedStyle(LVS_EX_CHECKBOXES);
CString str;
for(int i=0; i<m_list.GetItemCount(); i++)
{
if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED || m_list.GetCheck(i))
{
str.Format(_T("第%d行的checkbox为选中状态"), i);
AfxMessageBox(str);
}
}
5.得到listctrl中所有选中行的序号
POSITION pos = m_list.GetFirstSelectedItemPosition();
if (pos == NULL)
TRACE0("No items were selected!\n");
else
{
while (pos)
{
int nItem = m_list.GetNextSelectedItem(pos);
TRACE1("Item %d was selected!\n", nItem);
// you could do your own processing on nItem here
}
}
6.得到单击的listctrl的行列号
//添加listctrl控件的NM_CLICK消息相应函数
void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult)
{
// 方法一:
/*
DWORD dwPos = GetMessagePos();
CPoint point( LOWORD(dwPos), HIWORD(dwPos) );
m_list.ScreenToClient(&point);
LVHITTESTINFO lvinfo;
lvinfo.pt = point;
lvinfo.flags = LVHT_ABOVE;
int nItem = m_list.SubItemHitTest(&lvinfo);
if(nItem != -1)
{
CString strtemp;
strtemp.Format("单击的是第%d行第%d列", lvinfo.iItem, lvinfo.iSubItem);
AfxMessageBox(strtemp);
}
*/
// 方法二:
/*
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if(pNMListView->iItem != -1)
{
CString strtemp;
strtemp.Format("单击的是第%d行第%d列",
pNMListView->iItem, pNMListView->iSubItem);
AfxMessageBox(strtemp);
}
*/
*pResult = 0;
}
7.得到listctrl的所有列的header字符串内容
LVCOLUMN lvcol;
char str[256];
int nColNum;
CString strColumnName[4];//假如有4列
nColNum = 0;
lvcol.mask = LVCF_TEXT;
lvcol.pszText = str;
lvcol.cchTextMax = 256;
while(m_list.GetColumn(nColNum, &lvcol))
{
strColumnName[nColNum] = lvcol.pszText;
nColNum++;
}
8.右键点击listctrl的item弹出菜单
//添加listctrl控件的NM_RCLICK消息相应函数
void CTest6Dlg::OnRclickList1(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if(pNMListView->iItem != -1)
{
m_pRClickMenu = new CMenu();
ASSERT(m_pRClickMenu != NULL);
m_pRClickMenu->CreatePopupMenu();
m_pRClickMenu->AppendMenu(MF_STRING, IDC_BTN_SEND_EMAIL, "发送邮件");
m_pRClickMenu->AppendMenu(MF_STRING, IDC_BTN_COPY, "复制到剪切板");
// DWORD dwPos = GetMessagePos();
// CPoint point( LOWORD(dwPos), HIWORD(dwPos) );
CPoint point;
GetCursorPos(&point);
m_pRClickMenu->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this, NULL);
}
*pResult = 0;
}
combo box控件的使用
1.改变下拉框大小
1)直接在控件上操作,先点向下的箭头,就可以调整下拉框大小;
2)为了让列表框变的更宽,可以用setdroppedwidth(int width)函数来调整列表框的宽度。
2.定义控件对应变量
假定已经创建了一个Dialog,并且从控件工具箱将Combo Box 控件拖放到上面。打开 Class Wizard,添加控件对应变量,如:CComboBox m_combo。
3.向控件添加 Items
1)在Combo Box控件属性的Data标签里面添加,一行表示Combo Box下拉列表中的一行。换行用ctrl+回车。若在VS2005中,Items间用";"隔开即可;
2)利用函数 AddString()向 Combo Box 控件添加Items,如:
m_combo.AddString(“StringData1”);
m_combo.AddString(“StringData2”);
m_combo.AddString(“StringData3”);
3) 也可以调用函数 InsertString() 将 Item 插入指定位置 nIndex,如:
m_combo.InsertString(nIndex, “StringData” );
4)int GetCount( )可以得到当前列表框中行的数量。
示例代码:程序初始化时动态添加Items
CString strTemp;
m_combo.ResetContent();//消除现有所有内容
for(inti=1;i<=100;i++)
{
strTemp.Format(“%d”,i);
m_combo.AddString(strTemp);
}
4.从控件得到选定的Item
假设在控件列表中已经选定某项,现在要得到被选定项的内容,首先要得到该项的位置,然后得到对应位置的内容。这里会用到两个函数,如:
int nIndex = m_combo.GetCurSel();
CString strText;
m_combo.GetLBText( nIndex, strText);
这样,得到的内容就保存在 strText 中。若要选取当前内容,可调用函数GetWindowText(strText)。
5.在控件中查找给定Item
这种操作一般用于在程序中动态修改控件中该项的值,可以用函数FindStringExact() 精确匹配,如:
int nIndex = m_combo.FindStringExact( nStartAfter, “value to befound”);
nStartAfter指明从哪一行开始查找。如果查找成功,返回的是该项的位置;否则,返回CB_ERR。
也可以选中包含指定字符串的项,如:
int nIndex = m_combo.SelectString( nStartAfter, “value to beselected”);
6.删除控件中的Item
该操作可以利用函数DeleteString(),需要指定被删除项的位置,如:
m_combo.DeleteString(nIndex);
也可以使用函数ResetContent(),清除目前的所有项,如:
m_combo.ResetContent();
文件保存
//法1.C++,fstream类的操作
//法2.MFC的CFile操作:
CFile test;
CFileException e;
TCHAR* pszFileName = "test.txt";
if(!test.Open(pszFileName,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite, &e))//建立、打开test.txt文件
{
AfxMessageBox("File could not be opened %d\n", e.m_cause);
}
CString m_str;
pm_dedit=(CEdit*)GetDlgItem(IDC_edit);
pm_dedit->GetWindowText(m_str);
test.Write(m_str,m_str.GetLength());
m_str.Close();//关闭文件
//法3.MFC的CStdioFile操作
CFile文件操作详见:VS2010/MFC编程入门之四十五(MFC常用类:CFile文件操作类)
登录对话框的建立
1.在资源视图中添加一个窗体资源。插入Dialog。(此处窗体的ID选用的是默认的,可根据自己的情况进行修改)
2.在对话框区域右键,选择添加类,则会弹出一个添加类的对话框,基类选择CDialog,类名自己起个名字。这里取名为CSignIn。然后确认。(新建一个对话框以后一定要添加类,否则上面的控件都不能添加变量,可能还会出现一些其他的问题。)
3.将登录对话框的名字在属性窗口中修改为“登录”。并为其添加两个静态文本框,两个文本编辑框和两个按钮控件( 登录、退出 )。
4.依次为各个控件修改属性或者添加程序。
- a.静态文本框
修改两个静态文本框的ID,要不相同;修改其文本内容,例如“用户名”,“密码”。 - b.文本编辑框
为两个编辑框分别添加变量,如 m_Name,m_Password,;方法:选中编辑框,右键,选择添加变量,输入变量的名字,且此时变量的类型为Value。并将密码文本编辑框的password属性改为Ture ( 注意此时的Multiline属性应为False,否则可能会出现password属性不能编辑的情况 )。 - c.按钮控件
//登录按钮
void CSignIn::OnBnClickedOk1()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
if (m_name!="CSDN" || m_Password!="CSDN")
{
MessageBox("用户名或密码错误!");
return;
}
CDialog::OnOK();
}
//要在 主窗体的OnInitDialog 中添加登录窗体显示代码如下
CSignIn dlg;
if(dlg.DoModal()!=IDOK)
{
OnOK();
}
return TRUE;//这句代码一定要放在OnInitDialog的结尾。
//退出按钮
OnCancel();
问题-MFC读取文件在EditControl中显示乱码
Visual Studio2008以上的版本和VC6生成的项目默认编码不同,visual studio项目默认使用的是UNICODE编码,但是我们在读取文件的时候读取的是ANSI的文本,因此直接设置到edit control中就出现乱码了。
解决这个的办法也很简单,只要在SetWindow Text的时候使用SetWindowTexeA函数,强迫使用ANSI格式就可以了。如:
添加bmp文件和ICO文件
左侧-资源视图-文件名.rc-右键-添加资源-选择资源类型-导入-窗口选择显示全部类型文件-可将res文件中的资源导入
画图实现实时显示图形轨迹
//1.在类里定义变量和消息:
bool m_bClickEmpty; //判断是否点击了空白的地方,以实现拖动框选择
CPoint OldEmptyBegin;//点击空白开始的座标
CPoint NowEmptyEnd;//移动时保存座标
afx_msg void OnMouseMove(UINT nFlags, CPoint point);afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
//2.在鼠标相关的消息里面写代码:
void XX::OnLButtonDown(UINT nFlags, CPoint point){
m_bClickEmpty = true;
OldEmptyBegin = point;
NowEmptyEnd = point;
}
void XX::OnMouseMove(UINT nFlags, CPoint point)
{
if ( m_bClickEmpty ) { CClientDC dc(this);
CBrush *pBrush = CBrush::FromHandle( (HBRUSH)GetStockObject( NULL_BRUSH) );
CBrush *POldBrush = dc.SelectObject( pBrush );
int nOldMode = dc.SetROP2(R2_NOTXORPEN);
dc.Rectangle( &CRect( OldEmptyBegin, NowEmptyEnd ) );
dc.Rectangle( &CRect( OldEmptyBegin, point ) );
NowEmptyEnd = point;
dc.SelectObject( POldBrush );
dc.SetROP2( nOldMode );
}
}
void XX::OnLButtonUp(UINT nFlags, CPoint point){
if ( m_bClickEmpty ) { m_bClickEmpty = false;
CClientDC dc(this);
CBrush *pBrush = CBrush::FromHandle( (HBRUSH)GetStockObject( NULL_BRUSH) );
CBrush *POldBrush = dc.SelectObject( pBrush );
int nOldMode = dc.SetROP2(R2_NOTXORPEN);
dc.Rectangle( &CRect( OldEmptyBegin, NowEmptyEnd ) );
dc.SelectObject( POldBrush );
dc.SetROP2( nOldMode );
}}
MessageBox()的使用
功能: 显示一个消息对话框。
语法: MessageBox(text,title{,icon{,button{,default}}})
参数:
title:string类型,指定消息对话框的标题;
text:指定消息对话框中显示的消息,该参数可以是数值数据类型、字符串或boolean值;
icon:Icon枚举类型,可选项,指定要在该对话框左侧显示的图标;
button:Button枚举类型,可选项,指定显示在该对话框底部的按钮
default:数值型,可选项,指定作为缺省按钮的按钮编号,按钮编号自左向右依次计数,缺省值为1,如果该参数指定的编号超过了显示的按钮个数,那么MessageBox()函数将使用缺省值返回值Integer。函数执行成功时返回用户选择的按钮编号(例如1、2、3等),发生错误时返回-1。如果任何参数的值为NULL,MessageBox()函数返回NULL。
**用法:**当你的应用程序需要显示一段简短信息(比如显示出错、警告等信息)时,没有必要自己从头创建窗口、安排控件,使用MessageBox()函数既简单又方便。用户只有响应该窗口后,程序才能继续运行下去。MessageBox()函数的icon参数指定显示在窗口中的图标,它是枚举类型,可能取值为: 取值 图标Information! StopSign! Exclamation! Question! None! 无图标其中Information!是Icon参数的缺省值。Button参数指定在窗口中显示哪些按钮,有效取值为:取值中文Windows 95下显示OK!“确定”按钮OKCancel!“确定”、“取消”按钮YesNo!“是”、“否”按钮 YesNoCancel!“是”、“否”、“取消”按钮RetryCancel!“重试”、“取消”按钮AbortRetryIgnore!“终止”、“重试”、“忽略”按钮
函数功能: 该函数创建、显示、和操作一个消息框。消息框含有应用程序定义的消息和标题,加上预定义图标与Push(下按)按钮的任何组合。
Invalidate,UpdateWindow,UpdateDate
详见;Invalidate和UpdateWindow,UpdateData区别联系
Invalidate():
该函数的作用是使整个窗口客户区无效。窗口的客户区无效意味着需要重绘。例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的,需要重绘。这时Windows会在应用程序的消息队列中放置WM_PAINT消息。MFC为窗口类提供了WM_PAINT的消息处理函数OnPaint,OnPaint负责重绘窗口。视图类有一些例外,在视图类的OnPaint函数中调用了OnDraw函数,实际的重绘工作由OnDraw来完成。参数bErase为TRUE时,重绘区域内的背景将被擦除,否则,背景将保持不变。
InvalidateRect():
该函数的功能与Invalidate基本一样,不同的是,它是使指定的某个区域无效,需要输入一个区域,如果参数为NULL,则设置整个窗口为无效区。
UpdateData():
该函数的作用是对空间进行更新。
当你使用了ClassWizard建立了控件和变量之间的联系后,当你修改了变量的值,而希望对话框控件更新显示,就应该在修改变量后调用UpdateData(FALSE);如果你希望知道用户在对话框中到底输入了什么,就应该在访问变量前调用UpdateData(TRUE),将控件的输入映射到变量中。
UpdateWindow():
该函数的作用是使窗口立即重绘。
调用Invalidate等函数后窗口不会立即重绘(这是由于WM_PAINT消息的优先级很低,它需要等消息队列中的其它消息发送完后才能被处理)。
调用UpdateWindow函数可使WM_PAINT被直接发送到目标窗口,从而导致窗口立即重绘。
UpdateWindow:如果有无效区,则马上sending a WM_PAINT message到窗口处理过程,不进消息队列进行排队等待,立即刷新窗口,否则,什么都不做。
InvalidateRect:设置无效区,如果为NULL参数,则设置整个窗口为无效区。当应用程序的那个窗口的消息队列为空时,则sending a WM_PAINT message(即使更新区域为空).在sending a WM_PAINT message的所有InvalidateRect的更新区域会累加。
引用以下文章,侵删
list control控件:https://www.cnblogs.com/crearo-ssy/archive/2012/11/05/2754641.html
Combo Box控件:https://www.cnblogs.com/ggbailei/articles/2769504.html
登录框:https://blog.csdn.net/qq_31275519/article/details/52120910
读取文件在EditControl中显示乱码:https://blog.csdn.net/xuyangcao123/article/details/44057003
实时显示轨迹:https://blog.csdn.net/mikasoi/article/details/81415564
MessageBox()用法简介:https://blog.csdn.net/weixin_37605770/article/details/79049986
Invalidate和UpdateWindow,UpdateData区别联系:https://blog.csdn.net/komtao520/article/details/49491687