Start printer spool manager?

 Create a shortcut for the designate printer. Example: Printer.lnk from A LaserJet Printer. Then, call
  ShellExecute(0, nil, 'Printer.lnk', nil, nil, SW_Show);
We can start the spool manager of this printer.
  How to directly start the manager without creating a shortcut?
delphi1Asked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
MadshiConnect With a Mentor Commented:
unit uni1;

interface

uses Windows, ShlObj, ActiveX, ShellAPI, Forms, sysUtils;

implementation

const maxCard = high(cardinal);

function ExecuteContextMenuCommand(sf: IShellFolder; childPidl: PItemIDList; verb: string) : boolean;
var cm   : IContextMenu;
    cm2  : IContextMenu2;
    cm3  : IContextMenu3;
    ici  : TCMInvokeCommandInfo;
    pop1 : HMenu;
    c1   : cardinal;
begin
  result:=false;
  if sf.GetUIObjectOf(Application.handle,1,childPidl,IID_IContextMenu,nil,pointer(cm))<>NOERROR then exit;
  try
    cm2:=cm as IContextMenu2;
    cm:=cm2;
    try
      cm3:=cm as IContextMenu3;
      cm:=cm3;
    except end;
  except end;
  zeroMemory(@ici,sizeOf(ici));
  with ici do begin
    cbSize:=sizeOf(TCMInvokeCommandInfo);
    fMask:=CMIC_MASK_FLAG_NO_UI;
    hwnd:=Application.handle;
    lpVerb:=PChar(verb);
    nShow:=SW_SHOW;
  end;
  if verb='' then begin
    pop1:=CreatePopupMenu;
    try
      if succeeded(cm.QueryContextMenu(pop1,0,1,$7FFF,CMF_DEFAULTONLY)) then begin
        c1:=GetMenuDefaultItem(pop1,0,0);
        if c1<>0 then begin
          ici.lpVerb:=MakeIntResource(c1-1);
          result:=cm.InvokeCommand(ici)=NOERROR;
        end;
      end;
    finally DestroyMenu(pop1) end;
  end else result:=cm.InvokeCommand(ici)=NOERROR;
end;

procedure FreePidl(var pidl: PItemIDList);
var malloc : IMalloc;
begin
  if (pidl<>nil) and (SHGetMalloc(malloc)=NOERROR) then begin
    malloc.Free(pidl);
    pidl:=nil;
  end;
end;

function PidlToStr(sf: IShellFolder; childPidl: PItemIDList) : string;
var sr : _StrRet;
begin
  result:='';
  if (sf=nil) or (childPidl=nil) then exit;
  sr.uType:=STRRET_CSTR;
  if sf.GetDisplayNameOf(childPidl,SHGDN_NORMAL,sr)<>NOERROR then exit;
  case sr.uType of
    STRRET_CSTR   : result:=string(sr.cStr);
    STRRET_OFFSET : result:=string(PChar(cardinal(childPidl)+sr.uOffset));
    STRRET_WSTR   : result:=string(sr.pOleStr);
    else            result:='';
  end;
end;

function EnumObjects(sf: IShellFolder) : string; overload;
var el     : IEnumIDList;
    malloc : IMalloc;
    pidl1  : PItemIDList;
    c1     : cardinal;
begin
  result:='';
  if (sf=nil) or (SHGetMalloc(malloc)<>NOERROR) or (sf.EnumObjects(Application.handle,maxCard,el)<>NOERROR) then
    exit;
  el.Reset;
  while el.Next(1,pidl1,c1)=NOERROR do begin
    result:=result+#$D#$A+PidlToStr(sf,pidl1);
    ExecuteContextMenuCommand(sf,pidl1,'');
    malloc.Free(pidl1);
  end;
  Delete(result,1,2);
end;

