VC6模拟C#的Anchor

类别:VC语言 点击:0 评论:0 推荐:

用C#写Windows程序的时候,我们可以注意到里面有个很有意思并且很有用的东东“Anchor”。它可以被指定为“Top, Bottom, Left, Right”的组合。这个东西可以简化我们的界面上的很多工作,很多时候都可以不用对布局写代码。以下是我在VC6里给出的模拟解决方案:
#pragma warning(disable: 4786)
#include <map>
typedef enum anchor{
 AR_NONE   = 0,  
 AR_LEFT   = 1,  
 AR_TOP    = 2,  
 AR_RIGHT  = 4, 
 AR_BOTTOM = 8, 
 
 AR_FILL = AR_LEFT | AR_TOP | AR_RIGHT | AR_BOTTOM, 
 AR_LEFTTOP = AR_LEFT | AR_TOP, 
 AR_RIGHTTOP = AR_RIGHT | AR_TOP, 
 AR_LEFTBOTTOM = AR_LEFT | AR_BOTTOM,
 AR_RIGHTBOTTOM = AR_RIGHT | AR_BOTTOM
}anchor;
typedef std::map<CWnd*, UINT> anchorMap;
typedef std::map<UINT, UINT> anchorMapById;

。。。。。。

void baseDlg::registerAnchor(CWnd* child, UINT anchor /* = AR_NONE */)
{
 anchors[child] = anchor;
}
void baseDlg::unRegisterAnchor(CWnd* child)
{
 anchorMap::iterator iter = anchors.find(child);
 if (iter != anchors.end())
  anchors.erase(iter);
}

void baseDlg::registerAnchorById(UINT itemId, UINT anchor /* = AR_NONE */)
{
 anchorsById[itemId] = anchor;
}

void baseDlg::unRegisterAnchorById(UINT itemId)
{
 anchorMapById::iterator iter = anchorsById.find(itemId);
 if (iter != anchorsById.end())
  anchorsById.erase(iter);
}

void baseDlg::OnSize(UINT nType, int cx, int cy)
{
 CDialog::OnSize(nType, cx, cy);

 if (!IsWindowVisible())
  return;

 CRect rtClientNew;
 GetClientRect(&rtClientNew);
 int dx = rtClientNew.right - oldClient.right;
 int dy = rtClientNew.bottom - oldClient.bottom;

 if (rtClientNew.Width() < 2 || rtClientNew.Height() < 2)
  return;

 for (anchorMap::iterator iter = anchors.begin();
 iter != anchors.end();
 ++iter)
 {
  CWnd* child = iter->first;
  if (child == NULL || !IsWindow(child->m_hWnd))
   continue;

  UINT anchor = iter->second;
  static CRect rtOrign;
  child->GetWindowRect(&rtOrign);
  ScreenToClient(&rtOrign);

  static CRect rtNew;
  rtNew = rtOrign;
  if (anchor & AR_LEFT)
  {
   rtNew.left = rtOrign.left;
  }
  else
  {
   rtNew.left += dx / 2;
  }

  if (anchor & AR_TOP)
  {
   rtNew.top = rtOrign.top;
  }
  else
  {
   rtNew.top += dy / 2;
  }

  if (anchor & AR_RIGHT)
  {
   rtNew.right += dx;
   if (!(anchor & AR_LEFT))
    rtNew.left = rtOrign.left + dx;
  }
  else
  {
   rtNew.right += dx / 2;
   if (anchor & AR_LEFT)
    rtNew.right = rtNew.left + rtOrign.Width();
  }

  if (anchor & AR_BOTTOM)
  {
   rtNew.bottom += (dy);
   if (!(anchor & AR_TOP))
    rtNew.top = rtOrign.top + dy;
  }
  else
  {
   rtNew.bottom += dy / 2;
   if (anchor & AR_TOP)
    rtNew.bottom = rtNew.top + rtOrign.Height();
  }

  child->MoveWindow(&rtNew);
 }

 for (anchorMapById::iterator iterById = anchorsById.begin();
 iterById != anchorsById.end();
 ++iterById)
 {
  CWnd* child = GetDlgItem(iterById->first);
  if (child == NULL || !IsWindow(child->m_hWnd))
   continue;

  UINT anchor = iterById->second;
  static CRect rtOrign;
  child->GetWindowRect(&rtOrign);
  ScreenToClient(&rtOrign);

  static CRect rtNew;
  rtNew = rtOrign;
  if (anchor & AR_LEFT)
  {
   rtNew.left = rtOrign.left;
  }
  else
  {
   rtNew.left += dx / 2;
  }

  if (anchor & AR_TOP)
  {
   rtNew.top = rtOrign.top;
  }
  else
  {
   rtNew.top += dy / 2;
  }

  if (anchor & AR_RIGHT)
  {
   rtNew.right += dx;
   if (!(anchor & AR_LEFT))
    rtNew.left = rtOrign.left + dx;
  }
  else
  {
   rtNew.right += dx / 2;
   if (anchor & AR_LEFT)
    rtNew.right = rtNew.left + rtOrign.Width();
  }

  if (anchor & AR_BOTTOM)
  {
   rtNew.bottom += (dy);
   if (!(anchor & AR_TOP))
    rtNew.top = rtOrign.top + dy;
  }
  else
  {
   rtNew.bottom += dy / 2;
   if (anchor & AR_TOP)
    rtNew.bottom = rtNew.top + rtOrign.Height();
  }

  child->MoveWindow(&rtNew);
 }

 oldClient = rtClientNew;

 Invalidate();
}

本文地址:http://com.8s8s.com/it/it247.htm