Xiangism

从一个无知角落里开始,蹒跚学步,一个未知到另一个未知,在跌跌撞撞中越走越快,越走越远,最后宇宙也为之开源。对于探索者来说,最后他们的思想总是变得和自己的足迹一样伟大。
  博客园  :: 首页  :: 联系 :: 管理

C#、MFC、Win32——移动无标题窗口

Posted on 2009-12-17 23:16  Xiangism  阅读(1995)  评论(1编辑  收藏  举报

本篇介绍如何分别在c#,MFC,WIN32程序中移动无标题窗口

 

C#

  

  C#中总结起来有两种方法:

    1.自己控制,鼠标左键点击、移动时窗体的状态,代码见下:

    

Point offSet;
privatevoid frm_MouseDown(object sender, MouseEventArgs e)
{
  offSet =new Point(-e.X, -e.Y);
}
privatevoid frm_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
  {
Point newPoint = Control.MousePosition;
newPoint.Offset(offSet.X, offSet.Y);
Location = newPoint;
}
}

 

  这个算法也很容易分析,不用多说了(只要注意:在MouseDown中记录的坐标是相对于窗体的坐标,而在MouseMove中是相对于桌面的坐标)。但感觉这种方法的效率不是很高。

  2.重载WndProc方法  

protectedoverridevoid WndProc(ref Message m) 
{
if (m.Msg ==0x0201) { //鼠标左键按下的消息
m.Msg =0x00A1; //更改消息为非客户区按下鼠标
m.LParam = IntPtr.Zero; //默认值
m.WParam =new IntPtr(2); //鼠标放在标题栏内
base.WndProc(ref m);
}
}

感觉这种方法在C#中实现起来是最好的。  

 

MFC

 MFC程序分为对话框程序和文档程序

  对话框:

     在对话框程序里有两种方法都可以:

     1.在对话框中添加对消息WM_LBUTTONDOWN的响应,并添加代码

      

void CTestDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(point.x,point.y));

CDialog::OnLButtonDown(nFlags, point);

 

      2.或者添加对消息WM_NCHITTEST的响应,并添加代码

LRESULT CTestDlg::OnNcHitTest(CPoint point)
{
CRect rc;
GetClientRect(
&rc);
ClientToScreen(
&rc);
return rc.PtInRect(point) ? HTCAPTION : CDialog::OnNcHitTest(point);

//return CDialog::OnNcHitTest(point);
}

 

    MFC文档程序中:      

         在文档程序中就不能用上面的方法了,本人在CView的派生类中尝试了一下上面的代码,发现只能移动客户区,而不能移动整个程序窗口。只能用C#中的那第一种方法了。

              具体的代码为:

              在CView类的派生类中定义一个字段 CPoint offset 用来记录鼠标点击时的坐标

     鼠标左击消息代码为:      

void CtryView::OnLButtonDown(UINT nFlags, CPoint point)
{
//ClientToScreen(&point);
offset =CPoint (-point .x,-point .y);

//这里减65,太硬性了。
offset.y -=65;
CView::OnLButtonDown(nFlags, point);
}

    响应鼠标移动的函数为:

void CtryView::OnMouseMove(UINT nFlags, CPoint point)
{
ClientToScreen(
&point);
if(nFlags &MK_LBUTTON)
{
CPoint newpoint
=point;
newpoint .Offset(offset.x,offset.y);
GetParentFrame()
->SetWindowPos(&wndNoTopMost,newpoint .x,newpoint .y,0,0,SWP_NOSIZE);
}

CView::OnMouseMove(nFlags, point);
}

 

  

上面那个offset.y 要减去非客户区的高度,才能让程序运行得合理。不过这个65太硬性了,如果程序中没有工具栏或者菜单栏就不能用65了。希望哪位朋友给出计算这个高度的方法!!

 

WIN32   

  在WndProc函数中添加对WM_LBUTTONDOWN消息的响应,代码如下
    case WM_LBUTTONDOWN:
        SendMessage(hWnd,WM_SYSCOMMAND,SC_MOVE+HTCAPTION,0);
     break;