用C#实现在客户区拖动窗体

当你设计一个应用程序时,或许你希望用户能够通过客户区来拖动窗体,比如:当窗体没有标题栏或创建的是不规则的窗体时,就只有通过客户区来拖动窗体了。

一个发生在我们身边很好的例子就是Microsoft Windows Media Player。Media Player有项功能是根据用户的爱好可以随意换掉外观(换肤),这个时候标题栏就隐藏了,但是你能够通过客户区来拖动窗体。

好了,言归正传,开始我们的旅程吧

首先必须了解Windows的消息传递机制,当有鼠标活动消息时,系统发送WM_NCHITTEST 消息给窗体作为判断消息发生地的根据。假如你点击的是标题栏,窗体收到的消息值就是 HTCAPTION ,同样地,若接受到的消息是 HTCLIENT,说明用户点击的是客户区,也就是鼠标消息发生在客户区。

当重载窗体的 WndProc 方法时,可以截获 WM_NCHITTEST 消息并改些该消息,当判断鼠标事件发生在客户区时,改写改消息,发送 HTCAPTION 给窗体,这样,窗体收到的消息就时 HTCAPTION ,在客户区通过鼠标来拖动窗体就如同通过标题栏来拖动一样。

注意:当你重载 WndProc 并改写鼠标事件后,整个窗体的鼠标事件也就随之改变了。

例子:
1.创建一个C#工程文件,默认的窗体时Form1 。

2.在View面板上点击Code.

3.将下面的代码粘贴到Form1类中

private const int WM_NCHITTEST = 0x84;
private const int HTCLIENT = 0x1;
private const int HTCAPTION = 0x2;

4.在Form1中改写鼠标消息

protected override void WndProc(ref Message m)
{
switch(m.Msg)
{
case WM_NCHITTEST:
base.WndProc(ref m);
if ((int)m.Result == HTCLIENT)
m.Result = (IntPtr)HTCAPTION;
return;
break;
}
base.WndProc(ref m);
}

5.保存并运行工程。

6.试试看,点击窗体的任何地方,是不是都可以拖动窗体啊?

时间: 2024-08-24 12:08:04

用C#实现在客户区拖动窗体的相关文章

如何按非客户区移动窗体

看到一介绍如何按非客户区移动窗体,既重载WM_NCHITTEST,返回HTCAPTION.但我认为有一点不妥就是没有了鼠标右键功能.这里我介绍一种方法,即可已在客户区移动窗体又可以实现鼠标右键功能. 1.新建一工程DLG.采用默认设置. 2.添加消息处理函数: void CDlgDlg::OnLButtonDown(UINT nFlags, CPoint point) { PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(point.x,poin

MFC对话框禁止移动 使标题栏不响应鼠标消息 通过客户区移动窗体 OnNcHitTest()的实现

  //这个函数允许我们对 windows鼠标消息进行处理  对于基类函数的返回值  我们可以通过判断消息类型来进行不同的处理 //也就是说 我们可以对鼠标消息做任意处理   比如 是菜单栏上的消息 我们可以返回标题栏的值 //对应的消息类型有如下   查找MSDN此函数的 值有介绍 UINT CMyDlg::OnNcHitTest(CPoint point) {       UINT nFlags= CDialog::OnNcHitTest(point);   //调用基类的OnNcHitTe

修改窗体非客户区大小更改窗体标题栏高度

想修改窗体的非客户区,首先就得明白为什么要修改非客户区,什么是非客户区 从窗体或控件来看,非客户区就是无法放置控件的区域,比如窗体的标题栏,和边框,菜单栏也是非客户区,菜单栏不是控件是画上去的 文本框的边框,滚动条区域都是非客户区 为什么要修改非客户区呢?? 原因是为了自绘,让边框好看一些,比如要加高窗体标题栏,就需要改非客户区,自绘非客户区会响应 WM_NCPAINT消息 在这个消息里,你可以进行窗体,控件,非客户区的自绘 好啦,现在转入正题,要修改非客户大小,必须处理 WM_NCCALCSI

VC 窗体非客户区的绘制

VC 窗体非客户区的绘制 OnNcPaint(UINT message, WPARAM wParam, LPARAM lParam) . void CSkinAndLangDlg::OnNcPaint(UINT message, WPARAM wParam, LPARAM lParam) { HDC WindowDC = ::GetWindowDC(m_hWnd); // //取得整个窗体矩形 RECT WindowRect; GetWindowRect(&WindowRect); Offset

Delphi中把窗体客户区图像保存到文件或剪切板

unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; procedure Button1Click(Sender: TObject); procedu

再谈客户区对话框拖动操作

<无标题对话框的拖动>,示范了如何用鼠标点击窗口或对话框背景(即客户区)进行拖动操作,文章中提供的解决方法在没有上下文菜单的情况下运行很正常,一旦有上下文菜单时,文中所提供的方法便显现出了缺陷--上下文菜单无法显示出来.本文将针对这个问题对前一篇提出的方法进行改进. 当初实现拖动的基本思路是改写 OnNcHitTest 例程,让鼠标在客户区中的点击始终返回 HTCAPTION 而不是 HTCLIENT,从而诱使 Windows 实现拖动操作.没想到这样做使上下文菜单的操作出现了混乱,原因是如果

xp系统下半透明窗体(即A.EXE)放置在(B.EXE)用opengl绘制的客户区中出现闪烁

问题描述 xp系统下半透明窗体(即A.EXE)放置在(B.EXE)用opengl绘制的客户区中出现闪烁 请问在xp系统下,用c++实现的半透明窗体(即A.EXE)放置在(B.EXE)用opengl绘制的客户区中,为什么会出现闪烁的问题?是什么原因?有没有解决的办法 解决方案 opengl是直接写屏的,所以有冲突,除非关掉显卡的视频加速.

VS2010 VB.net Splitter 在拖动的时候会在客户区留下一条竖线,是条阴影坚线

问题描述 问题如题目,拖动时会留下一条坚的阴影线. 解决方案 解决方案二:拖动完留下的还是拖动的时候有?解决方案三:有阴影不是挺好的?难不成你想搞成透明的解决方案四:拖动过后留下的,想去掉这条线,各位前辈有什么好的办法?解决方案五:没有人能回答这个问题吗?解决方案六:应该是客户区重绘的问题

VC 窗体非客户区的绘制 OnNcPaint(UINT message, WPARAM wParam, LPARAM lParam)

void CSkinAndLangDlg::OnNcPaint(UINT message, WPARAM wParam, LPARAM lParam) { HDC WindowDC = ::GetWindowDC(m_hWnd); // //取得整个窗体矩形 RECT WindowRect; GetWindowRect(&WindowRect); OffsetRect(&WindowRect, -WindowRect.left, - WindowRect.top); // //取得客户区矩