2010-07-20 9 views
20

Tôi có một ứng dụng có nhiều điều khiển trên đó. Và nó có một số lượng lớn nhấp nháy, đặc biệt là khi khởi động.Nhấp nháy trong ứng dụng Windows Forms

Tôi đã áp dụng điều này fix cho nó.

protected override CreateParams CreateParams 
    { 
     get 
     { 
      CreateParams cp = base.CreateParams; 
      cp.ExStyle |= 0x02000000; // WS_EX_COMPOSITED 
      return cp; 
     } 
    } 

Điều này làm việc tuyệt vời - việc nhấp nháy đã giảm xuống một số tiền không thể tin được. Tuy nhiên, tác dụng phụ là các nút Thu nhỏ, Tối đa hóa và Đóng ở trên cùng bên phải cửa sổ không hoạt ảnh khi tôi di chuyển chuột lên hoặc nhấp vào chúng (chúng vẫn hoạt động). Điều này mang lại cho ứng dụng một cảm giác treo.

Làm cách nào để giữ WS_EX_COMPOSITED trong khi vẫn giữ lại khả năng sử dụng của các nút Phóng to, Thu nhỏ và Đóng?

Điều này xảy ra trên Windows XP. Như @fallenidol đã chỉ ra, đây không phải là vấn đề trên Windows 7.

+5

Câu hỏi hoàn hảo (Tôi muốn chức năng này, tôi đã thử giải pháp này, làm cách nào để tôi đạt được chức năng này với ràng buộc mới này). –

+0

BTW, tôi đã thử bản sửa lỗi này trong một ứng dụng thử nghiệm chạy trên Windows 7 và các nút Phóng to, Thu nhỏ và Đóng vẫn có vẻ động. – pmcilreavy

+0

@fallenidol. Đó là điều tốt để biết. Tất cả khách hàng của tôi đều sử dụng XP. – AngryHacker

Trả lời

11

Tôi đã tìm ra. Bí quyết là xóa cờ WS_EX_COMPOSITED sau khi biểu mẫu được hiển thị. Lời giải thích đầy đủ và mã tại blog của tôi:

How to get rid of flicker on Windows Forms applications

+0

Rất tuyệt vời .. đã làm việc cho tôi – Marshal

+0

Tài liệu hay. Cảm ơn vì điều đó. Được thăng hạng. – C4u

+0

@Hossein vâng, blog đã ngừng hoạt động ... hy vọng sẽ khôi phục vào một thời điểm nào đó trong tháng này. – AngryHacker

0

Bạn nên thử các cửa sổ chuẩn biểu mẫu kiểm soát thuộc tính được gọi là DoubleBuffered. http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered.aspx

+0

Điều đó chỉ hoạt động trên cơ sở mỗi kiểm soát. Ví dụ tôi đã cung cấp lực lượng đệm đôi lên mọi điều khiển trên biểu mẫu. – AngryHacker

+0

Bạn có thể sử dụng sự phản chiếu ở đầu ứng dụng để điền vào thuộc tính này của mọi điều khiển. – Kru

+0

Tôi không thể làm điều đó cho các điều khiển của bên thứ 3 không hiển thị thuộc tính này. – AngryHacker

4

Hãy thử mã sau. Điều này sẽ đi vào biểu mẫu chính và bất kỳ điều khiển người dùng tùy chỉnh nào khác mà bạn có.

 // Enable double duffering to stop flickering. 
     this.SetStyle(ControlStyles.DoubleBuffer, true); 
     this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
     this.SetStyle(ControlStyles.UserPaint, true); 
     this.SetStyle(ControlStyles.SupportsTransparentBackColor, false); 
     this.SetStyle(ControlStyles.Opaque, false); 
     this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 
     this.SetStyle(ControlStyles.ResizeRedraw, true); 
+0

Toàn bộ điểm của mã tôi đăng là bạn làm điều này một lần, không phải cho mọi điều khiển người dùng (có hàng trăm + một tấn các điều khiển bên thứ 3). – AngryHacker

