求助:如何用代码实现窗体拖动或者改变大小时出现虚线边框,顺便散分

sfnt 2007-08-03 10:28:13
小弟我手头在做的一个2.0的项目,
把Form重画了,做了个自己的皮肤。
但是发现.Net重绘窗体的效率太低,拖动或者改变窗体大小时会有非常厉害的延迟,拖动的时候非常恐怖。
开了双缓冲也没有好转。
所以我想回避拖动和改变大小时整个窗体重绘的问题,改用MouseDown时出现窗体的虚框,调整好后MouseUp时需框消失并且按照虚框的大小和位置设置窗体大小位置。
但是我不知道怎么实现这个功能。

思路有,但是不知道怎么将边框延伸到窗体以外的部分。
还有调整大小和移动……
混乱ing

或者大家推荐下好的解决重绘的问题的方法?

小弟拜谢啦~
顺便散散分,聚聚人气,呵呵。
...全文
807 26 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
wsczhuliang 2011-04-26
  • 打赏
  • 举报
回复
[DllImport("user32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(int hWnd, int wMsg, int wParam, int lParam);
[DllImport("user32.dll", EntryPoint = "ReleaseCapture")]
public static extern int ReleaseCapture();
public const int WM_SysCommand = 0x0112;
public const int SC_MOVE = 0xF012;
private void Frm_Irrgular_MouseDown(object sender, MouseEventArgs e)
{
ReleaseCapture();
SendMessage(this.Handle.ToInt32(), WM_SysCommand, SC_MOVE, 0);
}

Frm_Irrgular 为窗体名称、 就这样就可以实现无标题 窗体的移动 以及虚框的出现==
wsczhuliang 2011-04-26
  • 打赏
  • 举报
回复
汗、 我也做了这种窗体、、

拖动倒是可以拖动了、、

但是拖动时 抖动的厉害、

所以我只想只让原窗体定义一次、、

但是虚框不知道怎么画、、

private int oldX, oldY;
private void Frm_Irrgular_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
oldX = e.Location.X;
oldY = e.Location.Y;
}
}

private void Frm_Irrgular_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
int x = e.Location.X;
int y = e.Location.Y;

//获取移动的 长宽
int dx = x - oldX;
int dy = y - oldY;

//把新的位置重新赋值给虚框
//虚框.Location = new Point(this.Width += dx, this.Height += dy);

oldX = x;
oldY = y;
}
}

private void Frm_Irrgular_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
int x = e.Location.X;
int y = e.Location.Y;

int dx = x - oldX;
int dy = y - oldY;

this.Left += dx;
this.Top += dy;

oldX = x;
oldY = y;
}
}
ooo0000ooooo 2009-12-23
  • 打赏
  • 举报
回复
帮顶
fht123 2007-08-08
  • 打赏
  • 举报
回复
帮顶一下
xwk789xwk 2007-08-08
  • 打赏
  • 举报
回复
帮顶一下
通者归来 2007-08-08
  • 打赏
  • 举报
回复
用GDI+自己画虚框吧!
nacarat 2007-08-08
  • 打赏
  • 举报
回复
接分
sfnt 2007-08-08
  • 打赏
  • 举报
回复
恩,好的,我一个个试试
等下再来
lovingkiss 2007-08-08
  • 打赏
  • 举报
回复
hbxtlhx——提供的代码肯定能做到,但是肯定会卡到你郁闷~~~
尤其是液晶显示器,呵呵~~

==================================================================
博客空间:http://blog.csdn.net/lovingkiss
资源下载:http://download.csdn.net/user/lovingkiss
优惠接单开发,组件控件定制开发,成品源代码批发
联系方式:Q64180940 全天在线
==================================================================
北京的雾霾天 2007-08-08
  • 打赏
  • 举报
