簡體   English   中英

C#WinForms-以編程方式創建的窗體的自定義邊框僅顯示左邊框和上邊框

[英]C# WinForms - Custom borders of a programmatically created form only shows left and top border

嘗試學習編程並進行一些實驗。 遇到了一個我無法找到解決方案的小問題。 我有一個以編程方式創建的按鈕和一個以編程方式創建新表單的click事件。 表單具有一些創建的標簽以及自定義邊框。 在主窗體上使用相同的自定義邊框,即使在自動調整大小並動態更改內容大小的情況下,也可以使用該邊框。 但是在以編程方式創建的表單上,邊框僅顯示在左側和頂部,而我一直無法通過實驗找到答案或解決問題。

不知道多少代碼就足夠了,但是我制作了一個簡化的程序來顯示問題。 從我的程序代碼中簡化了該代碼,該程序使用數百個以編程方式創建的按鈕和幾條信息數組,這些信息填充了myForm表單上使用的標簽,因此自從我刪除了數組和按鈕創建過程以來,有些事情似乎很奇怪。

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace StackoverflowSample
{
public partial class Form1 : Form
{
    private Button myButton;

    /// <summary>
    /// Borrowed code snippet for custom border: http://stackoverflow.com/q/5092216. Would have preferred no to do dllimport yet, but will let it pass this time.
    /// </summary>
    /// <param name="nLeftRect"></param>
    /// <param name="nTopRect"></param>
    /// <param name="nRightRect"></param>
    /// <param name="nBottomRect"></param>
    /// <param name="nWidthEllipse"></param>
    /// <param name="nHeightEllipse"></param>
    /// <returns></returns>
    [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
    private static extern IntPtr CreateRoundRectRgn
    (
        int nLeftRect, // x-coordinate of upper-left corner
        int nTopRect, // y-coordinate of upper-left corner
        int nRightRect, // x-coordinate of lower-right corner
        int nBottomRect, // y-coordinate of lower-right corner
        int nWidthEllipse, // height of ellipse
        int nHeightEllipse // width of ellipse
     );

    public Form1()
    {
        InitializeComponent();

        this.BackColor = Color.White;
        this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;

        Region = System.Drawing.Region.FromHrgn(CreateRoundRectRgn(0, 0, 0, 0, 0, 0)); // Since our form is dynamically created and/or filled and auto sized, set starting values here to 0.
        Region.MakeInfinite(); // This one was my own, to solve size problems with my dynamically created forms auto size, further reading required for other ways to do it.
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        Font font = new System.Drawing.Font("Meiryo UI", 16.0f);

        myButton = new Button();
        myButton.Name = "tstButton";
        myButton.Size = new Size(50, 50);
        myButton.Location = new Point(10, 10);
        myButton.Font = font;
        myButton.Text = "Test Button";
        myButton.Click += (sender2, e2) => { ButtonClick(sender, e); };

        this.Controls.Add(myButton);
    }

    private void ButtonClick(object sender, EventArgs e)
    {
        Font font = new System.Drawing.Font("Meiryo UI", 16.0f);

        Button myButton = (sender as Button);

        Form myForm = new Form();
        Label row1Label = new Label();
        Label row2Label = new Label();
        Label row3Label = new Label();
        Label row4Label = new Label();
        Label row5Label = new Label();

        row2Label.AutoSize = true;
        row2Label.Text = "Row 1: ";
        row2Label.Font = font;
        row2Label.Location = new Point(5, 5);

        row1Label.AutoSize = true;
        row1Label.Text = "Row 2: ";
        row1Label.Font = font;
        row1Label.Location = new Point(5, 35);

        row3Label.AutoSize = true;
        row3Label.Text = "Row 3: ";
        row3Label.Font = font;
        row3Label.Location = new Point(5, 65);

        row4Label.AutoSize = true;
        row4Label.Text = "Row 4: ";
        row4Label.Font = font;
        row4Label.Location = new Point(5, 95);

        row5Label.AutoSize = true;
        row5Label.Text = "Row 5: ";
        row5Label.Font = font;
        row5Label.Location = new Point(5, 125);

        myForm.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
        myForm.AutoSize = true;
        myForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;

        myForm.Controls.Add(row1Label);
        myForm.Controls.Add(row2Label);
        myForm.Controls.Add(row3Label);
        myForm.Controls.Add(row4Label);
        myForm.Controls.Add(row5Label);

        myForm.Font = font;
        myForm.BackColor = Color.White;
        myForm.Padding = new System.Windows.Forms.Padding(10, 10, 10, 10);
        myForm.Show();
        myForm.Paint += (sender4, e4) => { Form1_Paint(sender4, e4); }; // Hijacking the borrowed code for custom borders again for the info boxes.
        myForm.Location = new Point(Cursor.Position.X + 25, Cursor.Position.Y - 100); // Create info box a little to the right and up from the cursors position.
        myForm.LostFocus += (sender3, e3) => { CloseForm(sender3, e3, myForm); }; // If the info box loses focus, for example by clicking another button, close that box (form)
        myForm.MouseEnter += (sender3, e3) => { CloseForm(sender3, e3, myForm); }; // Also, if the mouse enters the box, also close, so we can show the buttons under it.
    }

    /// <summary>
    /// Event for closing my "custom" info boxes. Runs at LostFocus or MouseEnter events. So, clicking another button or entering the info box will close it.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    /// <param name="myForm">Gets the relevant form that the event will run on. Solved my problem of targeting dynamically created forms from outside its scope.</param>
    private void CloseForm(object sender, EventArgs e, Form myForm)
    {
        myForm.Close();
    }

    /// <summary>
    /// Paint event. Holds some borrowed code for getting custom border. Works so far, but further reading required.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        // Borrowed code snippet for custom border: http://stackoverflow.com/q/5092216
        ControlPaint.DrawBorder(e.Graphics, this.ClientRectangle,
            Color.LightBlue, 5, ButtonBorderStyle.Solid,
            Color.LightBlue, 5, ButtonBorderStyle.Solid,
            Color.LightBlue, 5, ButtonBorderStyle.Solid,
            Color.LightBlue, 5, ButtonBorderStyle.Solid);
    }
}
}

