您的位置:首页 > 其它

窗口自动停靠至屏幕边缘

2014-06-19 19:56 525 查看
实现功能:当拖动窗口至屏幕边缘(未接触屏幕边缘)至某个范围内时,自动移动窗口紧贴屏幕边缘。

引用函数:MoveWindow

其实,原理很简单:先判断窗口是否处于自动停靠的范围内,若是,则通过MoveWindow函数执行停靠操作。

我们知道,屏幕有上下左右四个方向,即屏幕有四个边缘。为了使函数尽可能全面,为函数添加一个direct参数,用于确定在那个方向上执行自动停靠。另外,就是执行自动停靠时机的确定了。为此,再添加一个参数triggerDistance,即触发距离,也就是窗体距离屏幕边缘多近时触发自动停靠。

为direct参数定义5个值,具体如下:

#define CLOSE_TO_LEFT   1
#define CLOSE_TO_TOP    2
#define CLOSE_TO_RIGHT  4
#define CLOSE_TO_BOTTOM 8
#define CLOSE_TO_ALL    15


下面是函数的具体实现:

/************************************************************************/
/* 自动贴紧屏幕边缘                                                     */
/************************************************************************/
void CxxxDlg::AutoCloseToEdge(int direct, int triggerDistance)
{
// direct参数有4个取值:
// 分别为:
// 靠左贴紧:CLOSE_TO_LEFT
// 靠上贴紧:CLOSE_TO_TOP
// 靠右贴紧:CLOSE_TO_RIGHT
// 靠下贴紧:CLOSE_TO_BOTTOM
// 四面贴紧:CLOSE_TO_ALL
// triggerDistance为触发距离

int screenWidth = GetSystemMetrics(SM_CXSCREEN);  // 获取屏幕宽度
int screenHeight = GetSystemMetrics(SM_CYSCREEN); // 获取屏幕高度

CRect rect;
GetWindowRect(&rect);  // 获取窗口大小

switch (direct)
{
case 1:
// 左
if (rect.left<triggerDistance)
{
MoveWindow(0, rect.top, rect.Width(), rect.Height(), FALSE);
}
break;

case 2:
// 上
if (rect.top<triggerDistance)
{
MoveWindow(rect.left, 0, rect.Width(), rect.Height(), FALSE);
}
break;

case 4:
// 右
if (rect.right>screenWidth-triggerDistance)
{
MoveWindow(screenWidth-rect.Width(), rect.top, rect.Width(), rect.Height(), FALSE);
}
break;

case 8:
// 下
if (rect.bottom>screenHeight-triggerDistance)
{
MoveWindow(rect.left, screenHeight-rect.Height(), rect.Width(), rect.Height(), FALSE);
}
break;

case 3:
// 左+上
if (rect.left<triggerDistance)
{
MoveWindow(0, rect.top, rect.Width(), rect.Height(), FALSE);
}
if (rect.top<triggerDistance)
{
MoveWindow(rect.left, 0, rect.Width(), rect.Height(), FALSE);
}
break;

case 5:
// 左+右
if (rect.left<triggerDistance)
{
MoveWindow(0, rect.top, rect.Width(), rect.Height(), FALSE);
}
if (rect.right>screenWidth-triggerDistance)
{
MoveWindow(screenWidth-rect.Width(), rect.top, rect.Width(), rect.Height(), FALSE);
}
break;

case 9:
// 左+下
if (rect.left<triggerDistance)
{
MoveWindow(0, rect.top, rect.Width(), rect.Height(), FALSE);
}
if (rect.bottom>screenHeight-triggerDistance)
{
MoveWindow(rect.left, screenHeight-rect.Height(), rect.Width(), rect.Height(), FALSE);
}
break;

case 6:
// 上+右
if (rect.top<triggerDistance)
{
MoveWindow(rect.left, 0, rect.Width(), rect.Height(), FALSE);
}
if (rect.right>screenWidth-triggerDistance)
{
MoveWindow(screenWidth-rect.Width(), rect.top, rect.Width(), rect.Height(), FALSE);
}
break;

case 10:
// 上+下
if (rect.top<triggerDistance)
{
MoveWindow(rect.left, 0, rect.Width(), rect.Height(), FALSE);
}
if (rect.bottom>screenHeight-triggerDistance)
{
MoveWindow(rect.left, screenHeight-rect.Height(), rect.Width(), rect.Height(), FALSE);
}
break;

case 7:
// 左+上+右
if (rect.left<triggerDistance)
{
MoveWindow(0, rect.top, rect.Width(), rect.Height(), FALSE);
}
if (rect.right>screenWidth-triggerDistance)
{
MoveWindow(screenWidth-rect.Width(), rect.top, rect.Width(), rect.Height(), FALSE);
}
if (rect.top<triggerDistance)
{
MoveWindow(rect.left, 0, rect.Width(), rect.Height(), FALSE);
}
break;

case 14:
// 上+右+下
if (rect.right>screenWidth-triggerDistance)
{
MoveWindow(screenWidth-rect.Width(), rect.top, rect.Width(), rect.Height(), FALSE);
}
if (rect.top<triggerDistance)
{
MoveWindow(rect.left, 0, rect.Width(), rect.Height(), FALSE);
}
if (rect.bottom>screenHeight-triggerDistance)
{
MoveWindow(rect.left, screenHeight-rect.Height(), rect.Width(), rect.Height(), FALSE);
}
break;

case 13:
// 左+右+下
if (rect.left<triggerDistance)
{
MoveWindow(0, rect.top, rect.Width(), rect.Height(), FALSE);
}
if (rect.right>screenWidth-triggerDistance)
{
MoveWindow(screenWidth-rect.Width(), rect.top, rect.Width(), rect.Height(), FALSE);
}
if (rect.bottom>screenHeight-triggerDistance)
{
MoveWindow(rect.left, screenHeight-rect.Height(), rect.Width(), rect.Height(), FALSE);
}
break;

case 11:
// 左+上+下
if (rect.left<triggerDistance)
{
MoveWindow(0, rect.top, rect.Width(), rect.Height(), FALSE);
}
if (rect.top<triggerDistance)
{
MoveWindow(rect.left, 0, rect.Width(), rect.Height(), FALSE);
}
if (rect.bottom>screenHeight-triggerDistance)
{
MoveWindow(rect.left, screenHeight-rect.Height(), rect.Width(), rect.Height(), FALSE);
}
break;

case 15:
if (rect.left<triggerDistance)
{
MoveWindow(0, rect.top, rect.Width(), rect.Height(), FALSE);
}
if (rect.right>screenWidth-triggerDistance)
{
MoveWindow(screenWidth-rect.Width(), rect.top, rect.Width(), rect.Height(), FALSE);
}
if (rect.top<triggerDistance)
{
MoveWindow(rect.left, 0, rect.Width(), rect.Height(), FALSE);
}
if (rect.bottom>screenHeight-triggerDistance)
{
MoveWindow(rect.left, screenHeight-rect.Height(), rect.Width(), rect.Height(), FALSE);
}
break;

default:
break;
}
}


以上函数可以结合计时器函数使用或响应移动窗口的消息,再结束移动后自动停靠。
例如,可以在如下位置调用

/************************************************************************/
/* 重载函数,响应鼠标左键在标题栏的释放                                 */
/************************************************************************/
void CxxxDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
// TODO: Add your message handler code here and/or call default

CDialog::OnSysCommand(nID, lParam);  // 这句放在判断语句之前

// 判断是否是鼠标左键弹起
if( (nID & 0xFFF0) == SC_MOVE )
{
// 鼠标左键释放,调用一次紧贴函数(若此时窗口靠近屏幕边缘,则紧贴屏幕边缘)
AutoCloseToEdge(CLOSE_TO_LEFT|CLOSE_TO_RIGHT|CLOSE_TO_TOP, 20);
}

}


效果是:当移动窗口至左边、上边或右边距离屏幕边缘小于20时,窗口在移动结束(鼠标左键释放)后自动紧贴屏幕边缘。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: