2013-03-23 23 views
0

試圖學習編程並進行了一些試驗。遇到了一個我一直無法找到解決方案的問題。我有一個編程創建的按鈕和一個單擊事件,以編程方式創建一個新的窗體。該表單有一些創建的標籤以及自定義邊框。在主窗體上使用相同的自定義邊框,並且即使在自動調整尺寸的情況下也可以工作,並且動態創建的內容會改變其大小。但是,在這個以編程方式創建的窗體上,邊框只顯示在左側和頂部,我一直無法找到答案或通過實驗解決問題。C#WinForms - 以編程方式創建的窗體的自定義邊框僅顯示左側和頂部邊框

不知道有多少代碼就夠了,但我做了一個簡化的程序來顯示問題。它從我的程序的代碼中簡化了,它使用數百個程序創建的按鈕和幾個信息數組填充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); 
    } 
} 
} 

我是編程的初學者,所以要有點寬容和展示正確的方式,而不是譴責任何錯誤的編碼。

親切的問候,

馬蒂亞斯

+0

你可以顯示「Form2_Paint(sender4,e4);'事件的代碼嗎?它在您展示的代碼中缺失! – 2013-03-23 11:23:52

+0

對不起,剛剛注意到它,當我試圖從一個單獨的項目運行它。 它應該是Form1_Paint,我已經在示例中更正了它。另外,我必須再次創建Load和Paint事件才能正確顯示程序。當您獲得帶淺藍色邊框且沒有標題欄和一個按鈕的主窗口時,您知道它正常工作。點擊按鈕將顯示一個帶有一些標籤的類似窗口。 – 2013-03-23 11:39:02

回答

3

的問題是,你正在使用的兩種形式相同的事件處理程序。如果你想繼續這種方式,你應該根據Pain事件處理程序被調用的形式(現在你總是使用主窗體的ClientSize)更改ClientRectangle的大小。 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

+0

謝謝,作品完美!一些填充到myForm中,以便標籤不會覆蓋邊框,並按照我的需要工作!將上述代碼添加到上面的代碼中,但遺漏了更正後的代碼,以免讀者感到困惑。我的代碼將繼續顯示主要問題,您的文章將是展示正確方式的文章。 – 2013-03-23 11:52:21

0

davidovic的解決方案將有一個副作用,當控制檯左/右/上/下,你不能在這個區域畫,因爲你正在使用由控件覆蓋的「ClientRectangle」。

有重新繪製邊界的兩個正常的解決方案:

  1. 把另一種形式的形式下,反而會產生形式處置問題,可能會導致內存不足

  2. 抓非工作區窗口消息,重新繪製邊框。但是這非常棘手,並且可能導致很多問題,例如,當表單被最小化時,表單被調整大小時,某些表單區域被隱藏,並且您應該處理該事件。

如果你想使用的方法2,我建議你採取Lizard.dll參考,它仍然有缺陷,但比其他類型庫的多穩定。