MFC的使用

1.初使用的简单代码

该程序包含两个代码 头文件mfc.h和mfc.cpp文件

头文件mfc.h

#pragma once
#include<afxwin.h>

class MyApp:public CWinApp//CWinApp应用程序类
{
public:
    //程序入口
    virtual BOOL InitInstance();
};
class MyFrame : public CFrameWnd//继承窗口框架类a
{
public:
    MyFrame();
};


程序文件mfc.cpp

#define _CRT_SECURE_NO_WARNINGS

#include"mfc.h"

MyApp app;//全局应用程序对象
BOOL MyApp::InitInstance()
{
    //创建窗口对象
    MyFrame* frame = new MyFrame;
    //显示和更新
    frame->ShowWindow(SW_SHOWNORMAL);
    frame->UpdateWindow();
    
    m_pMainWnd = frame;//保存窗口的指针

    return TRUE;
}

MyFrame::MyFrame()
{
    Create(NULL, L"mfc");//创建窗口
}

代码解析

mfc需要包含的头文件 afxwin.h

自定义类MyApp,继承了cWinApp应用程序类,使用MyApp创建应用程序类对象,该对象有且仅有一个

在MyApp类中定义的函数 InitInstance 是整个应用程序的入口

自定义类MyFrame,继承了框架类CFrameWnd ,使用该类的构造函数创建了一个窗口,

Create函数的使用, Create(NULL, 标题名称)

使用MyFrame创建一个窗口对象

使用ShowWindow和UpdateWindow两个函数显示和更新

注意:在该程序中编译会出现错误,需要在 项目属性-> 高级-> MFC的使用中调成 在共享DLL中使用MFC

2.消息映射机制

消息映射声明和分界宏

DECLARE_MESSAGE_MAP

声明将在类中使用消息映射来将消息映射到函数(必须在类声明中使用)

BEGIN_MESSAGE_MAP

开始消息映射的定义(必须在类实现中使用)

BEGIN_TEMPLATE_MESSAGE_MAP

开始在包含单个模板参数的类类型上定义消息映射

END_MESSAGE_MAP

结束消息映射的定义(必须在类实现中使用)

处理消息程序的宏

映射条目

函数原型

ON_WM_LBUTTONDBLCLK()

afx_msg void OnLButtonDblClk(UINT, CPoint)

ON_WM_LBUTTONDOWN()

afx_msg void OnLButtonDown(UINT, CPoint);

ON_WM_CHAR()

afx_msg voidOnChar(UINT, UINT, UINT);

查看更多的映射条目可以查看该链接

https://learn.microsoft.com/zh-cn/cpp/mfc/reference/wm-message-handlers-a-c?view=msvc-170

使用的函数代码

class MyFrame : public CFrameWnd//继承窗口框架类a
{
public:
    MyFrame();
    //声明宏 提供消息映射机制
    DECLARE_MESSAGE_MAP()

    afx_msg void OnLButtonDown(UINT, CPoint);//鼠标左键点击的函数原型       ON_WM_LBUTTONDOWN()
    afx_msg void OnChar(UINT, UINT, UINT);//键盘按下的函数原型   ON_WM_CHAR()
    afx_msg void OnPaint();//绘图的函数原型    ON_WM_PAINT()
};
//分界宏
BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd)
    ON_WM_LBUTTONDOWN()//鼠标左键按下
    ON_WM_CHAR()//键盘点击
    ON_WM_PAINT()//绘图宏

//结束 消息映射机制
END_MESSAGE_MAP()

3.各个函数及类的解析

1.mfc中的字符串

在mfc中也有专属的字符串 CString,CString是一个类提供了许多函数对 CString 对象进行格式设置和分析,详细可查看该链接 https://learn.microsoft.com/zh-cn/cpp/mfc/reference/cstring-formatting-and-message-box-display?view=msvc-170

使用到的代码

CString str;
str.Format(L"x = %d  y = %d", point.x, point.y);//格式化字符串
MessageBox(str);

4.字符集

多字节:表示一个字符对应一个字节

宽字节:表示一个字符对应多个字节

宽字符字符串长度统计:

//统计宽字符的字符串长度
    wchar_t p[10] = TEXT("aaa");
    int a = wcslen(p);

