2011-01-14 46 views
11

Tôi đang tạo một chương trình mà tôi có rất nhiều bảng và bảng điều khiển trong bảng.Tại sao WinForms của tôi kiểm soát nhấp nháy và thay đổi kích thước chậm?

Tôi có một vài điều khiển được vẽ tùy chỉnh trong các bảng này.

Chức năng thay đổi kích cỡ của 1 bảng chứa mã để điều chỉnh kích thước và vị trí của tất cả các điều khiển trong bảng điều khiển đó.

Bây giờ ngay sau khi tôi thay đổi kích thước chương trình, việc thay đổi kích thước của bảng điều khiển này sẽ được kích hoạt. Điều này dẫn đến rất nhiều nhấp nháy của các thành phần trong bảng điều khiển này.

Tất cả các điều khiển được vẽ của người dùng đều được đệm đôi.

Ai đó có thể giúp tôi giải quyết vấn đề này không?

+0

Nếu tôi không bỏ phiếu, tôi sẽ bỏ phiếu để đóng câu hỏi này là bản sao của câu hỏi này: [Winforms Double Buffering] (http://stackoverflow.com/questions/3718380/winforms-double -buffering). Vì vậy, ở đây nó là miễn phí. –

+0

@Cody Gray - Tôi không đồng ý! Câu hỏi có thể tương tự, nhưng câu trả lời được cung cấp theo liên kết bạn gửi là hoàn toàn sai/xấu vì nó gây ra rất nhiều tác dụng phụ. – HABJAN

+0

@HABJAN: Bạn có thể cho tôi biết về một số tác dụng phụ đó không? –

Trả lời

1

Có thể giải pháp tốt cho bạn là sử dụng các sự kiện Form.ResizeBeginForm.ResizeEnd.

Bật ResizeBegin đặt chế độ hiển thị bảng chính thành false, trên ResizeEnd đặt hiển thị bảng chính thành true.

Bảng cách này sẽ không được vẽ lại khi người nào đó đang định lại kích thước biểu mẫu của bạn.

+0

Có ai muốn xem mã không? – user575579

+0

@ user575579 - bạn có thể làm cho câu hỏi này rõ ràng hơn không? Bạn có muốn tôi cung cấp cho bạn mẫu mã hoặc bạn muốn đăng giải pháp của mình không? – HABJAN

+0

đăng một giải pháp, nhưng tôi không biết làm thế nào tôi có thể làm điều này trên trang web này. – user575579

17

Nhìn vào dự án bạn đã đăng, nhấp nháy thực sự tồi khi bạn chọn tab đầu tiên, với các hộp nhóm được tô màu. Với tab thứ hai hoặc thứ ba hiển thị, hầu như không có bất kỳ nhấp nháy nào.

    Your main form

Vì vậy, rõ ràng các vấn đề có cái gì để làm với các điều khiển bạn đang hiển thị trên trang tab. Xem nhanh mã cho lớp hộp nhóm điền gradient tùy chỉnh cho biết nguyên nhân cụ thể hơn. Bạn đang thực hiện lot của quá trình xử lý thực sự tốn kém mỗi khi bạn vẽ một trong các điều khiển hộp nhóm. Bởi vì mỗi kiểm soát hộp nhóm phải tự sơn lại mỗi lần biểu mẫu được thay đổi kích thước, mã đó sẽ được thực thi một số lần không thể tin được.

Cộng với, bạn có nền điều khiển được đặt thành "Trong suốt", được đặt trong WinForms bằng cách yêu cầu cửa sổ chính vẽ đầu tiên bên trong cửa sổ điều khiển để tạo pixel nền. Sự kiểm soát sau đó tự vẽ lên trên đó. Đây cũng là công việc nhiều hơn điền vào nền điều khiển với một màu rắn như SystemColors.Control, và nó gây ra cho bạn để xem các điểm ảnh của biểu mẫu được rút ra trong khi bạn thay đổi kích thước hình thức, trước khi các hộp nhóm có cơ hội để vẽ mình.

Dưới đây là các mã cụ thể tôi đang nói về từ tùy chỉnh lớp kiểm soát GroupBox gradient điền của bạn:

protected override void OnPaint(PaintEventArgs e) 
{ 
    if (Visible) 
    { 
     Graphics gr = e.Graphics; 
     Rectangle clipRectangle = new Rectangle(new Point(0, 0), this.Size); 
     Size tSize = TextRenderer.MeasureText(Text, this.Font); 
     Rectangle r1 = new Rectangle(0, (tSize.Height/2), Width - 2, Height - tSize.Height/2 - 2); 
     Rectangle r2 = new Rectangle(0, 0, Width, Height); 
     Rectangle textRect = new Rectangle(6, 0, tSize.Width, tSize.Height); 

     GraphicsPath gp = new GraphicsPath(); 
     gp.AddRectangle(r2); 
     gp.AddRectangle(r1); 
     gp.FillMode = FillMode.Alternate; 

     gr.FillRectangle(new SolidBrush(Parent.BackColor), clipRectangle); 

     LinearGradientBrush gradBrush; 
     gradBrush = new LinearGradientBrush(clipRectangle, SystemColors.GradientInactiveCaption, SystemColors.InactiveCaptionText, LinearGradientMode.BackwardDiagonal); 
     gr.FillPath(gradBrush, RoundedRectangle.Create(r1, 7)); 

     Pen borderPen = new Pen(BorderColor); 
     gr.DrawPath(borderPen, RoundedRectangle.Create(r1, 7)); 
     gr.FillRectangle(gradBrush, textRect); 
     gr.DrawRectangle(borderPen, textRect); 
     gr.DrawString(Text, base.Font, new SolidBrush(ForeColor), 6, 0); 
    } 

} 

protected override void OnPaintBackground(PaintEventArgs pevent) 
{ 
    if (this.BackColor == Color.Transparent) 
     base.OnPaintBackground(pevent); 
} 

Và bây giờ mà bạn đã nhìn thấy mã, cờ cảnh báo đỏ phải đi lên. Bạn đang tạo một nhóm của các đối tượng GDI + (bàn chải, bút mực, vùng, v.v.), nhưng không thành Dispose bất kỳ đối tượng nào trong số chúng! Hầu hết tất cả mã đó phải được bao bọc trong các câu hỏi using. Đó chỉ là mã hóa cẩu thả.

Làm tất cả công việc đó tốn một cái gì đó.Khi máy tính bị buộc phải dành rất nhiều thời gian để điều khiển hiển thị, những thứ khác tụt lại phía sau. Bạn thấy một nhấp nháy vì nó căng để theo kịp với thay đổi kích thước. Nó không khác gì so với bất cứ thứ gì khác làm quá tải máy tính (như tính toán giá trị của pi), nó thực sự dễ dàng để làm như vậy khi bạn sử dụng nhiều điều khiển được vẽ tùy chỉnh như bạn làm ở đây. Minh bạch là khó khăn trong Win32, và như vậy là rất nhiều bức tranh 3D tùy chỉnh. Nó làm cho giao diện người dùng trông cảm thấy bối rối với người dùng. Tuy nhiên, một lý do khác mà tôi không hiểu sự vội vã đi từ kiểm soát bản địa.

Bạn thực sự chỉ có ba lựa chọn:

  1. Deal với nhấp nháy. (Tôi đồng ý, đây không phải là một lựa chọn tốt.)
  2. Sử dụng các điều khiển khác nhau, như các tiêu chuẩn được tích hợp sẵn. Chắc chắn, họ có thể không có một hiệu ứng gradient ưa thích, nhưng đó sẽ xem xét một nửa thời gian bị hỏng nếu người dùng đã tùy chỉnh chủ đề Windows của họ. Cũng rất khó đọc văn bản màu đen trên nền xám đậm.
  3. Thay đổi mã vẽ trong các điều khiển tùy chỉnh của bạn để thực hiện ít công việc hơn. Bạn có thể nhận được bằng một số "tối ưu hóa" đơn giản mà không làm bạn mất bất kỳ hiệu ứng hình ảnh nào, nhưng tôi nghi ngờ điều này là không thể. Đó là một sự cân bằng giữa tốc độ và kẹo mắt. Không làm gì luôn nhanh hơn.
+0

Tôi nhận được quan điểm của bạn, nhưng tôi đã sử dụng GradientGroupBox trong các chương trình khác một cách rộng rãi không kém với ít hơn đáng kể các vấn đề. Hãy xem chương trình này để so sánh nó. Tôi biết tôi đang làm điều gì sai trong mã này, nhưng tôi không thể đặt ngón tay lên đó. http://dl.dropbox.com/u/18687229/Combo%20Tuning.zip PS: Tôi không quen thuộc với sự khác biệt giữa bản vẽ với tuyên bố sử dụng và cách tôi đã làm. Bạn có một số thông tin về điều này? – user575579

+0

@ user575579: Trước hết, vui lòng không đăng tệp thi hành. Nếu tôi không có một máy ảo được thiết lập, tôi sẽ không chạy nó. Nó không phải là tôi không tin tưởng bạn, nhưng tôi không tin tưởng bạn. ;-) Thứ hai, tôi thực sự không hiểu sự khác biệt giữa hai dự án ... Cái đó chỉ lóe lên như mắt đầu tiên. Bản vẽ thực sự bị lag khi bạn thay đổi kích thước biểu mẫu. Không phải là * không sử dụng được *, nhưng đồng thời, không phải là chất lỏng. Thứ ba, vì bạn * không * đăng mã cho dự án thứ hai, tôi thực sự không thể nói cho bạn biết bạn đang làm gì khác với mã khôn ngoan. Tôi nghi ngờ có một số lý do mà ... –

