我也是借花献佛,大家分享一下。动 态 调 整 打 印 机 纸 张 大 小 ----信 息 管 理 系 统 中 经 常 要 提 供 各 种 打 印 功 能, 例 如 报 表 打 印、 凭 证 打 印 以 及 发 票 打 印。 在 这 些 打 印 过 程 中 所 需 要 纸 张 的 大 小 往 往 是 不 一 致 的, 例 如, 打 印 报 表 有 可 能 使 用A4 纸 或A3 纸, 打 印 凭 证 或 发 票 可 能 需 要 将 打 印 纸 张 设 置 成 自 定 义 大 小。 如 果 在 同 一 台 打 印 机 上 打 印 这 些 内 容, 那 么 就 应 该 针 对 不 同 的 打 印 内 容 设 置 不 同 的 纸 张 尺 寸。 显 然 如 果 用 手 动 的 方 法 来 设 置 打 印 机 的 纸 张 尺 寸 是 件 很 麻 烦 的 事, 最 好 的 方 法 是 让 程 序 动 态 地 修 改 打 印 机 的 纸 张 尺 寸。 解 决 问 题 的 思 路----通 过 查 阅API 函 数 技 术 文 档 可 知, 每 个 打 印 机 都 拥 有 唯 一 的 一 个 叫 做DevMode 的 结 构, 与 打 印 机 相 关 的 各 项 参 数 被 存 放 在 这 个 结 构 中。 通 过 对DevMode 结 构 的 分 析, 发 现 与 设 置 打 印 机 纸 张 大 小 有 关 的 结 构 成 员 有 四 项:dmFields、 dmPaperSize、dmPaperLength 以 及dmPaperWidth。dmFields 是DevMode 的 标 志 位 初 始 化 部 分, 如 果 要 修 改 结 构 中 的 某 些 成 员, 那 么dmFields 中 相 应 位 应 被 置 位。dmPaperSize 表 示 打 印 机 当 前 默 认 的 打 印 纸 张 的 大 小, 若 要 设 置 自 定 义 纸 张 该 项 应 为0( 注, 上 述 解 释 是 根 据 微 软 提 供 的 技 术 文 档, 但 是 在Delphi 中 应 将 该 成 员 设 置 成 $100 即256)。 dmPaperLength 和dmPaperWidth 只 是 在 设 置 自 定 义 大 小 纸 张 时 使 用, 分 别 表 示 纸 张 的 长 度 和 宽 度。 如 何 对 打 印 机 的DevMode 结 构 进 行 修 改 呢 ? 无 非 采 用 两 种 方 法, 一 种 是 利 用Delphi 提 供 的TPrinter 类 中 的 某 些 方 法, 还 有 一 种 是 调 用 与 打 印 有 关 的API 函 数。 下 面 就 以 Delphi 为 开 发 工 具, 以Epson 1600K 为 默 认 打 印 机, 用 两 种 不 同 的 方 法 来 实 现 这 一 功 能。 
方 法 一: 利 用Delphi 的TPrinter 类 ----TPrinter 类 是Delphi 对Windows 打 印 处 理 系 统 的 封 装, 它 能 够 帮 助 程 序 员 在 开 发 打 印 程 序 时 尽 可 能 地 减 少 工 作 量。 在 程 序 中 使 用TPrinter, 只 要 在 单 元 的Use 子 句 后 面 添 加Printers 即 可。 当 前 打 印 机 的DevMode 结 构 的 句 柄 可 以 通 过 调 用Tprinter 类 中 的GetPrinter 方 法 来 获 取。 当 程 序 获 得DevMode 结 构 的 句 柄 后, 就 调 用 GlobalLock 函 数 来 得 到 指 向 该 结 构 的 指 针, 随 后 可 对 结 构 中 的 某 些 成 员 进 行 修 改。 下 面 就 举 一 个 例 子 来 说 明 这 一 问 题: 假 设 当 前 打 印 机 的 默 认 纸 张 尺 寸 是A3 纸, 现 在 要 打 印 长 度 为114mm、 宽 度 为190mm 的 纸 张。 为 了 简 单 起 见, 我 们 只 在Form1 上 放 置 一 个 Button1 按 钮, 增 加 一 个OnClick 事 件, 在Use 子 句 后 添 加Printers。 程 序 的 代 码 如 下: Procedure TForm1.Button1Click(Sender: TObject);
var
  Device : array[0..cchDeviceName - 1] of Char;
  Driver : array[0..(MAX_PATH -1)] of Char;
  Port : array[0..32]of Char;
  hDMode : THandle;
  pDMode : PDevMode;
