Solved

Start printer spool manager?

Posted on 1999-01-08
9
374 Views
Last Modified: 2010-04-06
 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?
0
Comment
Question by:delphi1
  • 6
  • 3
9 Comments
 
LVL 20

Expert Comment

by:Madshi
ID: 1355238
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
 

Author Comment

by:delphi1
ID: 1355239
 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
 
LVL 20

Expert Comment

by:Madshi
ID: 1355240
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
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 
LVL 20

Expert Comment

by:Madshi
ID: 1355241
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
 

Author Comment

by:delphi1
ID: 1355242
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
 
LVL 20

Accepted Solution

by:
Madshi earned 50 total points
ID: 1355243
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
 
LVL 20

Expert Comment

by:Madshi
ID: 1355244
Hmmm. Looks like I implemented an almost ready to use solution. Just try it out!!! Was a lot of work...  :-(

Regards, Madshi.
0
 

Author Comment

by:delphi1
ID: 1355245
Excellent solution! Thank you very very much.

Regards Young
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1355246
No prob...   :-)
0

Featured Post

Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

822 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