char*与CString之间的转换

    //char*与CString之间的转换
    //char*转CString
    char str[10] = "aaa";
    char* p1 = str;
    CString cstr = CString(p1);
    //CString 转 char*
    CStringA temp;
    temp = cstr;
    char* pp = temp.GetBuffer();

宽字符的比较:

C++中字符串 string 容器的操作都与 str有关,比如 strchar,strstr…

但这都是对于ascll的字符串。

如果想操作宽字符串,把str换成wcs就可以,比如wcswcs 宽字符串比较函数

5.对话框的使用

一些控件:

  1. Button按钮:设置了这个按钮可以绑定其它控件,使其点击时可以触发控件,当双击按钮时可以自动生成代码

  1. Static Text控件:要控制该控件需要添加变量,要添加变量就需要修改他的ID,不能是以STATIC结尾

  1. Edit Contrl控件:这个控件可以编辑内容,在属性里可以设置单行,多行,接收Enter,滚动条等等

  1. Combo Box控件:这是一个下拉控件,在属性中找到 数据项可以加入数据,使用 ; 分割,默认排序修改为FALSE就不会排序,type类型改为 下拉列表 是不可以改变内容的

  1. List Control控件:列表控件,该控件可以设置一个表格,在属性中的视图可以修改格式

  1. Tree Control控件:树控件,在属性中可以设置一些风格

一些操作:

  • 右击对话框可以添加类进行绑定

  • 右击static控件可以添加变量

  • Edit Contrl控件有默认bug,需要在类视图中找到对话框类,然后右击属性,找到重写,添加 OnOk 功能,把里面的代码注释掉才可以按Enter不退出对话框

一些函数

xx.SetWindowTextW(字符串):设置控件或者按钮的内容

xx.GetWindowTextW(字符串变量):获取控件或者按钮的内容

xx.EnableWindow(BOOL值):设置按钮的状态

xx.OnOk():退出对话框

xx.OnCancel():退出对话框

UpdateData(BOOL):为FALSE时,表示将变量内容同步到控件中,为TRUE时,表示将控件内容同步到变量中

1.模态对话框

定义:在一个主窗口中打开一个子窗口,当只有关闭子窗口时,才可以操作主窗口,这个子窗口即为模态对话框

代码实例

//模态对话框按钮点击事件
void C模态对话框Dlg::OnBnClickedButton1()
{
    // TODO: 在此添加控件通知处理程序代码
    DlgExec dlg;
    dlg.DoModal();//模态对话框弹出

}

2.非模态对话框

定义:在一个主窗口中打开一个子窗口,不需要关闭该子窗口也能能够控制主窗口,则该子窗口即为非模态对话框

代码示例

//非模态对话框按钮点击事件
void C模态对话框Dlg::OnBnClickedButton2()
{
    // TODO: 在此添加控件通知处理程序代码
    //CDlgShow dlg;
    //dlg.Create(IDD_SHOW);//非模态对话框创建
    dlg.ShowWindow(SW_SHOWNORMAL);//显示模态对话框
}

3.Static Text(静态文本)控件添加图片

固定代码段:

 //设置静态控件窗口风格为位图居中显示
    n_pic.ModifyStyle(0xf, SS_BITMAP | SS_CENTERIMAGE);
    //通过路径获取bitmap句柄
#define HBMP(filepath, width, height) (HBITMAP)LoadImage(AfxGetInstanceHandle(), filepath, IMAGE_BITMAP, width, height, LR_LOADFR)
    //获取静态控件的大小
    CRect rect;
    n_pic.GetWindowRect(rect);
    //静态控件设置bitmap
    n_pic.SetBitmap(HBMP(TEXT("./1.webp"), rect.Width(), rect.Height()));

4.Edit Control(编辑框)

给Edit Control编辑框控件添加变量时,可以设置添加变量的类型是控件或者是

如果设置为控件需要调用内部函数对编辑框进行内容编辑,如果设置的类型为值则可以直接使用等号进行设置内容

控件类型代码:

void CMy03EditTextDlg::OnBnClickedButton1()
{
    // TODO: 在此添加控件通知处理程序代码

    CString str;
    n_edit1.GetWindowTextW(str);//获取内容
    n_edit2.SetWindowTextW(str);//设置内容
}

值类型代码:

