[VC]Dialog实现类似Winamp、千千静听的磁性吸附窗体(Dock)

关键词:Dock Form,磁性窗体,粘黏窗体

 

版本:Visual C++ 6.0 或以上均可

 

原理:

1. 判断是否符合吸附条件,拦截子窗体WM_WINDOWPOSCHANGING消息,将lParam转换为PWINDOWPOS后与主窗体的Rect对比,符合条件时候(比如子窗体right与主窗体的left差距小于10px),修改子窗体状态为“已吸附”,并记录下是吸附在主窗体的哪条边(LEFT、RIGHT、TOP、BOTTOM),然后记录下与主窗体的x,y的差距

 

2. 拖动主窗体时,同时移动所有已经吸附的子窗体,需要相应主窗体的WM_MOVE、WM_SIZE消息,在这些消息触发时候,根据子窗体吸附的边框和与主窗体x、y差距,计算新坐标之后,移动子窗体。

 

以上是最简单的条件了,其实上文所述的“主窗体”、“子窗体”,并不是dlg.Create(IDD_XX,pParent)中的pParent父级的意思。而是相对于吸附和被吸附的对象

 

并且10px我是直接写在了函数之中,大家可以随便改

 


 

 

子窗体中需要实现的代码:

在我的代码中,继承了CDialog对象(VS2008 ↑ 可以继承CDialogEx对象)为CMagnetDialog

新建private变量:CWnd* m_pMainDlg;CArray<CWnd*,CWnd*&> m_pMagnetismList;

 

· 当m_pMainDlg不为NULL时,表示此窗体是m_pMainDlg的子窗体,设置m_pMainDlg的对应函数是SetMainDlg(CWnd* pWnd);。

· m_pMagnetismList.GetSize() >0时,则表示此窗体下面有很多子窗体.

 

 

现假设新建了A、B、C三个窗体,A是主窗体,B、C都是A的子窗体

在B、C的InitDialog中写到:

this->SetMainDlg(A);

这样就将A设置成了B、C的子窗体

 

 


拦截消息:

 

 

 

 

以上代码并不是完整代码,只是实现了一些过程

 

完整代码请在这里下载:

http://download.csdn.net/source/2710558

 


 

 

 

这是第一个版本,在windows下 开启"拖动时显示窗口内容"下效果比较明显,千千静听只所以不受"拖动是显示窗口内容"的限制,是因为它没有标题栏,然后重写了一些代码,实现鼠标点击窗体任意部分后拖动窗体方式,目前这代码中只是简单的实现了鼠标点击之后发送HIT_TEST消息欺骗的方式,这和点击标题栏无异.以后再研究一下鼠标点击后拖动窗体,主要在于要平滑,我看网上很多例子都是很简单的,那种点住后用力甩都可以把窗体甩出去.

 

 

一些细节:

当子窗体和主窗体的某一边在10px的差距之内的时候,移动子窗体时,会有平滑移动的功能(总贴着主窗体的边)

当子窗体已经吸附,Resize子窗体时候,当子窗体已吸附的相邻的两条边会与主窗体的那两边有磁性功能,自己试一下吧

 

第二个版本中,将会实现如下功能:

1. 鼠标点击窗体任意部分后可拖动窗体(这样就可以无视“拖动时显示窗口内容”了)

2. 当有子窗体B吸附在主窗体上之后,别的子窗体C也可以吸附在这个子窗体B上。直到B失去吸附(移动或者Resize超过10px范围)

3. 磁性功能增强,子窗体移动到任意子窗体的某边时,吸附,Resize也同样带磁性,如图2

 

 

完整代码请在这里下载:

http://download.csdn.net/source/2710558

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值