Avatar of BiggBrotha
BiggBrotha
Ā asked on

How to call a CLSID Column Handler function to get the result string?

Hello,

I want to call a function of a Column Handler / InfoTip ActiveX.

Its of Embird Embroidery Software.

The software created a explorer column handler, to show embroidery file stitches count and other file Ā data.

How do i call this function to get the result string?

or how can i call the following method to get the resulting string?:
{DB8853E3-33CC-447E-84AA-FC319381A97B}6

this seems to be a CLSID id,Index (of column handler)

Here a InfoTip Registry Data of a .emb file, registered as: EMBIRd.file.emb under HKEY_CLASSES_ROOT

InfoTip REG_SZ "prop:Name;{DB8853E3-33CC-447E-84AA-FC319381A97B}6;{DB8853E3-33CC-447E-84AA-FC319381A97B}10;Type;Size;create;write;access;DocTitle;DocSubject;DocAuthor;DocCategory;DocComments"

QuickTip REG_SZ "prop:{DB8853E3-33CC-447E-84AA-FC319381A97B}6;Size"
TileInfo REG_SZ "prop:{DB8853E3-33CC-447E-84AA-FC319381A97B}6;Size"

You can see a screenshot bellow.
infotip.JPG
Web ComponentsWindows OSDelphi

Avatar of undefined
Last Comment
BiggBrotha

8/22/2022 - Mon
systan

something like that?
if that's the step to get what you want, please indicate what's next?
unit Unit1;

interface

uses Registry,
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  tS: TStringList;

implementation

{$R *.dfm}



procedure ReadCLSID;
var
  MyReg: TRegistry;
begin
  ts := TStringList.Create;
  MyReg := TRegistry.Create(KEY_EXECUTE);
   with MyReg do
    try
       RootKey := HKEY_CLASSES_ROOT;
       OpenKey('Clsid',false);
       GetKeyNames(ts);
    finally
       CloseKey;
       Free;
    end;
end;


procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
ReadCLSID;
Listbox1.Items := ts;
Caption := inttostr(Listbox1.Items.count);
for i := 0 to Listbox1.Items.count-1 do
begin
if listbox1.items[i]='{DB8853E3-33CC-447E-84AA-FC319381A97B}' then
begin
showmessage('found: ' + listbox1.items[i]);
exit;
end;
end;
end;

end.

Open in new window

BiggBrotha

ASKER
No, this will read Registry Keys.
i want toquery
BiggBrotha

ASKER
No, this will read Registry Keys.

i want to query the function number 6 of this activex object {DB8853E3-33CC-447E-84AA-FC319381A97B}
to return something like:

54.8x87.2mm, 3619st, 5/5clrs
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
systan

quering is reading
so, you must read first the {DB8853E3-33CC-447E-84AA-FC319381A97B} to get 6, then return 54.8x87.2mm, 3619st, 5/5clrs

I'll take a look
systan

Ok, can you save your registry and attach it, so I can see whats the structure inside.
To attach, just click file, then browse your save reg
systan

But probably I would not see your registry;
try to use this component;

unit TipTreeView;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls;

type
TInfoTipEvent = procedure(Sender: TObject; Item: TTreeNode;
var InfoTip: string) of object;
TTipTreeView = class(TTreeView)
private
FOnInfoTip: TInfoTipEvent;
published
property OnInfoTip: TInfoTipEvent read FOnInfoTip write FOnInfoTip;
public
procedure CMHintShow(var Message: TMessage); message CM_HINTSHOW;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Samples', [TTipTreeView]);
end;

