Jump to content


Photo

Drawing bug when Windows themes are activated


  • Please log in to reply
3 replies to this topic

#1 CSE

CSE
  • Members
  • 54 posts
  • Location:Germany

Posted 25 June 2012 - 12:04 PM

Hi Boki,

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.

Best regards,
Thomas

#2 CSE

CSE
  • Members
  • 54 posts
  • Location:Germany

Posted 12 July 2012 - 02:37 PM

Hello Boki,

what do you say about this?
Best regards,
Thomas

#3 Boki (Berg)

Boki (Berg)

    Boki (Berg)

  • Forum Admin
  • PipPipPipPipPip
  • 8,289 posts
  • Gender:Male

Posted 13 July 2012 - 06:48 AM

Hi,

I am working on it. Actually since I have gain a lot of experience with themes in previous versions, I have done things better in v6. Now I am trying to bring this back to v5.
boki@bergsoft.net | LinkedIn Profile
--
BergSoft Home Page: www.bergsoft.net
Users Section: users.bergsoft.net
Articles and Tutorials: help.bergsoft.net (Developers Network)
--
BergSoft Facebook page
--
Send us applications made with our components and we will submit them on: www.bergsoft.net/apps.htm. Link to this page will be also set on home page too.

#4 Victor Printing

Victor Printing
  • Members
  • 26 posts

Posted 09 August 2012 - 08:52 PM

Yes, it looks a bug in OpenThemeData after it's called 65,536 times. More info "]this post on microsoft.public.win32.programmer.ui. I stumbled across this on accident myself. There's some components and calls that will call OpenThemeData, draw their item, and close immediately and don't cache their handles that can exhaust available handles very quickly. (e.g., anything using ThemeRect() in NxThemesSupport.pas)

I keep a separate codebase where I've refactored out as many of those calls as possible to stave off this problem, cached handles on my own, etc., but there's a few components that don't have their own canvas and you just can't do it.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users