CFormView侧栏停靠

(MFC)Vs2010制作Visual Studio风格的停靠侧栏窗口(CDockablePane里嵌套FormView表单视图)

关键字:CDockablePane,  Visual Studio风格的Gui界面,,CDoackable里嵌套FormView表单视图步骤
转载注意作者原创:K_Linux_Man

一直比较喜欢Visual Studio两侧的窗口,可以来回滑动,并且和点击图钉,钉住悬浮的窗口。那就尝试着如何去做出来。

VC++6.0如果要去实现的话,不是不可以,但是得借助第三方的类库,比如说,ToolKit,但是非常的麻烦。。。

Visual Studio里面的新建Demo就可以实现这一功能,何乐而不为呢!!!

那停靠窗口里面用什么填充呢? 树形控件??新建的Demo里有了。更直观一点的话,还是用FormView吧。。。好的。。。开始

要不先来个最终的效果图..... 自己添加的解决方案停靠窗口,里面嵌套FormView视图窗口.而文件视图,类视图,还有属性,Demo里面默认生成的。只有解决方案那个是自己添加的。


新建两个文件,SolutionWnd.h SolutionWnd.cpp

在资源窗口里新建一个FormView的Dialog,修改ID为IDD_FORMVIEW,建立一个与FormView相关联的的类, 利用类向导,添加一个名为CMfcFormView,选择基类为CFormView. 生成在SolutionWnd.h和SolutionWnd.cpp文件里。

SoulutionWnd.h

#pragma once
#include "Resource.h"


// CMfcFormView 窗体视图

class CMfcFormView : public CFormView
{
  DECLARE_DYNCREATE(CMfcFormView)//具有动态创建对象的能力

public:
  CMfcFormView(): CFormView(CMfcFormView::IDD)
  {}// 动态创建所使用的受保护的构造函数
  ~CMfcFormView()
  {}
public:
  

public:
  enum { IDD = IDD_FORMVIEW };
#ifdef _DEBUG
  virtual void AssertValid() const;
#ifndef _WIN32_WCE
  virtual void Dump(CDumpContext& dc) const;
#endif
#endif

protected:
  virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

  DECLARE_MESSAGE_MAP()
};

SolutionWnd.cpp

#include "stdafx.h"
#include "SolutionWnd.h"


// CMfcFormView


IMPLEMENT_DYNCREATE(CMfcFormView, CFormView)


void CMfcFormView::DoDataExchange(CDataExchange* pDX)
{
  CFormView::DoDataExchange(pDX);
}



BEGIN_MESSAGE_MAP(CMfcFormView, CFormView)


END_MESSAGE_MAP()




// CMfcFormView 诊断


#ifdef _DEBUG
void CMfcFormView::AssertValid() const
{
  CFormView::AssertValid();
}


#ifndef _WIN32_WCE
void CMfcFormView::Dump(CDumpContext& dc) const
{
  CFormView::Dump(dc);
}
#endif
#endif //_DEBUG


// CMfcFormView 消息处理程序


至此我们已经把FormView派生出的CMfcFormView类建好了。

我们需要建立一个CDockablePane的派生类,予以容纳FormView,建立派生出的CDockablePane类为CSolutionWnd

利用类向导,添加名为CSolutionWnd,基类为CDockablePane...生成文件SolutionWnd.h和SolutionWnd.cpp

SolutionWnd.h里又添加了如下代码

class CSolutionWnd : public CDockablePane
{
   DECLARE_DYNAMIC(CSolutionWnd)
  //构造函数
public:
  CSolutionWnd();
  //析构函数
  ~CSolutionWnd();


  //特性
public:


protected:
  CMfcFormView*   m_pformView;


public:


  DECLARE_MESSAGE_MAP()
};
SolutionWnd.cpp

新添加的代码

BEGIN_MESSAGE_MAP(CSolutionWnd, CDockablePane)

END_MESSAGE_MAP()



IMPLEMENT_DYNAMIC(CSolutionWnd, CDockablePane)

CSolutionWnd::CSolutionWnd()
{
  m_pformView = (CMfcFormView*) (RUNTIME_CLASS(CMfcFormView)->CreateObject());
}

CSolutionWnd::~CSolutionWnd()
{

}

接着

1.在MainFrm.cpp里添加m_wndSolution变量,类型为CSolutionWnd

2.在MainFrm.cpp里的CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)函数里添加代码

// 创建停靠窗口
if (!CreateDockingWindows())                                                                                                                                        _
{
TRACE0("未能创建停靠窗口\n");      
return -1;        
}        
             