void CMy03EditTextDlg::OnBnClickedButton3()
{
    // TODO: 在此添加控件通知处理程序代码
    //利用关联value的方式 设置和改变edit的内容
    n_text1 = L"哈哈";
    UpdateData(FALSE);//将变量内容 同步到控件中
}

5.Combo Box(下拉框)

函数:

xx.AddString(字符串):添加下拉框中的内容

xx.SetCurSel(索引):设置下拉框中默认的内容

xx.InsertString(索引,字符串):向下拉框中插入内容,索引表示插入的位置

xx.DeleteString(索引):删除下拉框中的内容,索引表示删除的位置

xx.GetLBText(索引,字符串):获取下拉框中的内容,索引表示获取的位置内容

代码示例:

//添加下拉内容
    n_cbx.AddString(L"李白");
    n_cbx.AddString(L"韩信");
    n_cbx.AddString(L"马可");
    n_cbx.AddString(L"刘禅");

    n_cbx.SetCurSel(0);//设置下拉框的默认内容
    n_cbx.InsertString(4, L"妲己");//插入下拉列表中
    n_cbx.DeleteString(3);//删除指定的内容

    CString str;
    n_cbx.GetLBText(1, str);//获取下拉列表中的值
    MessageBox(str);

6.List Control(列表控件)

使用到的函数:

1.xx.InsertColumn函数:给列表插入表头,只有view属性为Report报表模式才可以,函数原型

int InsertColumn(
    int nCol,
    const LVCOLUMN* pColumn);

int InsertColumn(
    int nCol,
    LPCTSTR lpszColumnHeading,
    int nFormat = LVCFMT_LEFT,
    int nWidth = -1,
    int nSubItem = -1);

参数1 nCol:新列的索引

参数2 pColumn:包含新列属性的 LVCOLUMN 结构的地址 参数2 lpszColumnHeading:包含列标题的字符串的地址

参数3 nFormat:指定列的对齐方式的整数。 可以是以下值之一:LVCFMT_LEFT、LVCFMT_RIGHT 或 LVCFMT_CENTER

参数4 nWidth:列的宽度(以像素为单位)。 如果此参数为 -1,说明未设置列宽 参数5 nSubItem:与列相关联的子项的索引。 如果此参数为 -1,说明没有与列关联的子项

返回值:如果成功,返回下一列的索引;否则返回 -1

2.xx.InsertItem函数:在列表视图控件中插入项,有四个重载,函数原型

int InsertItem(const LVITEM* pItem);

int InsertItem(
    int nItem,
    LPCTSTR lpszItem);

int InsertItem(
    int nItem,
    LPCTSTR lpszItem,
    int nImage);

int InsertItem(
    UINT nMask,
    int nItem,
    LPCTSTR lpszItem,
    UINT nState,
    UINT nStateMask,
    int nImage,
    LPARAM lParam);

参数1 pItem:指向指定项的属性的 LVITEM 结构的指针

参数2 nItem:要插入的项的索引

参数3 lpszItem:包含项标签的字符串的地址;如果项为回调项,则为 LPSTR_TEXTCALLBACK

参数4 nImage:项的图像的索引;如果项为回调项,则为 I_IMAGECALLBACK

参数5 nMask:指定哪些作为参数传递的项属性有效

参数6 nState:指示项的状态、状态图像和覆盖图像

参数7 nStateMask:指示将检索或修改状态成员的哪些位

参数8 lparam:与项关联的 32 位(如果是为 x64 执行编译,则为 64 位)应用程序特定的值

3.xx.SetItemText函数:更改列表视图项或子项的文本,函数原型

BOOL SetItemText(
    int nItem,
    int nSubItem,
    LPCTSTR lpszText);

参数1 nItem:要设置文本的项的索引

参数2 nSubItem:子项的索引;若要设置项标签,则为零

参数3 lpszText:指向包含新项文本的字符串的指针

返回值:如果成功,则不为零,否则为零

4.xx.SetExtendedStyle函数:设置列表视图控件当前的扩展样式,函数原型

DWORD SetExtendedStyle(DWORD dwNewStyle);

参数:要由列表视图控件使用的扩展样式的组合

返回值:列表视图控件使用的以前的扩展样式的组合

代码示例:

