MFC 静态拆分视图窗口
今天学习了MFC中拆分窗口,现将方法记录下.
想要在窗口视图中拆分成左右两个视图窗口,首先要注意的是拆分后要加载到左右的视图要符合动态创建的类,
也就是要在自己创建的视图类中添加动态创建机制宏.
类内声明宏:
DECLARE_DYNCREATE(CSelectView) //CSelectView为自己创建的视图类
类外实现宏:
IMPLEMENT_DYNCREATE(CSelectView,CTreeView) //CTreeView为父类
**
1.创建两个自己的视图类,
**
CSelectView继承于CTreeView
CMyDialg继承于CFromView
CSelectView用于树形控件显示,没啥可说的.着重说下,对话框的视图类,要注意是子窗口,无边框.所以在窗口属性中要把.Border设置为None,Style设置为Child
下面是两个类的声明:
#pragma once
#include <afxcview.h> //树形视图类头文件
class CSelectView :
public CTreeView
{
DECLARE_DYNCREATE(CSelectView)
CSelectView();
protected:
//virtual void OnDraw(CDC* pDC) override;
private:
CTreeCtrl *m_pTreeCtrl;
public:
virtual void OnInitialUpdate();
DECLARE_MESSAGE_MAP()
afx_msg void OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult);
};
#pragma once
#include <afxext.h> //对话框视图类头文件
// CMyDialog 窗体视图
class CMyDialog : public CFormView
{
DECLARE_DYNCREATE(CMyDialog)
protected:
CMyDialog(); // 动态创建所使用的受保护的构造函数
virtual ~CMyDialog();
virtual void OnDraw(CDC* pDC) override;
public:
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_DIALOG1 };
#endif
#ifdef _DEBUG
virtual void AssertValid() const;
#ifndef _WIN32_WCE
virtual void Dump(CDumpContext& dc) const;
#endif
#endif
virtual void OnDragLeave() override;
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
};
在类外分别加上实现宏
#include "CSelectView.h"
#include "MyApp.h"
IMPLEMENT_DYNCREATE(CSelectView,CTreeView)
CSelectView::CSelectView()
{
}
#include "resource.h"
#include "CMyDialog.h"
// CMyDialog
IMPLEMENT_DYNCREATE(CMyDialog, CFormView)
CMyDialog::CMyDialog()
: CFormView(IDD_DIALOG1)
{
}
注意,如果父类中有纯虚函数要在自己创建的类中实现,不然无法动态创建类对象
2.在主框架类中重写OnCreateClient()函数
//m_splitter:为类的成员变量:
CSplitterWnd m_splitter;
BOOL MyWnd::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
//拆分窗口(一行两列)
m_splitter.CreateStatic(this, 1, 2);
//创建视图类对象
m_splitter.CreateView(0, 0, RUNTIME_CLASS(CSelectView),
CSize(200, 200), pContext);
m_splitter.CreateView(0, 1, RUNTIME_CLASS(CMyDialog),
CSize(200, 200), pContext);
return TRUE;
}
这样就把主窗口拆分成左右两个视图窗口了,中间的分隔栏可以用鼠标左右拖动
3.加载数据到树形视图中
树形视图类要加载数据就要在初始化函数OnInitialUpdate()中
首先要定义一个CTreeCtrl类型的控件,用来操作数据
在树形视图类中添加
CTreeCtrl* m_treeCtrl;
在OnInitialUpdate()中添加数据加载
void CSelectView::OnInitialUpdate()
{
CTreeView::OnInitialUpdate();
// TODO: 在此添加专用代码和/或调用基类
m_pTreeCtrl = &GetTreeCtrl();
m_pTreeCtrl->ModifyStyle(0, TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS| TVS_SHOWSELALWAYS);
m_pTreeCtrl->InsertItem(TEXT("显示数据"), 0,0,TVI_ROOT);
m_pTreeCtrl->InsertItem(TEXT("添加数据"), 0, 0, TVI_ROOT);
m_pTreeCtrl->InsertItem(TEXT("修改数据"), 0, 0, TVI_ROOT);
m_pTreeCtrl->InsertItem(TEXT("删除数据"), 0, 0, TVI_ROOT);
}
4.更改右边的视图类
根据左边树形视图中的选择,右边更改相应的窗口视图类
在树视图的OnTvnSelchanged函数中处理选择项改变的事件
在主框架类中定义自定义消息用
//自定义消息
#define NM_A (WM_USER+100)
#define NM_B (WM_USER+101)
#define NM_C (WM_USER+102)
在这里插入代码片
void CSelectView::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;
HTREEITEM hSel = pNMTreeView->itemNew.hItem;
CString str = m_pTreeCtrl->GetItemText(hSel);
//MessageBox(str);
if (str == TEXT("添加数据"))
{
::PostMessage(AfxGetMainWnd()->GetSafeHwnd(),NM_A, (WPARAM)NM_A, 0);
}
else if (str == TEXT("修改数据"))
{
::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_B, (WPARAM)NM_B, 0);
}
}
在主框架中捕获消息
BEGIN_MESSAGE_MAP(MyWnd,CFrameWnd)
ON_WM_CREATE()
ON_COMMAND(ID_BTN_NEW,&MyWnd::OnBtnNew)
ON_COMMAND(ID_BTN_EDIT,&MyWnd::OnBtnEdit)
ON_COMMAND(ID_BTN_DELETE,&MyWnd::OnBtnDelete)
ON_COMMAND(ID_BTN_QUIT,&MyWnd::OnBtnQuit)
ON_COMMAND(ID_BTN_MIN,&MyWnd::OnBtnMin)
ON_COMMAND(ID_BTN_FIND,&MyWnd::OnBtnFind)
ON_WM_PAINT()
ON_MESSAGE(NM_A,&MyWnd::OnMyChange) //添加自定义消息函数
ON_MESSAGE(NM_B,&MyWnd::OnMyChange) //添加自定义消息函数
ON_WM_SIZE()
END_MESSAGE_MAP()
在OnMyChange中实现窗口视图类的切换
LRESULT MyWnd::OnMyChange(WPARAM wParam, LPARAM lParam)
{
CCreateContext context;//动态创建机制结构体
switch (wParam)
{
case NM_A://创建IDD_DIALOG1对话框视图类CMyDialog
{
context.m_pNewViewClass = RUNTIME_CLASS(CMyDialog);//要创建的视图类
context.m_pCurrentFrame = this; //当前窗口类
context.m_pLastView = (CFormView*)m_splitter.GetPane(0, 1); //要在哪列创建新的视图类,(我这是要在右边,也就是第0行1列)
m_splitter.DeleteView(0, 1); //删除原来的视图类
m_splitter.CreateView(0, 1, RUNTIME_CLASS(CMyDialog), CSize(200, 200), &context); //动态创建新的视图类(大小无所谓,最后都是平铺分隔的左右窗口)
CMyDialog *pNewView = (CMyDialog*)m_splitter.GetPane(0, 1); //获取新创建的视图类对象
m_splitter.RecalcLayout();
pNewView->OnInitialUpdate(); //初始化新视图类
m_splitter.SetActivePane(0, 1); //激活新的视图类
}
break;
case NM_B: //创建IDD_DIALGO2对话框视图类MyAddDlg
{
context.m_pNewViewClass = RUNTIME_CLASS(MyAddDlg);
context.m_pCurrentFrame = this;
context.m_pLastView = (CFormView*)m_splitter.GetPane(0, 1);
m_splitter.DeleteView(0, 1);
m_splitter.CreateView(0, 1, RUNTIME_CLASS(MyAddDlg), CSize(200, 200), &context);
MyAddDlg *pNewView = (MyAddDlg*)m_splitter.GetPane(0, 1);
m_splitter.RecalcLayout();
pNewView->OnInitialUpdate();
m_splitter.SetActivePane(0, 1);
}
break;
case NM_C:
break;
}
/*if (wParam == NM_A)
{
MessageBox(TEXT("添加数据"));
}
else if(wParam==NM_B){
MessageBox(TEXT("修改数据"));
}*/
return 0;
}
效果:
这样就方便用对话框来拖拽控件来布局界面
签名:GreenLeaf1976