m_wndFileView.EnableDocking(CBRS_ALIGN_ANY);            
m_wndClassView.EnableDocking(CBRS_ALIGN_ANY);               
DockPane(&m_wndFileView);                                                                                                                                         |
CDockablePane* pTabbedBar = NULL;                                                                                                                        |
m_wndClassView.AttachToTabWnd(&m_wndFileView, DM_SHOW, TRUE, &pTabbedBar);                       
m_wndOutput.EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndOutput);
m_wndProperties.EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndProperties);_
m_wndSolution.EnableDocking(CBRS_ALIGN_ANY);
m_wndSolution.AttachToTabWnd(&m_wndProperties, DM_SHOW, TRUE, &pTabbedBar);
//  红色为自己添加


3.在MainFrm.cpp里的CMainFrame::CreateDockingWindows()中添加代码

//创建解决方案窗口
  CString strSolutionWnd;
  bNameValid = strSolutionWnd.LoadString(IDS_SOLUTION_WND);
  ASSERT(bNameValid);
  if(!m_wndSolution.Create(strSolutionWnd,this,CRect(0,0,200,200),TRUE,1234,WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_RIGHT | CBRS_FLOAT_MULTI))
  {
    TRACE0("未能创建“解决方案窗口\n");
    return FALSE;
  }
既然我们要创建CDockablePane那必然需要改写OnCreate函数和OnSize函数,原因是,通过CDockablePane的创建必然会调用OnCreate函数,在OnCreate函数里创建FormView,在OnSize里面调整FormView的大小,覆盖整个CDockablePane。

利用类向导在CSolution声明里添加消息映射函数

public:

  DECLARE_MESSAGE_MAP()
  afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
  afx_msg void OnSize(UINT nType, int cx, int cy);

int CSolutionWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
  if (CDockablePane::OnCreate(lpCreateStruct) == -1)
    return -1;

  // TODO:  在此添加您专用的创建代码

  return 0;
}



void CSolutionWnd::OnSize(UINT nType, int cx, int cy)
{
  CDockablePane::OnSize(nType, cx, cy);

  // TODO: 在此处添加消息处理程序代码
  
}

利用类向导在CMfcFormView里添加消息映射函数OnCreate以及改写虚函数Create

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);

// CMfcFormView 消息处理程序

int CMfcFormView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
  if (CFormView::OnCreate(lpCreateStruct) == -1)
    return -1;

  // TODO:  在此添加您专用的创建代码

  return 0;
}


BOOL CMfcFormView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
  // TODO: 在此添加专用代码和/或调用基类

  return CFormView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}

在CSolution.h里声明CMfcFormView*类型的指针变量 

protected:
  CMfcFormView*   m_pformView;

在CSolution的构造函数里创建CMfcFormView对象

CSolutionWnd::CSolutionWnd()
{
  m_pformView = (CMfcFormView*) (RUNTIME_CLASS(CMfcFormView)->CreateObject());
}

在CSolution的OnCreate函数里创建FormView

int CSolutionWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
  if (CDockablePane::OnCreate(lpCreateStruct) == -1)
    return -1;

  // TODO:  在此添加您专用的创建代码

  RECT rect;
  GetClientRect(&rect);

  m_pformView->Create(NULL, NULL,  WS_CHILD|WS_VISIBLE, rect, this, 123, NULL);



  return 0;
}

在CSolution的OnSize函数里调整FormView填充整个DockablePane区域

void CSolutionWnd::OnSize(UINT nType, int cx, int cy)
{
  CDockablePane::OnSize(nType, cx, cy);

  // TODO: 在此处添加消息处理程序代码
  
  if (GetSafeHwnd() == NULL)
  {
    return;
  }
  if(m_pformView->GetSafeHwnd()!=NULL)
  {
    CRect rect;
    GetClientRect(rect);
    m_pformView->SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOACTIVATE | SWP_NOZORDER);
  }
}


至此结束。。。回答一些疑问。

为什么要改写CMfcFormView的Create虚函数呢?

因为我们要用到这句函数。

m_pformView->Create(NULL, NULL, WS_CHILD|WS_VISIBLE, rect, this, 123, NULL);

调用到FormView::Create函数。由于FormView的Create函数是protected类型的.所以我们必须改写FormView::Create函数为Publc类型。虽然我们在Create函数里什么也没有做什么。如果不重写Create函数的话,那么会出现编译错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值