+0

thứ hai là đặt áp lực ít hơn vào bộ thu gom rác so với lần đầu tiên, nhưng đó chỉ là một phỏng đoán. Thứ tư và cuối cùng, câu lệnh 'using' không quá phức tạp. Tất cả những gì nó làm là đảm bảo rằng phương thức 'Dispose' của đối tượng được gọi bất cứ khi nào bạn sử dụng xong nó. Đây là một tài liệu tham khảo MSDN với mã mẫu: http://msdn.microsoft.com/en-us/library/yh598w02.aspx –

1

Trong khi nhập vào ResizeBegin và ResizeEnd là ý tưởng đúng, thay vì ẩn tầm nhìn của bảng chính, thay vào đó, hãy trì hoãn bất kỳ phép tính thay đổi kích thước nào cho đến ResizeEnd. Trong trường hợp này, bạn thậm chí không cần phải móc vào ResizeBegin hoặc Resize - tất cả các logic đi vào ResizeEnd.

Tôi nói điều này vì hai lý do. Một, mặc dù bảng điều khiển bị ẩn, thao tác thay đổi kích thước có thể vẫn sẽ tốn kém và do đó biểu mẫu sẽ không cảm thấy đáp ứng như nó nên trừ khi các phép tính thay đổi kích thước bị trì hoãn. Hai, ẩn nội dung của cửa sổ trong khi thay đổi kích thước có thể được jarring cho người dùng.

