BranchViewExtended wfx-plugin

Discuss and announce Total Commander plugins, addons and other useful tools here, both their usage and their development.

Moderators: Stefan2, white, sheep, Hacker

User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 37485
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) » 2009-10-08, 15:40 UTC

Indeed if you do not call ExtractImage with parameter LR_SHARED, you must tell TC to delete the icon after using it! Otherwise you will get a memory leak. See
http://msdn.microsoft.com/en-us/library/ms648045%28VS.85%29.aspx
Author of Total Commander
http://www.ghisler.com

User avatar
MVV
Power Member
Power Member
Posts: 8285
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV » 2009-10-08, 17:23 UTC

ghisler(Author) wrote:Indeed if you do not call ExtractImage with parameter LR_SHARED, you must tell TC to delete the icon after using it! Otherwise you will get a memory leak. See
http://msdn.microsoft.com/en-us/library/ms648045%28VS.85%29.aspx
I think this note is only for calling LoadImage in each FsExtractCustomIcon? If I extract icon only once during plugin initialization and tell to TC its handle every time, I do not create new resource and TC should not delete it.

User avatar
kotlomoy
Junior Member
Junior Member
Posts: 99
Joined: 2008-03-09, 07:27 UTC

Post by *kotlomoy » 2009-10-09, 18:29 UTC

kotlomoy wrote: -- When there is a LOT of directories (thousands) TC doesn't draw all my icons. More importantly that TC itself gets problems with redrawing of windows, buttons, menu... :?
Same here:

Code: Select all

HINSTANCE theDll = NULL;
HICON hIcon16, hIcon32;

BOOL APIENTRY DllMain( HINSTANCE hModule,
					  DWORD ul_reason_for_call,
					  LPVOID lpReserved
					  )
{
	theDll = hModule;
	hIcon16 = (HICON)LoadImage(theDll,MAKEINTRESOURCE(IDI_ICON_FOLDER16),IMAGE_ICON,16,16,0);
	hIcon32 = (HICON)LoadImage(theDll,MAKEINTRESOURCE(IDI_ICON_FOLDER32),IMAGE_ICON,32,32,0);
	return TRUE;
} 

int __stdcall FsExtractCustomIcon(char* RemoteName,int ExtractFlags,HICON* TheIcon)
{
	if ('/' == RemoteName[ strlen( RemoteName ) - 1 ])
	{
		if(ExtractFlags&FS_ICONFLAG_SMALL)
			*TheIcon = hIcon16;
		else
			*TheIcon = hIcon32;

		return FS_ICON_EXTRACTED;

	}
	return FS_ICON_USEDEFAULT;
} 
And here:

Code: Select all

int __stdcall FsExtractCustomIcon(char* RemoteName,int ExtractFlags,HICON* TheIcon)
{
	if ('/' == RemoteName[ strlen( RemoteName ) - 1 ])
	{
     if(ExtractFlags&FS_ICONFLAG_SMALL)
         *TheIcon=(HICON)LoadImage(theDll,MAKEINTRESOURCE(IDI_ICON_FOLDER16),IMAGE_ICON,16,16,0);
      else
         *TheIcon=(HICON)LoadImage(theDll,MAKEINTRESOURCE(IDI_ICON_FOLDER32),IMAGE_ICON,32,32,0);

      return FS_ICON_EXTRACTED_DESTROY;

	}
	return FS_ICON_USEDEFAULT;
}
:?
#213083 Single user license
BranchViewExtended

User avatar
MVV
Power Member
Power Member
Posts: 8285
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV » 2009-10-10, 02:59 UTC

That's strange. If you return icon extracted before, or if you just return 0, there should be no difference - TC will draw existing icon - yours or its own, no matter. Did you try to pass LR_SHARED flag to LoadImage?

User avatar
kotlomoy
Junior Member
Junior Member
Posts: 99
Joined: 2008-03-09, 07:27 UTC

Post by *kotlomoy » 2009-10-10, 08:44 UTC

2MVV

Yes, I did.
Also I tried LoadIcon.

The result is same - after 9000-10000 dirs TC stops drawing my icons. TC draws 2-4 black squares then draws default icons. Then TC itself gets problems with redrawing.
#213083 Single user license
BranchViewExtended

User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 37485
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) » 2009-10-13, 18:47 UTC

You can watch the number used GDI and USER objects in Task Manager (Ctrl+Shift+ESC), you need to switch on additional columns to see them. This will show you that the icons aren't freed...
Author of Total Commander
http://www.ghisler.com

User avatar
kotlomoy
Junior Member
Junior Member
Posts: 99
Joined: 2008-03-09, 07:27 UTC

