文章目录
- 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;
}