Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: RadStudio XE6 - PrinterIndex - List Index out of Bounds Vcl.Printers.pas


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 3 - Last Post: Jun 2, 2014 4:03 PM Last Post By: Jared Johnson Threads: [ Previous | Next ]
Jared Johnson

Posts: 7
Registered: 9/7/98
RadStudio XE6 - PrinterIndex - List Index out of Bounds Vcl.Printers.pas  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 27, 2014 7:34 PM
It appears that the Vcl.Printers.Pas file has been changed which no longer allows setting the PrinterIndex = -1 to select the default printer. The application raises an exception class EStringsListError with message 'List Index out of bounds (-1)'.
This used to work in XE5, but no longer works in XE6.

I can set the PrinterIndex to any valid number referencing the indexes and that seems to work.

I see in the Vcl.Printers.Pas this paragraph:

{ Printer function - Replaces the Printer global variable of previous versions,
to improve smart linking (reduce exe size by 2.5k in projects that don't use
the printer). Code which assigned to the Printer global variable
must call SetPrinter instead. SetPrinter returns current printer object
and makes the new printer object the current printer. It is the caller's
responsibility to free the old printer, if appropriate. (This allows
toggling between different printer objects without destroying configuration
settings.) }

So it sounds like this is desired behavior (that software call the SetPrinter function instead), but this paragraph has been there since as far back as RadStudio 2009 - I don't have any other versions prior than that to check.

I have read other boards posting fixes for this by suggesting that we modify the SetPrinterIndex function in the Vcl.Printers.pas file:

procedure TPrinter.SetPrinterIndex(Value: Integer);
var
  lDevice, lDriver, lPort : Array[0..255] of Char;
  lDeviceMode : THandle;
begin
  CheckPrinting(False);
  if (Value < -1) or (Value >= Printers.Count) then
    RaiseError(SPrinterIndexError);
  if (Value = -1) or (PrinterIndex = -1) then //******************  condition from XE5 vcl.printers
    SetToDefaultPrinter;
  if Value <> FPrinterIndex then
  begin
      if Value <> -1 then //******************  condition from XE5 vcl.printers
          FPrinterIndex := Value;
    with TPrinterDevice(Printers.Objects[FPrinterIndex]) do
{$IF DEFINED (CLR)}
      SetPrinter(Device, Driver, Port, 0);
{$ELSE}
      Printer.GetPrinter(lDevice, lDriver, lPort, lDeviceMode);
    GlobalUnlock(lDeviceMode);
    GlobalFree(lDeviceMode);
    lDeviceMode := 0;
    Printer.SetPrinter(lDevice, lDriver, lPort, lDeviceMode);
{$ENDIF}
    FreeFonts;
    SetState(TPrinterState.psNoHandle);
  end;
end;


I don't believe this is the best solution for going forward, so I am looking for some advice on how to handle this.

Is this the List Index out of Bounds the desired behavior now?

If we have 3rd party components (QuickReports) that also get the same list index out of bounds - what is the best approach?
Brett Whittacre

Posts: 1
Registered: 7/12/07
Re: RadStudio XE6 - PrinterIndex - List Index out of Bounds Vcl.Printers.pas  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 27, 2014 8:56 PM   in response to: Jared Johnson in response to: Jared Johnson
Jared Johnson wrote:
It appears that the Vcl.Printers.Pas file has been changed which no longer allows setting the PrinterIndex = -1 to select the default printer. The application raises an exception class EStringsListError with message 'List Index out of bounds (-1)'.
This used to work in XE5, but no longer works in XE6.

I can set the PrinterIndex to any valid number referencing the indexes and that seems to work.

I see in the Vcl.Printers.Pas this paragraph:

{ Printer function - Replaces the Printer global variable of previous versions,
to improve smart linking (reduce exe size by 2.5k in projects that don't use
the printer). Code which assigned to the Printer global variable
must call SetPrinter instead. SetPrinter returns current printer object
and makes the new printer object the current printer. It is the caller's
responsibility to free the old printer, if appropriate. (This allows
toggling between different printer objects without destroying configuration
settings.) }

So it sounds like this is desired behavior (that software call the SetPrinter function instead), but this paragraph has been there since as far back as RadStudio 2009 - I don't have any other versions prior than that to check.

I have read other boards posting fixes for this by suggesting that we modify the SetPrinterIndex function in the Vcl.Printers.pas file:

procedure TPrinter.SetPrinterIndex(Value: Integer);
var
  lDevice, lDriver, lPort : Array[0..255] of Char;
  lDeviceMode : THandle;
begin
  CheckPrinting(False);
  if (Value < -1) or (Value >= Printers.Count) then
    RaiseError(SPrinterIndexError);
  if (Value = -1) or (PrinterIndex = -1) then //******************  condition from XE5 vcl.printers
    SetToDefaultPrinter;
  if Value <> FPrinterIndex then
  begin
      if Value <> -1 then //******************  condition from XE5 vcl.printers
          FPrinterIndex := Value;
    with TPrinterDevice(Printers.Objects[FPrinterIndex]) do
{$IF DEFINED (CLR)}
      SetPrinter(Device, Driver, Port, 0);
{$ELSE}
      Printer.GetPrinter(lDevice, lDriver, lPort, lDeviceMode);
    GlobalUnlock(lDeviceMode);
    GlobalFree(lDeviceMode);
    lDeviceMode := 0;
    Printer.SetPrinter(lDevice, lDriver, lPort, lDeviceMode);
{$ENDIF}
    FreeFonts;
    SetState(TPrinterState.psNoHandle);
  end;
end;


I don't believe this is the best solution for going forward, so I am looking for some advice on how to handle this.

Is this the List Index out of Bounds the desired behavior now?

If we have 3rd party components (QuickReports) that also get the same list index out of bounds - what is the best approach?

We are having the same issue. The fix above seems to only work for Delphi. We are at a loss for C++ Builder. It seems to be pulling the information from a lib file that is not getting rebuilt after the changes above.
Jared Johnson

Posts: 7
Registered: 9/7/98
Re: RadStudio XE6 - PrinterIndex - List Index out of Bounds Vcl.Printers.pas  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 28, 2014 4:56 PM   in response to: Jared Johnson in response to: Jared Johnson
Since we need to get a release out quickly and don't have time to wait for new C++Builder with the fix or for component vendors to update their components we did the following work around. Maybe this will help anyone else out that needs it.

When the program initially starts we create a variable (in a datamodule) and save the current default printer index.
  FDefaultPrinterIndex = Printer()->PrinterIndex;


So now we have the current default printer.

We change printers a lot in our program so we wanted to set the printer index back to the default printer (-1) after printing to a different printer.
So anywhere we set the PrinterIndex to -1 was changed to
  Printer()->PrinterIndex = FDefaultPrinterIndex;

To solve the QuickReports problem (because it must also be using the -1 to set the default printer) we had to set the PrinterIndex for the Quickrep.

  QuickRep1->PrinterSettings->PrinterIndex = FDefaultPrinterIndex;

before calling preview() or print()

Good luck!
Jared Johnson

Posts: 7
Registered: 9/7/98
Re: RadStudio XE6 - PrinterIndex - List Index out of Bounds Vcl.Printers.pas  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 2, 2014 4:03 PM   in response to: Jared Johnson in response to: Jared Johnson
Per Embarcadero Developer Support:

<quote>
I just got word that this issue (internally logged as RS-50679) is supposed to be fixed in our forthcoming update 1. I have attached reference to the case and will go ahead and close it out for you. Keep your eyes on your Registered Users Area of the EDN http://cc.embarcadero.com/myreg and hopefully we will have that out by end of the month or sooner.
</quote>

Looking forward to Update 1
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02