2.MFC基础(二)窗口创建

一、窗口的创建

 1.加载菜单

 2.调用CreateEx函数,设计并注册窗口类,创建窗口

  (1)调用PreCreateWindow函数,设计窗口并调用win32API函数::RegisterClass注册窗口类

  (2)调用AfxHookWindowCreate函数

     利用win32API函数GetWindowHookEx在程序中埋下一个类型为WH_CBT的钩子

     将自己new的框架类对象地址(pFrame)保存到当前程序线程信息中

  (3)调用win32API函数::CreateWindowEx创建窗口,此函数一旦执行成功立即执行钩子处理函数

 3.钩子处理函数

  (1)将窗口句柄和自己new的框架类对象(pFrame)建立一对一的绑定关系

      pFrame->m_hWnd = hWnd

      pMap->m_permanentMap[hWnd] = pFrame ;

  (2)利用win32API函数SetWindowLong将窗口处理函数更改为AfxWndProc(正真的窗口处理函数)

二、消息处理

 1.当消息产生后进入AfxWndProc函数处理

 2.找到和窗口句柄(hWnd)绑定在一起的框架类对象地址(pFrame)

 3.利用pFrame调用框架类的成员虚函数WindowProc完成消息处理

 补充://埋钩子

    HHOOK SetWindowsHookEx( int               idHook,           //钩子类型(WH_CBT)

                                                     HOOKPROC   lpfn,               //钩子处理函数

                                                     HINSTANCE   hMod,            //应用程序实例句柄,为NULL,所有进程都钩

                                                     DWORD        dwThreadId);  //线程ID,为0,所有线程都钩

    //钩子处理函数

    LRESULT  CALLBACK  CBTProc( int            nCode,    //钩子码(HCBT_CREATEWND)

                                                         WPARAM   wParam,  //附带信息(刚创建成功的窗口句柄)

                                                         LPARAM     lParam);  //附带信息

    //更改窗口处理函数

    LONG  SetWindowLong( HWND  hWnd,           //窗口句柄

                                               int       nIndex,          //GWL_WNDPROC

                                               LONG   dwNewLong);  //新的窗口处理函数

  伪代码:

    CMyFrameWnd  *pFrame  =  new  CMyFrameWnd;
    pFrame->Create( NULL, L"MFCCreate" )  //函数内部this为pFrame

    {

      //先加载菜单

      //创建窗口

      CreateEx( ..., NULL, ... )  //函数内部this为pFrame

      {      

        CREATESTRUCT cs;  //cs中就是CreateWindowEx中的12个参数
        ......
        cs.lpszClass = NULL;   //窗口类怎么可能为NULL????????

        ......

        cs.hInstance = AfxGetInstanceHandle();  //拿到WinMain的第一个参数

        ......

        PreCreateWindow( cs )

        {

          if  ( cs.lpszClass  ==  NULL )

          {            

            AfxDeferRegisterClass( ... ) 

            {

              WNDCLASS  wndcls;
              ......            
              wndcls.lpfnWndProc  =  DefWindowProc;  //我们怎么处理消息????? 
              ......

              _AfxRegisterWithIcon( &wndcls, L"AfxFrameOrView120sud", ... )

              {

                &wndcls->lpszClassName = L"AfxFrameOrView120sud";

                ......

                AfxRegisterClass( &wndcls )

                {

                  RegisterClass( &wndcls );  //注册窗口类

                }

              }

            }
            cs.lpszClass  =  _afxWndFrameOrView;  // L"AfxFrameOrView120sud"

          }

        }

        AfxHookWindowCreate( pFrame ) 

        {      

          _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData( );  //获取全局变量(当前程序线程信息)的地址

          //利用win32API函数在程序中埋下一个类型为WH_CBT的钩子

          ::SetWindowsHookEx( WH_CBT, _AfxCbtFilterHook, NULL, ::GetCurrentThreadId( ) );

          pThreadState->m_pWndInit = pFrame;  //将pFrame(自己new的框架类对象地址)保存到全局变量中

        }

        ::CreateWindowEx( ... );  //此函数一旦执行完成,WM_CREATE消息立即被钩子钩走(钩到钩子处理函数中,_AfxCbtFilterHook)

      }

    }

  *************************************************************************************************************

  //钩子处理函数

  LRESULT  CALLBACK  _AfxCbtFilterHook( int  code, WPARAM  wParam, LPARAM  lParam )

  {

    _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData( );  //获取全局变量(当前程序线程信息)的地址

    CWnd* pWndInit = pThreadState->m_pWndInit;  //从当前程序线程信息重新获取pFrame

    HWND hWnd = (HWND)wParam;  //获取刚创建的窗口句柄

    pWndInit->Attach( hWnd )  //函数内部this为pFrame

    {

      CHandleMap* pMap = afxMapHWND( TRUE )

      {

        AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState( );  //获取全局变量的地址

        pState->m_pmapHWND = new CHandleMap( ... );  //new了一个映射类对象,并将对象地址全局变量的成员中

        return pState->m_pmapHWND;

      }

      pMap->SetPermanent( pFrame->m_hWnd = hWnd, pFrame )  

      {

        //函数内部this指针为pMap(映射类对象地址)

        pMap->m_permanentMap[hWnd] = pFrame ;       

      }

    }  

    WNDPROC afxWndProc = AfxGetAfxWndProc( );  //获取AfxWndProc函数地址

    //利用win32API函数将窗口处理函数更改为AfxWndProc(真正的窗口处理函数)
    oldWndProc = (WNDPROC)SetWindowLongPtr( hWnd, GWLP_WNDPROC, (DWORD_PTR)afxWndProc ); 

  }

  *************************************************************************************************************

  //以WM_CREATE消息为例,查看消息的处理流程

  AfxWndProc( ... )

  {

    CWnd*  pWnd  =  CWnd::FromHandlePermanent( hWnd )   //获取pFrame

    {

      CHandleMap*  pMap  =  afxMapHWND( )  //映射类对象

      {

        AFX_MODULE_THREAD_STATE*  pState =  AfxGetModuleThreadState( );  //获取管局变量

        return  pState->m_pmapHWND;  //返回全局变量的成员(保存了映射类对象)

      }

      pWnd  =  (CWnd*)pMap->LookupPermanent( hWnd )  //函数内部this为映射类对象地址

      {

        return  (CObject*)m_permanentMap.GetValueAt( (LPVOID)hWnd ); //获取下标为窗口句柄的值,即pFrame

      }

      return  pWnd;  //返回pFrame

    }

    return  AfxCallWndProc( pWnd,  hWnd,  nMsg,  wParam,  lParam )  //参数的pWnd即为pFrame

    {

      lResult  =  pWnd->WindowProc( nMsg,  wParam,  lParam );  //调用虚函数,回到自己的代码

    }

  }

  相关代码:

