Solved

If you do this, you get the points.

Posted on 2000-04-15
9
150 Views
Last Modified: 2010-04-04
This is a rephrase of a previous question. I have a COMBOBOX Vcl that I'm set on using in my project. I will be using it. I'm aware there are components that do this, and I'm aware there are examples of this certain places. See the two example pictures at:
http://www.users.uswest.net/~psyreal/delphi/

I want to do this (through code) with a normal combobox.

If you don't want to do the work please don't answer. If you can make a form look like this with a normal combobox, then that is the code I need. It can't just "look" like it. It needs to function the same.

Thanks people!

-Psylord
0
Comment
Question by:Psylord
9 Comments
 
LVL 1

Expert Comment

by:DValery
ID: 2719951
I saw like this freeware component on:
http://www.torry.ru/
0
 

Author Comment

by:Psylord
ID: 2719986
hehe
You don't understand. I don't WANT a component. I WANT to use the one I already have. But thanks for the try.

-Psylord
0
 
LVL 10

Expert Comment

by:Lischke
ID: 2720057
Hi Psylord,

despite you rephrased the question, it hasn' become clearer... Actually, what you want (I think) is code to enumerate the shell's name space. Is this so? All the other stuff (icons, indentation etc.) is just some additional execercise.

Ciao, Mike
0
 

Author Comment

by:Psylord
ID: 2720113
Mike,
Well... Some people were trying to point me to components etc... I don't want to use a special component for this, and I have my reasons why. Y=ou said exactly what I wanted (I think).

THe problem is I'm not good enough to sort through piles of code and try to decipher them for my own needs... I can expect a lexure at this point but I assure you it's not needed.

I realize it's a lot of work to do... And I'm taking my chances trying to get someone to genrously donate some time to me. I will increase the points to this question as soon as my other ones are gone and I get the points back I'm not trying to rip anyone off.

You seem to have quite a bit of knowledge about the subject and I would appreciate any attempts you can make at answering this how I've explained.

Regards,
-Psylord
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 2

Expert Comment

by:hhamster
ID: 2720250
Have you looked at other components with source code?

I often (re)write components by my own, but there is realy a lot of them with the source code, so you can see whats the job to do and what are the directions to go when writing your own.

One of the best freeware collection is the Rx Library (www.rxlib.com) which is all in source code.

Such things you are attending to do are to complex to to it by this way (on an advice site). It's not one specific question which can be answered in some liitle code example (look at the guidelines on asking questions on this site). So, you can find a person here which will help you in doing this job or look at the sugested thinkgs (in this case - components) that people suggest to you.

Best whishes in solving your problem.
0
 
LVL 10

Expert Comment

by:ptmcomp
ID: 2720859
If you want to, you can write a owner draw combobox. In the Delphi help there is a good example.
To fill up your combo you have to call some shell commands, e.g: SHGetFileInfo.
ptm.
0
 
LVL 3

Expert Comment

by:bryan7
ID: 2721498
yep it's not a short code.. you have to manage getting all the drives etc ( as I saw in the gif ) and the icons using SHGetFileInfo, unless you want to use your own icons.. it's not so easy, not too difficult though
0
 
LVL 2

Accepted Solution

by:
mullet_attack earned 20 total points
ID: 2721643
Ok, here's some code that may help you out.

Form1 has button2, Imagelist1, and combobox1 on it.

It's not great code, but it works. I cheated on the icons for the drives, i should have used GetNormalIcon(ProperPath), instead of hardcoding GetNormalIcon('c:\') for each drive.

However, the code does show the use of SHGetFileInfo and owner-draw combo as ptmcomp mentioned.

Mark






unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, ShellAPI, ShlObj,ActiveX, ImgList, Spin, ExtCtrls ;

type
  PComboItem = ^TComboItem;
  TComboItem = record
    IconIndex : integer;
    sFolder : IShellFolder;
    id : PItemIDList;
    Level : integer;
  end;

  TForm1 = class(TForm)
    imaglst: TImageList;
    ComboBox1: TComboBox;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure ComboBox1DrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
  private
    FWinDir: string;
    procedure DoSubItems(ParentItem: PComboItem);
    function GetNormalIcon(Path: string): integer;
    function GetIcon(pidl: PItemIDList): integer;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  Desktop : IShellFolder;
  ppMalloc: IMalloc;

implementation

{$R *.DFM}


procedure TForm1.FormCreate(Sender: TObject);
var
  sfi: TShFileInfo;
begin
  try
    SetLength(FWinDir, MAX_PATH);
    Setlength(FWinDir, GetWindowsDirectory(PChar(FWinDir), MAX_PATH));
    FWinDir := FWinDir + '\';
    ImagLst.Handle := SHGetFileInfo(PChar(FWinDir), 0, sfi, sizeOf(sfi),
      SHGFI_SYSICONINDEX or SHGFI_SMALLICON or SHGFI_ICONLOCATION);
    ImagLst.ShareImages := True;
    ImagLst.BlendColor := clHighLight;
  finally
  end;

end;

function TForm1.GetIcon(pidl: PItemIDList): integer;
var
  sfi: TShFileInfo;
begin
  SHGetFileInfo(PChar(PIDL), 0, sfi, SizeOf(TSHFileInfo),
    SHGFI_SYSICONINDEX or SHGFI_SMALLICON or SHGFI_PIDL);
  Result := sfi.iIcon;
