DirectUI(一)

LRESULT CALLBACK CWindowWnd::__ControlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
   CWindowWnd
*  pThis  =  NULL;

   
if ( uMsg  ==  WM_NCCREATE ) 
   {
      LPCREATESTRUCT lpcs 
=  reinterpret_cast < LPCREATESTRUCT > (lParam);
      pThis 
=  static_cast < CWindowWnd *> (lpcs -> lpCreateParams);
      pThis
-> m_hWnd  =  hWnd;
      ::SetProp(hWnd, 
" WndX " , (HANDLE) pThis);
   } 
   
else  
   {
      pThis 
=  reinterpret_cast < CWindowWnd *> (::GetProp(hWnd,  " WndX " ));
      
if ( uMsg  ==  WM_NCDESTROY  &&  pThis  !=  NULL ) 
      {
         LRESULT lRes 
=  ::CallWindowProc(pThis -> m_OldWndProc, hWnd, uMsg, wParam, lParam);
         ::SetProp(hWnd, 
" WndX " , NULL);
         
if ( pThis -> m_bSubclassed ) pThis -> Unsubclass();
         pThis
-> m_hWnd  =  NULL;
         pThis
-> OnFinalMessage(hWnd);
         
return  lRes;
      }
   }

   
if ( pThis  !=  NULL ) 
   {
      
return  pThis -> HandleMessage(uMsg, wParam, lParam);
   } 
   
else  
   {
      
return  ::DefWindowProc(hWnd, uMsg, wParam, lParam);
   }
}

LRESULT CALLBACK CWindowWnd::__WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
   CWindowWnd
*  pThis  =  NULL;
   
if ( uMsg  ==  WM_NCCREATE ) 
   {
      LPCREATESTRUCT lpcs 
=  reinterpret_cast < LPCREATESTRUCT > (lParam);
      pThis 
=  static_cast < CWindowWnd *> (lpcs -> lpCreateParams);
      pThis
-> m_hWnd  =  hWnd;
      ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast
< LPARAM > (pThis));
   } 
   
else  
   {
      pThis 
=  reinterpret_cast < CWindowWnd *> (::GetWindowLongPtr(hWnd, GWLP_USERDATA));
      
if ( uMsg  ==  WM_NCDESTROY  &&  pThis  !=  NULL ) 
      {
         LRESULT lRes 
=  ::CallWindowProc(pThis -> m_OldWndProc, hWnd, uMsg, wParam, lParam);
         ::SetWindowLongPtr(pThis
-> m_hWnd, GWLP_USERDATA,  0L );
         
if ( pThis -> m_bSubclassed ) pThis -> Unsubclass();
         pThis
-> m_hWnd  =  NULL;
         pThis
-> OnFinalMessage(hWnd);
         
return  lRes;
      }
   }

   
if ( pThis  !=  NULL ) 
   {
      
return  pThis -> HandleMessage(uMsg, wParam, lParam);
   } 
   
else
   {
      
return  ::DefWindowProc(hWnd, uMsg, wParam, lParam);
   }
}


当 CreateWindow 采用已存在的类时,使用的是 __ControlProc, 位于 RegisterSuperclass()
wc.lpfnWndProc = CWindowWnd::__ControlProc;

当 CreateWindow 采用创建的类时,使用的是      __WndProc, 位于 RegisterWindowClass()
wc.lpfnWndProc = CWindowWnd::__WndProc;

这两个函数唯一不同的是,
__ControlProc 使用 SetProp() 的方式来设置 This 指针, 而
__WndProc     使用  SetWindowLogPtr -> GWLP_USERDATA 的方式来设置 This 指针

·使用已存在的类时,或许是怕别人已经设置过 GWLP_USERDATA ,所以这里采用了 SetProp() 的方式

void  CWindowWnd::CenterWindow()
{
   ASSERT(::IsWindow(m_hWnd));
   ASSERT((GetWindowStyle(m_hWnd)
& WS_CHILD) == 0 );

   RECT rcDlg 
=  {  0  };
   ::GetWindowRect(m_hWnd, 
& rcDlg);
   RECT rcArea 
=  {  0  };
   RECT rcCenter 
=  {  0  };
   HWND hWndParent 
=  ::GetParent(m_hWnd);
   HWND hWndCenter 
=  ::GetWindowOwner(m_hWnd);
   ::SystemParametersInfo(SPI_GETWORKAREA, NULL, 
& rcArea, NULL);
   
if ( hWndCenter  ==  NULL ) rcCenter  =  rcArea;  else  ::GetWindowRect(hWndCenter,  & rcCenter);

   
int  DlgWidth  =  rcDlg.right  -  rcDlg.left;
   
int  DlgHeight  =  rcDlg.bottom  -  rcDlg.top;

   
//  Find dialog's upper left based on rcCenter
    int  xLeft  =  (rcCenter.left  +  rcCenter.right)  /   2   -  DlgWidth  /   2 ;
   
int  yTop  =  (rcCenter.top  +  rcCenter.bottom)  /   2   -  DlgHeight  /   2 ;

   
//  The dialog is outside the screen, move it inside
    if ( xLeft  <  rcArea.left ) 
       xLeft 
=  rcArea.left;
   
else   if ( xLeft  +  DlgWidth  >  rcArea.right ) 
       xLeft 
=  rcArea.right  -  DlgWidth;
   
   
if ( yTop  <  rcArea.top ) 
       yTop 
=  rcArea.top;
   
else   if ( yTop  +  DlgHeight  >  rcArea.bottom ) 
       yTop 
=  rcArea.bottom  -  DlgHeight;

   ::SetWindowPos(m_hWnd, NULL, xLeft, yTop, 
- 1 - 1 , SWP_NOSIZE  |  SWP_NOZORDER  |  SWP_NOACTIVATE);
}