procedure TTipTreeView.CMHintShow(var Message: TMessage);
var
Item: TTreeNode;
ItemRect: TRect;
InfoTip: string;
begin
if Assigned(FOnInfoTip) then
with TCMHintShow(Message) do
begin
Item := GetNodeAt(HintInfo.CursorPos.X, HintInfo.CursorPos.Y);
if Item <> nil then
begin
InfoTip := Item.Text;
if Assigned(FOnInfoTip) then FOnInfoTip(Self, Item, InfoTip);
ItemRect := Item.DisplayRect(False);
ItemRect.TopLeft := ClientToScreen(ItemRect.TopLeft);
ItemRect.BottomRight := ClientToScreen(ItemRect.BottomRight);
with HintInfo^ do
begin
HintInfo^.CursorRect := ItemRect;
HintInfo^.HintStr := InfoTip;
HintPos.Y := CursorRect.Top + GetSystemMetrics(SM_CYCURSOR);
HintPos.X := CursorRect.Left + GetSystemMetrics(SM_CXCURSOR);
GetSystemMetrics(SM_CXCURSOR);
HintInfo^.HintMaxWidth := ClientWidth;
Message.Result := 0;
end
end;
end
else
inherited;
end;

end.

Open in new window

⚔ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
BiggBrotha

ASKER
here is the registry


Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\EMBIRD.File.emb]
"InfoTip"="prop:Name;{DB8853E3-33CC-447E-84AA-FC319381A97B}6;{DB8853E3-33CC-447E-84AA-FC319381A97B}10;Type;Size;create;write;access;DocTitle;DocSubject;DocAuthor;DocCategory;DocComments"
"QuickTip"="prop:{DB8853E3-33CC-447E-84AA-FC319381A97B}6;Size"
"TileInfo"="prop:{DB8853E3-33CC-447E-84AA-FC319381A97B}6;Size"
@="EMB File"

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\DefaultIcon]
@="%1"

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\PredchadzajucaAsociacia]
@="ES.Documento"

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shell]

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shell\convert]
@="&Convert"

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shell\convert\command]
@="\"C:\\Program Files\\EMBIRD32\\EMBIRD.EXE\" \"%1\" /C"

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shell\edit]
@="&Edit"

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shell\edit\command]
@="\"C:\\Program Files\\EMBIRD32\\EMBIRD.EXE\" \"%1\" /E"

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shell\open]

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shell\open\command]
@="\"C:\\Program Files\\EMBIRD32\\EMBIRD.EXE\" \"%1\""

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shell\print]

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shell\print\command]
@="\"C:\\Program Files\\EMBIRD32\\EMBIRD.EXE\" \"%1\" /P"

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shell\quickview]
@="&Quick View"

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shell\quickview\command]
@="\"C:\\Program Files\\EMBIRD32\\VIEWER.EXE\" \"%1\""

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shellex]

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shellex\ContextMenuHandlers]

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shellex\ContextMenuHandlers\EmbirdCH]
@="{18D7FD25-4D7C-11D6-AB9F-8FE66DD3F034}"

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shellex\IconHandler]
@="{6B44F8C0-6D93-11D5-A405-0040C72E0001}"

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shellex\PropertySheetHandlers]

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shellex\PropertySheetHandlers\EmbirdPS]
@="{BE0E21B1-AA13-4786-BCB3-0A97F641F23E}"

[HKEY_CLASSES_ROOT\EMBIRD.File.emb\shellex\{BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}]
@="{A81E778C-14EF-49B0-BC12-E7980ECC51EF}"
systan

Now where is 54.8x87 in your registry? Ā Did you find it?
BiggBrotha

ASKER
No, because it is not in registry . It's returned by a dynamic Ā  Activex function identified by the following Clsid {DB8853E3-33CC-447E-84AA-FC319381A97B}6, and the 6 is probably a column handler index function of this activex control. I want to know how to call this function to get the resulting string that is processed by this activex control , and probably uses the filename as only parameter to show file info ( total stitches , colors and so on ) but I don't need to know how this activex parse the file to get the data , I only need to know how windows calls this function to show in explorer the resulting information. I have found so much howtos teaching how to create these active x controls. but i dont need to create i need to use An existing control. these explorer activex controls are known by column handlers, infotip handlers , thumbnail handlers and so on.
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
systan

54.8x87.2mm is a dimension? image dimension?
systan

Do you want to get the return when file is clicked? or when file is pointed?
BiggBrotha

