如何设置Winform控件的ClientRectangle

       最近学习制作WinForm控件,自己动手写控件的时候才发现System.Windows.Forms.Control 竟然没有提供默认的border绘制。记得以前用API做控件的时候,只需要设置空间窗口的WS_BORDER 风格就可以。遍寻无方,只有自己绘制了,这里有出现一个,如果border在客户区,那么在OnPaint方法里不得不每次都要考虑Border所占用的区域,而且,如果从这个类派生的话,将无法获得准确的客户区。
      现在要解决的问题就是如何重新设置客户区的矩形区域的尺寸,查看了一下Control类的ClientRectangle属性:
public Rectangle ClientRectangle { get; }是个只读属性,看来是不能通过这个属性达到目的了。再查找Control类的文档,也没有这方面的说明,没有办法,只能用API搞定了。可以通过计算非客户区尺寸来设置客户区尺寸,Border在非客户绘制。下面就是主要的代码,就是通过重载WndProc方法,捕捉WM_NCCALCSIZE消息,实现自己的逻辑。
     
None.gif protected   override   void  WndProc( ref  Message m)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
switch (m.Msg)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
case (int)WinAPI_WM.WM_NCCALCSIZE:
InBlock.gif
if (m.WParam.ToInt32() == 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gifWinAPI_RECT rc 
= (WinAPI_RECT)m.GetLParam(typeof(WinAPI_RECT));
InBlock.gifrc.Left 
+= 1;
InBlock.gifrc.Top 
+= 1
InBlock.gifrc.Right 
-= 1
InBlock.gifrc.Bottom 
-= 1;
InBlock.gifMarshal.StructureToPtr(rc, m.LParam, 
true);
InBlock.gifm.Result 
= IntPtr.Zero;
ExpandedSubBlockEnd.gif}

InBlock.gif
else
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gifWinAPI_NCCALCSIZE_PARAMS csp;
InBlock.gifcsp 
= (WinAPI_NCCALCSIZE_PARAMS)m.GetLParam(typeof(WinAPI_NCCALCSIZE_PARAMS));
InBlock.gifcsp.rgrc0.Top 
+= 1
InBlock.gifcsp.rgrc0.Bottom 
-= 1;
InBlock.gifcsp.rgrc0.Left 
+= 1
InBlock.gifcsp.rgrc0.Right 
-= 1;
InBlock.gif
InBlock.gifMarshal.StructureToPtr(csp, m.LParam, 
true);
InBlock.gif
//Return zero to preserve client rectangle
InBlock.gif
m.Result = IntPtr.Zero;
ExpandedSubBlockEnd.gif}

InBlock.gif
break;
InBlock.gif
case (int)WinAPI_WM.WM_NCPAINT:
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gifm.WParam 
= NCPaint(m.WParam);
InBlock.gif
break;
ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
base.WndProc(ref m);
ExpandedBlockEnd.gif}