#include "stdafx.h"
#include "T09_MFCCreate.h"

class CMyFrameWnd : public CFrameWnd 
{
public:
    virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
};

//AfxWndProc(真正的窗口处理函数)会调用WindowProc
LRESULT CMyFrameWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    //此函数的this为pFram    
    PAINTSTRUCT ps = { 0 };
    HDC hdc;
    switch (message)
    {
    case WM_PAINT:        
        hdc = ::BeginPaint((HWND)this->m_hWnd, &ps);
        ::TextOut(hdc, 100, 100, L"hello", 5);
        ::EndPaint((HWND)m_hWnd, &ps);
        break;
    case WM_CREATE:
        AfxMessageBox(L"WM_CREATE");
        break;
    }
    return CFrameWnd::WindowProc(message, wParam, lParam);
}

class CMyWinApp : public CWinApp
{
public:
    virtual BOOL InitInstance();
};

CMyWinApp theApp;

BOOL CMyWinApp::InitInstance()
{
    CMyFrameWnd *pFrame = new CMyFrameWnd;
    pFrame->Create(NULL, L"MFCCreate");
    m_pMainWnd = pFrame;
    pFrame->ShowWindow(SW_SHOW);
    pFrame->UpdateWindow();
    return TRUE;
}

  运行结果:

  

 

转载于:https://www.cnblogs.com/csqtech/p/5678504.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值