function EnumObjects(pidl: PItemIDList) : string; overload;
var sf1,sf2 : IShellFolder;
begin
  result:='';
  if (pidl=nil) or (SHGetDesktopFolder(sf1)<>NOERROR) then exit;
  if pidl^.mkid.cb<>0 then begin
    if sf1.BindToObject(pidl,nil,IID_IShellFolder,pointer(sf2))<>NOERROR then exit;
    result:=EnumObjects(sf2);
  end else result:=EnumObjects(sf1);
end;

procedure EnumAllPrinters;
var pidl : PItemIDList;
begin
  if SHGetSpecialFolderLocation(INVALID_HANDLE_VALUE,CSIDL_PRINTERS,pidl)=NOERROR then
    try
      MessageBox(0,pchar(EnumObjects(pidl)),'All printers...',0);
    finally FreePidl(pidl) end;
end;

initialization
  EnumAllPrinters;
end.
0
 
MadshiCommented:
You could use SHGetSpecialFolderLocation(Application.Handle1,CSIDL_PRINTERS,pidl) to get the PItemIDList of the printer folder. Then you could bind this pidl to a IShellFolder interface to enumerate the content of the printer folder. Then you could use ShellExecuteEx to execute the pidl.

However, this is much more complicated then executing a shellLink.
BTW, how do you create this shellLink? With your program or manually with the win95 shell?

Regards, Madshi.
0
 
delphi1Author Commented:
 I create the shellLink manually. Otherwise, createing  a shortcut by program then execute it is also Ok, but not so good.
  I must start the printer manager, not just explore the printer folder. The printer folder may contain many printers. I like to execute the default printer manager. To get default printer name is easy.
  I know this PAQ http://www.experts-exchange.com/topics/comp/lang/delphi/Q.10114613 discussed on browse printer folder using SHGetSpecialFolderLocation and ShellExecuteEx to explore Windows95 special folder.

Regrads, Yang.
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
MadshiCommented:
Yes, but the other question was about Dialup Network which has its own Guid string (like {xxxxxxx-xxxx-xxxx-xxxx-xxxxxx}). The printers don't have such a Guid string, so the solution we found for the other question won't help you at all.
Perhaps there is an easy solution for your problem. But using GetSpecialFolder and enumerating all printer (to find the printer you're searching) is the only way I know...   :-(

I asked how you create the shellLink, because - again - the only way to create a printer shortLink with a program is to use SHGetSpecialFolderLocation...   :-(

So, as I see it, either you have to live with your currently implemented solution (manually created shellLinks), or you'll have to look at SHGetSpecialFolder and all that stuff. Of course I would help you with that. I've some functions, that would make it easier for you. Hmmm. Which Delphi version are you using?

Regards, Madshi.
0
 
MadshiCommented:
Yes, but the other question was about Dialup Network which has its own Guid string (like {xxxxxxx-xxxx-xxxx-xxxx-xxxxxx}). The printers don't have such a Guid string, so the solution we found for the other question won't help you at all.
Perhaps there is an easy solution for your problem. But using GetSpecialFolder and enumerating all printer (to find the printer you're searching) is the only way I know...   :-(

I asked how you create the shellLink, because - again - the only way to create a printer shortLink with a program is to use SHGetSpecialFolderLocation...   :-(

So, as I see it, either you have to live with your currently implemented solution (manually created shellLinks), or you'll have to look at SHGetSpecialFolder and all that stuff. Of course I would help you with that. I've some functions, that would make it easier for you. Hmmm. Which Delphi version are you using?

Regards, Madshi.
0
 
delphi1Author Commented:
I am now using Delphi4, not myself :-(
Can you give me more details, such as the functions what you said? Thank you very much!

Regard, Yang.
0
 
MadshiCommented:
Hmmm. Looks like I implemented an almost ready to use solution. Just try it out!!! Was a lot of work...  :-(

Regards, Madshi.
0
 
delphi1Author Commented:
Excellent solution! Thank you very very much.

Regards Young
0
 
MadshiCommented:
No prob...   :-)
0
All Courses

From novice to tech pro — start learning today.