全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:3595
推到 Plurk!
推到 Facebook!

用ShellExecute列印是否可以不用預設印表機

答題得分者是:danny
jook152
一般會員


發表:7
回覆:13
積分:4
註冊:2007-07-09

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-11-01 15:04:30 IP:60.249.xxx.xxx 訂閱
我要用ShellExecute列印pdf 檔案 ,
因為我的程式是preview主要檔案,當主要檔案被列印時利用ShellExecute列印出其附件,
但在印主要檔案時可能不是用預設印表機,
在印附件時是否可以依照主要檔案列印時選的印表機列印???
若用ShellExecute無法做到,那有什麼方式可以用嗎??
我只要主要檔案跟附件可以從同一台印表機印出但不一定是預設印表機
且要可以印pdf 檔,就可以了~~~不知道有什麼方法可以做到??

danny
版主


發表:100
回覆:522
積分:595
註冊:2002-03-11

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-11-01 18:09:41 IP:211.76.xxx.xxx 訂閱
應該沒辦法 .......
不過可以用切換的, 先記錄原來的預設印表機, 再設定你的印表機為預設印表機, 用ShellExecute列印pdf 檔案完畢後, 再切回原來的預設印表機

但是現在問題來了...
ShellExecute 並不會等你列印完就會繼續你Delphi中下一行程式, 所以你必須用 CreateProcess 取代 ShellExecute
至於 CreateProcess 的用法, 請善用搜尋功能可以找到好幾篇程式可以使用

===================引 用 jook152 文 章===================
我要用ShellExecute列印pdf 檔案 ,
因為我的程式是preview主要檔案,當主要檔案被列印時利用ShellExecute列印出其附件,
但在印主要檔案時可能不是用預設印表機,
在印附件時是否可以依照主要檔案列印時選的印表機列印???
若用ShellExecute無法做到,那有什麼方式可以用嗎??
我只要主要檔案跟附件可以從同一台印表機印出但不一定是預設印表機
且要可以印pdf 檔,就可以了~~~不知道有什麼方法可以做到??
------
將問題盡快結案也是一種禮貌!
jook152
一般會員


發表:7
回覆:13
積分:4
註冊:2007-07-09

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-11-15 11:01:58 IP:60.249.xxx.xxx 訂閱
不好意思,這麼久才回
先確定一下你的意思
你是指不要用ShellExecute直接用CreateProcess,但CreateProcess不是執行某個程式嗎??那這樣我要如何CreateProcess列印附件??它不是只能執行"執行檔"嗎??我的附件都是pdf.....
還是其實你的意思是要我先用切換預設印表機 ShellExecute列印附件後再用CreateProcess繼續執行下面的程式???
danny
版主


發表:100
回覆:522
積分:595
註冊:2002-03-11

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-11-15 14:33:44 IP:211.76.xxx.xxx 訂閱
使用 ShellExecute 基本上我想的到的是, 必需要配合 FinePrint 之類列印管理軟體, 然後再指定印表機

>但CreateProcess不是執行某個程式嗎??那這樣我要如何CreateProcess列印附件??它不是只能執行"執行檔"嗎?
是沒錯! 但你開啟 PDF 也需要某個 "執行檔" 吧! PDF 檔是當參數傳給他開啟而已

>還是其實你的意思是要我先用切換預設印表機 ShellExecute列印附件後再用CreateProcess繼續執行下面的程式???
不是, CreateProcess 是用來取代 ShellExecute 的方法

===================引 用 jook152 文 章===================
不好意思,這麼久才回
先確定一下你的意思
你是指不要用ShellExecute直接用CreateProcess,但CreateProcess不是執行某個程式嗎??那這樣我要如何CreateProcess列印附件??它不是只能執行"執行檔"嗎??我的附件都是pdf.....
還是其實你的意思是要我先用切換預設印表機 ShellExecute列印附件後再用CreateProcess繼續執行下面的程式???
------
將問題盡快結案也是一種禮貌!
jook152
一般會員


發表:7
回覆:13
積分:4
註冊:2007-07-09

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-11-16 08:50:13 IP:60.249.xxx.xxx 訂閱
我後來在討論區找到更改預設印表機的方式
我試了一下
[code delphi]
sprint:=GetDefaultPrinter; //取得原始預設印表機
SetDefaultPrinter2(sPrnName); // 更改預設印表機
ShellExecute(Application.Mainform.Handle,'Print',Pchar(要列印的pdf 路徑),nil, nil, SW_SHOW);
SetDefaultPrinter2(sprint); // 恢復原始預設印表機

function GetDefaultPrinter: string;
var
ResStr: array[0..255] of Char;
begin
GetProfileString('Windows', 'device', '', ResStr, 255);
Result := StrPas(ResStr);
end;

procedure SetDefaultPrinter1(NewDefPrinter: string);
var
ResStr: array[0..255] of Char;
begin
StrPCopy(ResStr, NewdefPrinter);
WriteProfileString('windows', 'device', ResStr);
StrCopy(ResStr, 'windows');
SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, Longint(@ResStr));
end;

procedure SetDefaultPrinter2(PrinterName: string);
var
I: Integer;
Device: PChar;
Driver: PChar;
Port: PChar;
HdeviceMode: THandle;
aPrinter: TPrinter;
begin
Printer.PrinterIndex := -1;
GetMem(Device, 255);
GetMem(Driver, 255);
GetMem(Port, 255);
aPrinter := TPrinter.Create;
try
for I := 0 to Printer.Printers.Count - 1 do
begin
if Printer.Printers[I] = PrinterName then
begin
aprinter.PrinterIndex := I;
aPrinter.getprinter(device, driver, port, HdeviceMode);
StrCat(Device, ',');
StrCat(Device, Driver);
StrCat(Device, Port);
WriteProfileString('windows', 'device', Device);
StrCopy(Device, 'windows');
SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, Longint(@Device));
end;
end;
finally
aPrinter.Free;
end;
FreeMem(Device, 255);
FreeMem(Driver, 255);
FreeMem(Port, 255);
end;

[/code]

GetDefaultPrinter,SetDefaultPrinter2,SetDefaultPrinter1這三個函式都是引用討論區的資料
執行結果是都可以印,但那必須是要用debug的方式一步一步的run並進入函式才會依我選的印表機列印出來
若直接run執行檔(exe)它還是會跑到原始的預設印表機!!
為什麼會這樣??不管我用SetDefaultPrinter2還是SetDefaultPrinter1結果都一樣
debug時就ok,但一run執行檔就不行??
danny
版主


發表:100
回覆:522
積分:595
註冊:2002-03-11

發送簡訊給我
#6 引用回覆 回覆 發表時間:2007-11-16 10:15:51 IP:203.79.xxx.xxx 訂閱
更改預設印表機有 OS 的分別, 以下是設定預設印表機的 procedure
有一點你必須注意, 在設定預設印表機時有可能會等一段時間, 但也可能不用等, 完全看你當時的 CPU 是否 busy

[code delphi]
// 設定 Default Printer Name
procedure SetDefaultPrinterName(PrinterName: String);
var
dwVersion: DWORD;
strPrinterInfo: string;
const
MAXPRINTERINFO = 50;
begin
SetLength(strPrinterInfo, MAXPRINTERINFO);

if GetProfileString(PChar('PrinterPorts'), PChar(PrinterName), '',
PChar(strPrinterInfo), MAXPRINTERINFO) > 0 then
begin
SetLength(strPrinterInfo, StrLen(PChar(strPrinterInfo)));

strPrinterInfo := PrinterName ','
Copy(strPrinterInfo, 1, Pos(':,', strPrinterInfo));

if not WriteProfileString(PChar('Windows'), PChar('Device'),
PChar(strPrinterInfo)) then
raise Exception.Create('無法設定預設印表機資訊')
else
begin
dwVersion := GetVersion();
if (dwVersion < $80000000) then
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0) // Windows NT 系列
else
SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0); // 非 Windows NT 系列
end;
end else
raise Exception.Create('無法讀取預設印表機資訊');
end;

[/code]

===================引 用 jook152 文 章===================
我後來在討論區找到更改預設印表機的方式
我試了一下
[code delphi]
sprint:=GetDefaultPrinter; //取得原始預設印表機
SetDefaultPrinter2(sPrnName); // 更改預設印表機
ShellExecute(Application.Mainform.Handle,'Print',Pchar(要列印的pdf 路徑),nil, nil, SW_SHOW);
SetDefaultPrinter2(sprint); // 恢復原始預設印表機

function GetDefaultPrinter: string;
var
ResStr: array[0..255] of Char;
begin
GetProfileString('Windows', 'device', '', ResStr, 255);
Result := StrPas(ResStr);
end;

procedure SetDefaultPrinter1(NewDefPrinter: string);
var
ResStr: array[0..255] of Char;
begin
StrPCopy(ResStr, NewdefPrinter);
WriteProfileString('windows', 'device', ResStr);
StrCopy(ResStr, 'windows');
SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, Longint(@ResStr));
end;

procedure SetDefaultPrinter2(PrinterName: string);
var
I: Integer;
Device: PChar;
Driver: PChar;
Port: PChar;
HdeviceMode: THandle;
aPrinter: TPrinter;
begin
Printer.PrinterIndex := -1;
GetMem(Device, 255);
GetMem(Driver, 255);
GetMem(Port, 255);
aPrinter := TPrinter.Create;
try
for I := 0 to Printer.Printers.Count - 1 do
begin
if Printer.Printers[I] = PrinterName then
begin
aprinter.PrinterIndex := I;
aPrinter.getprinter(device, driver, port, HdeviceMode);
StrCat(Device, ',');
StrCat(Device, Driver);
StrCat(Device, Port);
WriteProfileString('windows', 'device', Device);
StrCopy(Device, 'windows');
SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, Longint(@Device));
end;
end;
finally
aPrinter.Free;
end;
FreeMem(Device, 255);
FreeMem(Driver, 255);
FreeMem(Port, 255);
end;

[/code]

GetDefaultPrinter,SetDefaultPrinter2,SetDefaultPrinter1這三個函式都是引用討論區的資料
執行結果是都可以印,但那必須是要用debug的方式一步一步的run並進入函式才會依我選的印表機列印出來
若直接run執行檔(exe)它還是會跑到原始的預設印表機!!
為什麼會這樣??不管我用SetDefaultPrinter2還是SetDefaultPrinter1結果都一樣
debug時就ok,但一run執行檔就不行??
------
將問題盡快結案也是一種禮貌!
jook152
一般會員


發表:7
回覆:13
積分:4
註冊:2007-07-09

發送簡訊給我
#7 引用回覆 回覆 發表時間:2007-11-21 16:51:20 IP:60.249.xxx.xxx 訂閱
我測試之後,附件有時會從我選的印表機列印但有時還是從原本的預設印表機印出
這應該就是你說的"在設定預設印表機時有可能會等一段時間, 但也可能不用等, 完全看你當時的 CPU 是否 busy"
但這有辦法可以解決嗎??
我試過在用 ShellExecute列印前先判斷目前預設印表機是否跟我挑選的一樣,
若一樣才執行ShellExecute,可是這樣還是不太穩定!!
jook152
一般會員


發表:7
回覆:13
積分:4
註冊:2007-07-09

發送簡訊給我
#8 引用回覆 回覆 發表時間:2007-11-22 15:24:59 IP:60.249.xxx.xxx 訂閱
我的問題解決了 
我改用CreateOleObject來開啟pdf,加上前面講的引用討論區中的三個函式來更改預設印表機
這樣就可以將主要檔案與附件都從user所挑選的印表機列印

在這感謝danny大大的回答
u86210779
一般會員


發表:16
回覆:41
積分:16
註冊:2004-06-08

發送簡訊給我
#9 引用回覆 回覆 發表時間:2007-11-25 10:21:15 IP:218.175.xxx.xxx 訂閱
jook152你好:

可否將你的做法 pos 上來, 謝謝
===================引 用 jook152 文 章===================
我的問題解決了
我改用CreateOleObject來開啟pdf,加上前面講的引用討論區中的三個函式來更改預設印表機
這樣就可以將主要檔案與附件都從user所挑選的印表機列印

在這感謝danny大大的回答
jook152
一般會員


發表:7
回覆:13
積分:4
註冊:2007-07-09

發送簡訊給我
#10 引用回覆 回覆 發表時間:2007-11-26 08:26:02 IP:60.249.xxx.xxx 訂閱

[code delphi]
a:=GetDefaultPrinter; //取得原始預設印表機
SetDefaultPrinter2(user選擇的印表機); // 更改預設印表機
//開啟pdf
pdfAVDOC:=CreateOleObject('AcroExch.AVDoc'); // 建立Acrobat View 視覺化物件
pdfPDDOC:=CreateOleObject('AcroExch.PDDoc'); // 建立Acrobat View 非視覺化(控制)物件
pdfAPP:=CreateOleObject('AcroExch.APP'); // 建立Acrobat View application
pdfAVDOC.open(sPrnName,StrExtract(sPrnName,'/',3));
pdfAVDOC:=pdfAPP.GetActiveDoc;
pdfPDDOC:=pdfAVDOC.GetPDDoc;
//pdfAPP.Show; // 是否顯示 Acrobat View
vPage:=pdfPDDOC.GetNumPages;
pdfAVDOC.PrintPagesSilent(0,vPage-1, 0, 0, 0);
pdfPDDOC.close;
pdfAPP.Exit;
//列印完畢,恢復原始預設印表機
SetDefaultPrinter2(StrExtract(a,','));
[/code]

GetDefaultPrinter,SetDefaultPrinter2和CreateOleObject('AcroExch.AVDoc');CreateOleObject(...)
這些在討論區裡面都有,我都是引用討論區的前輩們分享函式
去搜尋一下應該找得到

jook152
一般會員


發表:7
回覆:13
積分:4
註冊:2007-07-09

發送簡訊給我
#11 引用回覆 回覆 發表時間:2007-11-26 08:29:41 IP:60.249.xxx.xxx 訂閱

[code delphi]
a:=GetDefaultPrinter; //取得原始預設印表機
SetDefaultPrinter2(user選擇的印表機); // 更改預設印表機
//開啟pdf
pdfAVDOC:=CreateOleObject('AcroExch.AVDoc'); // 建立Acrobat View 視覺化物件
pdfPDDOC:=CreateOleObject('AcroExch.PDDoc'); // 建立Acrobat View 非視覺化(控制)物件
pdfAPP:=CreateOleObject('AcroExch.APP'); // 建立Acrobat View application
pdfAVDOC.open(欲開啟的檔案路徑,欲顯示的pdf標題名稱);
pdfAVDOC:=pdfAPP.GetActiveDoc;
pdfPDDOC:=pdfAVDOC.GetPDDoc;
//pdfAPP.Show; // 是否顯示 Acrobat View
vPage:=pdfPDDOC.GetNumPages;
pdfAVDOC.PrintPagesSilent(0,vPage-1, 0, 0, 0);
pdfPDDOC.close;
pdfAPP.Exit;
//列印完畢,恢復原始預設印表機
SetDefaultPrinter2(StrExtract(a,','));
[/code]

GetDefaultPrinter,SetDefaultPrinter2和CreateOleObject('AcroExch.AVDoc');CreateOleObject(...)
這些在討論區裡面都有,我都是引用討論區的前輩們分享函式
去搜尋一下應該找得到

u86210779
一般會員


發表:16
回覆:41
積分:16
註冊:2004-06-08

發送簡訊給我
#12 引用回覆 回覆 發表時間:2007-11-26 16:32:45 IP:218.175.xxx.xxx 訂閱
Jook152:

謝謝你
系統時間:2024-04-29 12:44:42
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!