句柄映射机制的实现

mfc里实现句柄映射借助了两个类:句柄映射辅助类,模块--线程状态类

 

1.句柄映射辅助类:

class CHandleMap
{
private:    // implementation
 CFixedAllocNoSync m_alloc;
 void (PASCAL* m_pfnConstructObject)(CObject* pObject);
 void (PASCAL* m_pfnDestructObject)(CObject* pObject);


 CMapPtrToPtr m_permanentMap;                     //永久映射
 CMapPtrToPtr m_temporaryMap;                      //临时映射
 CRuntimeClass* m_pClass;
 size_t m_nOffset;       // offset of handles in the object
 int m_nHandles;         // 1 or 2 (for CDC)

 

// Constructor/Destructor
public:
 CHandleMap(CRuntimeClass* pClass,
  void (PASCAL* pfnConstructObject)(CObject* pObject),
  void (PASCAL* pfnDestructObject)(CObject* pObject),
  size_t nOffset, int nHandles = 1);
#ifdef _AFXDLL
 ~CHandleMap()
#else
 virtual ~CHandleMap()
#endif
  { DeleteTemp(); }

// Operations


public:
 CObject* FromHandle(HANDLE h);                                 //从句柄获取MFC对象
 void DeleteTemp();                                                        //删除临时句柄

 void SetPermanent(HANDLE h, CObject* permOb);      //向永久映射中添加一个记录
 void RemoveHandle(HANDLE h);                                    //从永久映射里删除一个记录

 CObject* LookupPermanent(HANDLE h);                       //查找永久映射表
 CObject* LookupTemporary(HANDLE h);                        //查处临时映射表


 friend class CWinThread;
};

 

2.模板--线程状态类

class AFX_MODULE_THREAD_STATE : public CNoTrackObject
{
public:
 AFX_MODULE_THREAD_STATE();
 virtual ~AFX_MODULE_THREAD_STATE();

 // current CWinThread pointer
 CWinThread* m_pCurrentWinThread;

 // list of CFrameWnd objects for thread
 CTypedSimpleList<CFrameWnd*> m_frameList;

 // temporary/permanent map state
 DWORD m_nTempMapLock;           // if not 0, temp maps locked


 CHandleMap* m_pmapHWND;
 CHandleMap* m_pmapHMENU;
 CHandleMap* m_pmapHDC;
 CHandleMap* m_pmapHGDIOBJ;
 CHandleMap* m_pmapHIMAGELIST;

 ..........................................................

 

模板--线程状态的初始化在CWinApp的构造函数里完成,也就是说它比WinMain更早,构造函数主要完成模块状态,模板--线程状态,

以及线程和全局对象的初始化。

 

每当一个窗口类调用Create或CreateEx时,都要设置钩子:

AfxHookWindowCreate(this);这个函数的作用在这不多讲了,总之它在执行过程中调用了:Attach(m_hWnd);

Attach()的定义如下:

BOOL CWnd::Attach(HWND hWndNew)
{
 ASSERT(m_hWnd == NULL);     
 ASSERT(FromHandlePermanent(hWndNew) == NULL);

 if (hWndNew == NULL)
  return FALSE;

 CHandleMap* pMap = afxMapHWND(TRUE); // create map if not exist
 ASSERT(pMap != NULL);

 pMap->SetPermanent(m_hWnd = hWndNew, this);          //加入到永久映射中


#ifndef _AFX_NO_OCC_SUPPORT
 AttachControlSite(pMap);
#endif

 return TRUE;
}

 

CWnd有这样几个函数:FromHandle(HWND hWnd),FromHandlePermanent(HWND hWnd).它们都用到CHandleMap类

函数定义如下:

CWnd* PASCAL CWnd::FromHandle(HWND hWnd)
{
 CHandleMap* pMap = afxMapHWND(TRUE); //如果不存在就创建它:afxMapHWND的作用
 ASSERT(pMap != NULL);
 CWnd* pWnd = (CWnd*)pMap->FromHandle(hWnd); //先从永久里找,再从临时中找,都找不到就创建一个Cwnd返回

#ifndef _AFX_NO_OCC_SUPPORT
 pWnd->AttachControlSite(pMap);
#endif

 ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);
 return pWnd;
}


CWnd* PASCAL CWnd::FromHandlePermanent(HWND hWnd)
{
 CHandleMap* pMap = afxMapHWND();
 CWnd* pWnd = NULL;
 if (pMap != NULL)
 {
  // only look in the permanent map - does no allocations
  pWnd = (CWnd*)pMap->LookupPermanent(hWnd);     //只从永久映射里找,如果找不到就返回NULL.
  ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);
 }
 return pWnd;
}

 

当一个窗口函数要销毁的时候,也就是在它接收的最后一个WMNCDESTROY里会调用Detach()来解除窗口对象与CWnd对象的关系。

Detach()的定义如下:

HWND CWnd::Detach()
{
 HWND hWnd = m_hWnd;
 if (hWnd != NULL)
 {
  CHandleMap* pMap = afxMapHWND(); // don't create if not exist
  if (pMap != NULL)
   pMap->RemoveHandle(m_hWnd);                    //从永久映射里删除。
 m_hWnd = NULL;
 }

#ifndef _AFX_NO_OCC_SUPPORT
 m_pCtrlSite = NULL;
#endif

 return hWnd;
}

 

在程序空闲的时候,也就是在OnIdle函数,会自动删除临时的映射。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值