MFC第二十九天 CView类的分支(以及其派生类的功能)、MFC六大关键技术

文章目录

  • CView类的分支
    • CEditView
    • CHtmlView
      • MainFrm.h CMainFrame 类的接口
      • CMainView .h
    • CListCtrl与CListView的创建原理
  • CTreeView
    • CTreeCtrl类简介
    • CTreeCtrl类的原理以及常用功能
  • MFC六大关键技术
  • 视图和带分割栏的框架开发与消息路由
    • CLeftView.cpp
    • CRightView.h
    • CRightView.cpp
    • CWelcome .h
    • CWelcome.cpp
    • division.h
    • division.cpp
    • MainFrm.h
    • MainFrm.cpp
  • 附录:为什么用户点击一下视图,即可让菜单有效?

CView类的分支

CEditView

对CMainView使用了CEditView类的派生,对其默认字体进行改变。

#include "CMainView.h"BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{CCreateContext cc;cc.m_pNewViewClass = RUNTIME_CLASS(CMainView);CreateView(&cc);return CFrameWnd::OnCreateClient(lpcs, pContext);
}
// CMainView 视图
class CMainView : public CEditView
{DECLARE_DYNCREATE(CMainView)protected:CMainView();           // 动态创建所使用的受保护的构造函数virtual ~CMainView();protected:DECLARE_MESSAGE_MAP()
public:virtual void OnInitialUpdate();afx_msg void OnEnChange();
};
void CMainView::OnInitialUpdate()
{CEditView::OnInitialUpdate();auto hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);SetFont(CFont::FromHandle(hFont), FALSE); //CFont::FromHandle(hFont) 将句柄转为指针 临时外壳}

在这里插入图片描述
在这里插入图片描述

CHtmlView

需要添加#include <afxhtml.h>头文件

MainFrm.h CMainFrame 类的接口

#pragma once
class CMainView;
class CMainFrame : public CFrameWnd
{CMainView* m_pMainView;
}
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{CCreateContext cc;cc.m_pNewViewClass = RUNTIME_CLASS(CMainView);m_pMainView =(CMainView*)CreateView(&cc);return  m_pMainView!=NULL;
}
BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{// 让视图第一次尝试该命令if (m_pMainView && m_pMainView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))return TRUE;// 否则,执行默认处理return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

CMainView .h

class CMainView : public CHtmlView
{DECLARE_DYNCREATE(CMainView)
}
#include "pch.h"
#include "Browse.h"
#include "CMainView.h"void CMainView::OnInitialUpdate()
{CHtmlView::OnInitialUpdate();Navigate2(_T("www.baidu.com")); //导航到目标地址上}

在这里插入图片描述

CListCtrl与CListView的创建原理

a)CListCtrl的内部创建原理是通过CWnd::Create(sClassName,…)来实现的。
b)CStatic,CEdit,CButton的内部创建原理无一不是这个原理,即使是拖入对话框的控件底层也是这样实现的。
(通过.rc读取风格和位置等要素,再调用CWnd类的Create函数)
c)CListView和CTreeView整个类都几乎没有代码,其实就是一个变种的CListCtrl或者CTreeCtrl。
d)所以你会看到直接强转:

INLINE CListCtrl& CListView::GetListCtrl() const{ return *(CListCtrl*)this; }

CListView和CTreeView的原理

// CListView
_AFXCVIEW_INLINE CListView::CListView() : CCtrlView(WC_LISTVIEW,AFX_WS_DEFAULT_VIEW){ }_AFXCVIEW_INLINE CListCtrl& CListView::GetListCtrl() const{ return *(CListCtrl*)this; }
_AFXCVIEW_INLINE CTreeView::CTreeView() : CCtrlView(WC_TREEVIEW,AFX_WS_DEFAULT_VIEW){ }_AFXCVIEW_INLINE CTreeCtrl& CTreeView::GetTreeCtrl() const{ return *(CTreeCtrl*)this; }

CTreeView

CTreeCtrl类简介

