Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何用Delphi中默认以外的打印机信息填充TpagesetupDlg记录?_Delphi_Printing - Fatal编程技术网

如何用Delphi中默认以外的打印机信息填充TpagesetupDlg记录?

如何用Delphi中默认以外的打印机信息填充TpagesetupDlg记录?,delphi,printing,Delphi,Printing,我正在拼命寻找如何在不调用对话框的情况下将非默认打印机的信息提供给StartDoc、StartPage等API函数 我发现我必须用适当的值填充TPageSetupDlg或TPrintDlg,特别是devNames结构,但我不知道如何填充 编辑 我已经写了这段代码,但它没有改变我想要的横向方向。可能我没有正确填充devMode结构 procedure TForm1.ButtonXClick(Sender: TObject); type TdevNames = record

我正在拼命寻找如何在不调用对话框的情况下将非默认打印机的信息提供给StartDoc、StartPage等API函数

我发现我必须用适当的值填充TPageSetupDlg或TPrintDlg,特别是devNames结构,但我不知道如何填充

编辑

我已经写了这段代码,但它没有改变我想要的横向方向。可能我没有正确填充devMode结构

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;

您不应该手动声明TDEVNAME和TDevMode记录类型。分别使用Delphi的Winapi.CommDlg和Winapi.Windows单元中的现有声明

您还错误地调用了CreateDC。事实上,您的代码甚至不应该编译,因为您正在传递一个需要PChar的PDEVMODE,并在需要PDEVMODE的地方传递一个整数

您还应该检查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驱动程序本身,而不是代码。

相关API需要HDC连接到所需的打印机设备。使用CreateIC或CreateDC获取该HDC。对话框只是提供了选择打印机和使用适当的HDC初始化VCL的Tprenter单例的便利。您可以只设置tpinter.PrinterIndex属性,然后读取tpinter.Canvas.Handle来执行相同的操作,但也可以使用tpinter.Canvas进行所有打印。雷米感谢您的回复。您的建议使用TPRINTS单元。从现在起我就使用了这种方法,但我面临的问题是打印到XPS时会弹出我不想要的saveAs对话框,因为我想保存到预定义的文件名。所以有人告诉我不用TPRINTS装置打印。但现在我必须绕过TPageSetupDlg或TPrintDlg。您不必使用打印机单元,这是一种方便,而不是一种要求。StartDoc、StartPage、CreateIC | DC,这些都是Win32 API函数,Win32 API没有VCL的概念。你读过MSDN的吗?甚至还有一个。你能提供一个关于准备画布创建带有XPS文件名和XPS打印机的hDC的代码吗?你一直在评论中添加信息,这些信息应该在你的帖子中可以看到。不要期望人们通过大量的评论来挑选有用的部分。花些时间认真回答你的问题,弄清楚你在问什么,你做了什么。再次感谢雷米。同时,我发现了我的错误,并且结构已经在delphi的单元中声明。除了错误检查之外,我能够正确打印。现在我要挖掘更多的信息,如利润等。