Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
494 Users Online NOW
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi



Loremo - the 1.5 liter car coming in 2009




Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (2)


Creating a simple Icon Handler for the Windows ExplorerComponent available for this articleFormat this article printer-friendly!Bookmark function is only available for registered users!
Showing a different icon for every file (like ICO and EXE)
Product:
Delphi 3.x (or higher)
Category:
Shell API
Skill Level:
Scoring:
Last Update:
04/25/2005
Search Keys:
delphi delphi3000 article borland vcl code-snippet Windows Icons Explorer Icon Handler File Image IExtractIcon IPersistFile
Times Scored:
4
Visits:
4181
Uploader: Daniel Wischnewski
Company: Delphi-PRAXiS
Reference: Delphi-PRAXiS
Component Download: http://www.gatenetwork.com/delphi-samples/iconhandler.zip
 
Question/Problem/Abstract:
Some of you might have wondered how automatically every Icon file automatically displays its own icon in the windows explorer. Especially some design and paint applications use this possibility to show the content of a file rather than the same icon for all of them.
Answer:



Getting across the point

This article shows you how to create a simple icon handler for windows text (*.txt) files that will display the first characters rather than the default icon.


Default view



Text icons using Icon Handler


The sample given here will only show you the outline of such a project, but this should be sufficient to get you started on your journey. The Icon handler will create large icons only, so the explorer will shrink them rather ugly. However, it is rather simple to extend the functionality.

Getting started

We'll have to create an in-process server DLL that will export the interfaces IExtractIcon and IPersistFile. Most of the methods we need to declare do not need to be actually implemented, because they are never used. We will simply return E_NOTIMPL for these methods. All we have to do is to provide handling for three of the methods.

Load

The Windows Explorer will pass along the file name of the file we have to create the icon for. We'll simple save the name in a variable.

GetIconLocation

We'll tell the Windows Explorer that it must call yet another procedure, because we must create the icon from scratch. Further we set some flags for caching and similar handling.

Extract

That's were we actually create the Icon. First we extract the desired size of the icon. Next, we create the bitmaps for the AND mask and the XOR mask. On the XOR mask we will write up to the first 3 lines of text from the text file. This does not really give a preview, however it shows the point for custom icons.

Last we are going to tell windows to create the icon desired and return it to the explorer. And we are done.

Registering the Icon Handler

First we will have to access the Registry. Assuming that your Text files will point to the entry HKCR\txtfile we will first back-up the old icon handler (key: DefaultIcon) and then set the new one. Further we register the IconHandler (Key: ShellEx\IconHandler). That's it.

To simplify the task of registering/deregistering the icon handler I have created a new class that is derived from TTypedComObjectFactory. There I'll simple override the method UpdateRegistry and we are done.

You can either register the DLL directly from Delphi or simply use Windows RegSvr32 utility.

Create your project

Create a new ACTIVE X library, add a type library to it and create a COM Object and name it TxtIcon. Finally paste the code below into the TxtIcon unit and compile it.

Note You may have to restart the computer (or the Windows Explorer using the Task Manager) to see the changes take effect.

You can simply download the code using this link.


THE CODE

unit TxtIcon;

interface

uses
  
Windows, ActiveX, Classes, ComObj, TxtViewer_TLB, StdVcl, ShlObj;

type
  
TTxtIcon = class(TTypedComObject, ITxtIcon, IExtractIcon, IPersistFile)
  private
    
FCurrFile: WideString;
  protected
    
{Declare ITxtIcon methods here}
    // IExtractIcon
    
function GetIconLocation(uFlags: UINT; szIconFile: PAnsiChar; cchMax: UINT;
      out piIndex: Integer; out pwFlags: UINT): HResult; stdcall;
    function Extract(pszFile: PAnsiChar; nIconIndex: UINT;
      out phiconLarge, phiconSmall: HICON; nIconSize: UINT): HResult; stdcall;
    // IPersist
    
function GetClassID(out classID: TCLSID): HResult; stdcall;
    // IPersistFile
    
function IsDirty: HResult; stdcall;
    function Load(pszFileName: POleStr; dwMode: Longint): HResult;
      stdcall;
    function Save(pszFileName: POleStr; fRemember: BOOL): HResult;
      stdcall;
    function SaveCompleted(pszFileName: POleStr): HResult;
      stdcall;
    function GetCurFile(out pszFileName: POleStr): HResult;
      stdcall;
  end;

  TIconHandlerFactory = class(TTypedComObjectFactory)
  protected
  public
    procedure
UpdateRegistry(Register: Boolean); override;
  end;

implementation

uses
  
SysUtils, ComServ, Graphics, Registry;

{ TTxtIcon }

function TTxtIcon.Extract(pszFile: PAnsiChar; nIconIndex: UINT;
  out phiconLarge, phiconSmall: HICON; nIconSize: UINT): HResult;
var
  
IconSize, I: Integer;
  MaskAnd, MaskXor: TBitmap;
  IconInfo: TIconInfo;
  SL: TStringList;
begin
  
// draw the large icon
  
IconSize := Lo(nIconSize);

  // create and prepare AND mask
  
MaskAnd := TBitmap.Create; try
  MaskAnd.Monochrome := true;
  MaskAnd.Width := IconSize;
  MaskAnd.Height := IconSize;

  MaskAnd.Canvas.Brush.Color := clBlack;
  MaskAnd.Canvas.FillRect(Rect(0, 0, IconSize, IconSize));

  // create and prepare XOR mask

  
