如何在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
相关产品推荐
相关产品推荐