Post by *kotlomoy » 2009-10-13, 19:32 UTC

ghisler(Author) wrote:You can watch the number used GDI and USER objects in Task Manager (Ctrl+Shift+ESC), you need to switch on additional columns to see them. This will show you that the icons aren't freed...
The problem is how to free icons. Where to free.
I've tried different ways but nothing works for me.

Can somebody give me a working example of FsExtractCustomIcon? :roll:
#213083 Single user license
BranchViewExtended

User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 37485
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) » 2009-10-13, 20:00 UTC

Did you try to return
FS_ICON_EXTRACTED_DESTROY

TC will then delete the icon. You must NOT use LR_SHARED in LoadImage then.
Author of Total Commander
http://www.ghisler.com

User avatar
kotlomoy
Junior Member
Junior Member
Posts: 99
Joined: 2008-03-09, 07:27 UTC

Post by *kotlomoy » 2009-10-14, 17:18 UTC

ghisler(Author) wrote:Did you try to return
FS_ICON_EXTRACTED_DESTROY

TC will then delete the icon. You must NOT use LR_SHARED in LoadImage then.
After some testing I've found out that TC deletes icons on changing current path of file panel.
If current path doesn't change TC DOES NOT DELETE ICONS.

So TC cannot show more than 9999 custom icons in file panel
#213083 Single user license
BranchViewExtended

User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 37485
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) » 2009-10-15, 16:01 UTC

Indeed the icons are cached in the file list, so TC doesn't need to re-request them from the plugin all the time...
Author of Total Commander
http://www.ghisler.com

User avatar
kotlomoy
Junior Member
Junior Member
Posts: 99
Joined: 2008-03-09, 07:27 UTC

Post by *kotlomoy » 2009-10-15, 16:12 UTC

MVV wrote:I suggest to return special folder icon instead of default icon. This will help to distinguish folders and files.
kotlomoy wrote:If current path doesn't change TC DOES NOT DELETE ICONS.

So TC cannot show more than 9999 custom icons in file panel
Unfortunately, my plugin cannot use custom icons :(
#213083 Single user license
BranchViewExtended

User avatar
MVV
Power Member
Power Member
Posts: 8285
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV » 2009-10-15, 18:56 UTC

kotlomoy wrote:Unfortunately, my plugin cannot use custom icons :(
I do not understand why TC with your plugin can't show icons if you use one pre-extracted icon for all cases.

Hm-m, you're right, when I return same icon handle for 15k of folders, TC uses 10k of GDI objects... LR_SHARED does not matter, ExtractIcon or LoadImage - also doesn't matter!!! :? :o :shock: but why? All TC need is to draw given icon. Unfortunately I don't know how TC works here.

Hm-m, how icons are being cached? Does TC keep icon handles or draws icon into internal icons array? I think in first case TC will not use 10k of GDI objects for 10k calls of FsExtractCustomIcon because if you draw same GDI object 10k times, system will not create 10k objects. In the second case it is obvious that TC will have 10k of images in memory.

User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 37485
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) » 2009-10-16, 15:35 UTC

TC converts each icon to a bitmap with the needed foreground and background colors, and scaled to the correct size.

If all the icons are identical, or many of them, you need to tell TC about it!

From the description of FsExtractCustomIcon():

RemoteName
This is the full path to the file or directory whose icon is to be retrieved. When extracting an icon, you can return an icon name here - this ensures that the icon is only cached once in the calling program. The returned icon name must not be longer than MAX_PATH characters (including terminating 0!). The icon handle must still be returned in TheIcon!

So TC caches a separate bitmap for each different RemoteName. It's best to return the path,filename and icon Nr. of the file from which the icon was extracted.
Author of Total Commander
http://www.ghisler.com

User avatar
kotlomoy
Junior Member
Junior Member
Posts: 99
Joined: 2008-03-09, 07:27 UTC

Post by *kotlomoy » 2009-10-17, 10:06 UTC

ghisler(Author) wrote: RemoteName
When extracting an icon, you can return an icon name here - this ensures that the icon is only cached once in the calling program.
Indeed, now icons are OK :D

Version with icons:
http://cid-9a15473c9a985119.skydrive.live.com/self.aspx/!work/BranchViewEx%5E_icons.wfx

This version is slower than previuos (w/o icons) though :( so I do not recommend this one
#213083 Single user license
BranchViewExtended

User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 37485
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) » 2009-10-19, 15:40 UTC

How about returning FS_ICON_DELAYED immediately, and extracting the icon in background? Or are you doing that already?

This way TC will request the icons in a background thread only when needed, as it does for exe/lnk icons in the foreground.
Author of Total Commander
http://www.ghisler.com

Post Reply