丢开Wizard, 自由创建应用程序窗口

ZDNet软件频道 时间:2002-08-28 作者:刘巍 |  我要评论()
本文关键词:liuwei
MFC向导是个非常有用的工具,但是有时希望做出风格怪异的窗口,就要编写干净清爽的代码,所以DIY是最好的方法。
作者:刘巍

每一个MFC应用程序都有一个CWinApp派生类的对象。这个对象对应着程序的主线程。而 CWinApp 类中有一个 CWnd * m_pMainWnd 成员变量。这个成员变量记录了应用程序的主窗口。当你新建一个MFC应用程序的时候,在 InitInstance 函数里都会出现对 m_pMainWnd 赋值的语句,拿基于对话框的应用程序来说,其中的代码为:


CMyDialog dlg;
m_pMainWnd=&dlg;

唯一的例外是单文档界面的MFC应用程序,你无法在 InitInstance 函数里看到这段代码,因为它已经被隐藏在 ProcessShellCommand 这个函数里了。由此你就可以下结论了:只要创建自己的窗口类,并将这个类的对象赋值给 m_pMainWnd 成员函数就可以实现自定义的应用程序主窗口。下面的程序将演示如何创建风格怪异的应用程序窗口。如图:

界面怪异的窗口

为什么要创建自己的主程序窗口

MFC向导是个非常有用的工具,但似乎在微软看来,应用程序的界面就只有对话框,单文档和多文档这么几种。我们有时希望做出风格怪异的窗口,虽然通过修改MFC自动生成的程序也可以做到这一点,但是这往往需要了解MFC里许多非常神秘的参数,而且修改后的代码往往臃肿,而且容易出现匪夷所思的错误。我们要编写干净清爽的代码,所以DIY是最好的方法。

生成MFC工程

我们最好不要完全不理MFC向导,它确实还是一个好工具。我们可以首先用MFC向导生成一个基于对话框的应用程序。在这个应用程序的基础上进行修改。

在生成了一个基于对话框的应用程序,假设工程名为MyWnd以后,将MyWndDlg.h 和MyWndDlg.cpp这两个文件从工程中删除,你甚至还可以把它们从硬盘上彻底删掉。因为这两个类包含的是应用程序主窗口类,我们已经不再需要它了。同时还应该删去资源文件中的对话框模板。

到了这一步,我们就做好了所有的准备工作,下面开始动手。

创建自己的窗口类

用MFC向导向应用程序添加一个MFC类,基类应该选成CWnd。假设这个类的名字是CMyWnd。单击确定以后,可以看见MFC向导已经为你生成了它的构造和析构函数。

每一个CWnd类对应了一个窗口,但创建CWnd及其派生类的一个对象并不能创建一个窗口。(注意:不要把窗口类的对象和操作系统中的窗口对象混淆,窗口类对象只是CWnd 及其派生类的对象,而窗口对象就是桌面上活蹦乱跳的窗口)你需要在一定的时候创建窗口对象,并把它们和你的窗口类对象关联起来。所以,我们在CMyWindow类中添加一个Create成员函数,用以创建这个窗口对象:


BOOL CMyWindow::Create()
{
     constchar * strClassName;
     //创建背景画刷
     m_BrushBGround.CreateSolidBrush(RGB(0,0,0));
     //注册窗口类
     strClassName=::AfxRegisterWndClass(CS_VREDRAW|CS_HREDRAW,
         ::LoadCursor(NULL,IDC_ARROW),(HBRUSH)m_BrushBGround.GetSafeHandle(),
         NULL);
     if(!strClassName)
     {
//       TRACE("strClassName
is null
");
         return FALSE;
     }
     //设置窗口的位置和大小
     CRect RectCreate;
     RectCreate.top=0;
     RectCreate.left=0;
     RectCreate.bottom=200;
     RectCreate.right=200;
 
     //创建窗口对象,注意:Create 函数只能用于创建子窗口,对于应用程序的主窗口,必须使用
     //CreateEx函数。
     if(!CreateEx(NULL,strClassName,NULL,WS_POPUP|WS_CLIPCHILDREN,
         RectCreate,(CWnd
*)pParent,NULL,NULL))
     {
         return FALSE;
     }
     return TRUE;
}

完成了这个函数以后,窗口类的框架就基本完成了。现在要做的就是修改Initinstance 函数。首先在CMyWndApp类里添加一个CMyWindow 类的成员变量m_MainWnd,这样在theApp对象被创建的时候,这个成员变量也就被创建了。当然有人倾向于使用new来创建窗口对象,但我个人认为可以不使用new的时候就尽量不要使用它。修改后的Initinstance函数变成:


BOOL
CMyWndApp::InitInstance()
{
     // 如果一个运行在 Windows XP 上的应用程序清单指定要
     // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
     //则需要 InitCommonControls()。否则,将无法创建窗口。
     InitCommonControls();
     CWinApp::InitInstance();
     AfxEnableControlContainer();
     m_pMainWnd =
&m_MainWnd;
     if(m_MainWnd.Create())
     {
         //窗口创建成功,开始消息循环;
         return TRUE;
     }
     else
     {
         MessageBox(NULL,"内存不够,主窗口创建失败","错误",MB_OK);
         return FALSE;
     }
}

我在这里使用的是VC.Net,其注释都是中文的。在修改了若干BUG以后,你就可以编译这个程序并开始运行了。运行的结果是一个长宽都为200,顶点在屏幕左上角的黑色窗口,没有标题栏,没有边框,整个就是屏幕上的一个大黑洞。如何?振奋人心吧,用MFC向导从来没有做过这样的怪窗口。


百度大联盟认证黄金会员Copyright© 1997- CNET Networks 版权所有。 ZDNet 是CNET Networks公司注册服务商标。
中华人民共和国电信与信息服务业务经营许可证编号:京ICP证010391号 京ICP备09041801号-159
京公网安备:1101082134