class CTreeCtrl : public CWnd
{// DECLARE_DYNAMIC virtual OK - CWnd has DECLARE_DYNAMICDECLARE_DYNAMIC(CTreeCtrl)// Constructors
public:CTreeCtrl();// Generic creatorBOOL Create(_In_ DWORD dwStyle, _In_ const RECT& rect, _In_ CWnd* pParentWnd, _In_ UINT nID);// Generic creator allowing extended style bitsBOOL CreateEx(_In_ DWORD dwExStyle, _In_ DWORD dwStyle, _In_ const RECT& rect,_In_ CWnd* pParentWnd, _In_ UINT nID);// Attributes// Retrieves the bounding rectangle for the specified item.BOOL GetItemRect(_In_ HTREEITEM hItem, _Out_ LPRECT lpRect, _In_ BOOL bTextOnly) const;// Gets the count of items in the control.UINT GetCount() const;// Returns the level-to-level indentation (in pixels).UINT GetIndent() const;// Sets the level-to-level indentation (in pixels).void SetIndent(_In_ UINT nIndent);// Retrieves the image list associated with the control.CImageList* GetImageList(_In_ int nImageList) const;// Sets the image list associated with this control.CImageList* SetImageList(_In_opt_ CImageList* pImageList, _In_ int nImageList);// Retrieves the next item having the given relationship with the// specified item. 遍历函数HTREEITEM GetNextItem(_In_ HTREEITEM hItem, _In_ UINT nCode) const;// Retrieves the next child item after the specified item.HTREEITEM GetChildItem(_In_ HTREEITEM hItem) const;
//	获取长子// Retrieves the next sibling item after the specified item.HTREEITEM GetNextSiblingItem(_In_ HTREEITEM hItem) const;// Retrieves the previous sibling item of the specified item.HTREEITEM GetPrevSiblingItem(_In_ HTREEITEM hItem) const;// Retrieves the parent of the specified item.HTREEITEM GetParentItem(_In_ HTREEITEM hItem) const;// Retrieves the topmost visible item in the control.HTREEITEM GetFirstVisibleItem() const;// Retrieves the next visible item after the specified item.HTREEITEM GetNextVisibleItem(_In_ HTREEITEM hItem) const;// Retrieves the previous visible item before the specified item.HTREEITEM GetPrevVisibleItem(_In_ HTREEITEM hItem) const;// Retrieves the last expanded item in the tree. This does not retrieve the last item visible in the tree-view window.HTREEITEM GetLastVisibleItem() const;// Retrieves the higlighted item, NULL if none.HTREEITEM GetSelectedItem() const;获取选中的项// Retrieves the currently drop-highlighted item, NULL if none.HTREEITEM GetDropHilightItem() const;// Retrieves the root item of the control, NULL if none.HTREEITEM GetRootItem() const;// Retrieves information about a particular item in the control.BOOL GetItem(_Out_ TVITEM* pItem) const;// Retrieves the text associated with the given item.CString GetItemText(_In_ HTREEITEM hItem) const;// Retrieves the images associated with the given item.BOOL GetItemImage(_In_ HTREEITEM hItem, _Out_ int& nImage,_Out_ int& nSelectedImage) const;// Retrieves the state of the given item.UINT GetItemState(_In_ HTREEITEM hItem, _In_ UINT nStateMask) const;// Retrieves the user-supplied data associated with the given item.DWORD_PTR GetItemData(_In_ HTREEITEM hItem) const;// Sets the state of the an item.BOOL SetItem(_In_ TVITEM* pItem);BOOL SetItem(_In_ HTREEITEM hItem, _In_ UINT nMask, _In_opt_z_ LPCTSTR lpszItem, _In_ int nImage,_In_ int nSelectedImage, _In_ UINT nState, _In_ UINT nStateMask, _In_ LPARAM lParam);BOOL SetItemEx(_In_ HTREEITEM hItem, _In_ UINT nMask, _In_opt_z_ LPCTSTR lpszItem, _In_ int nImage,_In_ int nSelectedImage, _In_ UINT nState, _In_ UINT nStateMask, _In_ LPARAM lParam,_In_ UINT uStateEx, _In_opt_ HWND hWnd, _In_ int iExpandedImage);// Sets the text of the specified item.BOOL SetItemText(_In_ HTREEITEM hItem, _In_z_ LPCTSTR lpszItem);// Sets the image on the specified item.BOOL SetItemImage(_In_ HTREEITEM hItem, _In_ int nImage, _In_ int nSelectedImage);// Sets the state of the specified item.BOOL SetItemState(_In_ HTREEITEM hItem, _In_ UINT nState, _In_ UINT nStateMask);// Sets the user data on the specified item.BOOL SetItemData(_In_ HTREEITEM hItem, _In_ DWORD_PTR dwData);// Determines if the specified item has children.BOOL ItemHasChildren(_In_ HTREEITEM hItem) const;// Gets the count of items presently visible in the control.UINT GetVisibleCount() const;// Retrieves the tool tip control associated with this control.CToolTipCtrl* GetToolTips() const;// Sets the tool tip control to be used by this control.CToolTipCtrl* SetToolTips(_In_ CToolTipCtrl* pWndTip);// Retrieves the background colour used throughout the control.COLORREF GetBkColor() const;// Sets the background color to be used throughout the control.COLORREF SetBkColor(_In_ COLORREF clr);// Retrieves the height of items in the control.SHORT GetItemHeight() const;// Sets the height of items in the control.SHORT SetItemHeight(_In_ SHORT cyHeight);// Retrieves the text color used for all items in the control.COLORREF GetTextColor() const;// Sets the text color used for all items in the control.COLORREF SetTextColor(_In_ COLORREF clr);// Gets the checked state of the specified item in the control.// (Only useful on a control with the TVS_CHECKBOXES style.)BOOL GetCheck(_In_ HTREEITEM hItem) const;// Sets the checked state of the specified item in the control.// (Only useful on a control with the TVS_CHECKBOXES style.)BOOL SetCheck(_In_ HTREEITEM hItem, _In_ BOOL fCheck = TRUE);COLORREF GetLineColor() const;COLORREF SetLineColor(_In_ COLORREF clrNew = CLR_DEFAULT);// Operations// Inserts a new item to the control.HTREEITEM InsertItem(_In_ LPTVINSERTSTRUCT lpInsertStruct);HTREEITEM InsertItem(_In_ UINT nMask, _In_z_ LPCTSTR lpszItem, _In_ int nImage,_In_ int nSelectedImage, _In_ UINT nState, _In_ UINT nStateMask, _In_ LPARAM lParam,_In_ HTREEITEM hParent, _In_ HTREEITEM hInsertAfter);HTREEITEM InsertItem(_In_z_ LPCTSTR lpszItem, _In_ HTREEITEM hParent = TVI_ROOT,_In_ HTREEITEM hInsertAfter = TVI_LAST);HTREEITEM InsertItem(_In_z_ LPCTSTR lpszItem, _In_ int nImage, _In_ int nSelectedImage,_In_ HTREEITEM hParent = TVI_ROOT, _In_ HTREEITEM hInsertAfter = TVI_LAST);// Removes the specified item from the control.BOOL DeleteItem(_In_ HTREEITEM hItem);// Removes all items from the control.BOOL DeleteAllItems();// Expands the children of the specified item.BOOL Expand(_In_ HTREEITEM hItem, _In_ UINT nCode);// Selects the specified item. 选中BOOL Select(_In_ HTREEITEM hItem, _In_ UINT nCode);// Selects the specified item.BOOL SelectItem(_In_opt_ HTREEITEM hItem);// Selects an item to be the drop target in the control.BOOL SelectDropTarget(_In_opt_ HTREEITEM hItem);// Draws the specified item as the drop target for the control.BOOL SelectSetFirstVisible(_In_ HTREEITEM hItem);// Begins editing the label of the specified item.CEdit* EditLabel(_In_ HTREEITEM hItem);
TVN_ENDEDIT 消息时获取编辑控件,把用户输入的文字取出来// Retrieves the edit control used to perform in-place editing.CEdit* GetEditControl() const;
};

