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

news2024/11/27 16:24:54

文章目录

  • 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_DYNAMIC
	DECLARE_DYNAMIC(CTreeCtrl)

// Constructors
public:
	CTreeCtrl();

	// Generic creator
	BOOL Create(_In_ DWORD dwStyle, _In_ const RECT& rect, _In_ CWnd* pParentWnd, _In_ UINT nID);

	// Generic creator allowing extended style bits
	BOOL 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派生的"));
	else
		AfxMessageBox(_T("m_pRightView对象不是CCtrlView派生的"));
	if (m_pRightView->IsKindOf(RUNTIME_CLASS(CFormView)))
		AfxMessageBox(_T("m_pRightView对象是CFormView派生的"));
	else
		AfxMessageBox(_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 FIRST
	CView* pView = GetActiveView();
	if (pView != NULL && pView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		return TRUE;
	// then pump through frame
	if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		return TRUE;
	// last but not least, pump through app
	CWinApp* pApp = AfxGetApp();
	if (pApp != NULL && pApp->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		return TRUE;
	return FALSE;
}

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

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

相关文章

Linux入门级命令

目录 1、开启终端 2、Linux命令格式 3、扩展&#xff1a;Linux下的命令补全 4、切换用户 5、uname命令 6、ls命令 ☆ 用法一 ☆ 用法二 ☆ 用法三 7、pwd命令 8、cd命令 9、clear命令 10、reboot命令 11、shutdown命令 12、type命令 13、history命令 14、host…

【学习】若依源码(前后端分离版)之 “ 分页以及查询的功能实现”

大型纪录片&#xff1a;学习若依源码&#xff08;前后端分离版&#xff09;之 “ 分页以及查询的功能实现” 前端部分后端部分结语 包括代码生成也好&#xff0c;最原始的系统也好&#xff0c;若依里每个页面只要有数据&#xff0c;基本上就有分页的功能&#xff0c;所以理解分…

背上大书包准备run之CSS篇

时隔一年多又要准备面试嘞。唉&#xff0c;人生呐&#xff0c;真是变幻莫测哟~ 社招应该不会问很多css吧&#xff0c;&#xff0c;&#xff0c;但是应该也会问吧&#xff0c;&#xff0c;&#xff0c;应该是从好多好多问题里只抽一两个问问吧&#x1f62d; 哦还有h5&#xff…

zabbix简易入门:基本的网络监控、WEB监控、拓朴图规划

需求背景&#xff1a; 我们越来越发现&#xff1a;网络越来越复杂&#xff0c;网络、应用、云端……故障点随时可能发生&#xff0c;而我们不能人工盯着所有的问题&#xff0c;所以&#xff0c;网管软件是必须的。那么没有预算的情况下&#xff0c;我们只好自己布署简单的…

24届近5年浙江工业大学自动化考研院校分析

今天给大家带来的是浙江工业大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、浙江工业大学 学校简介 浙江工业大学&#xff08;Zhejiang University of Technology&#xff09;&#xff0c;简称浙工大&#xff0c;主校区位于浙江省杭州市&#xff0c;是教育部与…

Stream API总结

Stream是Java 8提供的新特性&#xff0c;使得可以方便的对集合进行各种操作&#xff0c;本篇主要讲解StreamAPI常用方法。 Java8中有两大最为重要的改变。 第一个是 Lambda 表达式&#xff1b; 另外一个则是 Stream API(java.util.stream.*)。 Stream 是 Java8 中处理集合的关…

Java反射机制详解与使用方法大全!!!

❤ 作者主页&#xff1a;李奕赫揍小邰的博客 ❀ 个人介绍&#xff1a;大家好&#xff0c;我是李奕赫&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 记得点赞、收藏、评论⭐️⭐️⭐️ &#x1f4e3; 认真学习!!!&#x1f389;&#x1f389; 文章目录 Java反射机制…

Node.js学习笔记-03

七、网络编程 1. 构建 TCP 服务 TCP 是面向连接的协议&#xff0c;显著特征 在传输之前需要3次握手形成会话。 客户端 ——请求连接——> 服务器端 ——响应——> 客户端 ——开始传输——> 服务器端。 2. 构建 UDP 服务 3. 构建 HTTP 服务 http模块 在node中HTT…

电脑数据怎么加密?电脑数据加密软件有哪些?

在生活和工作中&#xff0c;我们总离不开电脑&#xff0c;而电脑中那些重要的数据&#xff0c;需要我们加密保护。那么电脑数据该怎么加密呢&#xff1f;电脑数据加密软件又有哪些呢&#xff1f;下面我们就来了解一下吧。 电脑数据加密软件 一般来说&#xff0c;常见的电脑加密…

Drools用户手册翻译——第四章 Drools规则引擎(十四)复杂事件处理(CEP)滑动窗口和内存管理

甩锅声明&#xff1a;本人英语一般&#xff0c;翻译只是为了做个笔记&#xff0c;所以有翻译错误的地方&#xff0c;错就错了&#xff0c;如果你想给我纠正&#xff0c;就给我留言&#xff0c;我会改过来&#xff0c;如果懒得理我&#xff0c;就直接划过即可。 目录 时间或长…

详解配置交换机多生成树MSTP+VRRP 的典型组网

详解配置交换机多生成树MSTPVRRP 的典型组网 组网&#xff1a; 1. 这是一个由三台交换机组成的倒三角型二层交换网络&#xff1b;网络中有4个VLAN&#xff1a;10、20、30、40&#xff1b;接口编号如图所示&#xff1b;SW3为接入层交换机&#xff0c;SW1、SW2为汇聚层交换机&am…

论文阅读 - Neutral bots probe political bias on social media

论文链接&#xff1a;Neutral bots probe political bias on social media | EndNote Click 试图遏制滥用行为和错误信息的社交媒体平台被指责存在政治偏见。我们部署中立的社交机器人&#xff0c;它们开始关注 Twitter 上的不同新闻源&#xff0c;并跟踪它们以探究平台机制与用…

linux自动程序

嵌入式linux下有软件需要自启动&#xff0c;只需要在/etc/init.d/rcS末尾添加所要启动的程序即可&#xff0c;开机就会自动运行 vi /etc/init.d/rcS在文件末尾添加 例&#xff1a;

Unity-Linux部署WebGL项目MIME类型添加

在以往的文章中有提到过使用IIS部署WebGL添加MIME类型使WebGL项目在浏览器中能够正常加载&#xff0c;那么如果咱们做的是商业项目&#xff0c;往往是需要部署在学校或者云服务器上面的&#xff0c;大部分情况下如果项目有接口或者后台管理系统&#xff0c;后台基本都会使用Lin…

对p-n结/AlGaN/GaN HEMTs中n-GaN掺杂浓度对栅极可靠性的影响

目录 第35届功率半导体器件与集成电路国际研讨会论文集2023年5月28日至6月1日&#xff0c;中国香港南方科技大学电气电子工程系&#xff0c;深圳标题&#xff1a;Impacts of n-GaN Doping Concentration on Gate Reliability of p-n Junction/AlGaN/GaN HEMTs摘要信息解释研究了…

MySQL基本语法总结

创建数据库 create database 数据库名&#xff1b; -- 字符集要看mysql 版本&#xff0c; 5.7 Latin&#xff0c; 8.0 utf8 create database 数据库名 character set ‘utf8’&#xff1b;-- 指定数据库的字符集 create database IF NOT EXISTS 数据库名 character se…

k8s-----集群调度

目录 一&#xff1a;调度约束 二&#xff1a;Pod 启动创建过程 三&#xff1a;k8s调度过程 1、Predicate 有一系列的常见的算法 2、常见优先级选项 3、指定调度节点 &#xff08;1&#xff09;nodeName指定 &#xff08;2&#xff09;nodeSelector指定 四&#xff1a;亲和…

数字工厂管理系统能给企业管理者带来哪些好处

数字工厂管理系统是现代企业管理的神器&#xff0c;它能够以数字化方式管理企业的生产过程&#xff0c;实现生产过程的自动化、智能化和可视化。数字工厂管理系统解决方案不仅提高了生产效率&#xff0c;还给企业管理者带来了很多好处。下面就让我们来详细了解一下。 首先&…

【Android】MVC,MVP,MVVM三种架构模式的区别

MVC 传统的代码架构模式&#xff0c;仅仅是对代码进行了分层&#xff0c;其中的C代表Controller&#xff0c;控制的意思 将代码划分为数据层&#xff0c;视图层&#xff0c;控制层&#xff0c;三层之间可以任意交互 MVP MVP是在MVC基础上改进而来的一种架构&#xff0c;其中的…

2023年10款常用的Mac工具合集

Typora Typora 是一款由 Abner Lee 开发的轻量级 Markdown 编辑器&#xff0c;与其他 Markdown 编辑器不同的是&#xff0c;Typora 没有采用源代码和预览双栏显示的方式&#xff0c;而是采用所见即所得的编辑方式&#xff0c;实现了即时预览的功能&#xff0c;但也可切换至源代…