我是編程的初學者,因此請原諒並顯示正確的方法,而不是譴責任何錯誤的編碼。

親切的問候,

馬蒂亞斯

問題是兩種表格都使用相同的事件處理程序。 如果要繼續這種方式,則應根據調用Pain事件處理程序的表單來更改ClientRectangle的大小(現在您始終使用主表單的ClientSize )。 Form1_Paint事件處理程序的代碼更改為此:

private void Form1_Paint(object sender, PaintEventArgs e)
{
        Form frm = (Form)sender;
        ControlPaint.DrawBorder(e.Graphics, frm.ClientRectangle,
        Color.LightBlue, 5, ButtonBorderStyle.Solid,
        Color.LightBlue, 5, ButtonBorderStyle.Solid,
        Color.LightBlue, 5, ButtonBorderStyle.Solid,
        Color.LightBlue, 5, ButtonBorderStyle.Solid);
}

在先前的代碼中,您在重繪子表單的情況下傳遞了主表單的ClientRectangle 更改代碼后, DrawBorder方法將為其調用的表單獲取正確的ClientRectangle

davidovic的解決方案會產生副作用,當控件停靠左/右/上/下時,您將無法在該區域繪畫,因為您正在使用控件覆蓋的“ ClientRectangle”。

有兩種重新繪制邊框的常規解決方案:

  1. 在表單下放置另一個表單,但是會出現表單處理問題,可能導致內存不足

  2. 捕獲非客戶區域Windows消息,重新繪制邊框。 但這非常棘手,並且可能導致許多問題,例如,最小化表單時,調整表單大小時,隱藏了某些表單區域,您應該處理此事件。

如果要使用方法2,建議您以Lizard.dll作為參考,它仍然存在bug,但比其他類型的庫穩定得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM