View与Frame的分离

Wow!! 几篇让人拍案的文章,啃完之后大呼过瘾!想不到微软也有如此精通windows编程的家伙?! 此时此刻,俺想到的是分享给KBASE里的兄弟们啊! 没的说,掌声伺候!!!!

[NOTE]:

罗头说了,最好不要把Frame/Doc/View拆的妻离子散。是啊,本来好好的一家人,谁会那么残忍呢!? 嘿嘿,偶只是给他们弄了个远房的亲戚。:)

Now, Stop 费话ing!! Let''s go on the stuff…

首先,这里有两个难点需要解决! 一是:既然最后的产物是CHtmlCtrl,如何能象其他控件(比如Button)随意的丢到对话框里呢? COM->ActiveX?? 你说的,你自己做去吧!偶可是个COM稀里糊涂者!! 偶要比你想象地懒的多(鼓励程序员锻炼一下这种惰性! 好处多多)。偶想,何不拉个替死鬼呢? 对了,CStatic不是可以随便被嗲来嗲去吗? 嗯,给它套上个SubclassDlgItem不就可以当成我们的CHtmlCtrl用了嘛! 有道理!! 然后是:View的确和Frame有着千丝万缕的联系。MFC是个半定制的框架,微软已做了很多手脚,说不定你在View里啪啪点几下,就有几个类似WM_MICROSPACE这样的消息传到了Frame里。然而控件是没有Frame可言的,而且控件也从不需要知道自己被放到了哪个容器里!!

所以,为了不至于编译器当啊当的乱叫,我们还要小心伺候着!:)

在继续往下做之前,你还要明确CHtmlView和我们最终生成的CHtmlCtrl到底有什么区别?

其实,区别仅仅是它们被使用的方法不同。控件通常是对话框里的子窗口---当然你可以把它作为任何窗口的子窗口。然而View却是专门为了实现MFC 文档视图结构而设计的。一个View有一个指向Document的指针并且被固定在一个特别的窗口里---人称:框架窗口(CFrameWnd)。对于Document来说,CView是它可以从形态上被表现的场作。但,指向Document的指针m_pDocument可能是NULL,所以每当我们在View里处理Document的时候,这么做是明智的:

If(m_pDocument!=NULL)
{
  // Do something here!
}

所以,View并不正真的需要一个Document,CHtmlView也不需要。你可能认为在CHtmlView里的Document就是一个HTML文件,但实际上,CHtmlView是使用IWebBrowser2实现的,而且它对MFC的文档视图结构一无所知。

那么需要一个Frame吗? 如果你仔细研究过相关的代码,就会发现:只是在极少地方,View

知道自己属于一个Frame。大多数文档视图结构是在更高一级的类比如Frame本身和CDocTemplate里实现的,它们把Frame,View,Document紧紧的粘在了一起。View并不知道外面发生了什么,这样设计的文档视图系统有很多优点。理论上来说,View是被动地受Frame控制,而且没有其他途径,所以认为View知道它自己的父窗口是错误的。有两处CView( 也是CHtmlView的父类 )会假想自己在一个Frame里。第一处是CView::OnMouseActive,它是WM_MOUSEACTIVE消息的处理函数,当你在View里点击鼠标以后,它会做很多细致的工作。这些细致的工作是不重要的,但重要的是View调用了GetParentFrame以得到它的父窗口框架,然后CFrameWnd::GetActiveView激活当前的活动视图---所有的这一切,都建立在假设View是CFrameWnd的一个子窗口的基础之上。

另外一处是在CView::OnDestroy里:

void CView::OnDestroy()
{
   CframeWnd* pFrame = GetParentFrame();
   If(pFrame!=NULL&&pFrame->GetActiveView==this)
   // deactive during death
   pFrame->SetActiveView(NULL);
   CWnd::OnDestroy();
}