end; {GetNormalIcon}


function TForm1.GetNormalIcon(Path: string): integer;
var
  sfi: TShFileInfo;
begin
  SHGetFileInfo(Pchar(Path), 0, sfi, SizeOf(TSHFileInfo),
    SHGFI_SYSICONINDEX or SHGFI_SMALLICON);
  Result := sfi.iIcon;
end; {GetNormalIcon}

procedure TForm1.Button2Click(Sender: TObject);
var
 DesktopItem : PComboItem;
 idDesktop : PItemIDList;
 sfi: TSHFileInfo;
begin
  SHGetMalloc(ppMalloc);
  SHGetDesktopFolder( Desktop );
  DesktopItem := new(PComboItem);
  DesktopItem^.sFolder := Desktop;
  DesktopItem^.Level := 0;
  combobox1.items.AddObject('Desktop',TObject(DesktopItem));
  if SHGetSpecialFolderLocation(Handle, CSIDL_DESKTOP, idDesktop) = NOERROR then
    if SHGetFileInfo(PChar(idDesktop), 0, Sfi, SizeOf(TSHFileInfo), SHGFI_PIDL
      or
      SHGFI_SYSICONINDEX or SHGFI_SMALLICON or SHGFI_DISPLAYNAME) <> 0 then
    begin
      DesktopItem^.IconIndex := Sfi.iIcon;
    end;
   DoSubItems(DeskTopItem);
end;

procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var
  Icon : TBitmap;
  ComboItem : TComboItem;
  srcRect, destRect : TRect;
begin
  with control as TComboBox do
    begin
      ComboItem := PComboItem(items.Objects[Index])^;
      try
        icon := tbitmap.create;
      ImagLst.GetBitmap(ComboItem.IconIndex, Icon);
     canvas.fillrect(rect);
     srcRect.left := 0;
     srcRect.top := 0;;
     srcRect.right := ImagLst.width;
     srcRect.bottom := ImagLst.Height;
     destRect := Rect;
     destRect.left :=  (ComboItem.level * 16);
     destRect.right := destRect.left + srcRect.right;
     destRect.bottom := destRect.top + srcRect.bottom;

      Canvas.Copyrect(destRect,Icon.canvas,srcRect);
      canvas.textout(destRect.right, destRect.top, items[index]);
      finally
      icon.free;
      end;
    end;
end;


procedure TForm1.DoSubItems(ParentItem: PComboItem);
var
  EnumIDList : IEnumIDList;
  fetched : ULONG;
  pidl : PItemIDList;
  MyNode : TTreeNode;
  Name: TStrRet;
  DisplayName : string;
  psfi: TSHFileInfo;
  ShellFolder : IShellFolder;
  tempComboItem : PComboItem;
  fullpath : array[0..Max_path] of char;
      idNetwork: PItemIDList;
  IndentLevel : integer;
type
  PSTRRet = ^TStrRet;
  _STRRET = record
     uType: UINT;              { One of the STRRET_* values }
     case Integer of
       0: (pOleStr: LPWSTR);                    { must be freed by caller of GetDisplayNameOf }
//       1: (pStr: LPSTR);                        { NOT USED }
       1: (uOffset: UINT);                      { Offset into SHITEMID (ANSI) }
       2: (cStr: array[0..MAX_PATH-1] of Char); { Buffer to fill in }
    end;
  TStrRet = _STRRET;
begin
  IndentLevel := pComboItem(ParentItem)^.Level + 1;
 ShellFolder := IShellFolder(pComboItem(ParentItem)^.sFolder);
 if ShellFolder.EnumObjects(handle,SHCONTF_FOLDERS,EnumIDList) = NOERROR then
   begin
     While EnumIDList.next(1, pidl, Fetched) <> S_FALSE do
       begin
         ShellFolder.GetDisplayNameOf(pidl,SHGDN_NORMAL, Name);
         case Name.uType of
            STRRET_WSTR : DisplayName := name.pOLEStr;
            STRRET_OFFSET :
              begin
                SHGetFileInfo(PChar(pidl), 0, psfi, sizeof(TSHFileInfo), SHGFI_PIDL
                      or SHGFI_SYSICONINDEX or SHGFI_SMALLICON or SHGFI_DISPLAYNAME);
                DisplayName := psfi.szDisplayName;
              end;
            STRRET_CSTR : DisplayName := name.cStr;
         end;
         ppMalloc.free(Name.pOleStr); // just in case
         Application.processmessages;
         tempComboItem := new(PComboItem);
         tempComboItem^.Level := IndentLevel;
         ShellFolder.BindToObject(pidl, nil, IID_IShellFolder, tempComboItem^.sFolder);
         ComboBox1.items.addObject(DisplayName, TObject(tempComboItem));
         if Pos(':',DisplayName) > 0 then
           begin
             tempComboItem^.IconIndex := GetNormalIcon('c:\');
           end
         else
         tempComboItem^.IconIndex := GetIcon(pidl);
         if DisplayName = 'My Computer' then
           DoSubItems(tempComboItem);
      end;
    end;
end;


end.

0
 

Author Comment

by:Psylord
ID: 2724326
mullet_attack,

MUCH APPRECIATED. Thanks millions. This is exactly what I've been looking for... It needs a bit of work, but it's a start... I think I can figure the rest out after a bit of reading etc. If not, I'll just port here again. :)

Thanks for actually taking the time to do the work.
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now