树形控件的属性

#define TVS_HASBUTTONS          0x0001
#define TVS_HASLINES       有虚线     0x0002
#define TVS_LINESATROOT         0x0004			#define TVS_EDITLABELS          0x0008
#define TVS_DISABLEDRAGDROP     0x0010
#define TVS_SHOWSELALWAYS       0x0020
#define TVS_RTLREADING          0x0040
#define TVS_NOTOOLTIPS          0x0080
#define TVS_CHECKBOXES          0x0100
#define TVS_TRACKSELECT         0x0200
#define TVS_SINGLEEXPAND        0x0400
#define TVS_INFOTIP             0x0800
#define TVS_FULLROWSELECT       0x1000
#define TVS_NOSCROLL            0x2000
#define TVS_NONEVENHEIGHT       0x4000
#define TVS_NOHSCROLL           0x8000  // TVS_NOSCROLL overrides this
#if (NTDDI_VERSION >= NTDDI_WINXP)
#define TVS_EX_NOSINGLECOLLAPSE     0x0001
#endif
#if (NTDDI_VERSION >= NTDDI_VISTA)
#define TVS_EX_MULTISELECT          0x0002
#define TVS_EX_DOUBLEBUFFER         0x0004
#define TVS_EX_NOINDENTSTATE        0x0008
#define TVS_EX_RICHTOOLTIP          0x0010
#define TVS_EX_AUTOHSCROLL          0x0020
#define TVS_EX_FADEINOUTEXPANDOS    0x0040
#define TVS_EX_PARTIALCHECKBOXES    0x0080
#define TVS_EX_EXCLUSIONCHECKBOXES  0x0100
#define TVS_EX_DIMMEDCHECKBOXES     0x0200
#define TVS_EX_DRAWIMAGEASYNC       0x0400
#endif

CTreeCtrl类的原理以及常用功能

CTreeCtrl类的选中消息分析:
a)结构体:

typedef struct tagTVITEMCHANGE {NMHDR hdr;UINT uChanged;HTREEITEM hItem;UINT uStateNew;UINT uStateOld;LPARAM lParam;
} NMTVITEMCHANGE;

b)State状态分析:

TVIS_SELECTED(0x0002):项被选中。
TVIS_CUT(0x0008):项被剪切。
TVIS_DROPHILITED(0x0004):项高亮显示,用于拖放操作。
TVIS_EXPANDED(0x0020):项展开。
TVIS_BOLD(0x0001):项以粗体显示。
TVIS_DISABLED(0x0040):项禁用(灰色显示)。
TVIS_EXPANDEDONCE(0x0200):项已经展开过一次。
TVIS_EXPANDPARTIAL(0x0400):项部分展开。
TVIS_OVERLAYMASK(0x0F00):覆盖层蒙版。

MFC六大关键技术

1、MFC Initialization —— MFC程序的初始化过程
参见:CWinApp::InitInstance的虚函数,MFC内部接管WinMain平台启动初始化之后再调用InitInstance。
开发者需要创建CWinApp的派生类,并且在全局区定义派生类的全局对象,最后在派生类礼重写InitInstance虚函数。

2、Message Mapping —— 消息映射
参见:任何窗口派生类的头文件中 :DECLARE_MESSAGE_MAP
源文件中:
BEGIN_MESSAGE_MAP(CMainDlg, CDialogEx)
消息映射的数组{数组的每个元素都是一个结构体(消息-ID-函数地址)}
END_MESSAGE_MAP()

3、Message Routing —— 消息传递(路由)
主要在框架与视图架构里,把框架收到的菜单和工具栏消息分发到各个视图类。

BOOL CMainFrame::OnCmdMsg(UINT nID...)if (m_pView && m_pView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))return TRUE;

4、RTTI(Runtime Type Identification)—— 运行时类型识别
核心的作用是任何MFC的类(CObject派生)都能够获取到类型信息。
而且能知道你的派生类是谁,甚至获取到整个派生树分枝的名字。

auto pInfo = obj.GetRuntimeClass();
while (pInfo)
{AfxMessageBox(CString(_T("你是:")) + pInfo->m_lpszClassName);pInfo = pInfo->m_pBaseClass;//pNext;
}

参见:RUNTIME_CLASS宏以及每个MFC类的信息管理:
DECLARE_DYNAMIC(CMainFrame)
IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
RTTI运行时识别类型,靠的就是

BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const;
CRuntimeClass* pClassThis = GetRuntimeClass();

5、Dynamic Creation —— 动态创建
比动态类型识别多了一个函数:
原理参见:DECLARE_DYNCREATE(CApp)

IMPLEMENT_DYNCREATE(CApp, CWinApp)
class CApp::public CWinApp
{
public:
static CObject* WINAPI CApp::CreateObject() 	{ return new CApp; } 
}

6、Persistence ——永久保存(串行化、序列化)
利用CArchive类将对象数据保存到磁盘上,把数据按照顺序连续(operator<<)存入到磁盘,加载时按照存入的顺序连续提取数据(operator>>);
优点是比结构体在存储文字时节省存储空间,存储文字时先存编码和长度,加载时再根据长度读取文字,并根据来源编码格式转换到目标格式。
MFC这种连续存储的机制称之为序列化存储(Serialize)。

视图和带分割栏的框架开发与消息路由

CLeftView.h

class CLeftView : public CTreeView{DECLARE_DYNCREATE(CLeftView) //动态创建CTreeCtrl& m_tree {	GetTreeCtrl() };CImageList m_iList;int GetDepth(HTREEITEM hItem) const;
protected:CLeftView();           // 动态创建所使用的受保护的构造函数virtual ~CLeftView();void InitCtrl();
protected:DECLARE_MESSAGE_MAP()
};

CLeftView.cpp

