-
问题内容:怎样实现Winnap 或者千千静听那样 窗体停靠效果
- 原讨论链接:http://community.csdn.net/expert/topicview1.asp?id=5105230
- 所属论坛:界面
审核组:VC/MFC
- 提问者:AsenWei
解决者:happyness44
- 感谢:carloshs starytx Saimen
- 关键字:VC/MFC 窗体 界面 矩形 停靠 nsep m_rectwnd abs dock pwndmain cdockdlg gap
- 答案:
如题!
给个思路 或者给个例子最好!
---------------------------------------------------------------
计算与窗口或屏幕的距离。然后小于多少间距就赋值为0就行了。看着就像粘上了。
---------------------------------------------------------------
以顶部停靠为例
在OnMove事件中检测窗体的top值,如果小于某个值(比如5),就将top设为0,同时调用MovwWindow即可
---------------------------------------------------------------
在每个窗口的 OnMoving 中处理一下就行啦
---------------------------------------------------------------
需要停靠的窗口
/////////////////////////////
BEGIN_MESSAGE_MAP(CDockDlg, CDialog)
//{{AFX_MSG_MAP(CDockDlg)
ON_WM_CLOSE()
ON_WM_MOVING()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDockDlg message handlers
void CDockDlg::OnClose()
{
// TODO: Add your message handler code here and/or call default
CDockWndDlg *pWnd;
pWnd = (CDockWndDlg *)this->FromHandle(m_hParent);
pWnd->InverseState();
}
BOOL CDockDlg::Init(HWND hParent)
{
m_hParent = hParent;
return Create(IDD_DISPLAY,this->GetDesktopWindow());
}
// 定义两个域值
#define THRESHOLD 1
#define GAP 30
void CDockDlg::Dock(UINT nDirection,CWnd *pWndMain)
{
// 得到主窗体矩形区域
CRect rectMain;
pWndMain->GetWindowRect(&rectMain);
// 进行停靠操作
m_nDirection = nDirection;
if (nDirection == LEAVE)
m_nDirection = NO_DIRECTION;
// 不再停靠
else if (!IsDocking(rectMain,m_rectWnd,nDirection))
Dock(LEAVE,pWndMain);
int nSep;
switch (m_nDirection)
{
case LEFT:
// 从左方停靠
nSep = rectMain.left - m_rectWnd.right;
if (abs(nSep) > THRESHOLD && abs(nSep) <= GAP)
{
m_rectWnd.OffsetRect(nSep,0);
Dock(LEFT,pWndMain);
}
else if (abs(nSep) > GAP)
Dock(LEAVE,pWndMain);
break;
case RIGHT:
// 从右边停靠
nSep = rectMain.right - m_rectWnd.left;
if (abs(nSep) > THRESHOLD && abs(nSep) <= GAP)
{
m_rectWnd.OffsetRect(nSep,0);
Dock(RIGHT,pWndMain);
}
else if (abs(nSep) > GAP)
Dock(LEAVE,pWndMain);
break;
case TOP:
// 从上边停靠
nSep = rectMain.top - m_rectWnd.bottom;
if (abs(nSep) > THRESHOLD && abs(nSep) <= GAP)
{
m_rectWnd.OffsetRect(0,nSep);
Dock(TOP,pWndMain);
}
else if (abs(nSep) > GAP)
Dock(LEAVE,pWndMain);
break;
case BOTTOM:
// 从下面停靠
nSep = rectMain.bottom - m_rectWnd.top;
if (abs(nSep) > THRESHOLD && abs(nSep) <= GAP)
{
m_rectWnd.OffsetRect(0,nSep);
Dock(BOTTOM,pWndMain);
}
else if (abs(nSep) > GAP)
Dock(LEAVE,pWndMain);
break;
case NO_DIRECTION:
// 子窗体未停靠
break;
case LEAVE:
// 不再是停靠状态
m_nDirection = NO_DIRECTION;
}
}
UINT CDockDlg::GetDirection() const
{
return m_nDirection;
}
BOOL CDockDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
CWnd *pWnd;
pWnd = this->FromHandle(m_hParent);
// 得到主窗体矩形
CRect rectMain;
pWnd->GetWindowRect(&rectMain);
// 获得自身矩形
this->GetWindowRect(&m_rectWnd);
// 左对齐
m_rectWnd.right = rectMain.left + m_rectWnd.Width();
m_rectWnd.left = rectMain.left;
// 开始将子窗体停靠在主窗体的下方
m_rectWnd.bottom = rectMain.bottom + m_rectWnd.Height();
m_rectWnd.top = rectMain.bottom;
this->MoveWindow(&m_rectWnd);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CDockDlg::OnMoving(UINT fwSide, LPRECT pRect)
{
// TODO: Add your message handler code here
// 得到自身矩形区域
m_rectWnd.CopyRect(pRect);
// 得到主窗体指针
CWnd *pWnd;
pWnd= this->FromHandle(m_hParent);
Dock(m_nDirection,pWnd);
*pRect = m_rectWnd;
}
BOOL CDockDlg::IsDocking(CRect &rectMain, CRect &rectMine, UINT nDirection)
{
if (nDirection == LEFT || nDirection == RIGHT)
{
if (rectMine.top >= rectMain.top && rectMine.top <= rectMain.bottom)
return TRUE;
else if (rectMine.bottom >= rectMain.top && rectMine.bottom <= rectMain.bottom)
return TRUE;
}
else if (nDirection == TOP || nDire
- 评价:
给朵鲜花(101)
扔个鸡蛋(15)