ASKER
I want to know how pragmatically using win32 API / activex Ā call the column handler function passing a file path as parameter to get the function result string . The dimension is of the embroidery file read by embroidery machines that has a proprietary format , it's not an image . It's a file with instructions and coordinates to the machine.
⚔ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
systan

This is the other way to get the dimension of your .EMB file.
Just use AnsiPos to position it.
unit Unit1;

interface

uses  CommCtrl, uProcessMemMgr,
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function ActiveCaption: string;
var
Handle: THandle;
Len: LongInt;
Title: string;
begin
Result := '';
Handle := GetForegroundWindow;
if Handle <> 0 then
begin
Len := GetWindowTextLength(Handle) + 1;
SetLength(Title, Len);
GetWindowText(Handle, PChar(Title), Len);
ActiveCaption := TrimRight(Title);
end;
end;

function GetStatusBarText(hStatusBarHandle: HWND; PanelNumber: Integer): string;
var
  PMM: TProcessMemMgr;
  NumberOfPanels, Len: Integer;
  PrcBuf: PChar;
  PartText: string;
begin
  if hStatusBarHandle = 0 then Exit;
  PMM := CreateProcessMemMgrForWnd(hStatusBarHandle);
  try
    NumberOfPanels := SendMessage(hStatusBarHandle, SB_GETPARTS, 0, 0);
    if PanelNumber < NumberOfPanels then
    begin
      Len := LOWORD(SendMessage(hStatusBarHandle, SB_GETTEXTLENGTH, PanelNumber, 0));
      if Len > 0 then
      begin
        PrcBuf := PMM.AllocMem(Len + 1);
        SendMessage(hStatusBarHandle, SB_GETTEXT, PanelNumber, Longint(PrcBuf));
        Result := PMM.ReadStr(PrcBuf);
        PMM.FreeMem(PrcBuf);
      end
      else
      begin
        Result := '';
      end;
    end;
  finally
    PMM.Free;
  end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  hWindow, hStatusBarHandle: HWND;
  char1:pchar;
begin
char1 := pchar(activecaption);
hWindow:= FindWindow(nil, char1);
hStatusBarHandle := FindWindowEx(hWindow, 0, 'msctls_statusbar32', nil);
Form1.Caption := GetStatusBarText(hStatusBarHandle,0);
end;

end.

Open in new window

BiggBrotha

ASKER
This works but need a person to interact with the explorer window.

i need a function like:

GetEMBInformation(fileName:string):string;


so i can feed the function with a filename and get the results.

must be a way to make the call to the activex control, like windows explorer do.
systan

If you need an ActiveX, Ā it would overwrite the infoTIP.

iS that what you want? Overwrite the infoTIP to get what you want?

OR leave the infoTIP alone and make your own goal to get the dimension?
Your help has saved me hundreds of hours of internet surfing.
fblack61
systan

If you need an ActiveX, Ā  it would overwrite the infoTIP.

iS that what you want? Ā Overwrite the infoTIP to get what you want?

OR leave the infoTIP alone and make your own goal to get the dimension?

If you really want to make your own infoTIP to get what you want and overwrite the old infoTIP that you have, try that link;
http://www.agnisoft.com/delphi/dfminfotip.zip
And don't forget to register it with regsvr32
systan

Ok;
>>i need a function like:
>>GetEMBInformation(fileName:string):string;

Here's the activeX code;
infoTIP.zip
BiggBrotha

ASKER
This is not what I want. please understand..

You provided a code that create an infotip.

