Convert CHtmlView to CHtmlCtrl View与Frame的分离 Reference from MSJ MicroSpace
下载源代码 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!}
void CView::OnDestroy(){CframeWnd* pFrame = GetParentFrame();If(pFrame!=NULL&&pFrame->GetActiveView==this)// deactive during deathpFrame->SetActiveView(NULL);CWnd::OnDestroy();}
int CHtmlCtrl::OnMouseActive(…){// bypass CView doc/frame stuffreturn CWnd::OnMouseActive(…);}void CHtmlCtrl::OnDestroy(){// bypass CView doc/frame stuffCWnd::OnDestroy();}
void CHtmlCtrl::PostNcDestroy(){// do nothing}
// in AboutHtml.rcABOUT.HTMLHTML DISCARDABLE "res\\about.htm"VCKBCOM.GIFHTML DISCARDABLE "res\\vckcom.gif"OKUP.GIFHTML DISCARDABLE "res\\okup.gif"OKDN.GIFHTML DISCARDABLE "res\\okdn.gif"MOZART.WAV HTML DISCARDABLE "res\\mozart.wav"
<BASE url="res://AboutHtml.exe/about.htm">
BOOL CaboutDialog::OnInitDialog(){VERIFY(Cdialog::OnInitDialog());VERIFY(m_page.CreateFromStatic(IDC_HTMLVIEW,this));m_page.LoadFromResource(_T("about.htm"));return TRUE;}
BOOL CHtmlCtrl::CreateFromStatic(UINT nID, CWnd* pParent){CStatic wndStatic;if (!wndStatic.SubclassDlgItem(nID, pParent))return FALSE;// Get static control rectCRect rc;wndStatic.GetWindowRect(&rc);pParent->ScreenToClient(&rc);wndStatic.DestroyWindow();// create HTML control (CHtmlView)return Create(NULL, // class nameNULL, // title(WS_CHILD | WS_VISIBLE ), // stylerc,// rectanglepParent,// parentnID,// control IDNULL);// frame/doc context not used}
<A href="ok"><IMG …></A>
void CmyHtmlCtrl::OnBeforeNavigate2(LPCTSTR lpszURL,…,BOOL *pbCancel){if(_tcscmp(lpszURL,_T("ok"))==0){//"ok" clicked*pbCancle=TRUE; // abort// will close dialogGetParent()->SendMessage(WM_COMMAND,IDOK);}}
void CmyHtmlCtrl::OnAppCmd(LPCTSTR lpszWhere){if(_tcsicmp(lpszWhere,_T("ok"))==0){GetParent()->SendMessage(WM_COMMAND,IDOK);}}