回复
比如如下的代码使用鼠标绘制拖动的框框:
public partial class Form1 : Form
{
private Point m_StartPoint;
private Point m_LastPoint;
public Form1()
{
InitializeComponent();
}

protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
this.m_StartPoint = e.Location;
m_LastPoint = this.m_StartPoint;
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
Point endPoint = e.Location;
int l = m_LastPoint.X > this.m_StartPoint.X ? this.m_StartPoint.X : m_LastPoint.X;
int t = m_LastPoint.Y > this.m_StartPoint.Y ? this.m_StartPoint.Y : m_LastPoint.Y;
int r = m_LastPoint.X > this.m_StartPoint.X ? m_LastPoint.X : this.m_StartPoint.X;
int b = m_LastPoint.Y > this.m_StartPoint.Y ? m_LastPoint.Y : this.m_StartPoint.Y;

Rectangle rect = Rectangle.FromLTRB(l, t, r, b);
ControlPaint.DrawReversibleFrame(this.RectangleToScreen(rect), SystemColors.Highlight, FrameStyle.Dashed);
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (e.Button == MouseButtons.Left)
{
Point endPoint = e.Location;
int l = m_LastPoint.X > this.m_StartPoint.X ? this.m_StartPoint.X : m_LastPoint.X;
int t = m_LastPoint.Y > this.m_StartPoint.Y ? this.m_StartPoint.Y : m_LastPoint.Y;
int r = m_LastPoint.X > this.m_StartPoint.X ? m_LastPoint.X : this.m_StartPoint.X;
int b = m_LastPoint.Y > this.m_StartPoint.Y ? m_LastPoint.Y : this.m_StartPoint.Y;

Rectangle rect = Rectangle.FromLTRB(l, t, r, b);
ControlPaint.DrawReversibleFrame(this.RectangleToScreen(rect), SystemColors.Highlight, FrameStyle.Dashed);

int _l = endPoint.X > this.m_StartPoint.X ? this.m_StartPoint.X : endPoint.X;
int _t = endPoint.Y > this.m_StartPoint.Y ? this.m_StartPoint.Y : endPoint.Y;
int _r = endPoint.X > this.m_StartPoint.X ? endPoint.X : this.m_StartPoint.X;
int _b = endPoint.Y > this.m_StartPoint.Y ? endPoint.Y : this.m_StartPoint.Y;

Rectangle _rect = Rectangle.FromLTRB(_l, _t, _r, _b);
ControlPaint.DrawReversibleFrame(this.RectangleToScreen(_rect), SystemColors.Highlight, FrameStyle.Dashed);
m_LastPoint = endPoint;
}
}
}
lovingkiss 2007-08-08
  • 打赏
  • 举报
回复
方法已经给你,是否能够正常使用。如果还不行,就联系我的QQ

==================================================================
博客空间:http://blog.csdn.net/lovingkiss
资源下载:http://download.csdn.net/user/lovingkiss
优惠接单开发,组件控件定制开发,成品源代码批发
联系方式:Q64180940 全天在线
==================================================================
北京的雾霾天 2007-08-08
  • 打赏
  • 举报
回复
使用如下的方法在屏上绘制虚框:

ControlPaint.DrawReversibleFrame
amandag 2007-08-08
  • 打赏
  • 举报
回复
only jf
lovingkiss 2007-08-08
  • 打赏
  • 举报
