通过 WndProc 调整 ClientRectangle

Set ClientRectangle in custom form in C#

只是转载 原贴地址

原提问

In C# I have custom form of None border style which override onPaint event and draw custom background with transparency key. I want to set my own client rectangle value (so content would be placed inside my custom border), but unfortunally Form’s ClientRectangle property is read-only. I found advice over net to override WndProc method (where it sets client size) but saddly, I found very little info about that. Especially it requires to fill data which are pointed by lParam and wParam and I really don’t know how to do this in C#.

原回答

Your question has a couple of things that concern me… first you want draw your own border and then adjust the client rectangle. This really isn’t possible as the client rectangle is determined when the window moves. Once determined a completely different paint message is responsible for drawing all non-client content. Thus you can do what you suggest; however, it will break your current border painting.

It would be FAR eaiser to move all your controls from your form into a new Panel control and place it on the form. Now you can position this panel as if you where adjusting the client area.

If you must proceed with your original thought to modify the window client area you would do the following:

Visual C# Code

private void AdjustClientRect(ref RECT rcClient)
{
    rcClient.Left += 10;
    rcClient.Top += 10;
    rcClient.Right -= 10;
    rcClient.Bottom -= 10;
}

struct RECT { public int Left, Top, Right, Bottom; }
struct NCCALCSIZE_PARAMS
{
    public RECT rcNewWindow;
    public RECT rcOldWindow;
    public RECT rcClient;
    IntPtr lppos;
}

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);
     const int WM_NCCALCSIZE = 0x0083;
    if (m.Msg == WM_NCCALCSIZE)
    {
        if (m.WParam != IntPtr.Zero)
        {
            NCCALCSIZE_PARAMS rcsize = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
            AdjustClientRect(ref rcsize.rcNewWindow);
            Marshal.StructureToPtr(rcsize, m.LParam, false);
        }
        else
        {
            RECT rcsize = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
            AdjustClientRect(ref rcsize);
            Marshal.StructureToPtr(rcsize, m.LParam, false);
        }
        m.Result = new IntPtr(1);
        return;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给初学者的简单例题! 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、付费专栏及课程。

余额充值