begin
   Printer.GetPrinter(Device,Driver,Port,hDMode);
// 获 取 打 印 机DevMode 结 构 的 句 柄 值,
  存 放 在hDMode 中 
   if hDMode < > 0 then begin
       pDMode := GlobalLock(hDMode); 
 // 获 取 指 向 打 印 机DevMode 结 构 的// 指 针
       if pDMode < > nil then begin
          pDMode^.dmPaperSize := 256; 
// 如 果 要 将 当 前 打 印 机 纸 张 变 为 自 定 义
dmPaperSize 必 须 设 置 成256
    pDMode^.dmPaperLength := 1140;
    pDMode^.dmPaperWidth := 1900;
    pDMode^.dmFields := pDMode^.dmFields or 
DM_PAPERSIZE;
  pDMode^.dmFields := 
    pDMode^.dmFields or DM_PAPERLENGTH;
  pDMode^.dmFields := 
    pDMode^.dmFields or DM_PAPERWIDTH;
     {  以 上 三 条 语 句 是 对 相 应
        的dmFields 成 员 进 行 置 位。}
    ResetDC(Printer.Handle,pDMode^); 
// 设 置 打 印 机 设 备 环 境 句 柄 的 值
    GlobalUnlock(hDMode);
    end;
   end;
{ 下 面 的 代 码 是 为 了 测 试 打 印 机 是 否
  按190 *114 纸 张 大 小 来 打 印 }
   with Printer do begin
      BeginDoc;
      Canvas.TextOut(10,10,‘Hello, My Friend!');
      EndDoc;
   end;
end;方 法 二: 利 用 有 关 打 印 的Windows API 函 数 ----解 决 问 题 的 思 路 和 第 一 种 方 法 类 似, 首 先 要 获 取 当 前 打 印 机 的DevMode 结 构 的 指 针, 然 后 再 对 该 结 构 进 行 修 改, 从 而 修 改 打 印 机 纸 张 大 小。 要 完 成 上 述 功 能, 就 得 调 用 DocumentProperties 函 数。 利 用 该 函 数 程 序 就 可 以 获 取 并 修 改 与 当 前 打 印 机 相 关 的DevMode 结 构 中 的 成 员。DocumentProperties 函 数 申 明 如 下: LONG DocumentProperties
(
    HWND       hWnd, 
    HANDLE     hPrinter,       
    LPTSTR      pDeviceName,   
    PDEVMODE  pDevModeOutput,  
    PDEVMODE  pDevModeInput,   
    DWORD     fMode 
);----六 个 参 数 中 只 有pDevModeOutput 是 输 出 变 量, 其 余 五 个 参 数 必 须 由 程 序 给 出 具 体 值。 其 中,hWnd 表 征 当 前 窗 口 的 句 柄 值;hPrinter 表 示 当 前 打 印 机 的 句 柄;pDeviceName 是 对 打 印 机 设 备 的 描 述;pDevModeOutput 是 指 向 句 柄 值 为hPrinter 的 打 印 机 DevMode 结 构 的 指 针;pDevModeInput 是 指 向 一 个 修 改 后 的DevMode 结 构 的 指 针, 该 结 构 有 待 于 被 句 柄 值 为hPrinter 的 打 印 机 接 受;fMode 定 义 了 该 函 数 的 具 体 功 能, 如 果 取 值DM_IN_BUFFER 那 么 表 示 打 印 机 接 受 由 参 数pDevModeInput 表 示 的 由 程 序 修 改 了 的DevMode 值, 如 果 取 值DM_OUT_BUFFER 那 么 程 序 可 以 通 过 参 数pDevModeOutput 来 获 取 打 印 机 的DevMode 值, 如 果fMode 为 零, 则 函 数 返 回 的 值 表 示 结 构 DevMode 所 需 的 字 节 数。 承 接 上 述 例 子, 现 在 将190 *114 大 小 的 纸 张 设 成A4 纸。 再 往Form1 上 放 置 按 钮Button2, 增 加OnClick 事 件, 在Use 子 句 后 面 添 加WinSpool。 代 码 如 下: Procedure TForm1.Button2Click(Sender: TObject);
var
   PrnHd  :  THandle;
   PrnInfo : PPrinterInfo1;
   pcbNeeded : DWORD;
   PDevModeBytes : DWORD;
   DevMode: PDeviceMode;
   PrnHdc : HDC;
   DocInfo : PDocInfo;
begin
   OpenPrinter(‘Epson LQ -1600K',PrnHd,nil); 
   // 获 得 打 印 机 句 柄PrnHd
   GetMem(PrnInfo,1024);
   GetPrinter(PrnHd,1,PrnInfo,1024,@pcbNeeded);
   PDevModeBytes:= DocumentProperties
( Handle,PrnHd,prninfo^.
  pDescription,DevMode^,DevMode^,0 );
{  获 取DevMode 结 构 所 需 的 字 节 数 }
   GetMem(DevMode,PDevModeBytes); 
 // 给 结 构DevMode 分 配 空 间
   DocumentProperties( Handle,PrnHd,PrnInfo^.p
  Description,DevMode^,DevMode^,DM_OUT_BUFFER );
 // 获 取 打 印 机 的DevMode 结 构
   With DevMode^ do begin
      dmPaperSize := DMPAPER_A4     ;
 // 将 纸 张 设 置 成A4 纸
      dmFields := dmFields or DM_PAPERSIZE;
   end;
   DocumentProperties( Handle,PrnHd,PrnInfo^.p
Description,DevMode^,DevMode^,
DM_OUT_BUFFER or DM_IN_BUFFER);
// 修 改DevMode 结 构。
  { 下 面 的 代 码 是 为 了 测 试 打 印 机
    是 否 按A4 纸 大 小 来 打 印  }
   PrnHdc := CreateDC
( nil, ‘Epson LQ -1600K',nil,DevMode );
   GetMem( DocInfo, 100 );
   With DocInfo^ do begin
      cbSize := sizeof(DocInfo);
      lpszDocName := nil;
      lpszOutput := nil;
      lpszDatatype := nil;
      fwType := DI_APPBANDING;
   end;
   StartDoc( PrnHdc, DocInfo^);
   StartPage(PrnHdc);
   TextOut( PrnHdc, 10, 10, ‘Hello My Friend!',17);
   EndPage(PrnHdc);
   EndDoc(PrnHdc);
   DeleteDC(PrnHdc);
   FreeMem(DocInfo);
   FreeMem(PrnInfo);
   FreeMem(DevMode);
end;----至 此, 程 序 实 现 了 本 文 开 头 所 提 出 的 要 求。 需 要 指 出 的 是, 上 述 代 码 是 在 程 序 运 行 时, 动 态 地 改 变 打 印 机 纸 张 大 小, 而 不 改 变 打 印 机 默 认 纸 张 大 小。 也 就 是 说 当 打 印 程 序 运 行 结 束 后, 打 印 机 还 是 会 按 照 默 认 打 印 纸 张 大 小 来 打 印、 走 纸。 动 态 调 整 打 印 机 纸 张 尺 寸 也 是 因 打 印 机 而 异, 某 些 打 印 机 基 本 不 支 持 自 定 义 纸 张, 例 如 惠 普 的HP DeskJet 1120C 喷 墨 打 印 机 以 及 众 多 激 光 打 印 机。 因 此 在 这 些 打 印 机 上, 不 能 实 现 按 任 意 纸 张 大 小 打 印。 对 于 一 些 针 式 打 印 机 则 没 有 上 述 问 题。 ----上 述 程 序 是 在Windows 95 环 境 下, 用Delphi 4.0 为 开 发 工 具 调 试 通 过。