VC6模拟C#的Anchor

本文属spanzhang原创,其blog地址为:http://blog.csdn.net/spanzhang。引用请注明出处,谢谢!!
用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();
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值