2

Tôi loại bỏ thành công nhấp nháy khi thay đổi kích thước biểu mẫu bằng mã này. Cảm ơn.

VB.NET

Public Class Form1 

Public Sub New() 
    Me.SetStyle(ControlStyles.UserPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.AllPaintingInWmPaint Or ControlStyles.SupportsTransparentBackColor, True) 
End Sub 

Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize 
    Me.Update() 
End Sub 

End Class 

C#

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
     Resize += Form1_Resize; 
     this.SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor, true); 
    } 

    private void Form1_Resize(object sender, System.EventArgs e) 
    { 
     this.Update(); 
    } 

} 
+0

Tôi đã có cùng một vấn đề, và giải pháp của bạn làm việc cho tôi, nhưng bây giờ tôi có một vấn đề với tốc độ thay đổi kích thước biểu mẫu - rất chậm. Tôi có vài điều khiển trên biểu mẫu như nút, tabControl, hình ảnh, hộp danh sách, datagridview ... Bất kỳ sugestions lý do của sự chậm lại là gì? –

16

Để thoát khỏi nhấp nháy trong khi thay đổi kích thước các hình thức chiến thắng, đình chỉ việc bố trí trong khi thay đổi kích thước. Ghi đè các hình thức resizebegin/resizeend phương pháp như dưới đây.

protected override void OnResizeBegin(EventArgs e) { 
    SuspendLayout(); 
    base.OnResizeBegin(e); 
} 
protected override void OnResizeEnd(EventArgs e) { 
    ResumeLayout(); 
    base.OnResizeEnd(e); 
} 

Điều này sẽ giữ nguyên các điều khiển (như trước đây khi thay đổi kích thước) và buộc vẽ lại khi thao tác thay đổi kích thước hoàn tất.

2

Vì vậy, tôi chạy vào vấn đề này cùng - kiểm soát của tôi với nền trong suốt được sơn lại như 34 lần, và những gì làm việc cho tôi là:

Mở hình thức của tôi có chứa kiểm soát

protected override void OnResize(EventArgs e) 
    { 
     myControl.Visible = false; 
     base.OnResize(e); 
     myControl.Visible = true; 
    } 

Và giống nhau trong điều khiển:

protected override void OnResize(EventArgs e) 
    { 
     this.Visible = false; 
     base.OnResize(e); 
     this.Visible = true; 
    } 

Điều này làm giảm số lượng sơn lại thành 4, loại bỏ hiệu quả bất kỳ nhấp nháy khi điều khiển được thay đổi kích thước.

0

Tôi gặp vấn đề tương tự.

Đường nối này xảy ra vì bạn đang sử dụng góc bo tròn. Khi tôi đặt thuộc tính CornerRadius thành 0, nhấp nháy đã biến mất.

Cho đến nay tôi chỉ tìm thấy cách giải quyết sau. Không phải là đẹp nhất, nhưng nó dừng nhấp nháy.

private void Form_ResizeBegin(object sender, EventArgs e) 
{ 
    rectangleShape.CornerRadius = 0; 
} 

private void Form_ResizeEnd(object sender, EventArgs e) 
{ 
    rectangleShape.CornerRadius = 15; 
} 
Các vấn đề liên quan