CString str[] = { L"姓名", L"性别", L"年龄" };
    for (int i = 0; i < 3; i++)
    {
        n_list.InsertColumn(i, str[i], LVCFMT_LEFT, 100);//给列表插入表头
    }
    n_list.InsertItem(0, L"张三");//插入正文,第一行插入
    n_list.SetItemText(0, 1, L"男");//在同一行插入第二列数据
    n_list.SetItemText(0, 2, L"23");//在同一行插入第三列数据
    //设置属性 整行选中状态  显示网格
    n_list.SetExtendedStyle(n_list.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

7.Tree Control(树控件)

一些函数:

1.xx.SetImageList函数:调用此函数,可设置树视图控件的普通或状态图像列表(也就是把图标资源和树控件绑定),并使用新图像重新绘制控件,函数原型

CImageList* SetImageList(
    CImageList* pImageList,
    int nImageListType);

参数1 pImageList:指向要分配的图像列表的指针。 如果 pImageList 为 NULL,则从树视图控件中删除所有图像

参数2 nImageListType:要检索的图像列表的类型,值可以是TVSIL_NORMAL和VSIL_STATE

详细在这里➡https://learn.microsoft.com/zh-cn/cpp/mfc/reference/ctreectrl-class?view=msvc-170#setimagelist

2.xx.InsertItem函数:调用此函数以在树视图控件中插入新项,详细在这里➡https://learn.microsoft.com/zh-cn/cpp/mfc/reference/ctreectrl-class?view=msvc-170#insertitem

3.xx.SelectItem函数:调用此函数以选择给定的树视图项,详细在这里➡

https://learn.microsoft.com/zh-cn/cpp/mfc/reference/ctreectrl-class?view=msvc-170#selectitem

代码示例:

//树控件使用
    //准备HICON图标
    HICON icons[2];
    icons[0] = AfxGetApp()->LoadIconW(IDI_ICON1);
    icons[1] = AfxGetApp()->LoadIconW(IDI_ICON2);

    //1.设置图标
    //CImageList list;
    list.Create(30, 30, ILC_COLOR32, 2, 2);//创建图片集合
    for (int i = 0; i < 2; i++)
    {
        list.Add(icons[i]);//添加具体的图片
    }
    n_tree.SetImageList(&list, TVSIL_NORMAL);//
    //设置节点
    HTREEITEM root = n_tree.InsertItem(L"根节点", 0, 0, NULL);
    HTREEITEM parent = n_tree.InsertItem(L"父节点", 1, 1, root);
    HTREEITEM sub1 = n_tree.InsertItem(L"字节点1", 2, 2, parent);
    HTREEITEM sub2 = n_tree.InsertItem(L"子节点2", 3, 3, parent);

    //设置默认项
    n_tree.SelectItem(sub1);

6.项目中的问题

项目基于mfc下单个文档编写。

1.在mfc项目中添加mfc类:右键项目->添加->新建项目->选中mfc类

CTreeView基类需要包含的头文件 afxcview.h 

2.切分窗口:

CSplitterWnd 创建一个切分窗口类的对象 m_splite

需要重写OnCreateClient函数,为框架创建客户端窗口,在 OnCreate 执行过程中由框架调用,返回TRUE表示自己拆分,在该函数中使用m_splite对象调用函数对窗口进行拆分,函数原型:

virtual BOOL OnCreateClient(
    LPCREATESTRUCT lpcs,
    CCreateContext* pContext);

m_splite.CreateStatic函数:对窗口进行拆分,函数详情➡https://learn.microsoft.com/zh-cn/cpp/mfc/reference/csplitterwnd-class?view=msvc-170#createstatic

函数原型:
virtual BOOL CreateStatic(
    CWnd* pParentWnd,
    int nRows,
    int nCols,
    DWORD dwStyle = WS_CHILD | WS_VISIBLE,
    UINT nID = AFX_IDW_PANE_FIRST);

参数 1 pParantWnd:拆分器窗口的父框架窗口

参数2 nRows:行数。 此值不得超过 16

参数3 nCols:列数。 此值不得超过 16

参数4 dwStyle:指定窗口样式

参数5 nID:窗口的子窗口的 ID。 ID 可以是 AFX_IDW_PANE_FIRST,除非拆分器窗口嵌套在另一个拆分器窗口中

m_splite.CreateView函数:指定拆分出来的窗口的类型,函数详情➡https://learn.microsoft.com/zh-cn/cpp/mfc/reference/csplitterwnd-class?view=msvc-170#createview

函数原型:
virtual BOOL CreateView(
    int row,
    int col,
    CRuntimeClass* pViewClass,
    SIZE sizeInit,
    CCreateContext* pContext);

参数1 row:指定要在其中放置新视图的拆分器窗口行

参数2 col:指定要在其中放置新视图的拆分器窗口列 参数3 pViewClass:指定新视图的 CRuntimeClass

参数4 sizeInit:指定新视图的初始大小 参数5 pContext:指向用于创建视图的创建上下文的指针(通常是 pContext 传递到父框架的被替代的 CFrameWnd::OnCreateClient 成员函数,其中正在创建拆分器窗口)

返回值:如果成功,则不为 0;否则为 0

代码示例:


BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
    // TODO: 在此添加专用代码和/或调用基类

    //return CFrameWnd::OnCreateClient(lpcs, pContext);//默认拆分
    
    //拆分成1行2列
    m_splite.CreateStatic(this, 1, 2);
    //左侧和右侧具体的显示内容
    m_splite.CreateView(0, 0, RUNTIME_CLASS(CSelectView), CSize(200, 500), pContext);
    m_splite.CreateView(0, 1, RUNTIME_CLASS(CDisplayView), CSize(600, 500), pContext);

    return TRUE;//表示自己拆分
}