在这里,View先让自己处于非活动状态。从另一个角度考虑,我们完全可以通过向父窗口发通知消息(Notification)代替C++方法调用从而回避掉View对Frame的依赖!! GetParentFrame可以返回一个CWnd,而非CFrameWnd,因为该函数只是强调了父窗口,而不是一定要返回一个特定的类。View可以通过发送一个类似WM_MICROSPACE的通知消息取代对CFrameWnd的方法调用,这些Notification会被"Frame"(或是CFrameWnd或是CfooWnd)正确的响应。但是,无论如何,你必须清楚:当View被激活或进入非活动状态时,是Frame决定该如何响应,而不是View本身。任何系统都是如此;函数向下调用(从父到子),事件向上传递(从子到父)。一个子类从来都不会知道自己所在的容器!! 生活本身就不是完美的! 但幸运的是我们将会很容易的克服MFC给我们带来的难题! CHtmlCtrl类( here! )正是我们需要的:一个HTML "View" ,你可以在对话框或任何窗口里使用。CHtmlCtrl重载了OnMouseActive和OnDestroy从而回避CView那些给我们惹麻烦的代码。

int CHtmlCtrl::OnMouseActive(…)
{
  // bypass CView doc/frame stuff
  return CWnd::OnMouseActive(…);
}
void CHtmlCtrl::OnDestroy()
{
  // bypass CView doc/frame stuff
  CWnd::OnDestroy();
}

除此之外,CHtmlCtrl也重载了PostNcDestroy

void CHtmlCtrl::PostNcDestroy()
{
   // do nothing
}

CView正常的PostNcDestroy实现是使用delete this销毁View。对于Views来说,这是正常的处理方式,因为View是直接在堆里建立的。但是,控件一般是作为另一个窗口对象的成员存在的。这时你就不要delete了,它会被父对象delete掉。通过以上的修改(OnMouseActive,OnDestroy和PostNcDestroy),CHtmlCtrl能顺利的在对话框里工作了!! 为此,偶写了个小程序:AboutHtml( 见源代码)显示一个About框(如图1)。那是完全用HTML写的。HTML的资源:图片,音频文件(对了!甚至可以有声音)都被存储到EXE文件里。

// in AboutHtml.rc
ABOUT.HTML  HTML DISCARDABLE "res\\about.htm"
VCKBCOM.GIF  HTML DISCARDABLE "res\\vckcom.gif"
OKUP.GIF  HTML DISCARDABLE "res\\okup.gif"
OKDN.GIF  HTML DISCARDABLE "res\\okdn.gif"
MOZART.WAV   HTML DISCARDABLE "res\\mozart.wav"

在一般的Web页面里,如果你这么做:<IMG src="vckcom.gif"> 就需要把vckcom.gif放到当前目录下。对于访问一个存储在EXE文件里的资源,同样也要这样。这种情况下,你必须使用下面的代码帮助浏览器寻找你的HTML元素: <BASE url="res://AboutHtml.exe/about.htm">浏览器就会知道当前的"目录"是res://AboutHtml.exe,所以当它遇到<IMG src="vckcom.gif">,它会自动找到res://AboutHtml.exe/vckcom.gif,否则,它将在HTML文件所在的当前目录下寻找。

图一

时间: 2024-11-08 17:26:28

View与Frame的分离的相关文章

ios-IOS8调用系统相机拍摄视频,所在view的frame高度多了20,底部标签栏下移20,怎么回事啊?

问题描述 IOS8调用系统相机拍摄视频,所在view的frame高度多了20,底部标签栏下移20,怎么回事啊? IOS8调用系统相机拍摄视频,退出相机后,所在view的frame高度多了20,怎么回事啊? 导致tabbar下移了20, 输出显示调用相机之前320*568 拍摄视频退出后变成320*588,只有相机拍摄视频模式会出现这样,拍照则不会出现 解决方案 升级到IOS9测试呢,看是不是iOS本身的问题

如何做好IOS View的布局

