Решение проблемы с печатью в Windows 10 при использовании Delphi 7 и QuickReport 5.02.2Delphi , Компоненты и Классы , TQuickReportЕсли вы столкнулись с проблемой печати в Windows 10 при использовании Delphi 7 и QuickReport 5.02.2, то данная статья поможет вам найти решение этой проблемы. Оригинальный вопрос: Delphi 7 / QuickReport 5.02.2 Мы использовали подобный код в течение нескольких лет, ноRecently, we've encountered an issue now that we're migrating workstations to Windows 10. Previously, we were using Windows 7 and all was fine. Maybe there's something I'm missing or doing wrong? Here's a simple test project I put together to test this. When the report is within a DLL every call to "Printer.GetPrinter" fails in Windows 10. Though, if the report is on a form within the main application it works fine. Below is the code, and a zipped up folder for anyone that's interested. There is the dependency on QuickReport though, which can't be helped. Thanks for looking. https://1drv.ms/u/s!AsbtokV75aocsXM6MQZcrvwpHKcg ДLL проект. library test_dll; uses SysUtils, Classes, Forms, report in 'report.pas' {report_test}; {$R *.res} function Report_Print(PrinterName: WideString): Integer; export; var Receipt: Treport_test; begin try Receipt := Treport_test.Create(nil); try Receipt.Print(PrinterName); Receipt.Close; finally Receipt.Free; end; except Application.HandleException(Application.Mainform); end; Result := 1; end; exports Report_Print; begin end. Единица отчета. unit report; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, QRCtrls, QuickRpt, ExtCtrls, Printers, QRpCtrls, QRPrntr; type Treport_test = class(TForm) QuickRep1: TQuickRep; DetailBand1: TQRBand; TitleBand1: TQRBand; QRLabel1: TQRLabel; SummaryBand1: TQRBand; QRLabel2: TQRLabel; QRLabel3: TQRLabel; private { Private declarations } public { Public declarations } procedure Print(const PrinterName: string); end; var report_test: Treport_test; procedure SetupPrinter(QuickRep: TQuickRep; const PrinterName: string); function SelectPrinter(QuickRep: TQuickRep; const PrinterName: string): boolean; implementation var DLL_QRPrinter: TQRPrinter; {$R *.dfm} function SelectPrinter(QuickRep: TQuickRep; const PrinterName: string): boolean; var i: integer; compareLength: integer; windowsPrinterName: string; selectedPrinter: Integer; defaultPrinterAvailable: Boolean; begin defaultPrinterAvailable := True; try // an exception will occur if there is no default printer i := Printer.printerIndex; if i > 0 then ; // this line is here so Delphi does not generate a hint except defaultPrinterAvailable := False; end; compareLength := Length(PrinterName); if (not Assigned(QuickRep.QRPrinter)) then begin QuickRep.QRPrinter := DLL_QRPrinter; end; // Look for the printer. selectedPrinter := -1; // Attempt #1: first try to find an exact match for i := 0 to QuickRep.QRPrinter.Printers.Count - 1 do begin windowsPrinterName := Copy(QuickRep.QRPrinter.Printers.Strings[i], 1, compareLength); if (UpperCase(windowsPrinterName) = UpperCase(PrinterName)) then begin selectedPrinter := i; Break; end; end; // Attempt #2: if no exact matches, look for the closest if (selectedPrinter < 0) then for i := 0 to QuickRep.QRPrinter.Printers.Count - 1 do begin windowsPrinterName := Copy(QuickRep.QRPrinter.Printers.Strings[i], 1, compareLength); if (Pos(UpperCase(PrinterName), UpperCase(QuickRep.QRPrinter.Printers.Strings[i])) > 0) then begin selectedPrinter := i; Break; end; end; // Attempt #3: if no exact matches, and nothing close, use default printer if (selectedPrinter < 0) and (defaultPrinterAvailable) then selectedPrinter := QuickRep.Printer.printerIndex; Result := False; if (selectedPrinter > -1) then begin QuickRep.PrinterSettings.PrinterIndex := selectedPrinter; Result := True; end; end; procedure SetupPrinter(QuickRep: TQuickRep; const PrinterName: string); begin //check if we have the default printer instead of the selected printer SelectPrinter(QuickRep, PrinterName); QuickRep.Page.Units := Inches; QuickRep.Page.Length := 11; end; procedure Treport_test.Print(const PrinterName: string); begin SetupPrinter(QuickRep1, PrinterName); QuickRep1.Print; end; initialization DLL_QRPrinter := TQRPrinter.Create(nil); finalization DLL_QRPrinter.Free; DLL_QRPrinter := nil; end. Тестовое приложение. program Project1; uses Forms, Unit1 in 'Unit1.pas' {Form1}; {$R *.res} begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. Главная форма. unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, QRPrntr, Dialogs, StdCtrls, QuickRpt, QRCtrls, ExtCtrls, Printers, QRPCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; type TPrintReport = function(PrinterName: WideString): Integer; var Form1: TForm1; procedure PrintReport(const PrinterName: string); implementation var DLLHandle: THandle = 0; POS: TPrintReport = nil; {$R *.dfm} procedure PrintReport(const PrinterName: string); begin try POS(PrinterName); except on e: Exception do ShowMessage(e.Message); end; end; procedure LoadDLL; var DLLName: string; DLLRoutine: PChar; begin DLLName := 'test_dll.dll'; DLLRoutine := 'Report_Print'; if not (FileExists(DLLName)) then raise Exception.CreateFmt('The DLL "%s" is missing. Build the DLL project and try again.', [DLLName]); Application.ProcessMessages; DLLHandle := LoadLibrary(PChar(DLLName)); Application.ProcessMessages; if (DLLHandle = 0) then raise Exception.CreateFmt('Error: %s, while attempting to load DLL %s.', [IntToStr(GetLastError), DLLName]); POS := GetProcAddress(DLLHandle, DLLRoutine); if (@POS = nil) then raise Exception.CreateFmt('Error: %s, while attempting get address to %s in DLL %s.', [IntToStr(GetLastError), DLLRoutine, DLLName]); end; procedure TForm1.Button1Click(Sender: TObject); begin LoadDLL; ShowMessage('dll loaded'); PrintReport('MyPrinter'); FreeLibrary(DLLHandle); end; end. Вырезка из QuickReport procedure TPrinterSettings.ApplySettings; var Cancel : boolean; begin FPrinter.GetPrinter(FDevice, FDriver, FPort, DeviceMode); DevMode := GlobalLock(DeviceMode); begin SetField(dm_paperlength); ... DeviceMode is 0, so SetField throws an access violation. See below. Access violation at address 036BFBA7 in module 'test_dll.dll'. Write of address 00000028. Возможное решение: Если вы используете Delphi 7 и QuickReport 5.02.2, и у вас возникла проблема с печатью в Windows 10, то вы можете попробовать следующее решение:
Если это не поможет, то вы можете попробовать другой подход: Альтернативное решение: Если предыдущее решение не помогло, то вы можете попробовать следующее альтернативное решение:
Надеюсь, что одно из этих решений поможет вам решить проблему с печатью в Windows 10 при использовании Delphi 7 и QuickReport 5.02.2. Проблема печати в Windows 10 при использовании Delphi 7 и QuickReport 5.02.2 Комментарии и вопросыПолучайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта. :: Главная :: TQuickReport ::
|
||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |