为默认打印机创建一个快捷方式后,用ShellExecute运行可以启动默认
打印机管理程序。如果不创建快捷方式,如何直接启动。
感谢http://www.experts-exchange.com/Q.10115433, 以下代码ShowPrintSpool可以实现:
function ExecuteContextMenuCommand(hParent: THandle; sf: IShellFolder; childPidl: PItemIDList;
verb: string = ''; propPage: string = ''; pidlCount: UInt = 1): Boolean;
var
cm, cm2, cm3: IContextMenu;
ici: TCMInvokeCommandInfo;
pop : HMenu;
c: Cardinal;
begin
Result := False;
if sf.GetUIObjectOf(hParent, pidlCount, 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 := hParent;
lpVerb := PChar(verb);
lpParameters := PChar(propPage); //'Settings';
nShow := SW_SHOW;
end;
if verb <> '' then
Result := cm.InvokeCommand(ici) = NOERROR
else
begin
pop := CreatePopupMenu;
try
if Succeeded(cm.QueryContextMenu(pop, 0, 1, $7FFF, CMF_DEFAULTONLY)) then
begin
c := GetMenuDefaultItem(pop, 0, 0);
if c <> 0 then
begin
ici.lpVerb := MakeIntResource(c - 1);
Result := cm.InvokeCommand(ici) = NOERROR;
end;
end;
finally
DestroyMenu(pop)
end;
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_FORPARSING,sr) = NOERROR then
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);
end;
end;
function DefaultPrinterDevice: string;
var
Device, Driver, Port: array [0..255] of Char;
Mode: THandle;
begin
Device := '';
with Printer do
if Printers.Count > 0 then
GetPrinter(Device, Driver, Port, Mode);
Result := Device;
end;
procedure ShowPrintSpool;
var
pidl1, pidl2: PItemIDList;
sf1, sf2: IShellFolder;
malloc: IMalloc;
el: IEnumIDList;
c: Cardinal;
sDefaultPrinter: string;
begin
if (SHGetSpecialFolderLocation(INVALID_HANDLE_VALUE, CSIDL_PRINTERS, pidl1) = NOERROR) and
(SHGetMalloc(malloc) = NOERROR) then
try
if (pidl1^.mkid.cb <> 0) and (SHGetDesktopFolder(sf1) = NOERROR) and
(sf1.BindToObject(pidl1, nil, IID_IShellFolder, Pointer(sf2)) = NOERROR) and
(sf2.EnumObjects(Application.Handle, High(Cardinal), el) = NOERROR) then
begin
sDefaultPrinter := DefaultPrinterDevice;
el.Reset;
while el.Next(1, pidl2, c) = NOERROR do
begin
if PidlToStr(sf2, pidl2) = sDefaultPrinter then
ExecuteContextMenuCommand(Application.Handle, sf2, pidl2);
malloc.Free(pidl2);
end;
end;
finally
malloc.Free(pidl1);
end;
end;