现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

使窗口移动时具有停靠吸附功能

2012-08-21 05:36 工业·编程 ⁄ 共 4712字 ⁄ 字号 暂无评论

一.前言:

封装了一个类,可以很简单的使窗口移动时具有自动吸附停靠在屏幕边缘或自定窗口边缘的功能。

二.使用方法:

0.添加MoveWnd.h 和 MoveWnd.cpp 到你的工程

1.左键按下时(OnNcLButtonDown)调用

1.左键按下时调用: PrepareMoveWnd的第二个参数是想停靠的目标窗口
void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
  CMoveWnd::PrepareMoveWnd(m_hWnd,::GetParent(m_hWnd));
  CDialog::OnLButtonDown(nFlags, point);
}

   如果在标题栏按下,则:
void CMyDlg::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
  if(nHitTest == HTCAPTION)
  {
   CMoveWnd::PrepareMoveWnd(m_hWnd,::GetParent(m_hWnd));
   return;
  }
  CDialog::OnNcLButtonDown(nHitTest, point);
}

2.左键弹起时调用 CMoveWnd::IsMovedWnd() 判断是否移动了窗口

void CMyDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
if (CMoveWnd::IsMovedWnd()) //判断是否移动了窗口
{
  trace("has mvoe");
}
else
  trace("no move");

CDialog::OnLButtonUp(nFlags, point);
}

3.鼠标移动时:

void CMyDlg::OnMouseMove(UINT nFlags, CPoint point)
{
  if( CMoveWnd::m_IsCapture && nFlags&MK_LBUTTON) 
   CMoveWnd::IsMovingWnd(m_hWnd);
  CDialog::OnMouseMove(nFlags, point);
}

4.可以自己设置Docking的距离  #define AUTO_DOCK_WIDTH 10


二.CMoveWnd代码

MoveWnd.h

#ifndef _MOVE_WND_H_
#define _MOVE_WND_H_

/****************************************************************************
1.左键按下时调用: PrepareMoveWnd的第二个参数是想停靠的目标窗口
void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
  CMoveWnd::PrepareMoveWnd(m_hWnd,::GetParent(m_hWnd));
  CDialog::OnLButtonDown(nFlags, point);
}

   如果在标题栏按下,则:
void CMyDlg::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
  if(nHitTest == HTCAPTION)
  {
   CMoveWnd::PrepareMoveWnd(m_hWnd,::GetParent(m_hWnd));
   return;
  }
  CDialog::OnNcLButtonDown(nHitTest, point);
}

2.左键弹起时调用 CMoveWnd::IsMovedWnd() 判断是否移动了窗口
void CMyDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
  if (CMoveWnd::IsMovedWnd()) //判断是否移动了窗口
  {
   trace("has mvoe");
  }
  else
   trace("no move");

  CDialog::OnLButtonUp(nFlags, point);
}

3.鼠标移动时判断
void CMyDlg::OnMouseMove(UINT nFlags, CPoint point)
{
  if( CMoveWnd::m_IsCapture && nFlags&MK_LBUTTON) 
   CMoveWnd::IsMovingWnd(m_hWnd);
  CDialog::OnMouseMove(nFlags, point);
}
4.可以设置Docking的距离
#define AUTO_DOCK_WIDTH 20 
希望对你有帮助!阿弥陀佛!
****************************************************************************/

#include <Windows.h>

//自动靠屏幕的距离
#define AUTO_DOCK_WIDTH 10   

class CMoveWnd 
{
public:
static bool  m_IsCapture;
static bool  m_IsDockedWnd;

static void  PrepareMoveWnd(HWND m_hWnd,HWND TargetWnd);
static bool  IsMovedWnd();
static void  IsMovingWnd(HWND m_hWnd);
private:
static POINT m_MouseOffsetFromRectLeftTop;
static RECT  m_TargetRect;
static POINT m_MouseDownPoint;

};

#endif //#define _MOVE_WND_H_

MoveWnd.cpp

#include "StdAfx.h"  //如果编译出错,请去掉这一行
#include "MoveWnd.h"

