ReportMachine不能打开打印设置的解决方法
1、问题现象
在使用ReportMachine作为报表打印时,发现不能调用本机打印机属性设置对话框,如下图:
点击“属性”按钮后无反应,从而不能对打印机属性进行设置。该问题同时也导致不能获取打印机设置信息。
2、问题原因
跟踪代码发现点击“属性”,会调用“PropertiesDlg”函数,RM_Printer.pas文件中,代码如下:
function TRMPrinter.PropertiesDlg: Boolean;
var
lDevMode: THandle;
lPDevMode: PDeviceMode;
lHandle: THandle;
lResult: Boolean;
begin
FLock.Acquire;
try
GetDevMode(lDevMode);
Result := False;
lResult := FALSE;
try
lPDevMode := GlobalLock(lDevMode);
if Screen.ActiveForm <> nil then
lHandle := Screen.ActiveForm.Handle
else
lHandle := 0;
if lPDevMode <> nil then
lResult := (Winspool.DocumentProperties(lHandle, PrinterHandle, PChar(PrinterInfo.Device),
lPDevMode^, lPDevMode^, DM_IN_BUFFER or DM_OUT_BUFFER or DM_IN_PROMPT) > 0);
if lResult then
begin
SetDevMode(lDevMode);
Result := True;
end;
GlobalUnlock(lDevMode);
finally
GlobalFree(lDevMode);
end;
finally
FLock.Release;
end;
end;
进而跟踪GetDevMode,找到RM_Printer.pas文件中GetDocumentProperties函数,代码段如下:
function TRMCustomPrinter.GetDocumentProperties: THandle;
var
lStubDevMode: TDeviceMode;
lPrinterInfo: TRMPrinterInfo;
begin
FLock.Acquire;
try
Result := 0;
if FDevMode = 0 then
begin
lPrinterInfo := RMPrinters.PrinterInfo[FPrinterIndex];
if lPrinterInfo = nil then
Exit;
FDevMode := GlobalAlloc(GHND,
DocumentProperties(0, PrinterHandle, PChar(lPrinterInfo.Device), lStubDevMode, lStubDevMode, 0));
if FDevMode <> 0 then
begin
FPDevMode := GlobalLock(FDevMode);
if DocumentProperties(0, PrinterHandle, PChar(lPrinterInfo.Device), FPDevMode^, FPDevMode^, DM_OUT_BUFFER) >= 0 then
begin
FDefaultBin := FPDevMode^.dmDefaultSource;
end
else
FreeDevMode;
end;
end;
Result := FDevMode;
finally
FLock.Release;
end;
end;
3、解决办法
更改GetDocumentProperties函数中的代码
DocumentProperties(0, PrinterHandle, PChar(lPrinterInfo.Device), lStubDevMode, lStubDevMode, 0)
为
DocumentProperties(0, PrinterHandle, PChar(lPrinterInfo.Device), nil, nil, 0)
完整代码如下:
function TRMCustomPrinter.GetDocumentProperties: THandle;
var
lPrinterInfo: TRMPrinterInfo;
begin
FLock.Acquire;
try
Result := 0;
if FDevMode = 0 then
begin
lPrinterInfo := RMPrinters.PrinterInfo[FPrinterIndex];
if lPrinterInfo = nil then
Exit;
FDevMode := GlobalAlloc(GHND,
DocumentProperties(0, PrinterHandle, PWideChar(lPrinterInfo.Device), nil, nil, 0));
if FDevMode <> 0 then
begin
FPDevMode := GlobalLock(FDevMode);
if DocumentProperties(0, PrinterHandle, PChar(lPrinterInfo.Device), FPDevMode^, FPDevMode^, DM_OUT_BUFFER) >= 0 then
begin
FDefaultBin := FPDevMode^.dmDefaultSource;
end
else
FreeDevMode;
end;
end;
Result := FDevMode;
finally
FLock.Release;
end;
end;