[C# .NET 4.0]Как предотвратить мерцание формы без полей при изменении размера (C#)?
Я изучаю C#, и я пытаюсь построить Windows Form с помощью C#, который имеет FormBorderStyle = FormBorderStyle.None
и может быть перемещен/изменении размера с помощью API Windows. В качестве примера я использую округленные угловые или пользовательские (перемещаемые/изменяемые размеры) схемы границ, используемые для Google Chrome и Norton 360 в качестве основы для моей формы.
Я до сих пор добился большого прогресса и получил все, чтобы работать, кроме , когда я изменяю размер формы, на длине правой и нижней границы мерцает черное/белое изображение при изменении размера формы быстро.
Я попытался добавить this.DoubleBuffer = true
в конструктор, а также попробовал this.SetStyles(ControlStyles.AllPaintInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true);
.
Поскольку я являюсь присосками для графической стороны вещей, мне нравится управлять полным дизайном формы, поэтому я вижу, что это то, что навсегда беспокоит меня ... , так что если кто-то может помочь я разрешаю это, поэтому мерцание больше не происходит, это было бы невероятно полезно для моего учебного процесса.
Я должен также упомянуть, что я использую Windows XP, так что я не уверен, что this post мне поможет, так как это, кажется, сосредоточены на Vista/7 (с DWM) ... не то, что я» m достаточно продвинулся, чтобы понять все в этом посте.
Ниже приведены две части кода, которые работают с API. У меня есть публичное перечисление для WM_NCHITTEST для Windows API ... вы можете увидеть значения in this link.
OnPaint Перекрыть метод:
protected override void OnPaint(PaintEventArgs e)
{
System.IntPtr ptrBorder = CreateRoundRectRgn(0, 0,
this.ClientSize.Width, this.ClientSize.Height, 15, 15);
SetWindowRgn(this.Handle, ptrBorder, true);
Rectangle rc = new Rectangle(this.ClientSize.Width - cGrip,
this.ClientSize.Height - cGrip, cGrip, cGrip);
ControlPaint.DrawSizeGrip(e.Graphics, this.BackColor, rc);
rc = new Rectangle(0, 0, this.ClientSize.Width, 32);
e.Graphics.FillRectangle(Brushes.SlateGray, rc);
}
WNDPROC Override Метод:
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)HitTest.WM_NCHITTEST)
{
// Trap WM_NCHITTEST
Point pos = new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16);
pos = this.PointToClient(pos);
if (pos.Y < cCaption)
{
m.Result = (IntPtr)HitTest.HTCAPTION;
return;
}
if (pos.X <= cGrip && pos.Y >= this.ClientSize.Height - cGrip)
{
m.Result = (IntPtr)HitTest.HTBOTTOMLEFT;
return;
}
if (pos.X >= this.ClientSize.Width - cGrip &&
pos.Y >= this.ClientSize.Height - cGrip)
{
m.Result = (IntPtr)HitTest.HTBOTTOMRIGHT;
return;
}
if (pos.X >= this.ClientSize.Width - cBorder)
{
m.Result = (IntPtr)HitTest.HTRIGHT;
return;
}
if (pos.Y >= this.ClientSize.Height - cBorder)
{
m.Result = (IntPtr)HitTest.HTBOTTOM;
return;
}
if (pos.X <= cBorder)
{
m.Result = (IntPtr)HitTest.HTLEFT;
return;
}
}
base.WndProc(ref m);
}
А вот полный код:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace PracticeForm
{
public partial class Form2 : Form
{
[DllImport("user32.dll")]
private static extern int SetWindowRgn(IntPtr hWnd, IntPtr hRgn, bool bRedraw);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateRoundRectRgn(int x1, int y1, int x2, int y2, int cx, int cy);
[DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
private static extern bool DeleteObject(System.IntPtr hObject);
private const int cGrip = 20;
private const int cCaption = 35;
private const int cBorder = 7;
private Point mouseOffset;
public Form2()
{
InitializeComponent();
this.FormBorderStyle = FormBorderStyle.None;
this.MaximumSize = new Size(670, 440);
this.DoubleBuffered = true;
this.SetStyle(ControlStyles.ResizeRedraw |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e)
{
System.IntPtr ptrBorder = CreateRoundRectRgn(0, 0,
this.ClientSize.Width, this.ClientSize.Height, 15, 15);
SetWindowRgn(this.Handle, ptrBorder, true);
Rectangle rc = new Rectangle(this.ClientSize.Width - cGrip,
this.ClientSize.Height - cGrip, cGrip, cGrip);
ControlPaint.DrawSizeGrip(e.Graphics, this.BackColor, rc);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)HitTest.WM_NCHITTEST)
{
// Trap WM_NCHITTEST
Point pos = new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16);
pos = this.PointToClient(pos);
if (pos.Y < cCaption)
{
m.Result = (IntPtr)HitTest.HTCAPTION;
return;
}
if (pos.X <= cGrip && pos.Y >= this.ClientSize.Height - cGrip)
{
m.Result = (IntPtr)HitTest.HTBOTTOMLEFT;
return;
}
if (pos.X >= this.ClientSize.Width - cGrip &&
pos.Y >= this.ClientSize.Height - cGrip)
{
m.Result = (IntPtr)HitTest.HTBOTTOMRIGHT;
return;
}
if (pos.X >= this.ClientSize.Width - cBorder)
{
m.Result = (IntPtr)HitTest.HTRIGHT;
return;
}
if (pos.Y >= this.ClientSize.Height - cBorder)
{
m.Result = (IntPtr)HitTest.HTBOTTOM;
return;
}
if (pos.X <= cBorder)
{
m.Result = (IntPtr)HitTest.HTLEFT;
return;
}
}
base.WndProc(ref m);
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
private void button2_MouseClick(object sender, MouseEventArgs e)
{
this.WindowState = FormWindowState.Minimized;
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
mouseOffset = new Point(-e.X, -e.Y);
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Point p = Control.MousePosition;
p.Offset(mouseOffset.X, mouseOffset.Y);
Location = p;
}
}
private void label1_MouseDown(object sender, MouseEventArgs e)
{
mouseOffset = new Point(-e.X, -e.Y);
}
private void label1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Point p = Control.MousePosition;
p.Offset(mouseOffset.X, mouseOffset.Y);
Location = p;
}
}
}
}
Спасибо за помощь.
Возможно, это немного улучшилось, но оно все еще мерцает очень плохо. Кроме того, по какой-то причине ваш код, по-видимому, переопределил начальную позицию форм (CenterScreen). – user2063351
У вас есть изображение в качестве фона формы? ... или, возможно, более сложная картина происходит в событии Paint()? –
Нет, все в форме создается в коде (и весь мой код, кроме класса перечисления, указан в моем сообщении). Это прямоугольная область, которая накладывает форму без полей, чтобы создать закругленные углы (как я понимаю). И, конечно, есть дополнительный прямоугольник для настраиваемого SizeGrip. Я думаю, что прямоугольник, создающий закругленные углы, вызывает проблемы, потому что он, кажется, не мерцает (или мерцает почти так же плохо), когда я вообще удаляю этот код CreateRoundRectRgn. Но закругленные углы - важная визуальная реализация для меня. – user2063351