MFC应用程序框架示例

作者在 2009-03-08 14:01:11 发布以下内容
这是一个简单的同时又可以运行的MFC库应用程序实例,
说明:按照惯例,MFC库类名用大写字母“C”打头。
下面给出的是MYAPP应用程序的头文件和源代码文件。类CMyApp和CMyFrame都是从MFC库基类中派生出来的。首先让我们看看这个MyApp应用程序的MyApp.h头文件:

//application class
class CMyApp:public CWinApp
{
public:
 virtual BOOL InitInstance();
}
//frame window class
class CMyFrame: public CFrameWnd
{
public:
 CMyFrame();
protected:
 //"afx_msg"indicates that the next two functions are part of the MFC library message dispatch system
 afx_msg void OnLButtonDowm(UINT nFlags,CPoint point);
 afx_msg void OnPaint(); 
 DECLARE_MESSAGE_MAP
};

#include<afswin.h>//MFC library header file declaree base classes
#include"myapp.h"
CMyApp theApp;//the one and only CMApp object
BOOL CMyApp::InitInstance()
{
 m_pMainWnd=new CMyFrame();
 m_pMainWnd->ShowWindow(m_nCmdShow);
 m_pMainWnd->UpdateWindow();
 return TRRE;
}
BEGIN_MESSAGE_MAP(CMyFrame,CFrameWnd)
 ON_WM_LBUTTONDOWN()
 ON_WM_PAINT()
END_MESSAGE_MAP()
CMyFrame::CMyFrame()
{
 Create(NULL,"MYAPP Application");
}
viod CMyFrame::OnLButtonDown(UINT nFlags,CPoint point)
{
 TRACE("Entering CMyFrame::OnLButtonDown - %1x,%f,%d\n",
  (long)nFlags,point.x,point.y);
}
woid CMyFrame::OnPaint()
{
 CPaintDC dc(this);
 dc.TextOut(0,0,"Hello,world!")
}
下面我们来介绍一下该程序中的一些元素:
WinMain函数  记住Windows总是要求每个应用程序都要有WinMain函数。您之所以在此见不到此函数,是因为它被隐藏在应用程序框架内部了。
CMYAPP类 类CMYAPP的对象就代表了一个应用程序。该程序定义了一个单独的全局CMyApp对象theApp。CWinApp基类决定了theApp的大部分行为。
应用程序的启动 当用运行该应用程序时,Windows会自动调用应用程序框架内部的WinMain函数,WinMain函数会去查找该应用程序的全局构造对象,该对象是由CWinApp所派生出的类的对象。你不要忘了,在C++中,全局对象在主程序被运行之前就已经被构造好了。
CMyApp::InitInstance成员函数  当WinMain发现了该应用程序对象时,它会自动调用虚拟INITINSTANCE成员函数,该函数会进一步调用相应的函数来完成主窗口的构造和显示工作。我们必须在派生出的应用程序类在重载InitInstance函数,因为CWinApp基类根本无法知道你具体需要什么样的主框架窗口。
CWinApp::Run成员函数  Run函数被隐藏在基类中,它用来负责传递应用程序的消息给相应的窗口,从而维护着应用程序的运转。WinMain在调用InitInstance之后将紧接着调用Run。
CMyFrame类 类CMyFrame的对象代表着应用程序的主框架窗口。当构造函数调用基类CFrameWnd的Create成员函数时,Windows将创建成具体的窗口结构,同时应用程序框架会将所创建的窗口结构连接到C++对象中。为了显示所创建的窗口,必须调用基类中的ShowWindow和UpdateWindow成员函数。
CMyFrame::OnLButtonDOown函数  在这里我们可以提前看到类库的消息处理机制。我们已经将鼠标的左键被按下这一事件映射到了CMyFrame的一个成员函数上。我们将会在第四章中学习有关类库消息映射的细节。以后我们就会明白,当用房户按下鼠标左键时,OnLButtonDown函数就会自动被调用。该函数将会激活类库TRACE宏,以便在调试窗口中显示一个消息。
CMyFRrame::OnPaint函数  应用程序框架在每次需要重新绘制窗口时,都要调用这个非常重要的且已被映射过的CMyFrame类的成员函数。在程序刚开始运行时,在用户改变了窗口的大小时,在窗口的全部或部分被重新显现时,在OnPaint成员函数都会被调用。CPaintDC和图形设备接口(GDI)有关,我们将在后面的章节中介绍。TextOut函数用来显示"Hello,World!"。
关闭应用程序  用户可以通过关闭主框架窗口来终止应用程序。这 一举动将会引起一系列事件的发生,首先CMyFrame对象将被删除,然后退出Run,进而退出WinMain,最后再删除CMyApp对象