+3

Đây là một tùy chọn khác cho những người khác xem trang này có thể không có quyền truy cập vào toàn bộ ứng dụng và chỉ đang phát triển kiểm soát người dùng một mình. Lần tới khi bạn đang phát triển một điều khiển người dùng duy nhất, bạn có thể sử dụng đoạn mã của tôi ở trên. Sau đó, bạn có thể không kết thúc trong một tình huống mà bạn có hàng trăm điều khiển nhấp nháy. – pmcilreavy

5

Tôi biết câu hỏi này là một ít tuổi, nhưng muộn còn hơn không. Tôi đã sử dụng ví dụ ban đầu của bạn mà bạn đã liên kết để đưa ra một ví dụ bật tắt khi thay đổi kích thước, sau đó bật lại để vẽ mọi thứ khác hoàn hảo. Hy vọng nó giúp người khác tìm kiếm giải pháp cho vấn đề này. Như OP biết, DoubleBuffering một mình tài sản không giải quyết các vấn đề nhấp nháy.

Dưới đây là một công việc xung quanh để ngăn chặn nhấp nháy khi người dùng thay đổi kích thước một hình thức, nhưng không rối tung lên các bản vẽ của các điều khiển như DataGridView, NumericUpDown vv Cung cấp tên hình thức của bạn là "Form1":

int intOriginalExStyle = -1; 
bool bEnableAntiFlicker = true; 

public Form1() 
{ 
    ToggleAntiFlicker(false); 
    InitializeComponent(); 
    this.ResizeBegin += new EventHandler(Form1_ResizeBegin); 
    this.ResizeEnd += new EventHandler(Form1_ResizeEnd); 
} 

protected override CreateParams CreateParams 
{ 
    get 
    { 
     if (intOriginalExStyle == -1) 
     { 
      intOriginalExStyle = base.CreateParams.ExStyle; 
     } 
     CreateParams cp = base.CreateParams; 

     if (bEnableAntiFlicker) 
     { 
      cp.ExStyle |= 0x02000000; //WS_EX_COMPOSITED 
     } 
     else 
     { 
      cp.ExStyle = intOriginalExStyle; 
     } 

     return cp; 
    } 
} 

private void Form1_ResizeBegin(object sender, EventArgs e) 
{ 
    ToggleAntiFlicker(true); 
} 

private void Form1_ResizeEnd(object sender, EventArgs e) 
{ 
    ToggleAntiFlicker(false); 
} 

private void ToggleAntiFlicker(bool Enable) 
{ 
    bEnableAntiFlicker = Enable; 
    //hacky, but works 
    this.MaximizeBox = true; 
} 
+0

Điểm tốt. Tôi đã có mã này trong ứng dụng của mình, nhưng bị bỏ qua để thêm nó vào mục nhập blog của tôi. Sẽ cập nhật nó trong một vài ngày. – AngryHacker

0

Tôi vừa xem qua bài đăng này và nhận ra nó hơi cũ. Tuy nhiên, tôi có cùng một vấn đề với hình thức của tôi và phát hiện ra (đối với XP, anyway) một giải pháp không thích hợp dường như không cho phép kiểu trực quan.

+0

Theo dõi, tôi dường như không có vấn đề với nhấp nháy khi tôi ghi đè lên OnPaintBackground. Nếu tôi không muốn nền được vẽ, tôi gọi e.Graphics.Clear ([màu thích hợp]) và trả về, nếu không phương thức sự kiện cơ bản được gọi. Như tôi đã nói, điều này "có vẻ" để làm giảm bớt vấn đề. Tuy nhiên, tôi tự hỏi những hậu quả không lường trước được có thể xảy ra. – Tebc

+0

Hiệu chỉnh. Ghi đè nói trên dường như hoạt động miễn là thuộc tính kích thước tối thiểu của biểu mẫu được đặt thành kích thước hiện tại. – Tebc