#include "pch.h"
#include "division.h"
#include "CLeftView.h"
#include "CRightView.h"
#include "CWelcome.h"
IMPLEMENT_DYNCREATE(CLeftView, CTreeView)
CLeftView::CLeftView()
{theApp.m_pLeftView = this;
}
CLeftView::~CLeftView()
{}
BEGIN_MESSAGE_MAP(CLeftView, CTreeView)ON_NOTIFY_REFLECT(TVN_SELCHANGED, &CLeftView::OnTvnSelchanged)ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, &CLeftView::OnTvnItemexpanded)ON_NOTIFY_REFLECT(TVN_ITEMCHANGED, &CLeftView::OnTvnItemChanged)ON_COMMAND(ID_COMP_ADD, &CLeftView::OnCompAdd)ON_COMMAND(ID_COMP_DEL, &CLeftView::OnCompDel)
END_MESSAGE_MAP()
// CLeftView 诊断
#ifdef _DEBUG
void CLeftView::AssertValid() const{CTreeView::AssertValid();
}
// CLeftView 消息处理程序
void CLeftView::OnInitialUpdate()
{CTreeView::OnInitialUpdate();if (m_iList.GetSafeHandle())return;InitCtrl();ModifyStyle(0, TVS_HASLINES| TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS);auto hItem = m_tree.InsertItem(_T("异人之下"),0,1);auto h = m_tree.InsertItem(_T("那都通"),2,3, hItem);m_tree.InsertItem(_T("张楚岚"),5,4,h);m_tree.InsertItem(_T("冯宝宝"),5,4,h);m_tree.InsertItem(_T("徐三"),  5,4,h);m_tree.InsertItem(_T("徐四"),  5,4,h);m_tree.Expand(h, TVE_EXPAND);auto h2 = m_tree.InsertItem(_T("武当山"),2,3 ,hItem);m_tree.InsertItem(_T("王也"),  5,4, h2);m_tree.InsertItem(_T("老天师"),5,4, h2);m_tree.InsertItem(_T("诸葛青"),5,4, h2);m_tree.InsertItem(_T("诸葛玄"),5,4, h2);m_tree.Expand(h2, TVE_EXPAND);m_tree.Expand(hItem, TVE_EXPAND); //要先插入再展开//m_tree.Select(h2, TVGN_CARET); //设置当前选择 并且带有样式m_tree.SelectItem(h); //设置当前选择 没有样式
}
void CLeftView::InitCtrl(){m_iList.Create(16, 16, ILC_COLOR32, 8, 8);int i = -1;while (++i < 6){m_iList.Add(theApp.LoadIcon(IDI_ICON1 + i));}m_tree.SetImageList(&m_iList, TVSIL_NORMAL);
}
int CLeftView::GetDepth(HTREEITEM hItem) const  //用于获取当前选中的行在 多深
{if (!hItem)return -1;int i = 0;while (hItem = m_tree.GetParentItem(hItem)){++i;}return i;
}
void CLeftView::OnTvnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)
{LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);// TODO: 在此添加控件通知处理程序代码*pResult = 0;
}
void CLeftView::OnTvnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult) //展开或者折叠
{LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);*pResult = 0;
}
void CLeftView::OnTvnItemChanged(NMHDR* pNMHDR, LRESULT* pResult)
{NMTVITEMCHANGE* p  = reinterpret_cast<NMTVITEMCHANGE*>(pNMHDR);auto hItem = p->hItem;if (TVIS_SELECTED & p->uStateNew){auto& split = theApp.m_split;auto pRightView = theApp.m_split.GetPane(0, 1);	 if (pRightView)split.DeleteView(0,1);switch (GetDepth(hItem)){case 0:case 1:split.CreateView(0, 1, RUNTIME_CLASS(CWelcome), { 0,0 }, NULL); break;case 2:{split.CreateView(0, 1, RUNTIME_CLASS(CRightView), { 0,0 }, NULL); CRightView* pRightView =(CRightView*) split.GetPane(0, 1);pRightView->Refresh();}}split.RecalcLayout();}*pResult = 0;
}

CRightView.h

class CRightView : public CListView{DECLARE_DYNCREATE(CRightView)//动态创建CListCtrl& m_list = GetListCtrl(); //说白了任何一个控件的创建都是由CWnd::Create(sCLassName)
protected:CRightView();           // 动态创建所使用的受保护的构造函数virtual ~CRightView();
public:void Refresh();
protected:DECLARE_MESSAGE_MAP()
public:afx_msg void OnStaffAdd();afx_msg void OnStaffDel();virtual void OnInitialUpdate();virtual BOOL PreCreateWindow(CREATESTRUCT& cs);	};

CRightView.cpp

#include "pch.h"
#include "division.h"
#include "CRightView.h"
IMPLEMENT_DYNCREATE(CRightView, CListView)
CRightView::CRightView(){theApp.m_pRightView = this;
}
CRightView::~CRightView()
{theApp.m_pRightView = nullptr;
}
BEGIN_MESSAGE_MAP(CRightView, CListView)ON_COMMAND(ID_STAFF_ADD, &CRightView::OnStaffAdd)ON_COMMAND(ID_STAFF_DEL, &CRightView::OnStaffDel)
END_MESSAGE_MAP()
void CRightView::Refresh()
{
}
void CRightView::AssertValid() const
{CListView::AssertValid();
}
void CRightView::OnStaffAdd()
{}
void CRightView::OnStaffDel()
{}
void CRightView::OnInitialUpdate(){CListView::OnInitialUpdate();if (m_list.GetHeaderCtrl()->GetItemCount() > 0) //防止标题插入两边return;m_list.InsertColumn(0, _T("工号"), 0, 150);m_list.InsertColumn(1, _T("姓名"), 0, 150);m_list.InsertColumn(2, _T("性别"), 0, 150);m_list.InsertColumn(3, _T("入职日期"), 0, 150);m_list.InsertColumn(4, _T("外语"), 0, 150);m_list.InsertColumn(5, _T("工资"), 0, 150);
}
BOOL CRightView::PreCreateWindow(CREATESTRUCT& cs)
{  cs.style |= LVS_REPORT;return CListView::PreCreateWindow(cs);
}