Ā  // show a very basic infotip
Ā  ppwszTip := StringToOleStr('The infotip for: ' + #13 + fName);
Ā  Result := S_OK;

I don't want to create an infotip.
I want to grab 3rd party infotips data.

lets assume that you created this infotip that you sent and registered the .dll. when i mousehover the file its show:
The infotip for: Filename .

I want to have access to this function that you created. from another delphi application.

like:
function GetSystanInfotip:string external 'systaninfotip.dll';
⚔ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
systan

>>I don't want to create an infotip.
>>I want to grab 3rd party infotips data.

Ok well leave the infoTIP alone and make our own goal to get the dimension.
And I think you know better than me in terms of infoTIP, Ā let me think if I can help you further more, nevertheless I am capable of this or not, Ā I will try to help.
BiggBrotha

ASKER
I think that what this guy tried to do , is the same thing i'm trying to do.

http://www.tech-archive.net/Archive/Development/microsoft.public.win32.programmer.ole/2004-07/0230.html


i tryed to convert to delphi but its givin-me access violation errors


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,activex,shlobj,shellapi, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

function SHILCreateFromPath(Path: Pointer; PIDL: PItemIDList; var Attributes: Cardinal): HResult; stdcall;

var
  Form1: TForm1;

  const IID_IQueryInfo: TGUID = '{DB8853E3-33CC-447E-84AA-FC319381A97B}';
//  const IID_IQueryInfo: TGUID = '{84F26EA0-42A0-1069-A2E3-08002B30309D}';
implementation

const Shell32DLL = 'shell32.dll';

function SHILCreateFromPath(Path: Pointer; PIDL: PItemIDList; var Attributes: Cardinal): HResult; external Shell32DLL name 'SHILCreateFromPath';

{$R *.dfm}


function GetInfoTip( psf:IShellFolder; pidl:PItemIdList; pszText:LPTSTR; cchTextMax:integer):boolean;
var pqi:IQueryInfo;
pwszTip:PWideChar;
begin
        Result:=False;
        pszText:='';

        if ( Assigned(pidl) )
        then begin

                if ( SUCCEEDED( psf.GetUIObjectOf( 0, 1, pidl, IID_IQueryInfo, nil, Pointer(pqi) ) ) )
                then begin
                        // assuming Unicode
                        pqi.GetInfoTip( 0, pwszTip );
                        if ( Assigned(pwszTip) )
                        then begin
                                Result:=True;
                                lstrcpyn( pszText, pchar(pwszTip), cchTextMax );
                                //SHFree( pwszTip );
                                CoTaskMemFree(pwszTip);
                        end;
                        pqi._Release;
                end;
        end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var infoTip:string;
var path:string[255];
shFolder:IShellFolder;
pidl:PITEMIDLIST;
a:cardinal;
begin
a:=0;
path:='c:\Design\Bird.EMB';
        SHGetDesktopFolder( shFolder );
        SHILCreateFromPath( @path, pidl, a );
        GetInfoTip( shFolder, pidl, pchar(infoTip), 255 );
       showmessage(infotip);
end;

end.

Open in new window

SOLUTION
systan

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
BiggBrotha

ASKER
I made some progress,

Got a function from Jedi that grabs item infotips, its almost the same function but does not contain errors due to C++ to delphi convertion.

and the program still reproducing access violations.

But if i inspect the variables in delphi breakpoint &Ā debugger: it shows the guys message:

'Shows the files, folders, program shortcuts, and other items on the desktop.'

So the function is grabbing Desktop Infotip, we just need to find a way to change these functions:

path:='c:/Design/Bird.EMB';
SHGetDesktopFolder( shFolder );
SHILCreateFromPath(@path, pidl, a );

pointing to a file. i think that is a function with same properties that SHGetDesktopFolder but something like "SHGetFolder" accepting the folder as param and shFolder as output result.
function SHFreeMem(var P: Pointer): Boolean;
var
  Malloc: IMalloc;
begin
  Result := False;
  if P <> nil then
  begin
    if Succeeded(SHGetMalloc(Malloc)) and (Malloc.DidAlloc(P) > 0) then
    begin
      Malloc.Free(P);
      P := nil;
      Result := True;
    end;
  end;
end;


function SHGetItemInfoTip(const Folder: IShellFolder; Item: PItemIdList): string;
var
  QueryInfo: IQueryInfo;
  InfoTip: PWideChar;
begin
  Result := '';
  if (Item = nil) or (Folder = nil) then
    Exit;
  if Succeeded(Folder.GetUIObjectOf(0, 1, Item, IQueryInfo, nil,
    Pointer(QueryInfo))) then
  begin
    if Succeeded(QueryInfo.GetInfoTip(0, InfoTip)) then
    begin
      Result := WideCharToString(InfoTip);
      SHFreeMem(Pointer(InfoTip));
    end;
  end;
end;

Open in new window

All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
Ephraim Wangoya

Do it like this, you have to get to the exact file itself

function TForm1.GetToolTip(const AFileName: string): string;
var
Ā  DesktopFolder, FileFolder: IShellFolder;
Ā  pidl, filePidl: PItemIdList;
Ā  QueryInfo: IQueryInfo;
Ā  foldername, filename: string;
Ā  pEaten, pAttribs: Cardinal;
Ā  InfoTip: PWideChar;
begin
Ā  foldername := ExtractFileDir(AFileName);
Ā  filename := ExtractFileName(AFileName);

Ā  SHGetDesktopFolder(desktopFolder);

Ā  DesktopFolder.ParseDisplayName(Handle, nil, PWideChar(folderName), pEaten, pidl, pAttribs);

Ā  DesktopFolder.BindToObject(pidl, nil, IID_IShellFolder, FileFolder);

Ā  FileFolder.ParseDisplayName(Handle, nil, PWideChar(filename), pEaten, filePidl, pAttribs);
Ā 
Ā  FileFolder.GetUIObjectOf(0, 1, filePidl, IID_IQueryInfo, 0, Pointer(QueryInfo));

Ā  if Succeeded(QueryInfo.GetInfoTip(0, InfoTip)) then
Ā  begin
Ā  Ā  Result:= WideCharToString(InfoTip);
Ā  Ā  SHFreeMem(Pointer(InfoTip));
Ā  end;
end;

BiggBrotha

ASKER
Its givin-me access violation error on line:

FileFolder.ParseDisplayName(Handle, nil, PWideChar(filename), pEaten, filePidl, pAttribs);

i tried to figure out why, but i didn't had success.

I don't know what to do.

Please help?
Ephraim Wangoya

Are you using Delphi 7

You have to change the line to
DesktopFolder.ParseDisplayName(Handle, nil, PWideChar(WideString(folderName)), pEaten, pidl, pAttribs);

Use this
function TForm1.GetToolTip(const AFileName: string): string;
var
Ā  DesktopFolder, FileFolder: IShellFolder;
Ā  pidl, filePidl: PItemIdList;
Ā  QueryInfo: IQueryInfo;
Ā  foldername, filename: string;
Ā  pEaten, pAttribs: Cardinal;
Ā  InfoTip: PWideChar;
Ā  hr: HResult;
begin
Ā  foldername := ExtractFileDir(AFileName);
Ā  filename := ExtractFileName(AFileName);

Ā  SHGetDesktopFolder(desktopFolder);

Ā  DesktopFolder.ParseDisplayName(Handle, nil, PWideChar(WideString(folderName)), pEaten, pidl, pAttribs);

Ā  if Succeeded(DesktopFolder.BindToObject(pidl, nil, IID_IShellFolder, FileFolder)) then
Ā  begin
Ā  Ā  FileFolder.ParseDisplayName(Handle, nil, PWideChar(WideString(filename)), pEaten, filePidl, pAttribs);
Ā  Ā  FileFolder.GetUIObjectOf(0, 1, filePidl, IID_IQueryInfo, 0, Pointer(QueryInfo));

Ā  Ā  if Succeeded(QueryInfo.GetInfoTip(0, InfoTip)) then
Ā  Ā  begin
Ā  Ā  Ā  Result := WideCharToString(InfoTip);
Ā  Ā  Ā  SHFreeMem(Pointer(InfoTip));
Ā  Ā  end;
Ā  end;
end;
⚔ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
ASKER CERTIFIED SOLUTION
Ephraim Wangoya

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚔ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
BiggBrotha

ASKER
Thanks