回复
WM_NULL = $0000;
  WM_CREATE = $0001;
  应用程序创建一个窗口
  WM_DESTROY = $0002;
  一个窗口被销毁
  WM_MOVE = $0003;
  移动一个窗口
  WM_SIZE = $0005;
  改变一个窗口的大小
  WM_ACTIVATE = $0006;
  一个窗口被激活或失去激活状态;
  WM_SETFOCUS = $0007;
  获得焦点后
  WM_KILLFOCUS = $0008;
  失去焦点
  WM_ENABLE = $000A;
  改变enable状态
  WM_SETREDRAW = $000B;
  设置窗口是否能重画
  WM_SETTEXT = $000C;
  应用程序发送此消息来设置一个窗口的文本
  WM_GETTEXT = $000D;
  应用程序发送此消息来复制对应窗口的文本到缓冲区
  WM_GETTEXTLENGTH = $000E;
  得到与一个窗口有关的文本的长度(不包含空字符)
  WM_PAINT = $000F;
  要求一个窗口重画自己
  WM_CLOSE = $0010;
  当一个窗口或应用程序要关闭时发送一个信号
  WM_QUERYENDSESSION = $0011;
  当用户选择结束对话框或程序自己调用ExitWindows函数
  WM_QUIT = $0012;
  用来结束程序运行或当程序调用postquitmessage函数
  WM_QUERYOPEN = $0013;
  当用户窗口恢复以前的大小位置时,把此消息发送给某个图标
  WM_ERASEBKGND = $0014;
  当窗口背景必须被擦除时(例在窗口改变大小时)
  WM_SYSCOLORCHANGE = $0015;
  当系统颜色改变时,发送此消息给所有顶级窗口
  WM_ENDSESSION = $0016;
  当系统进程发出WM_QUERYENDSESSION消息后,此消息发送给应用程序,
  通知它对话是否结束
  WM_SYSTEMERROR = $0017;
  WM_SHOWWINDOW = $0018;
  当隐藏或显示窗口是发送此消息给这个窗口
  WM_ACTIVATEAPP = $001C;
  发此消息给应用程序哪个窗口是激活的,哪个是非激活的;
  WM_FONTCHANGE = $001D;
  当系统的字体资源库变化时发送此消息给所有顶级窗口
  WM_TIMECHANGE = $001E;
  当系统的时间变化时发送此消息给所有顶级窗口
  WM_CANCELMODE = $001F;
  发送此消息来取消某种正在进行的摸态(操作)
  WM_SETCURSOR = $0020;
  如果鼠标引起光标在某个窗口中移动且鼠标输入没有被捕获时,就发消息给某个窗口
  WM_MOUSEACTIVATE = $0021;
  当光标在某个非激活的窗口中而用户正按着鼠标的某个键发送此消息给当前窗口
  WM_CHILDACTIVATE = $0022;
  发送此消息给MDI子窗口当用户点击此窗口的标题栏,或当窗口被激活,移动,改变大小
  WM_QUEUESYNC = $0023;
  此消息由基于计算机的训练程序发送,通过WH_JOURNALPALYBACK的hook程序
  分离出用户输入消息
  WM_GETMINMAXINFO = $0024;
  此消息发送给窗口当它将要改变大小或位置;
  WM_PAINTICON = $0026;
  发送给最小化窗口当它图标将要被重画
  WM_ICONERASEBKGND = $0027;
  此消息发送给某个最小化窗口,仅当它在画图标前它的背景必须被重画
  WM_NEXTDLGCTL = $0028;
  发送此消息给一个对话框程序去更改焦点位置
  WM_SPOOLERSTATUS = $002A;
  每当打印管理列队增加或减少一条作业时发出此消息  
  WM_DRAWITEM = $002B;
  当button,combobox,listbox,menu的可视外观改变时发送
  此消息给这些空件的所有者
  WM_MEASUREITEM = $002C;
  当button, combo box, list box, list view control, or menu item 被创建时
  发送此消息给控件的所有者
  WM_DELETEITEM = $002D;
  当the list box 或 combo box 被销毁 或 当 某些项被删除通过LB_DELETESTRING, LB_RESETCONTENT, CB_DELETESTRING, or CB_RESETCONTENT 消息
  WM_VKEYTOITEM = $002E;
  此消息有一个LBS_WANTKEYBOARDINPUT风格的发出给它的所有者来响应WM_KEYDOWN消息
  WM_CHARTOITEM = $002F;
  此消息由一个LBS_WANTKEYBOARDINPUT风格的列表框发送给他的所有者来响应WM_CHAR消息
  WM_SETFONT = $0030;
  当绘制文本时程序发送此消息得到控件要用的颜色
  WM_GETFONT = $0031;
  应用程序发送此消息得到当前控件绘制文本的字体
  WM_SETHOTKEY = $0032;
  应用程序发送此消息让一个窗口与一个热键相关连
  WM_GETHOTKEY = $0033;
  应用程序发送此消息来判断热键与某个窗口是否有关联
  WM_QUERYDRAGICON = $0037;
  此消息发送给最小化窗口,当此窗口将要被拖放而它的类中没有定义图标,应用程序能返回一个图标或光标的句柄,当用户拖放图标时系统显示这个图标或光标
  WM_COMPAREITEM = $0039;
  发送此消息来判定combobox或listbox新增加的项的相对位置
  WM_GETOBJECT = $003D;
  WM_COMPACTING = $0041;
  显示内存已经很少了
  WM_WINDOWPOSCHANGING = $0046;
  发送此消息给那个窗口的大小和位置将要被改变时,来调用setwindowpos函数或其它窗口管理函数
  WM_WINDOWPOSCHANGED = $0047;
  发送此消息给那个窗口的大小和位置已经被改变时,来调用setwindowpos函数或其它窗口管理函数
  WM_POWER = $0048;(适用于16位的windows)
  当系统将要进入暂停状态时发送此消息
  WM_COPYDATA = $004A;
  当一个应用程序传递数据给另一个应用程序时发送此消息
  WM_CANCELJOURNAL = $004B;
  当某个用户取消程序日志激活状态,提交此消息给程序
  WM_NOTIFY = $004E;
  当某个控件的某个事件已经发生或这个控件需要得到一些信息时,发送此消息给它的父窗口
  WM_INPUTLANGCHANGEREQUEST = $0050;
  当用户选择某种输入语言,或输入语言的热键改变
  WM_INPUTLANGCHANGE = $0051;
  当平台现场已经被改变后发送此消息给受影响的最顶级窗口
  WM_TCARD = $0052;
  当程序已经初始化windows帮助例程时发送此消息给应用程序
  WM_HELP = $0053;
  此消息显示用户按下了F1,如果某个菜单是激活的,就发送此消息个此窗口关联的菜单,否则就
  发送给有焦点的窗口,如果当前都没有焦点,就把此消息发送给当前激活的窗口
  WM_USERCHANGED = $0054;
  当用户已经登入或退出后发送此消息给所有的窗口,当用户登入或退出时系统更新用户的具体
  设置信息,在用户更新设置时系统马上发送此消息;
  WM_NOTIFYFORMAT = $0055;
  公用控件,自定义控件和他们的父窗口通过此消息来判断控件是使用ANSI还是UNICODE结构
  在WM_NOTIFY消息,使用此控件能使某个控件与它的父控件之间进行相互通信
  WM_CONTEXTMENU = $007B;
  当用户某个窗口中点击了一下右键就发送此消息给这个窗口
  WM_STYLECHANGING = $007C;
  当调用SETWINDOWLONG函数将要改变一个或多个 窗口的风格时发送此消息给那个窗口
  WM_STYLECHANGED = $007D;
  当调用SETWINDOWLONG函数一个或多个 窗口的风格后发送此消息给那个窗口
  WM_DISPLAYCHANGE = $007E;
  当显示器的分辨率改变后发送此消息给所有的窗口
  WM_GETICON = $007F;
  此消息发送给某个窗口来返回与某个窗口有关连的大图标或小图标的句柄;
  WM_SETICON = $0080;
  程序发送此消息让一个新的大图标或小图标与某个窗口关联;
  WM_NCCREATE = $0081;
  当某个窗口第一次被创建时,此消息在WM_CREATE消息发送前发送;
  WM_NCDESTROY = $0082;
  此消息通知某个窗口,非客户区正在销毁
  WM_NCCALCSIZE = $0083;
  当某个窗口的客户区域必须被核算时发送此消息
  WM_NCHITTEST = $0084;//移动鼠标,按住或释放鼠标时发生
  WM_NCPAINT = $0085;
  程序发送此消息给某个窗口当它(窗口)的框架必须被绘制时;
  WM_NCACTIVATE = $0086;
  此消息发送给某个窗口 仅当它的非客户区需要被改变来显示是激活还是非激活状态;
  WM_GETDLGCODE = $0087;
  发送此消息给某个与对话框程序关联的控件,widdows控制

