2009-07-15 8 views
6

Tôi có một kiểm soát CheckedListBox (WinForms) (mà kế thừa từ ListBox; googling cho thấy rằng vấn đề là với ListBox) được neo vào tất cả bốn mặt của biểu mẫu của nó. Khi biểu mẫu được thay đổi kích thước, ListBox có một nhấp nháy xấu xí. Tôi đã thử kế thừa CheckedListBox và thiết lập DoubleBuffered thành true trong ctor (kỹ thuật này hoạt động với các điều khiển khác, bao gồm ListView và DataGridView), nhưng nó không có hiệu lực.Bộ đệm đôi ListBox

Tôi đã thử thêm kiểu WS_EX_COMPOSITED vào CreateParams và điều này đã giúp, nhưng làm cho biểu mẫu thay đổi kích thước chậm hơn.

Có cách nào khác để ngăn chặn sự nhấp nháy này không?

Trả lời

10

Tôi đã gặp vấn đề tương tự mặc dù với một chủ sở hữu rút ra ListBox. chủ sở hữu được rút ra, nhưng có thể nó sẽ cung cấp cho bạn một số nguồn cảm hứng

Tôi thấy rằng TextRenderer gặp khó khăn khi hiển thị vị trí chính xác trừ khi tôi nhét TextFormatFlags.Prese rveGraphicsTranslateTransform. Cách khác là sử dụng P/Invoke để gọi BitBlt để sao chép trực tiếp các pixel giữa các bối cảnh đồ họa. Tôi đã chọn điều này là ít hơn của hai tệ nạn.

/// <summary> 
/// This class is a double-buffered ListBox for owner drawing. 
/// The double-buffering is accomplished by creating a custom, 
/// off-screen buffer during painting. 
/// </summary> 
public sealed class DoubleBufferedListBox : ListBox 
{ 
    #region Method Overrides 
    /// <summary> 
    /// Override OnTemplateListDrawItem to supply an off-screen buffer to event 
    /// handlers. 
    /// </summary> 
    protected override void OnDrawItem(DrawItemEventArgs e) 
    { 
     BufferedGraphicsContext currentContext = BufferedGraphicsManager.Current; 

     Rectangle newBounds = new Rectangle(0, 0, e.Bounds.Width, e.Bounds.Height); 
     using (BufferedGraphics bufferedGraphics = currentContext.Allocate(e.Graphics, newBounds)) 
     { 
      DrawItemEventArgs newArgs = new DrawItemEventArgs(
       bufferedGraphics.Graphics, e.Font, newBounds, e.Index, e.State, e.ForeColor, e.BackColor); 

      // Supply the real OnTemplateListDrawItem with the off-screen graphics context 
      base.OnDrawItem(newArgs); 

      // Wrapper around BitBlt 
      GDI.CopyGraphics(e.Graphics, e.Bounds, bufferedGraphics.Graphics, new Point(0, 0)); 
     } 
    } 
    #endregion 
} 
+0

Tôi chỉ thực hiện điều này và nó hoạt động hoàn hảo. – test

+1

@Eric: Bạn lấy GDI từ đâu? Nó là một tham chiếu? Ví dụ, tôi đã cố gắng thêm 'Graphics GDI = this.CreateGraphics();' nhưng nó không có phương thức CopyGraphics. Hay bạn đã nhập Gdi32.dll trước đây? – Matt

+0

Ok - đang hoạt động. Tôi đã thêm 'GDI32.dll' với phương thức' BitBlt', bọc nó thành 'GDI.CopyGraphics (...)' và bây giờ nó hoạt động ... điều duy nhất là nhấp nháy giống như ListBox gốc. làm thế nào để khắc phục các ý tưởng đó? – Matt

2

Bạn có thể kiểm tra xem chuyển sang hộp kiểm ListView có hộp kiểm có cải thiện vấn đề không. Nó không phải là dễ dàng để đối phó với (nhưng hey, WinBox ListBox không phải là một đột quỵ của thiên tài hoặc), tôi thấy rằng nó thay đổi kích cỡ hành vi với DoubleBuffered=true là bearable. Ngoài ra, bạn có thể thử giảm nhấp nháy bằng cách ghi đè bản vẽ nền của biểu mẫu gốc - hoặc cung cấp bàn chải rỗng hoặc ghi đè WM_ERASEBKND bằng cách không làm gì và trả về TRUE. (điều đó là ok nếu kiểm soát của bạn bao gồm toàn bộ khu vực khách hàng của biểu mẫu gốc, nếu không bạn sẽ cần một phương thức vẽ nền phức tạp hơn.

Tôi đã sử dụng thành công trong các ứng dụng Win32, nhưng tôi không biết Hình thức kiểm soát cho biết thêm một số ma thuật riêng của nó mà ám này nonfunctional

0

Điều này được sử dụng để xử lý bằng cách gửi tin nhắn WM_SETREDRAW tới bộ điều khiển.

const int WM_SETREDRAW = 0x0b; 

Message m = Message.Create(yourlistbox.Handle, WM_SETREDRAW, (IntPtr) 0, (IntPtr) 0); 
yourform.DefWndProc(ref m); 

// do your updating or whatever else causes the flicker 

Message m = Message.Create(yourlistbox.Handle, WM_SETREDRAW, (IntPtr) 1, (IntPtr) 0); 
yourform.DefWndProc(ref m); 

Xem thêm: WM_SETREDRAW reference at Microsoftcố định liên kết

Nếu bất cứ ai khác đã sử dụng cửa sổ thông điệp dưới NET, vui lòng cập nhật đăng tải này khi cần thiết.

+0

Nhấp nháy được gây ra bởi thay đổi kích thước, vì vậy đây là không phải là một giải pháp tối ưu. Tuy nhiên, tôi có thể làm điều đó anyway. – SLaks

+0

Điều này không giải quyết được vấn đề nhấp nháy trên ListBox của tôi. – AlainD

0

Mặc dù không giải quyết được vấn đề cụ thể của nhấp nháy, một phương pháp thường xuyên có hiệu lực đối với loại sự cố này là lưu vào bộ nhớ cache trạng thái tối thiểu của các mục ListBox. Sau đó xác định xem bạn có cần vẽ lại ListBox hay không bằng cách thực hiện một số phép tính trên mỗi mục. Chỉ cập nhật ListBox nếu ít nhất một mục cần được cập nhật (và dĩ nhiên lưu trạng thái mới này trong bộ nhớ cache cho chu kỳ tiếp theo).