View和Control的区别(如何在对话框上使用CView类)

VC++深入详解:经典MFC教程在现代开发中的核心价值与实践指南 Windows桌面应用开发的核心基础之一是理解其底层消息驱动机制与图形界面架构。从经典的Win32 SDK编程到MFC框架封装,这一技术演进路径揭示了事件循环、窗口过程等基础原理,这些概念至今仍是现代GUI框架(如Qt、.NET WPF)的设计基石。掌握这些底层知识,不仅能帮助开发者维护遗留的VC++/MFC系统,更能深刻理解高性能、低依赖的Windows原生工具开发。例如,通过分析MFC的消息映射机制,可以洞悉现代事件处理模型的本质;而GDI绘图基础则为学习Direct2D等现代图形API铺平道路。对于需 阅读详情

View和Control的区别(如何在对话框上使用CView类)

  CView继承类,和其他窗口类的区别,很重要的就是对CDocument类和CFrameWnd类的操作,而其中,涉及CDocument类的操作,都进行了有效性判断(m_pDocument != NULL),CView类初始化的时候,m_pDocument = NULL,因此并不影响CView类作为控件的使用。涉及CFrame类的操作,有这么几个地方:
  第一个地方:CView::OnDestroy()。
void CView::OnDestroy()
{
 CFrameWnd* pFrame = GetParentFrame();
 if (pFrame != NULL && pFrame->GetActiveView() == this)
  pFrame->SetActiveView(NULL);    // deactivate during death
 CWnd::OnDestroy();
}
  第二个地方:CView::OnActivateFrame()。
void CView::OnActivateFrame(UINT /*nState*/, CFrameWnd* /*pFrameWnd*/)
{
}
  这里,其实是空的,在CView继承类中,只有CFormView类继承了这个虚函数
void CFormView::OnActivateFrame(UINT nState, CFrameWnd* /*pFrameWnd*/)
{
 if (nState == WA_INACTIVE)
  SaveFocusControl();     // save focus when frame loses activation
}
  实际上都不需要真的CFrame指针,对CView类作为控件使用没有障碍。
  第三个地方:CView::OnMouseActivate()。
int CView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
 int nResult = CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
 if (nResult == MA_NOACTIVATE || nResult == MA_NOACTIVATEANDEAT)
  return nResult;   // frame does not want to activate
 CFrameWnd* pParentFrame = GetParentFrame();
 if (pParentFrame != NULL)
 {
  // eat it if this will cause activation
  ASSERT(pParentFrame == pDesktopWnd || pDesktopWnd->IsChild(pParentFrame));
  // either re-activate the current view, or set this view to be active
  CView* pView = pParentFrame->GetActiveView();
  HWND hWndFocus = ::GetFocus();
  if (pView == this &&
   m_hWnd != hWndFocus && !::IsChild(m_hWnd, hWndFocus))
  {
   // re-activate this view
   OnActivateView(TRUE, this, this);
  }
  else
  {
   // activate this view
   pParentFrame->SetActiveView(this);
  }
 }
 return nResult;
}
  另外,在CView::PostNcDestroy(),实现了CView类的自我销毁,这是因为CView类是可以动态生成的(DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE)。
// self destruction
void CView::PostNcDestroy()
{
 // default for views is to allocate them on the heap
 //  the default post-cleanup is to 'delete this'.
 //  never explicitly call 'delete' on a view
 delete this;
 
  基本上,修改了CView继承类的这几个地方,直接返回不要调用基类相应的成员函数,就可以在对话框上使用。
  下面举例,用向导生成对话框应用程序,对话框类为CMyDigalog。
  从CHTMLView类继承一个CHTMLCtrl类,建立相应的消息处理函数并修改以下几个地方:
// CHTMLCtrl 消息处理程序
int CHTMLCtrl::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
 //return CHtmlView::OnMouseActivate(pDesktopWnd, nHitTest, message);
}
void CHTMLCtrl::OnDestroy()
{
 //CHtmlView::OnDestroy();
 // TODO: 在此处添加消息处理程序代码
 CWnd::OnDestroy();
}
void CHTMLCtrl::PostNcDestroy()
{
 // TODO: 在此添加专用代码和/或调用基类
 //CHtmlView::PostNcDestroy();
}
void CHTMLCtrl::OnActivateFrame(UINT nState, CFrameWnd* pDeactivateFrame)
{
 // TODO: 在此添加专用代码和/或调用基类
 //CHtmlView::OnActivateFrame(nState, pDeactivateFrame);
}
  增加一个成员函数CreateFromCtrl:
public:
 BOOL CreateFromCtrl(UINT nID, CWnd* pParent);
  这个函数通过对话框上的控件创建一个CHTMLCtrl控件,目的是在对话框设计的时候便于布局:

BOOL CHTMLCtrl::CreateFromCtrl(UINT nID, CWnd* pParent)
{
 if (!pParent || !pParent->GetSafeHwnd())
  return FALSE;
 CWnd *pCtrl = pParent->GetDlgItem(nID);
 if (!pCtrl)
  return FALSE;
 CRect rcCtrl;
 pCtrl->GetWindowRect(rcCtrl);
 pParent->ScreenToClient(rcCtrl);
 UINT style = ::GetWindowLong(pCtrl->GetSafeHwnd(), GWL_STYLE);
 pCtrl->DestroyWindow();

 return Create(NULL, NULL, style | WS_CHILD | WS_VISIBLE, rcCtrl, pParent, nID, NULL);

}

  还应注意,默认的从CView继承的类,其构造函数和析构函数是protected的,需要修改成public。

  还应注意,默认的从CView继承的类,其构造函数和析构函数是protected的,需要修改成public。
public:
 CHTMLCtrl();           // 动态创建所使用的受保护的构造函数
 virtual ~CHTMLCtrl();

  然后,在对话框模板中(使用资源编辑器),插入一个Static Text控件,ID为IDC_HTML。
  在对话框头文件中,插入包含文件:
#include "htmlctrl.h"
  增加CHTMLCtrl类型的成员变量:

 CHTMLCtrl m_ctlHTML;

   在对话框初始化的时候,创建这个CHTMLCtrl控件:

BOOL CMyDialog::OnInitDialog()
{
 CDialog::OnInitDialog();
 ...
 m_ctlHTML.CreateFromCtrl(IDC_HTML, this);
 return TRUE;
}
  下面,再添加一个按钮,在按钮的消息响应函数中打开HTML文件:
void CMyDialog::OnSysCommand(UINT nID, LPARAM lParam)
{
 if ((nID & 0xFFF0) == IDM_ABOUTBOX)
 {
  CAboutDlg dlgAbout;
  dlgAbout.DoModal();
 }
 else
 {
  CDialog::OnSysCommand(nID, lParam);
 }
}

   本文参考MSDN上的一篇文章:MSJ 2000中的C++ Q&A,原文有关部分附在后面。

附:原文

What, after all, is the difference between a view and a control? Not much. Both are child windows; the only difference is how they're used. Controls are usually child windows in a dialog—though of course you can create a control as a child of any window you like—whereas views are special child windows designed to work in the MFC doc/view architecture. A view has a pointer to a document and it's designed to live inside a particular kind of window—namely, a frame (CFrameWnd).
      As for the document, CView is written so that the document pointer, m_pDocument, can be NULL. Any time the view does something with the document, it encloses the code within
if (m_pDocument!=NULL) { }
So a view doesn't really need a document. Nor does CHtmlView require one. You might think the document in CHtmlView is the HTML file, but in fact CHtmlView is implemented using IWebBrowser2, which has no knowledge of the MFC doc/view architecture.
      So CHtmlView doesn't need a document. What about the frame? If you examine the code carefully, you'll discover that there are very few places where a view knows that it belongs to a frame. Most of the doc/view stuff is implemented in higher-level classes such as the frame itself and CDocTemplate, which glues the frame, document, and view together. The view doesn't know too much about what's going on, which shows the system is well-designed. Conceptually, the frame controls the view—not the other way around—so it would be a mistake if the view knew about its parent window. Nevertheless, a little spaghetti wiring always creeps in to any system (usually to fix bugs), and MFC is no exception.
      There are two places where CView (and hence CHtmlView by inheritance) assumes it lives inside a frame. The first is CView::OnMouseActivate, the handler for WM_MOUSEACTIVATE. OnMouseActivate does a lot of mumbo-jumbo to make activation work properly when the user clicks the mouse on a view. The details aren't important; the important thing is that the view calls GetParentFrame to get its parent frame, and then CFrameWnd::GetActiveView to activate the active view—all of which assumes the view is a child window of a CFrameWnd.
      The other place the view knows it lives in a frame is in CView::OnDestroy.
