您的位置:首页 > 其它

[MFC学习笔记]--孙鑫第三课

2015-08-17 10:02 351 查看
    我新建了一个MFC app工程,名字叫mfcTest,然后VC6++给我自动生成了一些类。CAboutDlg类,CMainFrame类,CMfcTestApp类,CMfcTestDoc类,CMfcTestView类.

    接下来,我要一个个学习这种类。这些类都有基类,这些基类都是MFC的类库里面的。

    CMfcTestApp 是继承了CWinApp类。

    The CWinApp class is the base class from which you derive a Windows application object. An application object provides member functions for initializing your application (and each instance of it) and for running the application.

 

    CMfcTestApp theAPP;在自动生成的代码中,CMfcTestApp声明了一个全局对象theAPP。也就是,我们打开的窗口什么的,都是theAPP这个对象。

    Afx:Application Framework应用程序框架,集成了很多类用来设置。

 

    CMainFrame类生成的是框架窗口,就如下图的蓝色线,也就是app最大的那个窗口框。CMfcTestView产生的就是那个子窗口。就是用粗线描绘的地方。



 

CMfcDoc类是用来加载一些数据,然后CMfcView类是用来显示这些数据的。

 

CAboutDlg:关于对话框的类,是继承Cwnd类,也是一种窗口类。

 

 

在第三课中,自动生成的代码,在内部是怎么进行的呢?

step 1.CMfcTestApp类声明一个全局对象theAPP  this 指针指向这个对象

step 2.进入winmain()函数,在MFC\SRC\APPMODUL.CPP 中。他是这么定义的。

_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

 LPTSTR lpCmdLine, int nCmdShow)

{

 

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

}

最后跳转到AfxWinMain();函数当中去了。

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

 LPTSTR lpCmdLine, int nCmdShow)

{

 ASSERT(hPrevInstance == NULL);

 int nReturnCode = -1;

 CWinThread* pThread = AfxGetThread();

 CWinApp* pApp = AfxGetApp();

 // AFX internal initialization

 if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))

  goto InitFailure;

 // App global initializations (rare)

 if (pApp != NULL && !pApp->InitApplication())

  goto InitFailure;

 // Perform specific initializations

 if (!pThread->InitInstance())

 {

  if (pThread->m_pMainWnd != NULL)

  {

   TRACE0("Warning: Destroying non-NULL m_pMainWnd\n");

   pThread->m_pMainWnd->DestroyWindow();

  }

  nReturnCode = pThread->ExitInstance();

  goto InitFailure;

 }

 nReturnCode = pThread->Run();

在这个函数中,我们进行了一些初始化的工作。

 

然后进入一个pThread->InitInstance()函数,在这个函数中,完成应用程序的初始化工作,注册,创建,显示,更新窗口类。

 

step 3.注册一个窗口类 我们用了AfxEndDeferRegisterClass这个函数。这个函数在...\MFC\SRC\WINCORE.CPP 中。AfxRegisterClass这个也是注册这个窗口

 

BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)

{

 // mask off all classes that are already registered

 AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

 fToRegister &= ~pModuleState->m_fRegisteredClasses;

 if (fToRegister == 0)

  return TRUE;

 LONG fRegisteredClasses = 0;

 // common initialization

 WNDCLASS wndcls;

 memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL defaults

 wndcls.lpfnWndProc = DefWindowProc;

 wndcls.hInstance = AfxGetInstanceHandle();

 wndcls.hCursor = afxData.hcurArrow;

 INITCOMMONCONTROLSEX init;

 init.dwSize = sizeof(init);

 // work to register classes as specified by fToRegister, populate fRegisteredClasses as we go

 if (fToRegister & AFX_WND_REG)

 {

  // Child windows - no brush, no icon, safest default class styles

  wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

  wndcls.lpszClassName = _afxWnd;

  if (AfxRegisterClass(&wndcls))

   fRegisteredClasses |= AFX_WND_REG;

 }

 if (fToRegister & AFX_WNDOLECONTROL_REG)

 {

  // OLE Control windows - use parent DC for speed

  wndcls.style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

  wndcls.lpszClassName = _afxWndOleControl;

  if (AfxRegisterClass(&wndcls))

   fRegisteredClasses |= AFX_WNDOLECONTROL_REG;

 }

 if (fToRegister & AFX_WNDCONTROLBAR_REG)

 {

  // Control bar windows

  wndcls.style = 0;   // control bars don't handle double click

  wndcls.lpszClassName = _afxWndControlBar;

  wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);

  if (AfxRegisterClass(&wndcls))

   fRegisteredClasses |= AFX_WNDCONTROLBAR_REG;

 }

 if (fToRegister & AFX_WNDMDIFRAME_REG)

 {

  // MDI Frame window (also used for splitter window)

  wndcls.style = CS_DBLCLKS;

  wndcls.hbrBackground = NULL;

  if (_AfxRegisterWithIcon(&wndcls, _afxWndMDIFrame, AFX_IDI_STD_MDIFRAME))

   fRegisteredClasses |= AFX_WNDMDIFRAME_REG;

 }

 if (fToRegister & AFX_WNDFRAMEORVIEW_REG)

 {

  // SDI Frame or MDI Child windows or views - normal colors

  wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

  wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);

  if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))

   fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;

 }

 if (fToRegister & AFX_WNDCOMMCTLS_REG)

 {

  // this flag is compatible with the old InitCommonControls() API

  init.dwICC = ICC_WIN95_CLASSES;

  fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WIN95CTLS_MASK);

  fToRegister &= ~AFX_WIN95CTLS_MASK;

 }

 if (fToRegister & AFX_WNDCOMMCTL_UPDOWN_REG)

 {

  init.dwICC = ICC_UPDOWN_CLASS;

  fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_UPDOWN_REG);

 }

