本人在做一個專案,需要使用到雙緩沖模式,大家應該知道,雙緩沖模式本身是為了避免大量控制元件重繪時閃爍而使用的,使用此模式確實解決了控制元件繪制時的閃爍問題,但有一個控制元件似乎與此模式有沖突,就是delphi自帶的DBCtrlGrid控制元件。
DBCtrlGrid是一款資料庫控制元件,可以將資料以Panel面板的形式展現出來。但此控制元件在雙緩沖模式下,一旦加載資料(動態繪制Panel)后,整屏控制元件就會不斷閃爍。
經過跟蹤控制元件源代碼,發現procedure TDBCtrlGrid.WMEraseBkgnd(var Message: TMessage);、procedure TDBCtrlGrid.WMPaint(var Message: TWMPaint);這兩個函式不斷被呼叫,推測是Windows不斷發送重繪訊息,然后擦除背景和繪制的函式就一直被呼叫。研究了很長時間,沒有找到根源所在,據網上有資料說是Windows不斷發送重繪訊息一般是由于呼叫了begin paint沒有end paint導致,但delphi自帶控制元件應該不會犯這么低級的錯誤吧...從Delphi7到最新的XE10,都是這個問題。
以下是Demo代碼:放置了資料庫ado控制元件,然后dbctrl1的資料源配好,在其panel上放一個TDBText控制元件展示資料,btn1Click寫入呼叫sql陳述句,Form上再放置一個TImage圖片,以便閃爍問題能夠清晰的展現。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, dbcgrids, DB, ADODB, DBCtrls, ExtCtrls,
pngimage;
type
TForm1 = class(TForm)
ds1: TDataSource;
qry1: TADOQuery;
con1: TADOConnection;
dbctrl1: TDBCtrlGrid;
dbtxt1: TDBText;
btn1: TButton;
img1: TImage;
procedure FormCreate(Sender: TObject);
procedure btn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
SetWindowLong(Self.Handle, GWL_EXSTYLE, GetWindowLong(Self.Handle, GWL_EXSTYLE) or WS_EX_COMPOSITED); //啟用雙緩沖
end;
procedure TForm1.btn1Click(Sender: TObject);
begin
with qry1 do
begin
Close;
SQL.Clear;
SQL.Add('select top 10 * from goods');
Open;
end;
end;

運行結果是:點擊btn1,dbctrl1加載了資料并動態生成panel,當點擊第二個panel時,整屏控制元件就不斷閃爍。

求各路大神指點...小弟不勝感激!
uj5u.com熱心網友回復:
這恐怕不是DBCtrlGrid的問題,而是Windows的問題,其他語言也有類似情況。WS_EX_COMPOSITED擴展樣式強制改變界面繪制順序,能解決閃爍問題,但有嚴重的副作用。比如一個空表單,在經典主題下非客戶區的圖示點擊影片效果消失。最大化表單重繪有問題,CPU使用率特別高,和DWM不兼容等。你也可以嘗試用FMX庫的界面組件或設定DoubleBuffered屬性。表單和DBCtrlGrid控制元件都有DoubleBuffered屬性,可以設為True試試。這是和WS_EX_COMPOSITED不同的一種組件級別的雙緩沖方案,它是先把控制元件畫在記憶體位圖中,再拷貝到視窗上來防閃爍的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/56582.html
上一篇:關于List.Pack的問題
