You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Delphi中将打印机设备模式以十六进制格式保存并恢复

打印机设置的十六进制保存与恢复实现

问题

我希望将所选打印机的全部设置以十六进制格式保存到文件中,之后再从该文件加载恢复这些设置。尝试了以下代码,但它直接写入二进制数据而非十六进制格式:

procedure SaveDevModeToFile(deviceHandle: THandle; filePath: string);
var
  pDevmode: PDeviceMode;
  fs : TFileStream;
begin
  pDevMode := GlobalLock(deviceHandle);
  if pDevmode <> nil then
    try
      fs:= TFileStream.Create(filePath, fmCreate);
      try
        fs.WriteBuffer(PChar(pDevmode)^, sizeof(TDevicemode));
      finally
        fs.Free;
      end;
    finally
      GlobalUnlock(deviceHandle);
    end;
end;

procedure AskSettingsAndSave;
var MyPrinter, MyDriver, MyPort: array[0..255] of Char;
  DeviceHandle: THandle;
begin
  if PrinterSetupDialog1.Execute(Self.Handle) then
    begin
      Printer.GetPrinter(MyPrinter, MyDriver, MyPort, DeviceHandle);

      if DeviceHandle <> 0 then
      begin
        SaveDevModeToFile(DeviceHandle, 'd:\temp\dm.txt');
      end;
    end;
end;

解决方案

原代码直接写入TDeviceMode的二进制数据,要实现十六进制格式存储,需将二进制字节转换为十六进制字符串保存;恢复时再将十六进制字符串转回二进制数据。

1. 十六进制格式保存设置

修改保存函数,逐字节将二进制数据转为十六进制字符串后写入文件:

function ByteToHex(B: Byte): string;
const
  HexChars: array[0..15] of Char = '0123456789ABCDEF';
begin
  Result := String(HexChars[B shr 4]) + HexChars[B and $0F];
end;

procedure SaveDevModeToHexFile(deviceHandle: THandle; filePath: string);
var
  pDevmode: PDeviceMode;
  i: Integer;
  HexStr: string;
  SL: TStringList;
  Bytes: PByte;
begin
  pDevMode := GlobalLock(deviceHandle);
  if pDevmode <> nil then
    try
      SL := TStringList.Create;
      try
        HexStr := '';
        Bytes := PByte(pDevmode);
        // 遍历TDeviceMode的所有字节,转为十六进制
        for i := 0 to SizeOf(TDeviceMode) - 1 do
        begin
          HexStr := HexStr + ByteToHex(Bytes^);
          // 每32个字节换行,方便阅读(可选)
          if (i + 1) mod 32 = 0 then
          begin
            SL.Add(HexStr);
            HexStr := '';
          end;
        end;
        // 写入剩余的十六进制字符
        if HexStr <> '' then
          SL.Add(HexStr);
        SL.SaveToFile(filePath);
      finally
        SL.Free;
      end;
    finally
      GlobalUnlock(deviceHandle);
    end;
end;

// 调用方式(替换原AskSettingsAndSave中的SaveDevModeToFile)
procedure AskSettingsAndSaveHex;
var MyPrinter, MyDriver, MyPort: array[0..255] of Char;
  DeviceHandle: THandle;
begin
  if PrinterSetupDialog1.Execute(Self.Handle) then
    begin
      Printer.GetPrinter(MyPrinter, MyDriver, MyPort, DeviceHandle);
      if DeviceHandle <> 0 then
      begin
        SaveDevModeToHexFile(DeviceHandle, 'd:\temp\dm_hex.txt');
      end;
    end;
end;

2. 从十六进制文件恢复设置

读取十六进制文件内容,将字符串转回二进制数据,再写入TDeviceMode并更新打印机设置:

function HexToByte(HexStr: string): Byte;
const
  HexValues: array['0'..'F'] of Integer = (0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15);
var
  C1, C2: Char;
begin
  C1 := UpCase(HexStr[1]);
  C2 := UpCase(HexStr[2]);
  Result := (HexValues[C1] shl 4) or HexValues[C2];
end;

procedure LoadDevModeFromHexFile(deviceHandle: THandle; filePath: string);
var
  pDevmode: PDeviceMode;
  SL: TStringList;
  HexStr, TempStr: string;
  i, ByteIdx: Integer;
  Bytes: PByte;
begin
  pDevMode := GlobalLock(deviceHandle);
  if pDevmode <> nil then
    try
      SL := TStringList.Create;
      try
        SL.LoadFromFile(filePath);
        HexStr := '';
        // 合并所有行的十六进制字符串
        for i := 0 to SL.Count - 1 do
          HexStr := HexStr + SL[i];
        
        // 确保字符串长度为偶数(每个字节对应两位十六进制)
        if Length(HexStr) mod 2 <> 0 then
          raise Exception.Create('无效的十六进制文件格式');
        
        Bytes := PByte(pDevmode);
        ByteIdx := 0;
        // 将十六进制字符串转回二进制字节
        while (ByteIdx < SizeOf(TDeviceMode)) and (ByteIdx * 2 < Length(HexStr)) do
        begin
          TempStr := Copy(HexStr, ByteIdx*2 + 1, 2);
          Bytes^ := HexToByte(TempStr);
          Inc(Bytes);
          Inc(ByteIdx);
        end;
        
        // 更新打印机设置
        ResetDC(Printer.Handle, pDevmode);
      finally
        SL.Free;
      end;
    finally
      GlobalUnlock(deviceHandle);
    end;
end;

// 调用示例
procedure LoadPrinterSettings;
var MyPrinter, MyDriver, MyPort: array[0..255] of Char;
  DeviceHandle: THandle;
begin
  Printer.GetPrinter(MyPrinter, MyDriver, MyPort, DeviceHandle);
  if DeviceHandle <> 0 then
  begin
    LoadDevModeFromHexFile(DeviceHandle, 'd:\temp\dm_hex.txt');
    // 刷新打印机设置
    Printer.Refresh;
  end;
end;

注意事项

  • 部分打印机驱动的TDeviceMode实际大小可能大于SizeOf(TDeviceMode),可改用GlobalSize(deviceHandle)获取真实大小,避免数据截断。
  • 十六进制转换时已通过UpCase统一处理大小写,兼容大小写混合的十六进制字符串。
  • 恢复设置前需确认打印机处于正常连接状态,避免操作失败。

内容的提问来源于stack exchange,提问作者atome

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 15:08:31