一个MFC程序的生因死果

来源:互联网 发布:阿里云学生机带宽一兆 编辑:程序博客网 时间:2024/04/28 12:12

 这是一个关于JJHOU的写的一个MFC程序的生因死果的感想。如有疑问请去参考<<dessecting MFC 2ed Edtion>>

 

//Hello.h


class CMyWinApp : public CWinApp
{
public:
   virtual BOOL InitInstance();       // 每一个应用程序都应该改写此函数
   virtual BOOL OnIdle(LONG lCount);  //
};


class CMyFrameWnd : public CFrameWnd
{
public:
   CMyFrameWnd();            // constructor
   afx_msg void OnPaint();   // for WM_PAINT
   afx_msg void OnAbout();   // for WM_COMMAND (IDM_ABOUT)
   void IdleTimeHandler(LONG lCount);  // we want it call by CMyWinApp::OnIdle

private:
   DECLARE_MESSAGE_MAP()     // Declare Message Map
   static VOID CALLBACK LineDDACallback(int,int,LPARAM);
};

 

 

 

 

//Hello.cpp

 

CMyWinApp theApp;   // application object

BOOL CMyWinApp::InitInstance()
{
   m_pMainWnd = new CMyFrameWnd();
   m_pMainWnd->ShowWindow(m_nCmdShow);
   m_pMainWnd->UpdateWindow();
   return TRUE;
}


BOOL CMyWinApp::OnIdle(LONG lCount)
{
   CMyFrameWnd* pWnd = (CMyFrameWnd*)m_pMainWnd;
   pWnd->IdleTimeHandler(lCount);

   return TRUE;
}

 


CMyFrameWnd::CMyFrameWnd()
{
   Create(NULL, "Hello MFC", WS_OVERLAPPEDWINDOW, rectDefault,
          NULL, "MainMenu"); 
}

BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
   ON_COMMAND(IDM_ABOUT, OnAbout)
   ON_WM_PAINT()
END_MESSAGE_MAP()

void CMyFrameWnd::OnPaint()
{
CPaintDC dc(this);
CRect rect;

   GetClientRect(rect);

   dc.SetTextAlign(TA_BOTTOM | TA_CENTER);

   ::LineDDA(rect.right/2, 0, rect.right/2, rect.bottom/2,
       (LINEDDAPROC) LineDDACallback, (LPARAM) (LPVOID) &dc);
}

VOID CALLBACK CMyFrameWnd::LineDDACallback(int x, int y, LPARAM lpdc)
{
static char szText[] = "Hello, MFC";

   ((CDC*)lpdc)->TextOut(x, y, szText, sizeof(szText)-1);
   for(int i=1; i<50000; i++); 

void CMyFrameWnd::OnAbout()
{
   CDialog about("AboutBox", this);
   about.DoModal();
}

void CMyFrameWnd::IdleTimeHandler(LONG lCount)
{
  CString str;
  CRect rect(10,10,200,30);
  CDC* pDC = new CClientDC(this);

  str.Format("%010d", lCount);
  pDC->DrawText(str, &rect, DT_LEFT | DT_TOP);
}

 

因为运行SDK编写程序的时候WinMain和WndProc有一定的固定性,所以MFC将WinMain封装到了WinApp中,讲WndProc封装到了CFrameWnd中。但是只是一些固定行为,我们需要根据编写应用程序的需要来override这些函数。

class CMyWin:public CWinApp{}

class CMyFrame:public CFrameWnd{}

 

程序的诞生:

 

进入WinMain函数之前一个有且仅有一个的全局对象获得初始化,它是CMyWinApp theApp。若没有改写CMyWinApp中的InitInstance则调用CWinApp::InitInstance,但是每一个应用程序都应该override此函数,因为此函数在CWinApp::InitInstance中只是一个空函数(也许是一个纯虚函数,我没有看过这个类的源代码)

 

theApp获得初始化后,WinMain函数登场了。

但是这是MFC准备好由连接器直接加到应用程序代码中的

//in appmodul.cpp

extern "C" int WINAPI(extern "C"表示在C++中引用C中的变量)

 _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd )

{

    return AfxWinMain(hInstance, hPrevInstance,lpCmdLine, nShowCmd);

}

 

//这个AfxWinInit只是提取出了一些重要的操作

BOOL AFXAPI AfxWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow
)
{
CWinApp* pApp=AfxGetApp();
AfxWinInit(hInstance,hPrevInstance,lpCmdLine,nCmdShow);
pApp->InitApplication();
pApp->InitInstance();
nReturnCode=pApp->run();
AfxWinterm();
return nReturnCode;
}

 

 

 

theApp获得初始化后,接下来会调用AfxWinMain,AfxWinMain又会调用AfxWinInit,AfxWinInit又会调用AfxWinThread

接下来执行InitInstance,此函数我们必须改写

 

BOOL CMyWinApp::InitInstance()
{
   m_pMainWnd = new CMyFrameWnd();
   m_pMainWnd->ShowWindow(m_nCmdShow);
   m_pMainWnd->UpdateWindow();
   return TRUE;
}

new了一个CMyFrameWnd对象,再调用Create函数(实际上是 CreateEx)创建一个窗口接下来继续执行m_pMainWnd->ShowWindow(m_nCmdShow),m_pMainWnd->UpdateWindow,发出一个WM_PAINT消息,回到AfxWinMain(),执行run函数,进行消息循环。

 

 

 

 

 

 

 

原创粉丝点击