We help IT Professionals succeed at work.

Updating printersettings

b_vaneck
b_vaneck asked
on
2,536 Views
Last Modified: 2012-08-14
Hi,

I'm having a printerproblem. I've created my own printerdialog. Everythings goes ok like selecting a printer, changing the papersize and setting a number of copies. But when I want to change the properties of a printer is all goes wrong... Access Violation...
BTW: I'm working with Delphi 4

Here's my code for changing the properties:
procedure TMyPrintDlg.printInstellingenBtnClick(Sender: TObject);
var
  SpaceNeeded : word; // for pDriverinfo2
  pDBuff : _devicemodeA; // dummy
  aDevMode : PDeviceModeA;
  pDMode : PDEVMODE;
  Driver_info_2 : pDriverinfo2;
  DevModeSize : integer;
  dPtr : Pointer;
  hPrinter : THandle;
begin
  //Printername is a private variable of TMyPrintDlg
  OpenPrinter(PChar(Printername), hPrinter, nil);
  pDMode := GlobalLock(hPrinter);
  GetPrinter(hPrinter, 2, 0, 0, @SpaceNeeded);
  GetMem(Driver_info_2, SpaceNeeded);
  GetPrinter(hPrinter, 2, Driver_info_2, SpaceNeeded, @SpaceNeeded);
  DevModeSize := DocumentProperties(0, hPrinter, PChar(Printername), pDBuff, pDBuff, 0);
  dPtr := allocmem(DevModeSize);
  aDevMode := pDevmode(dPtr);
 
  //all goes ok until this point. When changing the properties of the printer, I get a unexpected Access Violation.
  DocumentProperties(0, hPrinter, PChar(PrinterName), aDevMode^, aDevMode^, DM_IN_BUFFER or DM_IN_PROMPT);
  //update the printersettings
  ResetDC(hPrinter, aDevMode^);
  ClosePrinter(hPrinter);
end;


Thankx in advance,

Benjamin
Comment
Watch Question

Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:
Benjamin,

Im not sure what your trying to do with the GlobalLock on the printer handle.... but its not right. The bigger problems are this:

1.) SpaceNeeded is defined as word, and should be DWORD. (this is the second occurrence of the same problem that I have seen in about a week?....)
2.) for DocumentProperties (the second call) you are specifying DM_IN_BUFFER but are passing in an empty structure??? You have basically told the api to use the values in the buffer (some of which are pointers to char strings) and provided the api with junk... resulting in a gpf.

Try the following, which should work correctly for you.  

var  dwSpaceNeeded:       DWORD;
     dwDMSize:            DWORD;
     dmMode:              TDeviceMode;
     lpdmMode:            PDeviceMode;
     lpPrintInfo2:        PPrinterInfo2;
     hPrinter:            THandle;
     PrinterName:         String;
begin

  // For demo only ** REPLACE WITH YOUR CODE **
  PrinterName:=Printer.Printers[Printer.PrinterIndex];

  // Set structure memory to nil
  lpPrintInfo2:=nil;

  // Open the printer
  if (OpenPrinter(PChar(PrinterName), hPrinter, nil)) then
  begin
     // Get required memory size
     GetPrinter(hPrinter, 2, lpPrintInfo2, 0, @dwSpaceNeeded);
     // Allocate memory
     lpPrintInfo2:=AllocMem(dwSpaceNeeded);
     // Resource protection
     try
        // Get printer info
        GetPrinter(hPrinter, 2, lpPrintInfo2, dwSpaceNeeded, @dwSpaceNeeded);
        // Get dev mode size
        dwDMSize:=DocumentProperties(Handle, hPrinter, PChar(PrinterName), dmMode, dmMode, 0);
        // Allocate memory for the device mode
        lpdmMode:=AllocMem(dwDMSize);
        // Resource protection
        try
           DocumentProperties(Handle, hPrinter, PChar(PrinterName), lpdmMode^, lpdmMode^, DM_OUT_BUFFER or DM_IN_PROMPT);
           // Update the printer settings
           ResetDC(hPrinter, lpdmMode^);
        finally
           // Free allocated memory
           FreeMem(lpdmMode);
        end;
     finally
        // Free allocated memory
        FreeMem(lpPrintInfo2);
     end;
     // Close printer handle
     ClosePrinter(hPrinter);
  end;

end;


--


Regards,
Russell

Author

Commented:
Well Russell,

I've tried your code and it compiles and runs, but when I change any printer properties it will not keep the changes. When I for instance change the lay-out of a page to landscape, instead of portrait, it still prints on a portrait lay-out. Some way or another it doesn't keep the changes of the printer properties...

Thankx,

Benjamin
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:

You indicated your problem was with an access violation, and I corrected your code so that it was syntactically and functionally correct. Now if you want this to work, then you should not be using ResetDC(...) which was meant to take an HDC handle, not a printer handle.

What you should be using is SetPrinter, passing the following:

SetPrinter(hPrinter, 2, lpdmMode, 0);

----

Russell

Author

Commented:
Hi Russell,

yes, my code is now syntactically correct and works almost fine. So thanks for that.
But when I try to apply the settings to change the printer properties it will give a winspool.drv error at SetPrinter(hPrinter, 2, lpdmMode, 0);. I tried the program on a different computer and still it give the winspool.drv error. So something goes wrong here.

Thankx,

Benjamin
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:
Do you mind sharing the error then? (it would make it easier to figure the problem out)

Russell

Author

Commented:
Okay, the full error:

exception raised class EAccessViolation with message 'Access violation at address 73001AE5 in module 'winspool.drv'. Read of address 39464450. Process stopped.
It occurs when clicking the 'OK' button of the printer document properties dialog.

Benjamin
Software Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION

Author

Commented:
Hey Russell,

well it worked eventually... So thankx, now I can finally move on to the next problem...

Benjamin
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.