目录
一. button 控件
1. CButton类
(1) 设置/获取 文本 : SetWindowText/GetWindowText
(2) 设置图标:button类是不能设置背景色或背景图片的,只能设置"图标" + “文本” 的格式
//设置button图标icon
CButton* pButton = static_cast<CButton*>(GetDlgItem(IDC_BTN_ICO));
ASSERT(nullptr != pButton);
pButton->ModifyStyle(0, BS_TOP); //添加内容的对齐方式:BS_TOP, BS_LEFT等
//设置图标
HICON hIcon = ::LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON_BTN));
pButton->SetIcon(hIcon);
//调整文本位置
CRect stRect = { 10, 10, 0, 10 };
pButton->SetTextMargin(&stRect);//设置文本外边距
(3) 从资源加载位图:LoadBitmap/LoadImage只能加载bmp格式,完全满足不了现在的需求 ,所以在MFC里我们使用CImage来加载,如果要使用GDI+ 编程,就就使用Gdiplus::Image, Win32里可以使用CxImag类:
https://www.codeproject.com/Articles/1300/CxImage
CImage objImage;
objImage.Load(_T(".//res//button.png"));
//HBITMAP hBitmap = objImage.Detach();//可行
CBitmap objBitmap;
objBitmap.Attach(objImage.Detach());
pBitBtn->SetBitmap(objBitmap);
objBitmap.DeleteObject();
(4) 一般我们修改控件背景色,文本色都是通过OnCtrlColor来实现,但是实践后你会发现此法对Button无用,那如何去改变呢?一种方式是使用 CMFCButton,它可以轻松地修改背景色和文本色;另一种方法就是派生CButton类,重载DrawItem,实现自绘。
2. CSplitButton类
(1) “按钮” + “菜单”的组合方式:关于菜单的相关操作,在讲菜单的时候再进行说明
m_objSplitBtn.SetDropDownMenu(IDR_MENU_BTN, 0);//菜单资源
3. CMFCButton类
(1) 对比Button类:①可以设置背景色;②还是"图标"+"文本",只是图标和文本都可以设置三种状态normal, hot(鼠标进入按钮), pushed(按钮按下);③设置提示文本
//直接给变量出来?为什么不设计函数,不解
m_objMFCBtn.m_nFlatStyle = CMFCButton::BUTTONSTYLE_NOBORDERS;//按钮样式:没有边框
m_objMFCBtn.m_nAlignStyle = CMFCButton::ALIGN_LEFT;//文本对齐方式
m_objMFCBtn.m_bTopImage = TRUE;//图片和文本呈现方式
//m_objMFCBtn.m_bTransparent = TRUE; //设置透明度,TRUE时SetFaceColor无效
//设置图片
//m_objMFCBtn.SetImage(IDB_PNG_NORMAL, IDB_PNG_HOT, IDB_PNG_DISABLE);//设置按钮的normal, hot, disabled状态图
//m_objMFCBtn.SizeToContent();//按钮自适应图片和文本大小
//设置文本色
m_objMFCBtn.SetFaceColor(RGB(0, 191, 255));
m_objMFCBtn.SetTextColor(RGB(255, 255, 255));
m_objMFCBtn.SetTextHotColor(RGB(255, 105, 180));
//设置提示
//需要把CMFCButton属性里的fulltooltips(大工具窗口)设置为false
//SetToolTip会造成内存泄露,有一个m_pToolTip没有被释放,解决办法动态创建
m_objMFCBtn.SetTooltip(_T("提示我是一个MFC按钮"));
4. CMFCColorButton类
(1) MFC自己做的颜色拾取器,基本不需要再重新设计,设置下相关属性就行了
m_objMFCColorBtn.EnableAutomaticButton(_T("Default"), afxGlobalData.clrBtnText);//设置颜色说明文本
m_objMFCColorBtn.EnableOtherButton(_T("Other..."));//设置颜色拾取器的标题
m_objMFCColorBtn.SetColor((COLORREF)-1);//设置默认颜色
m_objMFCColorBtn.SetColorName((COLORREF)-1, _T("Default Color"));//设置弹出窗口的颜色说明文本
m_objMFCColorBtn.SetColumnsNumber(6);//设置弹出窗口的颜色列数
5. CMFCMenuButton类
(1) 和CSplitButton类似,也是“按钮” + “菜单”的格式,但是可以设置菜单弹出的位置:“下” 或 “右”
//CMFMenuButton: 这里的menu一定不要是局部变量,原因是菜单消息被转到MenuButton内部处理
m_objMenu.LoadMenu(IDR_MENU_BTN);
m_objMFCMenuBtn.m_hMenu = m_objMenu.GetSubMenu(0)->GetSafeHmenu();//关联menu
m_objMFCMenuBtn.m_bOSMenu = FALSE;
m_objMFCMenuBtn.m_bRightArrow = TRUE;
6. CRadioButton类
(1) button设计分组:eg. 6个按钮, "Ctrl + D" 设置6个按钮序号连续(eg.1,2,3,4,5,6),1和4设置了"group"属性,那么,1,2,3一组, 4,5,6一组
(2) 怎么获取按钮被选中呢?两种方式实现
① 消息响应
ON_BN_CLICKED(IDC_RADIO1, &CDlgButton::OnBnClickedRadio1)
... ...
void CDlgButton::OnBnClickedRadio1()
{
// TODO: 在此添加控件通知处理程序代码
m_iRadio = 1;
}
② API检测哪个按钮被选中:IsDlgButtonChecked
UINT auiCtrlID[] = { IDC_RADIO4, IDC_RADIO5, IDC_RADIO6 };
for (int iCount = 0; iCount < ARRAYSIZE(auiCtrlID); iCount++)
{
if (BST_CHECKED == IsDlgButtonChecked(auiCtrlID[iCount]))
{
CString strRadio;
strRadio.Format(_T("Radio %d is selected"), iCount + 4);
AfxMessageBox(strRadio);
}
}
7. CCheckBox类
(1) 可以多选,其他用法和CRadioButton差不多,这里不再进行说明
二. StaticText
1. CStatic类
(1) 更多地用来设置提醒文字,我们还是看下如何修改它的背景色和文本色
ON_WM_CTLCOLOR()
... ...
HBRUSH CDlgText::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: 在此更改 DC 的任何特性
if ((CTLCOLOR_STATIC == nCtlColor) && (&m_objStcText == pWnd))
{
//pDC->SetBkMode(TRANSPARENT);
pDC->SetBkColor(RGB(255, 255, 0));//设置字体背景色
pDC->SetTextColor(RGB(255, 0, 0));//设置字体颜色
pDC->SelectObject(&m_objFont);//设置字体大小,注意销毁字体
//return (HBRUSH)::GetStockObject(WHITE_BRUSH);//选择白色画刷,不用系统画刷 可选颜色太少了
return ::CreateSolidBrush(RGB(0, 255, 255));//自定义画刷,这样就可以画控件的背景色了
}
// TODO: 如果默认的不是所需画笔,则返回另一个画笔
return hbr;
}
2. CLinkCtrl类
(1) 对比CStatic类,多一个"超链接"文本设置, 设置控件颜色还是使用OnCtrlColor
m_objFont.CreatePointFont(180, _T("宋体"));
//link text
m_objLinkFont.CreatePointFont(180, _T("宋体"));
m_objLinkCtrl.SetFont(&m_objLinkFont);//设置字体大小
m_objLinkCtrl.SetWindowText(_T("国内搜索用度娘:<a href=\"http://www.baidu.com\">百度搜索</a> \
国外搜索用谷歌:<a href=\"http://www.google.com\">谷歌搜索</a> "));
//设置超链接信息:这样设置之后就能修改超链接的文本颜色了
LITEM stItem = { 0 };
stItem.mask = LIF_ITEMINDEX | LIF_STATE;
stItem.state = LIS_DEFAULTCOLORS; // 修改默认超链接颜色需要vista以上系统才支持.
stItem.stateMask = LIS_DEFAULTCOLORS;
//
stItem.iLink = 0;
m_objLinkCtrl.SetItem(&stItem);//链接1
stItem.iLink = 1;
m_objLinkCtrl.SetItem(&stItem);//链接2
(2) 点击超链接文本的消息响应
ON_NOTIFY(NM_CLICK, IDC_SYSLINK_TEXT, &CDlgText::OnNMClickSyslinkText)
... ...
void CDlgText::OnNMClickSyslinkText(NMHDR *pNMHDR, LRESULT *pResult)
{
PNMLINK pNMlink = (PNMLINK)pNMHDR;
::ShellExecute(NULL, _T("open"), pNMlink->item.szUrl, NULL, NULL, SW_SHOWNORMAL);
*pResult = 0;
}
三. CComboBox
1. CComboBox类
(1) 用法比较简单,添加字符AddString,插入指定位置字符InsertString, 设置选择序号SetCurSel
LPCTSTR alpString[] = { _T("abcd"), _T("abdef"), _T("abefg"), _T("abcdddd"), _T("abcc") };
for (int iCount = 0; iCount < ARRAYSIZE(alpString); iCount++)
{
m_objComboBox.AddString(alpString[iCount]);//添加
}
m_objComboBox.InsertString(3, _T("在河上一起游泳"));//插入
m_objComboBox.SetCurSel(0);//选择第几条列表项
2. CComboBoxEx类
(1) 在CComboBox类的基础上,添加了"图标" + "文本"的结合方式, 这里使用了CImageList类,用来绑定CComBoxEx类,CImageList需要手动释放
//ComboBoxEx
m_objImageList.Create(16, 16, ILC_COLOR32, 3, 3);//背景透明,默认为ILC_COLORDDB
m_objImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON_COMBO1));
m_objImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON_COMBO2));
m_objImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON_COMBO3));
m_objComboBoxEx.SetImageList(&m_objImageList);//设置图像列表
//comboBox item
COMBOBOXEXITEMW stComboItem = { 0 };
LPTSTR alpFruit[] = {_T("蓝梅"), _T("棒棒糖"), _T("开心果")};
for (int iNum = 0; iNum < m_objImageList.GetImageCount(); iNum++)
{
stComboItem.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE;
stComboItem.iItem = iNum;
stComboItem.iImage = iNum;
stComboItem.iSelectedImage = iNum;
stComboItem.pszText = alpFruit[iNum];
m_objComboBoxEx.InsertItem(&stComboItem);
}
m_objComboBoxEx.SetCurSel(0);
3. CMFCFontComboBox
(1) MFC自己做了一个系统字体选择的Combox,可以直接使用
m_objFontComboBox.SelectFont(_T("宋体"));
四. CEdit/CRichEdit
1. CEdit类
(1) 有一些功能可以直接在"属性"栏设置,eg,只能输入数字,只读,密码输入方式等,其中OEM字符说明:
https://www.cnblogs.com/KevinYang/archive/2010/06/18/1760597.html
(2) 设置背景色,文本色等,使用OnCtrlColor实现
HBRUSH CDlgEdit::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
if (GetDlgItem(IDC_EDIT_NORMAL)->m_hWnd == pWnd->m_hWnd)
{
pDC->SetBkColor(RGB(255, 255, 0));
pDC->SetTextColor(RGB(255, 0, 0));
}
// TODO: 如果默认的不是所需画笔,则返回另一个画笔
return hbr;
}
(3) 多行显示:SetSel 和 ReplaceSel 实现
CString strEdit;
m_objEditMulti.GetWindowText(strEdit);
DWORD dwEditLen = m_objEditMulti.GetWindowTextLength();
if (0 >= dwEditLen)
{
strEdit = _T("我想测试一下换行功能\r\n");
}
//m_objEditMulti.SetSel(0, -1);//选择编辑器所有文本
m_objEditMulti.SetSel(-1, 0);//不选择文本
m_objEditMulti.ReplaceSel(strEdit);
m_objEditMulti.ScrollWindow(0, 0);//光标始终停在尾部
(4) 变量类型:UpdateData(FALSE):显示变量在界面上 UpdateData(TRUE):获取变量的值
m_dbEdit = 3.14159;
UpdateData(FALSE);//在edit上显示
... ...
CString strData;
UpdateData(TRUE);//获取Edit上内容
strData.Format(_T("%lf"), m_dbEdit);
AfxMessageBox(strData);
(5) 文件拖放到CEdit上显示: CEdit的父窗口属性:Accept files为true
ON_WM_DROPFILES()
... ...
void CDlgEdit::OnDropFiles(HDROP hDropInfo)//拖放文件处理
{
CString strFilePath;
int iDropCount = DragQueryFile(hDropInfo, -1, NULL, 0);
if (1 == iDropCount)//单个文件
{
DragQueryFile(hDropInfo, 0, strFilePath.GetBuffer(MAX_PATH), MAX_PATH);//获取文件名
//文件读写及网络传输尽量使用ANSI:数据量小,传送快
CFile objFile;
if (TRUE == objFile.Open(strFilePath, CFile::modeRead))
{
UINT uiBuffLen = (UINT)objFile.GetLength() + 1;//给文件一个'\0'结束这符
char* pcBuffer = new char[uiBuffLen];
ZeroMemory(pcBuffer, uiBuffLen);
objFile.Read(pcBuffer, uiBuffLen);//读文本
#if _UNICODE
ATL::CA2W objA2W(pcBuffer);
TCHAR* pcBuffW = (TCHAR*)objA2W;
m_objEditMulti.SetWindowText(pcBuffW);
#else
m_objEditMulti.SetWindowText(pcBuffer);
#endif
objFile.Close();
delete[]pcBuffer;
pcBuffer = nullptr;
}
}
else if (1 < iDropCount)//文件夹
{
//暂时不处理
}
CDialogEx::OnDropFiles(hDropInfo);
}
(6) ANSI, UNICODE乱码在编码时使用位置: 文件也要是ANSI格式,ANSI 文件操作及网络数据传输时使用:数据量小一倍,传送快
2. CMFCEditBrowseCtrl类
(1) "Edit" + "Button"组合模式:用来做选择文件/文件夹的组合框,也不需要写button的响应函数,系统都帮我们做好了,非常方便
//m_objEditBrowse.EnableBrowseButton(FALSE);//是否显示选择按钮
m_objEditBrowse.EnableFileBrowseButton(nullptr, _T("zip Files(*.zip)|*.zip|"));//使用"选择文件"模式,可以过滤文件后缀名
//m_objEditBrowse.EnableFolderBrowseButton();//使用"选择文件夹"模式
3. CRichEdit
(1) 对比Edit设置文本色使用OnCtrlColor, CRichEdit不用,而是使用CHARFORMAT2来设置,并且可以设置某一部分的文本大小和文本色
m_objRichEdit.SetWindowText(TEXT("做一个富文本编辑框例子\n"));
CHARFORMAT2 cf;
ZeroMemory(&cf, sizeof(cf));
cf.cbSize = sizeof(CHARFORMAT2);
cf.dwMask = CFM_COLOR | CFM_FACE | CFM_SIZE/* | CFM_BACKCOLOR*/; //
cf.crBackColor = RGB(0, 255, 0); // 背景色
cf.crTextColor = RGB(255, 0, 0); //文字颜色
cf.yHeight = 440;
_tcscpy_s(cf.szFaceName, _T("微软雅黑"));
m_objRichEdit.SetSel(1, 6); // 选中区域文字
m_objRichEdit.SetSelectionCharFormat(cf);
m_objRichEdit.SetSel(-1, -1);
(2) CRichEdit最大的特点是可以加载OLE控件,这样就大大丰富了CRichEdit可以使用的场景,像word,excel,pdf,图像,视频等都可以被加载进来,codeproject 上有一个例子加载rtf文件:https://www.codeproject.com/Articles/9541/A-Rich-Edit-Control-That-Displays-Bitmaps-and-Othe
这里不使用派生,加载一下图像(bmp,pgn,jpg)
void CDlgEdit::AddImage(CRichEditCtrl& objRichEdit, LPCTSTR strFilePath)
{
//获取位图
HBITMAP hBmp = NULL;
Gdiplus::Bitmap * pBmp = Gdiplus::Bitmap::FromFile(strFilePath);
pBmp->GetHBITMAP(0, &hBmp);
STGMEDIUM stgm;
stgm.tymed = TYMED_GDI;
stgm.hBitmap = hBmp;
stgm.pUnkForRelease = NULL;
FORMATETC fm;
fm.cfFormat = CF_BITMAP;
fm.ptd = NULL;
fm.dwAspect = DVASPECT_CONTENT;
fm.lindex = -1;
fm