WEB开发网
开发学院软件开发VC View与Frame的分离 阅读

View与Frame的分离

 2010-07-01 20:43:12 来源:WEB开发网   
核心提示:一般来说,你可以使用res://modulename访问任何存储在EXE和DLL里的资源,View与Frame的分离(2),res:是一个类似http:,ftp:,我们还是很乐意尝试,这个也不难!! 我们同样使用子类化的原理就能实现,file:,或mailto:的协议

一般来说,你可以使用res://modulename访问任何存储在EXE和DLL里的资源。res:是一个类似http:,ftp:,file:,或mailto:的协议。它告诉浏览器资源的路径和名字,细节工作浏览器知道如何去做!:) 为实现About对话框,偶写了个类,CAboutDialog,它有个CHtmlCtrl类型的成员m_page。我们来看看CaboutDialog的初始化过程:

BOOL CaboutDialog::OnInitDialog()
{
   VERIFY(Cdialog::OnInitDialog());
   VERIFY(m_page.CreateFromStatic(IDC_HTMLVIEW,this));
   m_page.LoadFromResource(_T("about.htm"));
   return TRUE;
}

你可能对CHtmlCtrl::CreateFromStatic有点迷惑。还记得我们刚开始谈到的CStatic吗? 我们打算用它来代表CHtmlCtrl控件,它将从CStatic建立一个CHtmlCtrl控件对象,这是一个子类化的过程,该对象将和CStatic有同样的ID,大小和位置。这么做很方便,很有效!:)

BOOL CHtmlCtrl::CreateFromStatic(UINT nID, CWnd* pParent)
{
  CStatic wndStatic;
  if (!wndStatic.SubclassDlgItem(nID, pParent))
    return FALSE;
  // Get static control rect
  CRect rc;
  wndStatic.GetWindowRect(&rc);
  pParent->ScreenToClient(&rc);
  wndStatic.DestroyWindow();
  // create HTML control (CHtmlView)
  return Create(NULL,           // class name
    NULL,             // title
    (WS_CHILD | WS_VISIBLE ),       // style
    rc,            // rectangle
    pParent,    // parent
    nID,      // control ID
    NULL);      // frame/doc context not used
}

然后是使用CHtmlCtrl::LoadFromResource打开页面,它从CHtmlView继承而来。当然偶也可以这样打开页面:res://AboutHtml.exe/about.html OK! 偶已经向你展示了CHtmlCtrl如何通过回避CView而顺利代替frame在dialog里显示!。偶也介绍了如何如何在资源文件里定位HTML文件和图象文件。并且告诉你如何打开一个Web页面。但还有一个极为精彩的处理没有告诉你!:) ,能猜到是什么吗? 哇哈哈哈!!! 看到About对话框里的OK按钮了吧? 它并不是一个按钮!!仅仅是HTML文件里的一副图片! 偶使用了Javascript使得它在被单击时有up和down两种状态,但是它是如何和我们的对话框程序通讯的呢??? 你说好玩不?

如果你搞过DHTML,你可能会想到DHTML文档层可使用COM发现IMG元素然后监听它的OnClick事件。但是那样做对于偶这样的COM半文盲是way,way,way,WAY痛苦和麻烦的工作!!:( 其实,有一个更为简单的方法。假设你让这个"button"链接到一个叫做ok的文档: 现在,当用户单击它,浏览器将转到ok文件。但在它这么做以前,控制权交给 CHtmlCtrl::OnBeforeNavigate2。这时CHtmlCtrl可以做任何合法的事情:

<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 dialog
    GetParent()->SendMessage(WM_COMMAND,IDOK);
  }
}

[这是多么振奋人心的消息?? 想一想,我们几乎可以让对话框做几乎所有能做的事情! 而且我们可以将Web页面处理的更为美观!!:]] 所以,ok并不正真的是另一个文件,而CHtmlCtrl正是利用它来解释OK按钮!! 太完美了! 为了让这个想法更紧凑,偶引入了一个伪协议! 叫做:app:。用它来代替使用ok,在about.htm里正真的链接是app:ok。当CHtmlCtrl发现浏览器试图导航到app:somewhere时,它调用一个新的虚函数,CHtmlCtrl::OnAppCmd,它用somewhere作为参数,并cancels调航(navigation),所以CmyHtmlCtrl并没有重载OnNavigate2,而是重载了OnAppCmd:

void CmyHtmlCtrl::OnAppCmd(LPCTSTR lpszWhere)
{
  if(_tcsicmp(lpszWhere,_T("ok"))==0)
  {
    GetParent()->SendMessage(WM_COMMAND,IDOK);
  }
}

你可以在HTML文件里使用其他链接,比如app:cancel,app:refresh,或者app:whatever!:) 并同时使用OnAppCmd函数寻找相应的字串,"cancel","refresh",以及"whatever"。好了!! 可以做你自己想做的事去了!…在你疯狂的code之前,提醒几句:加载IE DLLs需要极少的等待,但是如果加载About对话框超过10秒并且搬出来个沙漏晃来晃去,用户将感到非常不舒服!:)。最后,当你在About对话框里单击鼠标右键,会弹出个标准的浏览器快捷菜单,你可能觉得这是多余的,或者出于保护你的源代码的目的,你会买力的屏蔽调右键的功能。其实这很简单,你仅仅需要在HTML的 标签里加入一句脚本代码……但我们毕竟是在玩VC。所以,尽管麻烦,我们还是很乐意尝试。这个也不难!! 我们同样使用子类化的原理就能实现。但不是现在,而是将来的某个时候!! :)

本文配套源码

上一页  1 2 

Tags:View Frame 分离

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接