·一直以为有 CenterWindow() 这个API……,看来是因为MFC用久的缘故罢

HWND CWindowWnd::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle,  int  x,  int  y,  int  cx,  int  cy, HMENU hMenu)
{
   
if ( GetSuperClassName()  !=  NULL  &&   ! RegisterSuperclass() ) 
       
return  NULL;
   
   
if ( GetSuperClassName()  ==  NULL  &&   ! RegisterWindowClass() ) 
       
return  NULL;
   
   m_hWnd 
=  ::CreateWindowEx(dwExStyle, GetWindowClassName(), pstrName, dwStyle, x, y, cx, cy, hwndParent, hMenu, CPaintManagerUI::GetResourceInstance(),  this );
   ASSERT(m_hWnd
!= NULL);

   
return  m_hWnd;
}

这里在 lpParam 参数将 this 指针传过去,在 WM_NCCREATE  消息中再获取 this 指令,但MSDN 相关解释却是在 WM_CREATE  消息处理……

lpParam
[in]  Pointer to a value to be passed to the window through the CREATESTRUCT structure ( lpCreateParams member) pointed to by the lParam param of the WM_CREATE message. This message is sent to the created window by this function before it returns.

If an application calls CreateWindow to create a MDI client window, lpParam should point to a CLIENTCREATESTRUCT structure. If an MDI client window calls CreateWindow to create an MDI child window, lpParam should point to a MDICREATESTRUCT structure. lpParam may be NULL if no additional data is needed.

 

void  CWindowWnd::ResizeClient( int  cx  /* = -1 */ int  cy  /* = -1 */ )
{
   ASSERT(::IsWindow(m_hWnd));
   RECT rc 
=  {  0  };;
   
if ! ::GetClientRect(m_hWnd,  & rc) )
       
return ;
   
   
if ( cx  !=   - 1  ) rc.right  =  cx;
   
if ( cy  !=   - 1  ) rc.bottom  =  cy;
   
   
if ! ::AdjustWindowRectEx( & rc, GetWindowStyle(m_hWnd), ( ! (GetWindowStyle(m_hWnd)  &  WS_CHILD)  &&  (::GetMenu(m_hWnd)  !=  NULL)), GetWindowExStyle(m_hWnd)) ) 
       
return ;
   
   UINT uFlags 
=  SWP_NOZORDER  |  SWP_NOMOVE;
   ::SetWindowPos(m_hWnd, NULL, 
0 0 , rc.right  -  rc.left, rc.bottom  -  rc.top, uFlags);
}

AdjustWindowRectEx()

函数功能:该函数依据所需客户矩形大小,计算需要的窗口矩形的大小。计算出的窗口矩形随后可以传送给CreateWindowEx函数,用于创建一个客户区所需大小的窗口。
函数原型:BOOL AdjustWindowRectEX(LPRECT lpRect,DWORD dwStyte;BOOL bMenu;DWORD dwExStyle);
参数:
lpRect:指向RECT结构的指针,该结构包含所需客户区域的左上角和右下角的坐标。函数返回时,该结构包含容纳所需客户区域的窗口的左上角和右下角的坐标。
dwStyle:指定将被计算尺寸的窗口的窗口风格。
bMenu:指示窗口是否有菜单。
dwExStyle:指定将被计算尺寸的窗口的扩展窗口风格。
返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。
备注:客户矩形是指完全包含一个客户区域的最小矩形;窗口矩形是指完全包含一个窗口的最小矩形,该窗口包含客户区与非客户区。
当一个菜单条下拉出两行或更多行时,AdjustWindowRect函数不增加额外的空间。
速查:Windows NT:3.1以上版本;Windows:95以上版本;Windows CE:1.0以上版本;头文件:winuser.h;库文件:user32.lib。

你可能感兴趣的:(DirectUI(一))