[C#.NET 4.0]如何防止調整大小(C#)時無邊界Windows窗體閃爍?
我學習C#,我試圖建立有FormBorderStyle = FormBorderStyle.None
和可移動/使用Windows API調整Windows窗體中使用C#。舉個例子,我使用圓角或用於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)......不是我」米先進到足以理解這篇文章中的所有內容。
與該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覆蓋方法:
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 2013-05-09 18:00:25
您是否有圖像作爲表單的背景?或者可能是Paint()事件中的一些更復雜的繪畫? – 2013-05-09 18:25:39
不,表單中的所有內容都是在代碼中創建的(除了枚舉類以外,我的所有代碼都列在了我的文章中)。這只是一個矩形區域,覆蓋無邊界形式來創建圓角(據我瞭解)。當然,還有自定義SizeGrip的附加矩形。我認爲創建圓角的矩形是導致問題的原因,因爲當我完全刪除該CreateRoundRectRgn代碼時,它看起來不會閃爍(或閃爍幾乎不如壞)。但圓角對我來說是一個重要的視覺實現。 – user2063351 2013-05-09 19:03:57