VC窗口类注册与诞生

来源:互联网 发布:1 手机 知乎 编辑:程序博客网 时间:2024/05/17 09:13

1、窗口类的结构

typedef struct tagWNDCLASSA {
    UINT        style;//style = CS_VREDRAW|CS_HREDRAW表示窗口在运动或者调整大小时需要重画
    WNDPROC     lpfnWndProc;
    int         cbClsExtra;
    int         cbWndExtra;
    HINSTANCE   hInstance;
    HICON       hIcon;
    HCURSOR     hCursor;
    HBRUSH      hbrBackground;
    LPCSTR      lpszMenuName;
    LPCSTR      lpszClassName;
} WNDCLASSA, *PWNDCLASSA, NEAR *NPWNDCLASSA, FAR *LPWNDCLASSA;

2、MFC类注册宏

    AFXIMPL.H中,定义了五个默认窗口宏:

#define AFX_WND_REG                     0x00001
#define AFX_WNDCONTROLBAR_REG           0x00002
#define AFX_WNDMDIFRAME_REG             0x00004
#define AFX_WNDFRAMEORVIEW_REG          0x00008
#define AFX_WNDOLECONTROL_REG           0x00020

#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)

BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister);

    又定义了这样的一个宏:

#ifndef _UNICODE
#define _UNICODE_SUFFIX
#else
#define _UNICODE_SUFFIX _T("u")
#endif

#ifndef _DEBUG
#define _DEBUG_SUFFIX
#else
#define _DEBUG_SUFFIX _T("d")
#endif

#ifdef _AFXDLL
#define _STATIC_SUFFIX
#else
#define _STATIC_SUFFIX _T("s")
#endif
#define AFX_WNDCLASS(s) /
 _T("Afx") _T(s) _T("42") _STATIC_SUFFIX _UNICODE_SUFFIX _DEBUG_SUFFIX

#define AFX_WND             AFX_WNDCLASS("Wnd")
#define AFX_WNDCONTROLBAR   AFX_WNDCLASS("ControlBar")
#define AFX_WNDMDIFRAME     AFX_WNDCLASS("MDIFrame")
#define AFX_WNDFRAMEORVIEW  AFX_WNDCLASS("FrameOrView")
#define AFX_WNDOLECONTROL   AFX_WNDCLASS("OleControl")

    WINCORE.cpp中,初始化了以上宏:

const TCHAR _afxWnd[] = AFX_WND;
const TCHAR _afxWndControlBar[] = AFX_WNDCONTROLBAR;
const TCHAR _afxWndMDIFrame[] = AFX_WNDMDIFRAME;
const TCHAR _afxWndFrameOrView[] = AFX_WNDFRAMEORVIEW;
const TCHAR _afxWndOleControl[] = AFX_WNDOLECONTROL;

3、MFC类注册函数

    在定义AFX_WND_REG时,就有,

#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)

BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister);

     其实现函数在WINCORE.CPP中,(其他的均在此中)

     BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)

//已注册检测

   AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
 fToRegister &= ~pModuleState->m_fRegisteredClasses;//当前模块求反再求与运算
 if (fToRegister == 0)//为0则注册
  return TRUE;

 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);

//只有style 、lpszClassName值修改了

 if (fToRegister & AFX_WND_REG)//The first digit is 1,第1位为1
 {
  // 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;//Long型局部变量,求或

 

  ……


 }

    来看看这个函数

    BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass)
{
 WNDCLASS wndcls;

上面: wndcls.lpfnWndProc = DefWindowProc;
 wndcls.hInstance = AfxGetInstanceHandle();
 wndcls.hCursor = afxData.hcurArrow;
 if (GetClassInfo(lpWndClass->hInstance, lpWndClass->lpszClassName,
  &wndcls))//获取到了,说明hInstance,lpszClassName已注册
 {
  // class already registered
  return TRUE;
 }

 if (!::RegisterClass(lpWndClass))//开始注册
 {
  TRACE1("Can't register window class named %s/n",
   lpWndClass->lpszClassName);
  return FALSE;
 }

 if (afxContextIsDLL)//如果是dll,做相应的处理
 {
  AfxLockGlobals(CRIT_REGCLASSLIST);
  TRY
  {
   // class registered successfully, add to registered list
   AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
   LPTSTR lpszUnregisterList = pModuleState->m_szUnregisterList;
   // the buffer is of fixed size -- ensure that it does not overflow
   ASSERT(lstrlen(lpszUnregisterList) + 1 +
    lstrlen(lpWndClass->lpszClassName) + 1 <
    _countof(pModuleState->m_szUnregisterList));
   // append classname + newline to m_szUnregisterList
   lstrcat(lpszUnregisterList, lpWndClass->lpszClassName);
   TCHAR szTemp[2];
   szTemp[0] = '/n';
   szTemp[1] = '/0';
   lstrcat(lpszUnregisterList, szTemp);
  }
  CATCH_ALL(e)
  {
   AfxUnlockGlobals(CRIT_REGCLASSLIST);
   THROW_LAST();
   // Note: DELETE_EXCEPTION not required.
  }
  END_CATCH_ALL
  AfxUnlockGlobals(CRIT_REGCLASSLIST);
 }

 return TRUE;
}

4、MFC注册窗口实现

 

 WINCORE.CPP中,

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)//11个参数,//hInstance参数没有,

 CREATESTRUCT cs;
 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))//此处调用this指向的对象,一般都会返回TRUE
 {
  PostNcDestroy();
  return FALSE;
 }

 }

来看看PreCreateWindow(cs)),

1>

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
 if( !CFrameWnd::PreCreateWindow(cs) )
  return FALSE;
 // TODO: Modify the Window class or styles here by modifying
 //  the CREATESTRUCT cs

 return TRUE;
}

2>

BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
 if (cs.lpszClass == NULL)
 {
  VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
  cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background
 }

 if ((cs.style & FWS_ADDTOTITLE) && afxData.bWin4)
  cs.style |= FWS_PREFIXTITLE;

 if (afxData.bWin4)
  cs.dwExStyle |= WS_EX_CLIENTEDGE;

 return TRUE;
}

3>

BOOL CSingleView::PreCreateWindow(CREATESTRUCT& cs)
{
 // TODO: Modify the Window class or styles here by modifying
 //  the CREATESTRUCT cs

 return CView::PreCreateWindow(cs);
}

4>

BOOL CView::PreCreateWindow(CREATESTRUCT & cs)
{
 ASSERT(cs.style & WS_CHILD);

 if (cs.lpszClass == NULL)
 {
  VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
  cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background
 }

 if (afxData.bWin4 && (cs.style & WS_BORDER))
 {
  cs.dwExStyle |= WS_EX_CLIENTEDGE;
  cs.style &= ~WS_BORDER;
 }

 return TRUE;
}

  在来看看代码后面,

 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);//创建

//创建的检验

#ifdef _DEBUG
 if (hWnd == NULL)
 {
  TRACE1("Warning: Window creation failed: GetLastError returns 0x%8.8X/n",
   GetLastError());
 }
#endif

 if (!AfxUnhookWindowCreate())
  PostNcDestroy();        // cleanup if CreateWindowEx fails too soon

 if (hWnd == NULL)
  return FALSE;
 ASSERT(hWnd == m_hWnd); // should have been set in send msg hook
 return TRUE;