None.gif
None.gif
public  IntPtr NCPaint(IntPtr region)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gifIntPtr hDC 
= GetWindowDC(this.Handle);
InBlock.gif
if (hDC != IntPtr.Zero)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gifGraphics grTemp 
= Graphics.FromHdc(hDC);
InBlock.gif
InBlock.gif
int ScrollBarWidth = SystemInformation.VerticalScrollBarWidth;
InBlock.gif
int ScrollBarHeight = SystemInformation.HorizontalScrollBarHeight;
InBlock.gif
InBlock.gifWINDOWINFO wi 
= new WINDOWINFO();
InBlock.gifwi.cbSize 
= (uint)Marshal.SizeOf(wi);
InBlock.gif
InBlock.gif
//得到当前控件的窗口信息
InBlock.gif
GetWindowInfo(Handle, ref wi);
InBlock.gif
InBlock.gifwi.rcClient.Right
--;
InBlock.gifwi.rcClient.Bottom
--;
InBlock.gif
InBlock.gif
InBlock.gif
//获得当前控件的区域
InBlock.gif
Region UpdateRegion = new Region(new Rectangle(wi.rcWindow.Top,wi.rcWindow.Left,wi.rcWindow.Right-wi.rcWindow.Left,wi.rcWindow.Bottom-wi.rcWindow.Top));
InBlock.gif
InBlock.gif
//获得客户区以外的区域
InBlock.gif
UpdateRegion.Exclude(new Rectangle(wi.rcClient.Top, wi.rcClient.Left, wi.rcClient.Right - wi.rcClient.Left, wi.rcClient.Bottom - wi.rcClient.Top));
InBlock.gif
InBlock.gif
if (IsHScrollVisible && IsVScrollVisible)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gifUpdateRegion.Exclude(Rectangle.FromLTRB
InBlock.gif(wi.rcClient.Right 
+ 1, wi.rcClient.Bottom + 1,
InBlock.gifwi.rcWindow.Right, wi.rcWindow.Bottom));
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
//得到当前区域的句柄
InBlock.gif
IntPtr hRgn = UpdateRegion.GetHrgn(grTemp);
InBlock.gif
InBlock.gif
//For Painting we need to zero offset the Rectangles.
InBlock.gif
Rectangle WindowRect = new Rectangle(wi.rcWindow.Top, wi.rcWindow.Left, wi.rcWindow.Right - wi.rcWindow.Left, wi.rcWindow.Bottom - wi.rcWindow.Top);
InBlock.gif
InBlock.gifPoint offset 
= Point.Empty - (Size)WindowRect.Location;
InBlock.gif
InBlock.gifWindowRect.Offset(offset);
InBlock.gif
InBlock.gifRectangle ClientRect 
= WindowRect;
InBlock.gif
InBlock.gifClientRect.Inflate(
-1-1);
InBlock.gif
InBlock.gif
//Fill the BorderArea
InBlock.gif
Region PaintRegion = new Region(WindowRect);
InBlock.gifPaintRegion.Exclude(ClientRect);
InBlock.gifgrTemp.FillRegion(SystemBrushes.Control, PaintRegion);
InBlock.gif
InBlock.gif
//Fill the Area between the scrollbars
InBlock.gif
if (IsHScrollVisible && IsVScrollVisible)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gifRectangle ScrollRect 
= new Rectangle(ClientRect.Right - ScrollBarWidth,
InBlock.gifClientRect.Bottom 
- ScrollBarHeight, ScrollBarWidth + 2, ScrollBarHeight + 2);
InBlock.gifScrollRect.Offset(
-1-1);
InBlock.gifgrTemp.FillRectangle(SystemBrushes.Control, ScrollRect);
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
//Adjust ClientRect for Drawing Border.
InBlock.gif
ClientRect.Inflate(22);
InBlock.gifClientRect.Width
--;
InBlock.gifClientRect.Height
--;
InBlock.gif
InBlock.gif
//Draw Outer Raised Border
InBlock.gif
ControlPaint.DrawBorder3D(grTemp, WindowRect, Border3DStyle.Raised,
InBlock.gifBorder3DSide.Bottom 
| Border3DSide.Left | Border3DSide.Right | Border3DSide.Top);
InBlock.gif
InBlock.gif
//Draw Inner Sunken Border
InBlock.gif
ControlPaint.DrawBorder3D(grTemp, ClientRect, Border3DStyle.Sunken,
InBlock.gifBorder3DSide.Bottom 
| Border3DSide.Left | Border3DSide.Right | Border3DSide.Top);
InBlock.gif
InBlock.gifReleaseDC(Handle, hDC);
InBlock.gif
InBlock.gifgrTemp.Dispose();
InBlock.gif
InBlock.gif
return hRgn;
InBlock.gif
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gifRefreshScrollBar();
InBlock.gif
return region;
ExpandedBlockEnd.gif}

None.gif

给初学者的简单例题! private System.ComponentModel.IContainer components; private const int kNumberOfRows = 8; private const int kNumberOfTries = 3; private int NumTotalBricks = 0; private int NumBalls = 0; private Ball TheBall = new Ball(); private Paddle ThePaddle = new Paddle(); private System.Windows.Forms.Timer timer1; private Row[] Rows = new Row[kNumberOfRows]; private Score TheScore = null; private Thread oThread = null; [DllImport("winmm.dll")] public static extern long PlaySound(String lpszName, long hModule, long dwFlags); public Form1() { // // Required for Windows Form Designer support // InitializeComponent(); for (int i = 0; i < kNumberOfRows; i++) { Rows[i] = new Row(i); } ThePaddle.Position.X = 5; ThePaddle.Position.Y = this.ClientRectangle.Bottom - ThePaddle.Height; TheBall.Position.Y = this.ClientRectangle.Bottom - 200; this.SetBounds(this.Left, this.Top, Rows[0].GetBounds().Width, this.Height); TheScore = new Score(ClientRectangle.Right - 50, ClientRectangle.Bottom - 180); // choose Level SpeedDialog dlg = new SpeedDialog(); if (dlg.ShowDialog() == DialogResult.OK) { timer1.Interval = dlg.Speed; } // // TODO: Add any constructor code after InitializeComponent call // } /// /// Clean up any resources being used. /// protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } private string m_strCurrentSoundFile = "BallOut.wav"; public void PlayASound() { if (m_strCurrentSoundFile.Length > 0) { PlaySound(Application.StartupPath + "\\" + m_strCurrentSoundFile, 0, 0); } m_strCurrentSoundFile = ""; oThread.Abort(); } public void PlaySoundInThread(string wavefile) { m_strCurrentSoundFile = wavefile; oThread = new Thread(new ThreadStart(PlayASound)); oThread.Start(); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.timer1 = new System.Windows.Forms.Timer(this.components); // // timer1 // this.timer1.Tick += new System.EventHandler(this.timer1_Tick); // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(552, 389); this.KeyPreview = true; this.Name = "Form1"; this.Text = "Brick Out"; this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown); this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint); } #endregion /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.Run(new Form1()); } private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) { Graphics g = e.Graphics; g.FillRectangle(Brushes.White, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height); TheScore.Draw(g); ThePaddle.Draw(g); DrawRows(g); TheBall.Draw(g); } private void DrawRows(Graphics g) { for (int i = 0; i < kNumberOfRows; i++) { Rows[i].Draw(g); } } private void CheckForCollision() { if (TheBall.Position.X < 0) // hit the left side, switch polarity { TheBall.XStep *= -1; TheBall.Position.X += TheBall.XStep; PlaySoundInThread("WallHit.wav"); } if (TheBall.Position.Y this.ClientRectangle.Right - TheBall.Width ) // hit the left side, switch polarity { TheBall.XStep *= -1; TheBall.Position.X += TheBall.XStep; PlaySoundInThread("WallHit.wav"); } if (TheBall.Position.Y > this.ClientRectangle.Bottom - TheBall.YStep) // lost the ball! { IncrementGameBalls(); Reset(); PlaySoundInThread("BallOut.wav"); } if (RowsCollide(TheBall.Position)) { TheBall.YStep *= -1; PlaySoundInThread("BrickHit.wav"); } int hp = HitsPaddle(TheBall.Position); if (hp > -1)// lost the ball! { PlaySoundInThread("PaddleHit.wav"); switch (hp) { case 1: TheBall.XStep = -7; TheBall.YStep = -3; break; case 2: TheBall.XStep = -5; TheBall.YStep = -5; break; case 3: TheBall.XStep = 5; TheBall.YStep = -5; break; default: TheBall.XStep = 7; TheBall.YStep = -3; break; } } } private int HitsPaddle(Point p) { Rectangle PaddleRect = ThePaddle.GetBounds(); if (p.Y >= this.ClientRectangle.Bottom - (PaddleRect.Height + TheBall.Height) ) { if ((p.X > PaddleRect.Left) && (p.X PaddleRect.Left) && (p.X PaddleRect.Left + PaddleRect.Width/4) && (p.X PaddleRect.Left + PaddleRect.Width/2) && (p.X = kNumberOfTries) { timer1.Stop(); string msg = "Game Over\nYou knocked out " + NumTotalBricks; if (NumTotalBricks == 1) msg += " brick."; else msg += " bricks."; MessageBox.Show(msg); Application.Exit(); } } private void Reset() { TheBall.XStep = 5; TheBall.YStep = 5; TheBall.Position.Y = this.ClientRectangle.Bottom - 190; TheBall.Position.X = 5; timer1.Stop(); TheBall.UpdateBounds(); Invalidate(TheBall.GetBounds()); } private int SumBricks () { int sum = 0; for (int i = 0; i < kNumberOfRows; i++) { sum += Rows[i].BrickOut; } return sum; } private bool RowsCollide (Point p) { for (int i = 0; i < kNumberOfRows; i++) { if (Rows[i].Collides(TheBall.GetBounds())) { Rectangle rRow = Rows[i].GetBounds(); Invalidate(rRow); return true; } } return false; } private void timer1_Tick(object sender, System.EventArgs e) { TheBall.UpdateBounds(); Invalidate(TheBall.GetBounds()); TheBall.Move(); TheBall.UpdateBounds(); Invalidate(TheBall.GetBounds()); CheckForCollision(); NumTotalBricks = SumBricks(); TheScore.Count = NumTotalBricks; Invalidate(TheScore.GetFrame()); if (NumTotalBricks == kNumberOfRows*Row.kNumberOfBricks) { timer1.Stop(); MessageBox.Show("You Win! You knocked out all the bricks!"); Application.Exit(); } } private void Form1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) { string result = e.KeyData.ToString(); Invalidate(ThePaddle.GetBounds()); switch (result) { case "Left": ThePaddle.MoveLeft(); Invalidate(ThePaddle.GetBounds()); if (timer1.Enabled == false) timer1.Start(); break; case "Right": ThePaddle.MoveRight(ClientRectangle.Right); Invalidate(ThePaddle.GetBounds()); if (timer1.Enabled == false) timer1.Start(); break; default: break; } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值