3.界面挂载

使用到了 CCreateContext 结构,是没有基类的,创建窗口时,

此结构中的值提供用于将文档组件连接到其数据视图的信息。 仅当重写部分创建过程时才需使用 CCreateContext

CCreateContext 结构包含指向文档、框架窗口、视图和文档模板的指针。 它还包含指向 CRuntimeClass(用于标识要创建的视图类型)的指针。 运行时类信息和当前文档指针用于动态创建新视图

使用的成员函数:

CCreateContext结构中的成员函数

函数

类型

用途

m_pNewViewClass

CRuntimeClass*

要创建的新视图的 CRuntimeClass

m_pCurrentFrame

CFrameWnd*

用于对其他框架窗口进行建模的框架窗口,如在文档中创建第二个框架窗口

m_pLastView

CView*

用于对其他视图进行建模的原始视图,如创建拆分器窗口视图或在文档中创建第二个视图

CSplitterWnd类中的函数

DeleteView

从拆分器窗口中删除视图

CreateView

调用,用于在拆分器窗口中创建窗格

GetPane

返回指定行和列的窗格

RecalcLayout

调整行或列大小后调用,以重新显示拆分器窗口

SetActivePane

将窗格设置为框架中的活动窗格

以下代码是把需要的界面挂载上去:

        CCreateContext Context;

        Context.m_pNewViewClass = RUNTIME_CLASS(CUserDlg);
        Context.m_pCurrentFrame = this;
        Context.m_pLastView = (CFormView*)m_splite.GetPane(0, 1);
        m_splite.DeleteView(0, 1);
        m_splite.CreateView(0, 1, RUNTIME_CLASS(CUserDlg), CSize(600, 500), &Context);
        CUserDlg* pNewView = (CUserDlg*)m_splite.GetPane(0, 1);
        m_splite.RecalcLayout();
        pNewView->OnInitialUpdate();
        m_splite.SetActivePane(0, 1);

4.发送自定义的函数信号

        //PostMessage:将消息放入窗口的消息队列中,然后返回且不等待相应的窗口处理消息
        //需要包含框架类头文件#include "MainFrm.h" 
        //CWnd::PostMessage 将一个消息放入窗口的消息队列
        //AfxGetMainWnd():框架窗口对象的指针
        //AfxGetMainWnd()->GetSafeHwnd():获取返回窗口的句柄,CWnd::GetSafeHwnd
        //NM_A:发送自定义消息
        //(WPARAM)NM_A:指定了附加的消息信息
        //(LPARAM)0:指定了附加的消息信息,此参数这里没有意义
        ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_A, (WPARAM)NM_A, (LPARAM)0);//把消息发出去

发送出去的消息会给到CMainFrame类中的自定义消息处理函数中

猜你喜欢

转载自blog.csdn.net/weixin_62859191/article/details/128677096
今日推荐