我们最好再仔细看一下这个例子,不过这次应该着重从整体来观察。该应用程序的大部分功能都包含在类库的基类CWinApp和CFrameWnd中,在编写MYAPP的过程中,我们遵循了一些简单的结构规则,并且编写了派生类中的关键函数。C++可以允许我们”借用“许多代码而用不着去拷贝,这就好比我们和应用程序框架是非常好的合作伙伴一样,应用程序框架为我们提出供了大致的结构,而我们只需将应用程序具体化。
现在,你应该开始明白为什么应用程序框架不仅仅是一种类库了。应用程序框架不但定义了应用程序的结构,而且它所包含的东西还不仅仅是C++的基类。我们已经见过的WinMain函数,以及其他一些用来支持消息处理,诊断,DLL等诸如此类的元素都包含在应用程序框架中。
 
 
参考内容:
CObject
 └CCmdTarget
    └CWinThread
       └CWinApp

CWinApp是一个基类,你通过它来继承Windows应用程序对象。应用程序对象为你提供了初始化应用程序(以及它的每一个实例)和运行应用程序所需的成员函数。
每个使用微软基础类库的应用程序都只能包含一个从CWinApp继承的对象。当Windows调用WinMain函数时,这个对象在其它C++全局对象都已经生成并且可用之后才被创建,WinMain函数是由微软基础类库提供的。将你的CWinApp对象定义为全局的。
当你从CWinApp继承应用程序类的时候,应重载InitInstance成员函数以创建应用程序的主窗口对象。
 

CWinThread::InitInstance
virtual BOOL InitInstance( );
返回值:
若初始化成功,返回值为非零;不成功则返回0。
说明:
InitInstance必须被重载以初始化每个用户界面线程的新实例。统称,你重载InitInstance函数来执行当线程首次被创建时必须完成的任务。
此成员函数仅在用户界面线程中使用。工作者线程的初始化在传递给AfxBeginThread的控制函数中完成。
 