lovingkiss 2007-08-08
  • 打赏
  • 举报
回复
呵呵,你用其他的方式都会很卡的,自定义窗体用消息接受就可以了,直接让他可以调整大小就是了。

这段代码是拖动无边框窗体的,调整大小也是类似的操作,和拖动区别就在于消息值不同罢了——C#我写不大好,你可以自己修改一下
private IntPtr HTCAPTION = (IntPtr)2;
private IntPtr HTCLIENT = (IntPtr)1;
private int WM_NCHITTEST = 132;

protected override void WndProc(ref Message m)
{
//ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.chs/CPref17/html/M_System_Windows_Forms_Control_WndProc_1_89703afe.htm#codeExampleToggle
//拖动无边框窗体
if ((m.Msg == WM_NCHITTEST))
{
base.WndProc(m);
if ((m.Result == HTCLIENT))
{
m.Result = HTCAPTION;
}
}
else
{
if ((m.Msg == 163))
{
}
//屏蔽最大化!
else
{
base.WndProc(m);
}
}
}

==================================================================
博客空间:http://blog.csdn.net/lovingkiss
资源下载:http://download.csdn.net/user/lovingkiss
优惠接单开发,组件控件定制开发,成品源代码批发
联系方式:Q64180940 全天在线
==================================================================
lovingkiss 2007-08-08
  • 打赏
  • 举报
