MFC基础控件说明

本文详细介绍了MFC中的各种基础控件,包括按钮、静态文本、组合框、编辑框/富文本框、图片控件、滑块/进度条、自旋按钮、热键控件、动物控件、日期时间控件、IP地址控件、列表控件、树形控件、属性网格、选项卡控件、菜单和工具栏,以及模态对话框和窗口子类化。并讨论了如何设置控件的属性、颜色和样式,以及如何处理用户交互。文章提供了基础用法和一些高级特性的实现方法,旨在帮助开发者更好地理解和使用MFC控件。
摘要由CSDN通过智能技术生成

目录

        一. button 控件

      1. CButton类

      2. CSplitButton类

      3.  CMFCButton类

      4. CMFCColorButton类

      5. CMFCMenuButton类

      6.  CRadioButton类

      7. CCheckBox类

二.  StaticText

        1. CStatic类

        2.  CLinkCtrl类

三.  CComboBox

        1. CComboBox类

        2. CComboBoxEx类

        3. CMFCFontComboBox

四.  CEdit/CRichEdit

       1.  CEdit类       

       2.  CMFCEditBrowseCtrl类

      3.  CRichEdit

五. Pic Ctrl

六.  Slider/Progress

七.  SPinCtrl

八. CHotKey

九. CAnimalCtrl

十. CDateTime

          1. CDateTime

          2. CMonthCtrl

十一. IP Ctrl

         1. CIPAddressCtrl

         2. CNetAddressCtrl

十二.  List Ctrl

         1.  CListBox

         2.  CVSListBox

         3.  CListCtrl

十三. Tree Ctrl

十四. Shell List/Tree

十五.  CPropertyGrid

十六. TabCtrl

十七.  CMenu

十八. CToolBar

十九. Modal Dialog

二十. 窗口子类化

 二十一. 总结        


        一. 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类:①可以设置背景色;②还是"图标"+"文本",只是图标和文本都可以设置三种状态normalhot(鼠标进入按钮), 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 filestrue 

        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
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值