CWinApp::InitInstance
virtual BOOL InitInstance( );
返回值:如果初始化成功,则返回非零值;否则返回0。
说明:
Windows允许在同一时刻运行程序的几份拷贝。在概念上,应用程序的初始化可以被分为两个部分:一次性的应用程序初始化工作,这些在应用程序第一次运行时完成,以及示例的初始化工作,每次运行程序的一个拷贝时都会执行这些操作,包括第一次运行时。框架中WinMain的实现调用这个函数。
重载InitInstance以初始化在Windows下运行的应用程序的每个新实例。通常,你重载InitInstance以构造主窗口对象并设置CWinThread::m_pMainWnd数据成员,使其指向这个窗口。有关重载这个成员函数的更多信息参见“Visual C++ 程序员指南”中的“CWinApp:应用程序类”。
示例:
// AppWizard 根据你选择的选项实现重载的InitInstance函数。
// 例如,对于下面由AppWizard创建的代码,选择了单文档界面(SDI)选项。
// 你可以在AppWizard创建的代码中加入其它的每个实例都执行的初始化代码。
BOOL CMyApp::InitInstance()
{
  // 标准的初始化工作
  // 如果你没有使用这些特性,并且希望减小最终可执行程序的大小,
  // 你应当从下面的初始化例程中移去不必要的代码。
  SetDialogBkColor(); // 将对话框的背景色设为灰色。
  LoadStdProfileSettings(); // 载入标准的INI文件选项(包括MRU)
  // 注册应用程序的文档模板。文档模板
  //被用作文档、框架窗口和视图之间的联系。
  CSingleDocTemplate* pDocTemplate;
  pDocTemplate = new CSingleDocTemplate(
    IDR_MAINFRAME,
    RUNTIME_CLASS(CMyDoc),
    RUNTIME_CLASS(CMainFrame), // SDI的主框架窗口
    RUNTIME_CLASS(CMyView)
   );
  AddDocTemplate(pDocTemplate);
  // 创建一个新(空的)文档
  OnFileNew();
  if (m_lpCmdLine[0] != '\0')
  {
    // 任务:在这里加入命令行处理代码
  }
  return TRUE;
}
 
 
CFrameWnd::CFrameWnd
CFrameWnd( )
说明:构造一个CFrameWnd对象,但不构造可视框架窗口。调用Create构造可视窗口。
 
CFrameWnd类提供Windows单文档界面重叠或弹出式框架窗口,以及管理窗口的成员。
CObject
 └CCmdTarget
    └CWnd
       └CFrameWnd
要为应用构造有用的框架窗口,可从CFrameWnd中派生类。向派生类加入成员变量,以便存储指定给应用的数据。在派生类中实现消息处理成员函数和消息映射,指定当消息指向窗口时的动作。
有三种方法可以构造一个框架窗口: · 用Create直接构造。 
· 用LoadFrame直接构造。 
· 用文档模板间接构造。
 
CFrameWnd::Create
BOOL Create(
     LPCTSTR lpszClassName,
     LPCTSTR lpszWindowName,
     DWORD dwStyle = WS_OVERLAPPEDWINDOW,
     const RECT &rect = rectDefault,
     CWnd* pParentWnd = NULL,
     LPCTSTR lpszMenuName = NULL,
     DWORD dwExStyle = 0,
     CCreateContext* pContext = NULL
     );
返回值:如果初始化成功,则返回非零值,否则为0。
参数: lpszClassName 指向一个用于命名Windows类的以空终止的字符串。类名可以是任何以AfxRegisterJWndClass全局函数登记或RegisterClassWindows函数登记的名。如果为NULL,使用预定义的缺省CFrameWnd属性。 
lpszWindowName 指向代表窗口名的以空终止的字符串,用作标题条的文本。 
dwStyle 指定窗口风格属性。如果想标题条自动显示窗口代表的文档名,则应包含FWS_ADDTOTITLE风格。 
rect 定义窗口大小和位置。rectDefault值使Windows为一个新窗口指定大小和位置。 
pParentWnd 指定框架窗口的父窗口,对最高层框架窗口来说应为NULL。 
lpszMenuName 指定与窗口一起使用的菜单资源名。如果菜单有一个整数ID而不是字符串ID,则使用MAKEINTRESOURCE。此参数可为NULL。 
dwExStyle 指定窗口扩展的风格属性。 
pContext 指向CCreateContext结构的指针。可为NULL。 
说明:
分两步构造一个CFrameWnd对象。首先调用构造函数来构造CFrameWnd对象,然后调用Create来构造Windows框架窗口并把它附加给CFrameWnd对象,Create初始化窗口的类名、窗口名,登记它的风格、父窗口和相关菜单的缺省值。
使用LoadFrame而不用Create来从资源而不是指定其参数加载一个框架窗口。
默认分类 | 阅读 5463 次
文章评论,共1条
flamemiracle
2009-03-08 22:10
1
好东西,拿走了
游客请输入验证码
浏览78533次