CWelcome .h

class CWelcome : public CFormView{DECLARE_DYNCREATE(CWelcome)
protected:CWelcome();           // 动态创建所使用的受保护的构造函数virtual ~CWelcome();protected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持DECLARE_MESSAGE_MAP()
};

CWelcome.cpp

#include "pch.h"
#include "division.h"
#include "CWelcome.h"
IMPLEMENT_DYNCREATE(CWelcome, CFormView)CWelcome::CWelcome(): CFormView(IDD_FORMVIEW)
{theApp.m_pRightView = this;
}
CWelcome::~CWelcome()
{theApp.m_pRightView = NULL;
}
BEGIN_MESSAGE_MAP(CWelcome, CFormView)
END_MESSAGE_MAP()

division.h

#include "resource.h"       // 主符号
#include "CLeftView.h"
// CApp:有关此类的实现,请参阅 division.cpp
class CLeftView;
class CRightView;
class CApp : public CWinApp
{
public:CApp() noexcept;CLeftView* m_pLeftView{};CView* m_pRightView{};CSplitterWnd m_split;
};
extern CApp theApp;

division.cpp

#include "pch.h"
#include "framework.h"
#include "afxwinappex.h"
#include "afxdialogex.h"
#include "division.h"
#include "MainFrm.h"#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CApp
BEGIN_MESSAGE_MAP(CApp, CWinApp)ON_COMMAND(ID_APP_ABOUT, &CApp::OnAppAbout)
END_MESSAGE_MAP()
BOOL CApp::InitInstance(){			// CApp 初始化CFrameWnd* pFrame = new CMainFrame;if (!pFrame)	return FALSE;m_pMainWnd = pFrame; 	// 创建并加载框架及其资源pFrame->LoadFrame(IDR_MAINFRAME,WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, nullptr,nullptr);if (m_pRightView->IsKindOf(RUNTIME_CLASS(CCtrlView)))AfxMessageBox(_T("m_pRightView对象是CCtrlView派生的"));elseAfxMessageBox(_T("m_pRightView对象不是CCtrlView派生的"));if (m_pRightView->IsKindOf(RUNTIME_CLASS(CFormView)))AfxMessageBox(_T("m_pRightView对象是CFormView派生的"));elseAfxMessageBox(_T("m_pRightView对象不是CFormView派生的"));pFrame->ShowWindow(SW_SHOW);	// 唯一的一个窗口已初始化,因此显示它并对其进行更新pFrame->UpdateWindow();				return TRUE;				}
// 唯一的 CApp 对象
CApp theApp;// 用于运行对话框的应用程序命令
void CApp::OnAppAbout()
{CAboutDlg aboutDlg;aboutDlg.DoModal();
}

MainFrm.h

class CMainFrame : public CFrameWnd{	 
public:CMainFrame() noexcept;
protected: DECLARE_DYNAMIC(CMainFrame)  //动态识别
public:				// 重写virtual BOOL PreCreateWindow(CREATESTRUCT& cs);virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo);
public:  // 实现virtual ~CMainFrame();
protected:afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);afx_msg void OnSetFocus(CWnd *pOldWnd);DECLARE_MESSAGE_MAP()virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);		};

MainFrm.cpp

#include "pch.h"
#include "framework.h"
#include "division.h"
#include "CLeftView.h"
#include "CRightView.h"
#include "MainFrm.h"// CMainFrame 构造/析构
CMainFrame::CMainFrame() noexcept
{// TODO: 在此添加成员初始化代码
}
CMainFrame::~CMainFrame()
{
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){if (CFrameWnd::OnCreate(lpCreateStruct) == -1)return -1;if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))	{TRACE0("未能创建工具栏\n");return -1;      // 未能创建	}if (!m_wndStatusBar.Create(this))	{TRACE0("未能创建状态栏\n");return -1;      // 未能创建	}m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);// TODO: 如果不需要可停靠工具栏,则删除这三行EnableDocking(CBRS_ALIGN_ANY);DockControlBar(&m_wndToolBar);		return 0;	}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{if( !CFrameWnd::PreCreateWindow(cs) )return FALSE;// TODO: 在此处通过修改//  CREATESTRUCT cs 来修改窗口类或样式cs.dwExStyle &= ~WS_EX_CLIENTEDGE;cs.lpszClass = AfxRegisterWndClass(0);return TRUE;
}
// CMainFrame 消息处理程序void CMainFrame::OnSetFocus(CWnd* /*pOldWnd*/)
{// 将焦点前移到视图窗口if (theApp.m_pLeftView)theApp.m_pLeftView->SetFocus();
}
BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{// 让视图第一次尝试该命令if (theApp.m_pLeftView &&theApp.m_pLeftView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))return TRUE;if (theApp.m_pRightView &&theApp.m_pRightView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))return TRUE;// 否则,执行默认处理return CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext){auto& split = theApp.m_split;split.CreateStatic(this, 1, 2);split.CreateView(0, 1, RUNTIME_CLASS(CRightView), { 0,0 }, NULL); //righrview 要在leftview之前  因为在leftview中调用rightview读取数据时,rightview还没有创建,拿不到数据 报它为空split.CreateView(0, 0, RUNTIME_CLASS(CLeftView), { 150,0 }, NULL);//theApp.m_pLeftView = (CLeftView*)split.GetPane(0, 0);  //做这个的目的为了是 点击左边的时候找右边方便 点击右边的时候找左边方便
//theApp.m_pRightView = (CRightView*)split.GetPane(0, 1);//给这个指针赋值也可通过构造函数赋值//CCreateContext cc;//cc.m_pNewViewClass = RUNTIME_CLASS(CLeftView);//theApp.m_pLeftView =(CLeftView*) CreateView(&cc);return TRUE;
}

