如何在程序里判断一个打印作业已经进入打印队列(也就是可以在打印管理程序里看到该作业的信息),或者说如何察看打印队列里已有的作业信息?
看下面的这个例程。还有测试代码。
uses WinSpool;
type JOB_INFO_1_ARRAY = Array of JOB_INFO_1;
Function GetSpoolerJobs(sPrinterName : String) : JOB_INFO_1_ARRAY;
var
i : Integer;
hPrinter : THandle;
bResult : Boolean;
cbBuf : DWORD;
pcbNeeded : DWORD;
pcReturned : DWORD;
aJobs : Array[0..99] of JOB_INFO_1;
begin
cbBuf := 1000;
bResult := OpenPrinter(PChar(sPrinterName), hPrinter, Nil);
if NOT bResult then begin
ShowMessage('Error opening the printer');
exit;
end;
bResult := EnumJobs(hPrinter,0,Length(aJobs),1,@aJobs,cbBuf,pcbNeeded,pcReturned);
if NOT bResult then begin
ShowMessage('Error Getting Jobs information');
exit;
end;
for i:=0 to pcReturned-1 do begin
if aJobs[i].pDocument <> Nil then begin
SetLength(Result, Length(Result)+1);
Result[Length(Result)-1] := aJobs[i];
end;
end;
end;
测试例子:
1- 创建工程有 StringGrid 和一个 Timer.
2- StringGrid 'ColCount' and “RowCount” 值为 20
3- Timer的 “Interval” 属性值 500.
4- “OnTime” 实践中写这个代码
procedure TForm1.Timer1Timer(Sender: TObject);
var
i, ii : Integer;
aJobs : JOB_INFO_1_ARRAY;
begin
for i:=0 to StringGrid1.ColCount-1 do
for ii:=0 to StringGrid1.RowCount-1 do StringGrid1.Cells[i,ii] := '';
aJobs := GetSpoolerJobs('\\ibmserver\HP LaserJet 1100');//正在打印的打印机名字,这里我的打印机时网打。这里你要自己改
for i:=0 to Length(aJobs)-1 do begin
StringGrid1.Cells[i,0] := aJobs[i].pPrinterName;
StringGrid1.Cells[i,1] := aJobs[i].pMachineName;
StringGrid1.Cells[i,2] := aJobs[i].pUserName;
StringGrid1.Cells[i,3] := aJobs[i].pDocument;
StringGrid1.Cells[i,4] := aJobs[i].pDatatype;
StringGrid1.Cells[i,5] := aJobs[i].pStatus;
StringGrid1.Cells[i,6] := IntToStr(aJobs[i].Status);
case aJobs[i].Status of
JOB_STATUS_PAUSED: StringGrid1.Cells[i,6] := 'JOB_STATUS_PAUSED';
JOB_STATUS_ERROR: StringGrid1.Cells[i,6] := 'JOB_STATUS_ERROR';
JOB_STATUS_DELETING: StringGrid1.Cells[i,6] := 'JOB_STATUS_DELETING';
JOB_STATUS_SPOOLING: StringGrid1.Cells[i,6] := 'JOB_STATUS_SPOOLING';
JOB_STATUS_PRINTING: StringGrid1.Cells[i,6] := 'JOB_STATUS_PRINTING';
JOB_STATUS_OFFLINE: StringGrid1.Cells[i,6] := 'JOB_STATUS_OFFLINE';
JOB_STATUS_PAPEROUT: StringGrid1.Cells[i,6] := 'JOB_STATUS_PAPEROUT';
JOB_STATUS_PRINTED: StringGrid1.Cells[i,6] := 'JOB_STATUS_PRINTED';
JOB_STATUS_DELETED: StringGrid1.Cells[i,6] := 'JOB_STATUS_DELETED';
JOB_STATUS_BLOCKED_DEVQ: StringGrid1.Cells[i,6] := 'JOB_STATUS_BLOCKED_DEVQ';
JOB_STATUS_USER_INTERVENTION: StringGrid1.Cells[i,6] := 'JOB_STATUS_USER_INTERVENTION';
JOB_STATUS_RESTART: StringGrid1.Cells[i,6] := 'JOB_STATUS_RESTART';
JOB_POSITION_UNSPECIFIED: StringGrid1.Cells[i,6] := 'JOB_POSITION_UNSPECIFIED';
else StringGrid1.Cells[i,6] := 'Unknown status...';
end;
end;
StringGrid1.Refresh;
end;
5- 运行程序,打印程序测之
为默认打印机创建一个快捷方式后,用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_NORMAL,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;
没有研究过打印机的东西,手头有些资料,你看能不能用上用API直接打印
uses CommDlg;
{$ IFNDEF WIN32}
const MAX_PATH = 144;
{$ ENDIF}
procedure TForm1.Button1Click(Sender: TObject);
var
Pd : TPrintDlg;
DocInfo: TDocInfo;
begin
FillChar(Pd, sizeof(Pd), #0);
Pd.lStructSize := sizeof(Pd);
Pd.hWndOwner := Form1.Handle;
Pd.Flags := PD_RETURNDC;
if PrintDlg(pd) then begin
FillChar(DocInfo, sizeof(DocInfo), #0);
DocInfo.cbSize := SizeOf(DocInfo);
GetMem(DocInfo.lpszDocName, 32);
GetMem(DocInfo.lpszOutput, MAX_PATH);
lStrCpy(DocInfo.lpszDocName, 'My Document');
{Add this line to print to a file }
lStrCpy(DocInfo.lpszOutput, 'C:\Download\Test.doc');
StartDoc(Pd.hDc, DocInfo);
StartPage(Pd.hDc);
TextOut(Pd.hDc, 100, 100, 'Page 1', 6);
EndPage(Pd.hDc);
StartPage(Pd.hDc);
TextOut(Pd.hDc, 100, 100, 'Page 2', 6);
EndPage(Pd.hDc);
EndDoc(Pd.hDc);
FreeMem(DocInfo.lpszDocName, 32);
FreeMem(DocInfo.lpszOutput, MAX_PATH);
end;
end;
回复Comments
作者:
{commentrecontent}