我拼命寻找如何在不调用对话框的情况下向 StartDoc()
、StartPage()
等 API 函数提供非默认打印机信息。
发现我必须用适当的值(尤其是devNames
结构(填充TPageSetupDlg
或TPrintDlg
,但我不知道该怎么做。
编辑
我编写了这段有效的代码,但它不会像我想要的那样改变横向的方向。可能我没有正确填充开发模式结构。
procedure TForm1.ButtonXClick(Sender: TObject);
type
TdevNames = record
wDriverOffset : WORD;
wDeviceOffset : WORD;
wOutputOffset : WORD;
wDefault : WORD;
end;
TdevMode = record
dmDeviceName : array[0..CCHDEVICENAME-1] of char;
dmSpecVersion : WORD;
dmDriverVersion: WORD;
dmSize: WORD;
dmDriverExtra: WORD;
dmFields : DWORD;
dmOrientation : short;
dmPaperSize : short;
dmPaperLength : short;
dmPaperWidth : short;
dmScale : short;
dmCopies : short;
dmDefaultSource : short;
dmPrintQuality : short;
dmColor : short;
dmDuplex : short;
dmYResolution : short;
dmTTOption : short;
dmCollate : short;
dmFormName : array[0..CCHFORMNAME-1] of char;
dmLogPixels : WORD;
dmBitsPerPel : DWORD;
dmPelsWidth : DWORD;
dmPelsHeight : DWORD;
dmNup : DWORD;
dmDisplayFrequency : DWORD;
end;
var
DocInfo: TDocInfo;
devNames : TdevNames;
aDC : hDC;
devMode : TdevMode;
str1, str2 : string;
const
DOC_NAME = 'Stack Overflow';
FILE_NAME = 'test.xps';
MAX_PATH = 260;
begin
devMode := default(TdevMode);
devMode.dmSize := sizeof(TDEVMODE);
devMode.dmPaper.dmOrientation := DMORIENT_LANDSCAPE;
devMode.dmFields := DM_ORIENTATION;
aDC := createDC('',pchar('Microsoft XPS Document Writer'),@devMode,0);
DocInfo := Default(TDocInfo);
DocInfo.cbSize := SizeOf(DocInfo);
GetMem(DocInfo.lpszDocName, 32);
GetMem(DocInfo.lpszOutput, MAX_PATH);
lStrCpynW(DocInfo.lpszDocName, DOC_NAME, Length(DOC_NAME) * sizeof(char));
lStrCpynW(DocInfo.lpszOutput, FILE_NAME, Length(FILE_NAME) * sizeof(char));
StartDoc(aDC, DocInfo);
StartPage(aDC);
str1 := 'page 1';
str2 := 'page 2';
TextOut(aDC, 100, 100, pchar(str1), length(str1));
EndPage(aDC);
StartPage(aDC);
TextOut(aDC, 100, 100, pchar(str2), length(str2));
EndPage(aDC);
EndDoc(aDC);
FreeMem(DocInfo.lpszDocName, 32);
FreeMem(DocInfo.lpszOutput, MAX_PATH);
shellExecute(application.Handle,'open',FILE_NAME,'','',SW_MAXIMIZE);
deleteDC(aDC);
end;
不应手动声明TDevNames
和TDevMode
记录类型。 分别使用 Delphi Winapi.CommDlg
和 Winapi.Windows
单位中的现有声明。
您也不正确地调用CreateDC()
。 事实上,您的代码甚至不应该编译,因为您要在预期PChar
的地方传递PDEVMODE
,并在预期PDEVMODE
的地方传递Integer
。
您还应该检查 API 调用是否存在错误。
尝试更多类似的东西:
uses
..., Winapi.Windows, Winapi.CommDlg;
procedure TForm1.ButtonXClick(Sender: TObject);
var
lDocInfo: DOCINFO;
lDevMode: DEVMODE;
lDC: hDC;
str: string;
const
DOC_NAME = 'Stack Overflow';
FILE_NAME = 'test.xps';
begin
lDevMode := default(DEVMODE);
lDevMode.dmSize := sizeof(lDevMode);
lDevMode.dmFields := DM_ORIENTATION;
lDevMode.dmOrientation := DMORIENT_LANDSCAPE;
lDC := CreateDC(nil, 'Microsoft XPS Document Writer', nil, @lDevMode);
if lDC = 0 then
raise Exception.Create('Unable to open printer');
try
lDocInfo := Default(DOCINFO);
lDocInfo.cbSize := SizeOf(lDocInfo);
lDocInfo.lpszDocName := DOC_NAME;
lDocInfo.lpszOutput := FILE_NAME;
if StartDoc(lDC, lDocInfo) <= 0 then
raise Exception.Create('Unable to start print document');
try
if StartPage(lDC) <= 0 then
raise Exception.Create('Unable to start a new print page');
str := 'page 1';
TextOut(lDC, 100, 100, PChar(str), Length(str));
EndPage(lDC);
if StartPage(lDC) <= 0 then
raise Exception.Create('Unable to start a new print page');
str := 'page 2';
TextOut(lDC, 100, 100, PChar(str), Length(str));
EndPage(lDC);
EndDoc(lDC);
except
AbortDoc(lDC);
raise;
end;
finally
DeleteDC(lDC);
end;
if ShellExecute(Handle, 'open', FILE_NAME, nil, nil, SW_MAXIMIZE) < 32 then
raise Exception.Create('Unable to open printed file');
end;
如果仍然无法横向打印,则问题出在 XPS 驱动程序本身,而不是代码。