I've found a drawing bug in NextInspector, when Windows themes are activated (I use Windows XP).
Please check out the example program at the end of this message I made for demonstration:
You need a NextGrid with a TreeColumn and a CheckboxColumn, two Buttons and a SpinEdit.
When adding a few rows including child rows and empty the grid calling ClearRows procedure, the bug occurs after a loop count of about 8639 or 8640!
Strange thing about this is, when wrapping ClearRows in BeginUpdate and EndUpdate or deleting the rows one by one by calling DeleteRow procedure no drawing bug occurs.
I looked for the exact spot where the bug comes from and found it in NxThemesSupport.pas in procedure ThemeRect:
Calling the function OpenThemeData too many times causes the result to be an invalid handle even tough it is released in CloseThemeData. (This looks like an stupid Windows bug!
It is not clearly documented, but I think OpenThemeData function is supposed to be called just once in the lifetime of an object, because in MSDN description of CloseThemeData it says:
"The CloseThemeData function should be called when a window that has a visual style applied is destroyed.". So I think this applies vice versa for OpenThemeData, when the object is created.
Please let me know, what you think about this. Do you plan to call OpenThemeData function in constructor and CloseThemeData function in destructor of your components in future?
Now the example code:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Spin,
NxColumns, NxColumnClasses, NxScrollControl, NxCustomGridControl, NxCustomGrid, NxGrid;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
SpinEdit1: TSpinEdit;
NextGrid1: TNextGrid;
NxTreeColumn1: TNxTreeColumn;
NxCheckBoxColumn1: TNxCheckBoxColumn;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
cancel: boolean;
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
const
maxRowsPerLoop = 4;
maxChildRowsPerRow = 3;
var
i, j, k,
ParentRow: integer;
fast: boolean;
begin
Button1.Enabled := false;
fast := true;
with NextGrid1 do
begin
for i := 1 to SpinEdit1.Value do
begin
// without ClearRows or wrapping ClearRows in BeginUpdate/Endupdate everything works fine
if fast then
begin
BeginUpdate;
ClearRows;
EndUpdate;
end
else
begin
while RowCount > 0 do
DeleteRow(RowCount - 1);
end;
Application.ProcessMessages;
for j := 1 to maxRowsPerLoop do
begin
ParentRow := AddRow;
Cell[0, LastAddedRow].AsString := 'Parent ' + IntToStr(i) + '_' + IntToStr(j);
Cell[1, LastAddedRow].AsBoolean := Odd(j);
Application.ProcessMessages;
for k := 1 to maxChildRowsPerRow do
begin
AddChildRow(ParentRow);
Cell[0, NextGrid1.LastAddedRow].AsString := 'Child ' + IntToStr(k);
end;
Expanded[ParentRow] := false;
Application.ProcessMessages;
if cancel then
break;
end;
if cancel then
break;
end;
end;
cancel := false;
Button1.Enabled := true;
Button1.SetFocus;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
cancel := true;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
cancel := false;
end;
end.