回复
Private HTCAPTION As IntPtr = CType(2, IntPtr)
Private HTCLIENT As IntPtr = CType(1, IntPtr)
Private WM_NCHITTEST As Integer = 132

Protected Overrides Sub WndProc(ByRef m As Message)
'ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.chs/CPref17/html/M_System_Windows_Forms_Control_WndProc_1_89703afe.htm#codeExampleToggle
'拖动无边框窗体
If (m.Msg = WM_NCHITTEST) Then
MyBase.WndProc(m)
If (m.Result = HTCLIENT) Then
m.Result = HTCAPTION
End If
Else
If (m.Msg = 163) Then
'屏蔽最大化!
Else
MyBase.WndProc(m)
End If
End If
End Sub
sfnt 2007-08-08
  • 打赏
  • 举报
回复
是啊
在上面作了比较多事情。
空窗体跑起来很好
但是东西多了后一拖动就很卡。
所以想那样弄下

楼上的,系统中设置没有用的,除了我这个窗体其他的都是那种样子移动……
yaoshuwen()
你说的伪造的是怎么回事?
能不能具体讲下?

我用的方法是
this.Left += moveLeft;
this.Top += moveTop;
这种方法实在不好,还有别的没?
包括窗体的Resize,我也是用类似的方法的。
太慢了……

有没有什么别的有效的调整窗体的方法?
yucong 2007-08-07
  • 打赏
  • 举报
回复
直接在系统中设置一下不就可以了
yaoshuwen 2007-08-07
  • 打赏
  • 举报
回复
还有,我自定义窗体调整大小怎么没有像你说的那样恐怖?你是不是上面干太多事了?
yaoshuwen 2007-08-07
  • 打赏
  • 举报
回复
你所说的窗体其实是伪造的,边框才是重新绘制的窗体。
加载更多回复(6)

111,107

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