这个命题貌似有点大,那就尽量将我理解的分享一下吧,首先说明一点,我是代码党,所以我所讲的都是代码布局.本文会围绕一些我们平常开发中常遇到的布局问题来进行叙述,包括以下几个方面: 如何布局UIViewController的view childViewController的处理 Autolayout来布局 tableView管理 1.如何布局UIViewController的view 首先给出设计原则: 屏幕尺寸变化时能自适应,如不同尺寸设备,屏幕旋转,热点,电话等. 无论是否有navigation

深入浅出了解frame和bounds

frame frame的官方解释如下: The frame rectangle, which describes the view's location and size in its superview's coordinate system. This rectangle defines the size and position of the view in its superview's coordinate system. Use this rectangle during layou

iOS - MVC 架构模式

1.MVC 从字面意思来理解,MVC 即 Modal View Controller(模型 视图 控制器),是 Xerox PARC 在 20 世纪 80 年代为编程语言 Smalltalk-80 发明的一种软件设计模式,至今已广泛应用于用户交互应用程序中.其用意在于将数据与视图分离开来.在 iOS 开发中 MVC 的机制被使用的淋漓尽致,充分理解 iOS 的 MVC 模式,有助于我们程序的组织合理性. MVC 的几个明显的特征和体现: View 上面显示什么东西,取决于 Model. 只要 M

ios-alpha=0或者隐藏起来的UIView占用CPU么

问题描述 alpha=0或者隐藏起来的UIView占用CPU么 如果一个视图已经隐藏了或者alpha=0状态,还消耗CPU么? 比如设置: [view setAlpha:0]; 然后: [view setFrame:newFrameRect]; 对性能有什么影响么? 解决方案 alpha为0的话会更加浪费CPU,因为绘图时CPU需要计算alpha下的图层的叠加效果,比一般的覆盖要更加耗费 资源 2.如果一个view的frame在window可显示范围之外,我想应该消耗CPU少些

WWDC 2014 Session笔记 - 可视化开发,IB 的新时代

本文是我的 WWDC 2014 笔记 中的一篇,涉及的 Session 有 What's New in Xcode 6 What's New in Interface Builder 如果说在 WWDC 14 之前 Interface Builder (IB) 还是可选项的话,我相信在此之后 IB 已经是毫无疑问的 iOS 开发标配了,纯代码界面可以说已经渐行渐远,可以逐渐离开我们的视线了. 一言蔽之,就是 Apple 在催促大家使用 IB,特别是 Storyboard 做为界面开发的唯一选择这

cell-ios-lable中文无法显示

问题描述 ios-lable中文无法显示 在TableView cell添加一个View在View上添加Label设置Label.text = @""添加""为什么在模拟器界面上不显示中文 解决方案 参考:http://www.baidu.com/link?url=Ah6XECznsYxtrvuMDqr0LqSBqVcdPy_6rd1QCvg8D9oGnw_9WPDxGZtq5pwvT5qO9eSKYDIoWPnvf3H857GI9xuacTRFVRfu8lV8V0

实现图片浏览器功能

实现图片浏览器功能 效果: 此教程涉及到较多的category的使用,注意.   思路: 1. 获取一个view在UIWindow中的frame值 2. 获取这个view的快照 3. 对这个快照进行动画全屏 4. 全屏消失后移除掉这个快照   源码: NSObject+WeakRelated.h 与 NSObject+WeakRelated.m (让两个对象之间产生关联) // // NSObject+WeakRelated.h // ScrollViewShowImage // // Crea

J2ME中实现可伸展目录树TreeList

J2ME里面有自带的List类,但是功能太弱,没有实现View和Model的分离,所以操作起来比较费事.本来事想写一个Canvas的TreeList,但是画起来算坐标又太麻烦,所以选取了一个折中的方法,继承List,实现一个操作起来比较方便的组件. 目的: 1.可伸缩的目录树结构,暂时先实现两层. 2.Label和存储内容分离. 3.激活和非激活图片分开. 4.通过选择事件可以准确快速找到对应内容 5.存储内容无关性,里面可以放置任何Object 实现思路: 1.封装一个ExpandItem类,