RECT CMoveWnd::m_TargetRect={-100,-100,-100,-100};
bool CMoveWnd::m_IsDockedWnd=false;
POINT CMoveWnd::m_MouseOffsetFromRectLeftTop={-1000,0};
POINT CMoveWnd::m_MouseDownPoint={-10,0};
bool CMoveWnd::m_IsCapture=false;

void CMoveWnd::PrepareMoveWnd(HWND m_hWnd,HWND TargetWnd)
{
::SetCapture(m_hWnd);
m_IsCapture=true;

::GetCursorPos(&m_MouseDownPoint);

RECT rect;    
::GetWindowRect(m_hWnd,&rect);
//获取鼠标相对于Rect左上角的偏移量m_MouseOffsetFromRectLeftTop
m_MouseOffsetFromRectLeftTop.x=m_MouseDownPoint.x-rect.left;
m_MouseOffsetFromRectLeftTop.y=m_MouseDownPoint.y-rect.top;

//保存要停靠的目标窗口Rect
::GetWindowRect(TargetWnd,&m_TargetRect);
}

bool CMoveWnd::IsMovedWnd()
{
::ReleaseCapture();
m_IsCapture=false;

//判断是否移动了窗口
POINT point;
::GetCursorPos(&point);
return (point.x==m_MouseDownPoint.x && point.y==m_MouseDownPoint.y) ? false : true;
}

void CMoveWnd::IsMovingWnd(HWND m_hWnd)
{
//移动窗口,停泊效果

//get cursor point
POINT point;
::GetCursorPos(&point);
//count the new position (当前鼠标位置-移动窗口前保存的鼠标偏移量=新的窗口位置)
int x_pos_new=point.x-m_MouseOffsetFromRectLeftTop.x;
int y_pos_new=point.y-m_MouseOffsetFromRectLeftTop.y;
//用于后面和x_pos_new y_pos_new 对比从而判断是否停靠了
int TempX=x_pos_new;
int TempY=y_pos_new;
//get window rectangle
RECT rect; 
::GetWindowRect(m_hWnd,&rect);
//停靠在目标窗口的右边
if (abs(m_TargetRect.right-x_pos_new)<AUTO_DOCK_WIDTH)
  x_pos_new=m_TargetRect.right;

//停靠在目标窗口的下边
if (abs(m_TargetRect.bottom-y_pos_new)<AUTO_DOCK_WIDTH)
  y_pos_new=m_TargetRect.bottom;
  m_IsDockedWnd=true;

//停靠在目标窗口的左边
if (abs( (x_pos_new+rect.right-rect.left) -m_TargetRect.left)<AUTO_DOCK_WIDTH)
  x_pos_new=m_TargetRect.left-(rect.right-rect.left);
  m_IsDockedWnd=true;

//停靠在目标窗口的上边
if (abs( (y_pos_new+rect.bottom-rect.top) -m_TargetRect.top)<AUTO_DOCK_WIDTH)
  y_pos_new=m_TargetRect.top-(rect.bottom-rect.top);
  m_IsDockedWnd=true;

//判断是否停靠了
if (x_pos_new!=TempX || y_pos_new!=TempY)
  m_IsDockedWnd=true;
else
{
  m_IsDockedWnd=false;

  //获得屏幕的高和宽
  int cxScreen=GetSystemMetrics(SM_CXSCREEN); 
  int cyScreen=GetSystemMetrics(SM_CYSCREEN);
  //如果靠近屏幕,则进行贴边处理
  if ( abs(x_pos_new)<AUTO_DOCK_WIDTH) x_pos_new=0;
  if ( abs(y_pos_new)<AUTO_DOCK_WIDTH) y_pos_new=0;
  if ( abs(x_pos_new+rect.right-rect.left-cxScreen)<AUTO_DOCK_WIDTH) x_pos_new=cxScreen-(rect.right-rect.left);
  if ( abs(y_pos_new+rect.bottom-rect.top-cyScreen)<AUTO_DOCK_WIDTH) y_pos_new=cyScreen-(rect.bottom-rect.top);
}

::SetCursor(::LoadCursor(NULL,IDC_SIZEALL)); 
::SetWindowPos(m_hWnd,HWND_TOPMOST,x_pos_new,y_pos_new,0,0,SWP_NOSIZE);
}

给我留言

留言无头像?