.....

 // must have registered at least as mamy classes as requested

 return (fToRegister & fRegisteredClasses) == fToRegister;

}

step 4:创建窗口  这里用的是CreateEX.代码如下,在WINCORE.CPP中可以看见。

BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,

  LPCTSTR lpszWindowName, DWORD dwStyle,

  const RECT& rect, CWnd* pParentWnd, UINT nID,

  LPVOID lpParam /* = NULL */)

{

 return CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,

  rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,

  pParentWnd->GetSafeHwnd(), (HMENU)nID, lpParam);

}

BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,

 LPCTSTR lpszWindowName, DWORD dwStyle,

 int x, int y, int nWidth, int nHeight,

 HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)

{

 // allow modification of several common create parameters

 CREATESTRUCT cs;//这个CREATESTRUCT
就是为了能够让程序员在创建窗口之前,修改一些基本的窗口参数

 cs.dwExStyle = dwExStyle;

 cs.lpszClass = lpszClassName;

 cs.lpszName = lpszWindowName;

 cs.style = dwStyle;

 cs.x = x;

 cs.y = y;

 cs.cx = nWidth;

 cs.cy = nHeight;

 cs.hwndParent = hWndParent;

 cs.hMenu = nIDorHMenu;

 cs.hInstance = AfxGetInstanceHandle();

 cs.lpCreateParams = lpParam;

 if (!PreCreateWindow(cs))

 {

  PostNcDestroy();

  return FALSE;

 }

 AfxHookWindowCreate(this);

 HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,

   cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,

   cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);

 

step 5: 显示 和 更新 窗口

 

m_pMainWnd->ShowWindow(SW_SHOW);

m_pMainWnd->UpdateWindow();

 

step 6:消息循环   在   ...\MFC\SRC\THRDCORE.CPP

 

 

int CWinThread::Run()

{

 ASSERT_VALID(this);

 // for tracking the idle time state

 BOOL bIdle = TRUE;

 LONG lIdleCount = 0;

 // acquire and dispatch messages until a WM_QUIT message is received.

 for (;;)

 {

  // phase1: check to see if we can do idle work

  while (bIdle &&

   !::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))

  {

   // call OnIdle while in bIdle state

   if (!OnIdle(lIdleCount++))

    bIdle = FALSE; // assume "no idle" state

  }

  // phase2: pump messages while available

  do

  {

   // pump message, but quit on WM_QUIT

   if (!PumpMessage())

    return ExitInstance();

   // reset "no idle" state after pumping "normal" message

   if (IsIdleMessage(&m_msgCur))

   {

    bIdle = TRUE;

    lIdleCount = 0;

   }

  } while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));

 }

 ASSERT(FALSE);  // not reachable

}

知识点补充:我们自己在写一些类的成员函数的时候,比如我们定义了一个CWnd::ShowWindow();但是我们在实现的时候用了SDK的API函数。

就可以这样  BOOL CWnd::ShowWindow(int nCndShow){ ::ShowWindow()}  //
::ShowWindow()这样就是表示调用了SDK的API函数。

 

BOOL Create( LPCTSTR lpszCaption, DWORD
dwStyle, const RECT& rect, CWnd*
pParentWnd, UINT nID );

const RECT& rect 这是一个结构体的引用。结构体本质上也是一种class,于是我们用CRect类的构造函数,声明了一个对象来代替这个结构体。比如,这个参数

就可以设置成为 CRect(0,0,100,100)

 

int CMainFrame::OnCreate();函数专门用来处理窗口创建时的消息int CMfcTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

 if (CView::OnCreate(lpCreateStruct) == -1)

  return -1;

 

  m_btn.Create("weixin",WS_CHILD|WS_VISIBLE|BS_AUTO3STATE ,CRect(0,0,100,100),/*GetParent()*/this,123);

  m_btn.ShowWindow(SW_SHOWNORMAL); // TODO: Add your specialized creation code here

 

 return 0;

}

上面的GetParent()是为了得到父窗口的指针,this是theAPP的指针,

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: