我的目标是在用户通过鼠标移动时防止部分或全部隐藏。 例如,如果我的桌面分辨率为1024x768,则表格位置属性的坐标的最小值/最大值为“x / y”:0,1024 - form.width,0,768 - form.height。
我使用一些原生APi完成所有这些并且一切正常,但我经常注意到我的表单刷新(闪烁)(我正在管理form_move事件)。
似乎SuspendLayout
方法不能正常工作,否则表单移动事件不会触发每个像素更改,但可能不止一个(请参阅下面的代码以实现我的意思)。
我的代码如下所示:
private void Form1_Move(object sender, EventArgs e)
{
this.SuspendLayout();
// Desktop Resolution (API utility)
int x = Desktop.GetXResolution();
int y = Desktop.GetYResolution();
// Taskbar Info (API utility)
Taskbar tb = new Taskbar();
int minX = 0;
int maxX = x - this.Width;
int minY = 0;
int maxY = y - this.Height;
if (!tb.AutoHide)
{
if (tb.Position != TaskbarPosition.Unknown && !tb.Size.IsEmpty)
{
if (tb.Position == TaskbarPosition.Top) minY += tb.Size.Height;
switch (tb.Position)
{
case TaskbarPosition.Top: minY = tb.Size.Height; break;
case TaskbarPosition.Bottom: maxY -= tb.Size.Height; break;
case TaskbarPosition.Left: minX = tb.Size.Width; break;
case TaskbarPosition.Right: maxX -= tb.Size.Width; break;
}
}
}
// Restore X Position
if (this.Location.X < minX) this.Location = new Point(minX, this.Location.Y);
if (this.Location.X > maxX) this.Location = new Point(maxX, this.Location.Y);
// Restore Y Poistion
if (this.Location.Y < minY) this.Location = new Point(this.Location.X, minY);
if (this.Location.Y > maxY) this.Location = new Point(this.Location.X, maxY);
this.ResumeLayout(false);
}
正如我已经说过的,通常当我恢复位置属性时,我的winForm会闪烁。
任何建议都将受到赞赏。
答案 0 :(得分:2)
Move
。表单已移动,然后您将其移回。无论如何它会闪烁。
相反,请防止它首先移动:
private const int WM_MOVING = 0x216;
private void WriteTheRect(IntPtr dest, Rectangle rect) {
System.Runtime.InteropServices.Marshal.WriteInt32(dest, 0, rect.Left);
System.Runtime.InteropServices.Marshal.WriteInt32(dest, 4, rect.Top);
System.Runtime.InteropServices.Marshal.WriteInt32(dest, 8, rect.Right);
System.Runtime.InteropServices.Marshal.WriteInt32(dest, 12, rect.Bottom);
}
protected override void WndProc(ref Message m) {
if (m.Msg == WM_MOVING)
{
// RECT structure pointed to by lParam: left, top, right, bottom
Rectangle r = Rectangle.FromLTRB(System.Runtime.InteropServices.Marshal.ReadInt32(m.LParam, 0),
System.Runtime.InteropServices.Marshal.ReadInt32(m.LParam, 4),
System.Runtime.InteropServices.Marshal.ReadInt32(m.LParam, 8),
System.Runtime.InteropServices.Marshal.ReadInt32(m.LParam, 12)
);
Rectangle allowed = Rectangle.FromLTRB(0, 0, 1600, 900);
if (r.Left <= allowed.Left || r.Top <= allowed.Top || r.Right >= allowed.Right || r.Bottom >= allowed.Bottom)
{
int offset_x = r.Left < allowed.Left ? (allowed.Left - r.Left) : (r.Right > allowed.Right ? (allowed.Right - r.Right) : (0));
int offset_y = r.Top < allowed.Top ? (allowed.Top - r.Top) : (r.Bottom > allowed.Bottom ? (allowed.Bottom - r.Bottom) : (0));
r.Offset(offset_x, offset_y);
WriteTheRect(m.LParam, r);
}
}
base.WndProc(ref m);
}
显然,用你想要的实际边界替换常量。