void CView::OnDestroy() { CFrameWnd* pFrame = GetParentFrame(); if (pFrame != NULL && pFrame->GetActiveView() == this) // deactivate during death pFrame->SetActiveView(NULL); CWnd::OnDestroy(); }
Here the view deactivates itself when it's destroyed. As an aside—something for you to learn from—both of these frame dependencies could be avoided by sending notifications to the parent window instead of calling C++ methods. GetParentFrame could return a CWnd, not a CFrameWnd, since the important thing is that it's the top-level window—not that it's derived from any particular class. And instead of calling CFrameWnd methods, the view could send a notification like WM_IAMGOINGBYEBYENOW, which the "frame" (whether it's a CFrameWnd or a CFooWnd) would be responsible for handling appropriately. After all, it should be the frame, not the view, that decides what to do when a view is activated or destroyed. This is a general rule of thumb in any system; function calls go down (from parent to child), and events go up (from child to parent). A child class should never know what kind of container it lives in.
      Ah well, life is never so perfect. Fortunately, MFC's misdemeanors are easily overcome. I wrote a CHtmlCtrl class that's just what you want: an HTML "view" you can use in a dialog or any window. CHtmlCtrl overrides both OnMouseActivate and OnDestroy to bypass the offending CView code.
int CHtmlCtrl::OnMouseActivate(...) { // bypass CView doc/frame stuff return CWnd::OnMouseActivate(...); } void CHtmlCtrl::OnDestroy() { // bypass CView doc/frame stuff CWnd::OnDestroy(); }
      Hey, that was easy! The other thing CHtmlCtrl does is override PostNcDestroy.
void CHtmlCtrl::PostNcDestroy() { // Do nothing. Don't let CView get it. }
CView's implementation of PostNcDestroy does a "delete this" to destroy the view that's normal procedure. This is normal procedure for views, which are allocated directly from the heap. But controls customarily live as data members inside some other window object
class CMyDialog ... { CHtmlCtrl m_htmlCtrl; }
in which case you don't want to delete the object in PostNcDestroy because it'll be deleted with the parent object.
MFC框架深度解析:从Win32 API到现代C++桌面开发实战 Windows桌面开发的核心基础是Win32 API,它提供了操作系统底层的窗口管理、消息传递图形设备接口。在面向对象编程思想下,微软推出了MFC框架,通过封装Win32 API简化了C++桌面应用的开发流程。这一技术价值在于其与Windows系统的深度集成高执行效率,特别适用于对稳定性性能有严苛要求的工业软件、医疗影像金融交易终端等场景。本文聚焦MFC的消息映射机制文档/视图架构,深入剖析其实现原理,并结合GDI+界面美化与多线程资源管理等实战技巧,帮助开发者掌握维护升级遗留系统的关键能力。 阅读详情

相关推荐

创建MFC系统时钟并显示时间于状态栏

MFC(Microsoft Foundation Classes)是微软公司提供的一套C++库,用以帮助开发Windows应用程序。它封装了Windows API的复杂性,使得开发者可以利用面向对象的编程方法,更加高效地编写Windows应用程序。CStatusBarMFC中用来创建管理状态栏的。创建状态栏通常在主窗口中完成:// 创建一个CStatusBarCtrl对象// 在当前窗口中创建状态栏// 设置状态栏指示器// 设置一个自定义的时钟面板。

weixin_34581040的博客 766

CHtmlCtrl使用测试例子

CHtmlCtrl使用例子!希望能够对大家有用,以前认为有内存泄漏,后经确认无内存泄漏情况。

非常好用的CHtmlCtrl控件

非常好用的VC下的HtmlCtrl控件,我就是用的这个实现了一个小系统,强烈推荐。

C++调用百度地图案例(VC++)

C++调用百度地图案例(VC++),基于百度地图的二次开发。

mfc 显示html文本,CHtmlCtrl,继承CHtmlView,直接显示html文本

vckbase上看到的,但调试老出错,总结一下代码在vs2010下test通过功能如下:可以用于对话框其它窗口SetCmdMap 用于设置“app:command”链接的命令映射。.SetHTML 用于将字符串转换为 HTML 文档。SetHideContextMenu隐藏菜单CreateFromStatic关联到一个CStatic要用的头#include#include 用法m_wndPic....

weixin_28856717的博客 748

【win32 app调用html方法】CHtmlCtrl的应用流程

一、CHtmlCtrl  在 EXE 中应用     CHtmlCtrl  在网上一找一堆,这里只简要介绍一下,给出源码: 1、CHtmlView可实现显示HTML,CHtmlCtrl  是继承此而来 2、CHtmlView的实现是基于COM的。通过IWebBrowser2接口来实现,而且IWebBrowser2与MFC文档/视图结构之间没有任何关系。 3、创建一个静态控制,这个控制

pirate97的专栏 3288

(转)ViewControl区别(如何在对话框使用CView

CView继承其他窗口区别,很重要的就是对CDocumentCFrameWnd的操作,而其中,涉及CDocument的操作,都进行了有效性判断(m_pDocument != NULL)CView初始化的时候,m_pDocument = NULL,因此并不影响CView作为控件的使用。涉及CFrame的操作,有这么几个地方:   第一个地方:CView::OnDestroy()。 void CView::OnDestroy() { CFrameWnd

muzizongheng的专栏 3419

viewcontrol区别(如何在对话框使用cview

CView继承其他窗口区别,很重要的就是对CDocumentCFrameWnd的操作,而其中,涉及CDocument的操作,都进行了有效性判断(m_pDocument != NULL)CView初始化的时候,m_pDocument = NULL,因此并不影响CView作为控件的使用。涉及CFrame的操作,有这么几个地方:  第一个地方:CView::OnDestro

1040

MFC消息机制

1消息的分 1.1队列消息、非队列消息 ??队列消息: windows为每个应用程序都建立一个消息队列,那么通过消息队列,进行传送的消息都属于队列消息;一般来说,由鼠标、键盘产生的消息都属于队列消息。(为什么呢?想想,鼠标、键盘事件都是由系统捕获的,系统捕获后要传递给应用程序,就一定的通过消息队列); ??非队列消息: 除了队列消息,剩下的自然而然就是非队列消息了;

DOTM的专栏 1189

VC++ 6.0深度解析:从MFC框架到遗留系统维护实战

C++作为面向对象编程的核心语言,其编译链接机制内存管理原理是构建大型软件系统的基石。在Windows平台开发中,理解底层API调用框架设计对于开发高性能、高稳定性应用程序至关重要。MFC(Microsoft Foundation Classes)框架作为早期Windows C++开发的事实标准,通过文档/视图架构消息映射机制,极大地提升了GUI应用程序的开发效率。对于工业控制、嵌入式上位机等领域的遗留系统,掌握VC++ 6.0这一经典开发环境,不仅能深入理解PE文件格式、多线程同步等底层技术,更能实

weixin_33853827的博客 388

CHtmlCtrl在VC中的使用

CHtmlCtrl是一个可以在VC中使用的用来显示网页的控件。这个控件极大的方便了程序的开发扩展,以前局限于VC环境下的一些开发完全可以采用HTML来实现。当然,像读取数据库、本地文件处理等操作最好还是采用VC来编写,如果采用JS来写,由于用户机子上浏览器权限设置的不同程序容易正常运行(鄙人经验,两天开发的程序因为权限问题付诸东流,教训啊)。因此,将VCCHtmlCtrl结合开发,一方面保证了程序的安全性高效性,同时还保证了程序展示的美观性。首先去网上找一下这个CHTMLCTRL控件,只包含两个文件即

WangIcter的专栏 3811

控制器view加载/ViewControlView的创建

ViewControlView的创建

smilebigdear的专栏 500

对话框使用CHtmlView打开网页

客户端程显示一个网页,可以使用的是CHTMLView这个.关于这个使用可以参考ChtmlView控件显示HTML.这里仅作简单说明 为了在对话框中显示HTML文件,必须将CHtmlCtrl对话框中的一个静态控制(也可以是其它控制)关联起来,这样才能为显示HTML文件提供一个窗口,为此可以在CHtmlCtrl中定义一个创建函数: BOOLCHTM...

weixin_34051201的博客 357
上一篇: 一个简单的滑动控件CSlideTab类
下一篇: 在程序运行时用鼠标调整对话框上的控件
菜牛
博客等级 码龄24年 1365粉丝 13原创
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值