在这里插入图片描述

附录:为什么用户点击一下视图,即可让菜单有效?

CView* pView = GetActiveView();

BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo){CPushRoutingFrame push(this);// pump through current view FIRSTCView* pView = GetActiveView();if (pView != NULL && pView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))return TRUE;// then pump through frameif (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))return TRUE;// last but not least, pump through appCWinApp* pApp = AfxGetApp();if (pApp != NULL && pApp->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))return TRUE;return FALSE;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/28659.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flink多流处理之connect拼接流

Flink中的拼接流connect的使用其实非常简单,就是leftStream.connect(rightStream)的方式,但是有一点我们需要清楚,使用connect后并不是将两个流给串联起来了,而是将左流和右流建立一个联系,作为一个大的流,并且这个大的流可以使用相同的逻辑处理leftStream和rightStream,也可以…

【golang】工作区与GOPATH

在学习go语言时&#xff0c;我们会从官网下载go语言的二进制包&#xff0c;然后解压并安装到某个目录&#xff0c;最后会配置环境变量&#xff0c;通过输入命令go version来验证是否安装成功。 配置了path环境后&#xff0c;我们还需要再配置3个环境变量&#xff0c;GOROOT、G…

完美的分布式监控系统——Prometheus(普罗米修斯)与优雅的开源可视化平台——Grafana(格鲁夫娜)

一、基本概念 1、之间的关系 prometheus与grafana之间是相辅相成的关系。作为完美的分布式监控系统的Prometheus&#xff0c;就想布加迪威龙一样示例和动力强劲。在猛的车也少不了仪表盘来观察。于是优雅的可视化平台Grafana出现了。 简而言之Grafana作为可视化的平台&#xff…

在excel调用SAP函数执行SAP数据查找或提交

1、下载插件 2、安装插件 3、执行函数 3.1 第一步 通过SAPRegister连接SAP服务器 var reg SAPRegister("10.10.14.15", "00", "mes", "AQ123456", "800") 需要改为实际的连接信息 "10.10.14.15" 为SAP服务器I…

嘉楠勘智k230开发板上手记录(三)--K230_RVV实战

按照K230_RVV实战.md操作 在k230_sdk目录下运行&#xff0c;Makefile里默认的toolchain路径是在/opt下的&#xff0c;需要拷贝过去 cp -r toolchain /opt/ make rt-smart-apps 进入目录 src/big/rt-smart 运行脚本 source smart-env.sh riscv64 配置环境变量 source smart-e…

随着野火的增加,甲烷排放也会增加

2020 年对加利福尼亚州造成严重破坏的野火使大气中充满了强效温室气体。 2020 年&#xff0c;溪火烧毁了北加州的内华达山脉。图片来源&#xff1a;Zachary Cava/Flickr&#xff0c;CC BY-NC-SA 2.0 2020 年&#xff0c;在高温和干旱的推动下&#xff0c;加州野火烧毁了超过160…

Verilog求log10和log2近似

Verilog求log10和log2近似 Verilog求10对数近似方法&#xff0c;整数部分用位置index代替&#xff0c;小数部分用查找表实现 参考&#xff1a; Verilog写一个对数计算模块Log2(x) FPGA实现对数log2和10*log10

Netty:ChannelHandler的两个生命周期监听事件方法:handlerAdded 和 handlerRemoved

说明 io.netty.channel.ChannelHandler有两个生命周期监听事件方法&#xff1a; handlerAdded(ChannelHandlerContext ctx)&#xff1a;当ChannelHandler被添加到实际的上下文、并且已经准备就绪等待处理事件的时候被调用。 handlerRemoved(ChannelHandlerContext ctx)&#…

SQL-每日一题【1179. 重新格式化部门表】

题目 部门表 Department&#xff1a; 编写一个 SQL 查询来重新格式化表&#xff0c;使得新的表中有一个部门 id 列和一些对应 每个月 的收入&#xff08;revenue&#xff09;列。 查询结果格式如下面的示例所示&#xff1a; 解题思路 1.题目要求我们重新格式化表&#xff0c;…

C++入门篇6 C++的内存管理

在学习C的内存管理之前&#xff0c;我们先来回顾一下C语言中动态内存 int main() {int* p1 (int*)malloc(sizeof(int));free(p1);// 1.malloc/calloc/realloc的区别是什么&#xff1f;int* p2 (int*)calloc(4, sizeof(int));//calloc 可以初始化空间为0int* p3 (int*)reall…

SpringCloud实用篇1——eureka注册中心 Ribbon负载均衡原理 nacos注册中心

目录 1 微服务1.1 微服务的演变1.2 微服务1.3 SpringCloud1.4 小结 2 服务拆分及远程调用2.1 服务拆分2.2 服务拆分案例2.3 实现远程调用2.4 提供者与消费者 3 Eureka注册中心3.1 Eureka的结构和作用3.2 搭建eureka-server3.3 服务注册3.4 服务发现 4 Ribbon负载均衡4.1 负载均…

安全杂记 - Linux文本三剑客之awk

目录 1.什么是AWK2.正则表达式3.语法4.内置变量示例printf命令5.复现awk经典实例(1).插入几个新字段(2).格式化空白(3).筛选IPv4地址(4).筛选给定时间范围内的日志 1.什么是AWK awk、grep、sed是linux操作文本的三大利器&#xff0c;合称文本三剑客。三者的功能都是处理文本&a…

基于DETR (DEtection TRansformer)开发构建MSTAR雷达影像目标检测系统

关于DETR相关的实践在之前的文章中很详细地介绍过&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a; 《DETR (DEtection TRansformer)基于自建数据集开发构建目标检测模型超详细教程》 《书接上文——DETR评估可视化》 基于MSTAR雷达影像数据开发构建目标检测系统&am…

CentOS虚拟机更改屏幕锁屏时间

&#xff08;1&#xff09;点击“应用程序”&#xff0c;再点击“系统工具”&#xff0c;再点击“设置” &#xff08;2&#xff09; &#xff08;3&#xff09;在“设置”中点击“Privacy”&#xff0c;点击“锁屏”

免费实用的日记应用:Day One for Mac中文版

Day One for Mac是一款运行在Mac平台上的日记软件&#xff0c;你可以使用Day One for mac通过快速菜单栏条目、提醒系统和鼓舞人心的信息来编写更多内容&#xff0c;day one mac版还支持Dropbox同步功能&#xff0c;想要day one mac中文免费版的朋友赶紧来试试吧&#xff01; …

hive 字段注释乱码

hive 字段注释乱码: 在mysql中运行&#xff1a; alter table COLUMNS_V2 modify column COMMENT varchar(256) character set utf8;OK

【2.1】Java微服务: Nacos的使用

目录 Nacos介绍 Nacos安装 下载和安装 修改端口 启动 服务注册与发现 导入Nacos管理依赖 导入服务依赖 配置Nacos的服务地址 启动服务&#xff0c;查看已注册的服务 服务分级存储模型 分级存储模型介绍 具体结构 配置实例集群 同集群优先的负载均衡策略 服务权重配置…

Vue 整合 Element UI 、路由嵌套、参数传递、重定向、404和路由钩子(五)

一、整合 Element UI 1.1 工程初始化 使用管理员的模式进入 cmd 的命令行模式&#xff0c;创建一个名为 hello-vue 的工程&#xff0c;命令为&#xff1a; # 1、目录切换 cd F:\idea_home\vue# 2、项目的初始化&#xff0c;记得一路的 no vue init webpack hello-vue 1.2 安装…

探索未来:直播实时美颜SDK在增强现实(AR)直播中的前景

在AR直播中&#xff0c;观众可以与虚拟元素实时互动&#xff0c;为用户带来更加丰富、沉浸式的体验。那么&#xff0c;直播美颜SDK在AR中有哪些应用呢&#xff1f;下文小编将于大家一同探讨美颜SDK与AR有哪些关联。 一、AR直播与直播实时美颜SDK的结合 增强现实技术在直播中…

【MFC】08.MFC消息,自定义消息,常用控件(MFC菜单创建大总结),工具栏,状态栏-笔记

本专栏上几篇文章讲解了MFC几大机制&#xff0c;今天带领大家学习MFC自定义消息以及常用控件&#xff0c;最常用的控件请查看本专栏第一二篇文章&#xff0c;今天这篇文章介绍工具栏&#xff0c;菜单和状态栏&#xff0c;以及菜单创建大总结。 文章目录 MFC消息分类&#xff1…