zoukankan      html  css  js  c++  java
  • 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;
    }

      运行结果:

      

  • 相关阅读:
    A1023 Have Fun with Numbers (20分)(大整数四则运算)
    A1096 Consecutive Factors (20分)(质数分解)
    A1078 Hashing (25分)(哈希表、平方探测法)
    A1015 Reversible Primes (20分)(素数判断,进制转换)
    A1081 Rational Sum (20分)
    A1088 Rational Arithmetic (20分)
    A1049 Counting Ones (30分)
    A1008 Elevator (20分)
    A1059 Prime Factors (25分)
    A1155 Heap Paths (30分)
  • 原文地址:https://www.cnblogs.com/csqtech/p/5678504.html
Copyright © 2011-2022 走看看