केवल एक चीज मैं अच्छी तरह से काम करने के लिए मिल गया है WS_EX_COMPOSITED
खिड़की शैली का प्रयोग है। यह एक प्रदर्शन हॉग है इसलिए मैं इसे आकार देने के दौरान केवल इसे सक्षम करता हूं। यह मेरा अनुभव है कि, अंतर्निहित नियंत्रण के साथ, मेरे ऐप में, फ़्लिकरिंग केवल फ़ॉर्म का आकार बदलते समय होती है।
आपको यह देखने के लिए पहले एक त्वरित परीक्षण करना चाहिए कि यह दृष्टिकोण आपके सभी विंडो किए गए नियंत्रणों में WS_EX_COMPOSITED
विंडो शैली को जोड़कर आपकी सहायता करेगा या नहीं। अपने TForm
के लिए
त्वरित हैक
procedure EnableComposited(WinControl: TWinControl);
var
i: Integer;
NewExStyle: DWORD;
begin
NewExStyle := GetWindowLong(WinControl.Handle, GWL_EXSTYLE) or WS_EX_COMPOSITED;
SetWindowLong(WinControl.Handle, GWL_EXSTYLE, NewExStyle);
for i := 0 to WinControl.ControlCount-1 do
if WinControl.Controls[i] is TWinControl then
EnableComposited(TWinControl(WinControl.Controls[i]));
end;
इस कॉल, उदाहरण के लिए, OnShow
में, प्रपत्र उदाहरण गुजर: है कि आप नीचे और अधिक उन्नत दृष्टिकोण पर विचार कर सकते काम करता है। यदि यह मदद करता है तो आपको वास्तव में इसे और अधिक समझदारी से लागू करना चाहिए। मैं आपको अपने कोड से प्रासंगिक निष्कर्ष बताता हूं कि मैंने यह कैसे किया।
पूर्ण कोड
procedure TMyForm.WMEnterSizeMove(var Message: TMessage);
begin
inherited;
BeginSizing;
end;
procedure TMyForm.WMExitSizeMove(var Message: TMessage);
begin
EndSizing;
inherited;
end;
procedure SetComposited(WinControl: TWinControl; Value: Boolean);
var
ExStyle, NewExStyle: DWORD;
begin
ExStyle := GetWindowLong(WinControl.Handle, GWL_EXSTYLE);
if Value then begin
NewExStyle := ExStyle or WS_EX_COMPOSITED;
end else begin
NewExStyle := ExStyle and not WS_EX_COMPOSITED;
end;
if NewExStyle<>ExStyle then begin
SetWindowLong(WinControl.Handle, GWL_EXSTYLE, NewExStyle);
end;
end;
function TMyForm.SizingCompositionIsPerformed: Boolean;
begin
//see The Old New Thing, Taxes: Remote Desktop Connection and painting
Result := not InRemoteSession;
end;
procedure TMyForm.BeginSizing;
var
UseCompositedWindowStyleExclusively: Boolean;
Control: TControl;
WinControl: TWinControl;
begin
if SizingCompositionIsPerformed then begin
UseCompositedWindowStyleExclusively := Win32MajorVersion>=6;//XP can't handle too many windows with WS_EX_COMPOSITED
for Control in ControlEnumerator(TWinControl) do begin
WinControl := TWinControl(Control);
if UseCompositedWindowStyleExclusively then begin
SetComposited(WinControl, True);
end else begin
if WinControl is TPanel then begin
TPanel(WinControl).FullRepaint := False;
end;
if (WinControl is TCustomGroupBox) or (WinControl is TCustomRadioGroup) or (WinControl is TCustomGrid) then begin
//can't find another way to make these awkward customers stop flickering
SetComposited(WinControl, True);
end else if ControlSupportsDoubleBuffered(WinControl) then begin
WinControl.DoubleBuffered := True;
end;
end;
end;
end;
end;
procedure TMyForm.EndSizing;
var
Control: TControl;
WinControl: TWinControl;
begin
if SizingCompositionIsPerformed then begin
for Control in ControlEnumerator(TWinControl) do begin
WinControl := TWinControl(Control);
if WinControl is TPanel then begin
TPanel(WinControl).FullRepaint := True;
end;
UpdateDoubleBuffered(WinControl);
SetComposited(WinControl, False);
end;
end;
end;
function TMyForm.ControlSupportsDoubleBuffered(Control: TWinControl): Boolean;
const
NotSupportedClasses: array [0..1] of TControlClass = (
TCustomForm,//general policy is not to double buffer forms
TCustomRichEdit//simply fails to draw if double buffered
);
var
i: Integer;
begin
for i := low(NotSupportedClasses) to high(NotSupportedClasses) do begin
if Control is NotSupportedClasses[i] then begin
Result := False;
exit;
end;
end;
Result := True;
end;
procedure TMyForm.UpdateDoubleBuffered(Control: TWinControl);
function ControlIsDoubleBuffered: Boolean;
const
DoubleBufferedClasses: array [0..2] of TControlClass = (
TMyCustomGrid,//flickers when updating
TCustomListView,//flickers when updating
TCustomStatusBar//drawing infidelities , e.g. my main form status bar during file loading
);
var
i: Integer;
begin
if not InRemoteSession then begin
//see The Old New Thing, Taxes: Remote Desktop Connection and painting
for i := low(DoubleBufferedClasses) to high(DoubleBufferedClasses) do begin
if Control is DoubleBufferedClasses[i] then begin
Result := True;
exit;
end;
end;
end;
Result := False;
end;
var
DoubleBuffered: Boolean;
begin
if ControlSupportsDoubleBuffered(Control) then begin
DoubleBuffered := ControlIsDoubleBuffered;
end else begin
DoubleBuffered := False;
end;
Control.DoubleBuffered := DoubleBuffered;
end;
procedure TMyForm.UpdateDoubleBuffered;
var
Control: TControl;
begin
for Control in ControlEnumerator(TWinControl) do begin
UpdateDoubleBuffered(TWinControl(Control));
end;
end;
यह आप के लिए संकलन नहीं होगा, लेकिन यह कुछ उपयोगी विचार शामिल करना चाहिए। ControlEnumerator
बाल नियंत्रण के एक पुनरावर्ती चलने को एक फ्लैट for
लूप में बदलने के लिए मेरी उपयोगिता है। ध्यान दें कि मैं एक कस्टम स्प्लिटर का भी उपयोग करता हूं जो सक्रिय होने पर BeginSizing/EndSizing को कॉल करता है।
TLabel
के बजाय TStaticText
का उपयोग करने के लिए एक और उपयोगी चाल है जिसे आपको कभी-कभी पृष्ठ नियंत्रण और पैनलों के गहरे घोंसले के दौरान करने की आवश्यकता होती है।
मैंने अपना ऐप 100% झिलमिलाहट मुक्त करने के लिए इस कोड का उपयोग किया है, लेकिन मुझे यह सब कुछ जगह लेने के लिए प्रयोग करने की उम्र और उम्र ले गई। उम्मीद है कि दूसरों को यहां कुछ उपयोग मिल सकता है।
इस प्रश्न में उत्तर और टिप्पणियों में कुछ अतिरिक्त विचार हैं: http://stackoverflow.com/q uestions/4031147 – Argalatyr