MaskXor := TBitmap.Create; try
  MaskXor.Width := IconSize;
  MaskXor.Height := IconSize;

  MaskXor.Canvas.Brush.Color := clWhite;
  MaskXor.Canvas.FillRect(Rect(0, 0, IconSize, IconSize));
  MaskXor.Canvas.Font.Color := clNavy;

  // load file
  
SL := TStringList.Create; try
  try
    
SL.LoadFromFile(FCurrFile);
    I := 0;
    // paint up to three lines of text onto the canvas
    
while (I < SL.Count) and (I < 3) do
    begin
      
MaskXor.Canvas.TextOut(0, I * 15, SL.Strings[I]);
      Inc(I);
    end;
  except
    
// user may not have access rights
    
MaskXor.Canvas.TextOut(0, 0, '???');
  end;
  finally SL.Free; end;

  // create icon for explorer
  
IconInfo.fIcon := true;
  IconInfo.xHotspot := 0;
  IconInfo.yHotspot := 0;
  IconInfo.hbmMask := MaskAnd.Handle;
  IconInfo.hbmColor := MaskXor.Handle;
  // return large icon
  
phiconLarge := CreateIconIndirect(IconInfo);
  // signal success
  
Result := S_OK;

  finally MaskAnd.Free; end;
  finally MaskXor.Free; end;
end;

function TTxtIcon.GetClassID(out classID: TCLSID): HResult;
begin
  
classID := CLASS_TxtIcon;
  Result := S_OK;
end;

function TTxtIcon.GetCurFile(out pszFileName: POleStr): HResult;
begin
  
Result := E_NOTIMPL;
end;

function TTxtIcon.GetIconLocation(uFlags: UINT; szIconFile: PAnsiChar;
  cchMax: UINT; out piIndex: Integer; out pwFlags: UINT): HResult;
begin
  
piIndex := 0;
  pwFlags := GIL_DONTCACHE or GIL_NOTFILENAME or GIL_PERINSTANCE;
  Result := S_OK;
end;

function TTxtIcon.IsDirty: HResult;
begin
  
Result := E_NOTIMPL;
end;

function TTxtIcon.Load(pszFileName: POleStr; dwMode: Integer): HResult;
begin
  
FCurrFile := pszFileName;
  Result := S_OK;
end;

function TTxtIcon.Save(pszFileName: POleStr; fRemember: BOOL): HResult;
begin
  
Result := E_NOTIMPL;
end;

function TTxtIcon.SaveCompleted(pszFileName: POleStr): HResult;
begin
  
Result := E_NOTIMPL;
end;

{ TIconHandlerFactory }

procedure TIconHandlerFactory.UpdateRegistry(Register: Boolean);
var
  
ClsID: string;
begin
  
ClsID := GUIDToString(ClassID);
  inherited UpdateRegistry(Register);
  if Register then
  begin
    with
TRegistry.Create do
    try
      
RootKey := HKEY_CLASSES_ROOT;
      if OpenKey('txtfile\DefaultIcon', True) then
      try
        
WriteString('backup', ReadString(''));
        WriteString('', '%1');
      finally
        
CloseKey;
      end;
      if OpenKey('txtfile\shellex\IconHandler', True) then
      try
        
WriteString('', ClsID);
      finally
        
CloseKey;
      end;
    finally
      
Free;
    end;
  end else begin
    with
TRegistry.Create do
    try
      
RootKey := HKEY_CLASSES_ROOT;
      if OpenKey('txtfile\DefaultIcon', True) then
      try
        if
ValueExists('backup') then
        begin
          
WriteString('', ReadString('backup'));
          DeleteValue('backup');
        end;
      finally
        
CloseKey;
      end;
      if OpenKey('txtfile\shellex', True) then
      try
        if
KeyExists('IconHandler') then
          
DeleteKey('IconHandler');
      finally
        
CloseKey;
      end;
    finally
      
Free;
    end;
  end;
end;

initialization
  
TIconHandlerFactory.Create(
    ComServer, TTxtIcon, Class_TxtIcon, ciMultiInstance, tmApartment
  );
end.


This sample is brought to you by the German Delphi Forum!
Daniel Wischnewski





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
Great Stuff... BUT!!!!
    William Cossey (Oct 11 2006 11:07PM)

After registering (DllRegisterServer) the dll file try this...

right click on the file (default: .txt files), select "Properties"...

then close the properties dialog...

what do you get... a BIG FAT crash (Explorer.exe)...
Respond

RE: Great Stuff... BUT!!!!
Forud A (Sep 9 2007 2:28PM)

I know why this hapend. I think this is a bug LIKE in vcl. you can found this lines in ComObj.pas :
function TComObject.ObjRelease: Integer;
begin
  // InterlockedDecrement returns only 0 or 1 on Win95 and NT 3.51
  // returns actual result on NT 4.0
  Result := InterlockedDecrement(FRefCount);
  if Result = 0 then Destroy;
end;

the last line is problem.   if Result = 0 then Destroy; this should not happend since explorer try to use this object (even if there is no refrence to it) at another time.
I don't know but i tink its not good for an object to destroy himself. I have problem with this in create a custom property page and i try to write some nasty code and override (with some warning from compiler) then ObjRelese method , and ObjAddRef method of ComObject (its not good since they are not virtual or dynamic) but it work.

Sorry if my english is very bad :D
Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
A. B. Talal
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)