0

I have been looking for a way of retrieving the papers supported by an specific printer and their sizes (width and height) in millimeters if possible.

I have seen and "Studied" many posts and sites about using Printer.Getprinter and Printer.SetPrinter but I am really far from understanding the whole process to make that work, I learnt that I have to use DeviceCapabilities in order to retrieve data that is specific to one printer but I really don't know how to use those structures. I need something similar to this but for a specific printer and using the DeviceCapabilities. I use Delphi VCL.

In the question linked, they use EnumForms which I understand is for all the printers, they also mention that DeviceCapabilities is for a specific printer, and that is what I need, to get the supported paper names and sizes but only for the selected printer and not all of them. lets say I select my printer: Printer.PrinterIndex:= Printer.Printers.IndexOf(MyPrinter); I would like to get the papers and paper sizes for those supported by that printer.

Thank you so much for any help provided!

Hiram
  • 159
  • 1
  • 9
  • Do you want to write code for an arbitrary printer, or just this Brother model? – David Heffernan Aug 27 '19 at 20:48
  • @DavidHeffernan The printer may change depending on the user, but the brother model is the one I am currently running tests. – Hiram Aug 27 '19 at 20:50
  • Yes @whosrdaddy, that is actually the post I linked in my question. The thing is that Sertac said that if you want data from a specific printer you should use `DeviceCapabilities` instead of `EnumForms` – Hiram Aug 27 '19 at 20:54
  • You should remove reference to a specific printer to avoid anyone thinking you want code for that model specifically – David Heffernan Aug 27 '19 at 21:12
  • Thanks @DavidHeffernan, I edited my question. – Hiram Aug 27 '19 at 21:17
  • @whosrdaddy I tried the code, but It gives more papers than the current printer supports. in fact it doesn’t give me some papers that the printer actually supports. – Hiram Aug 27 '19 at 21:19
  • 1
    Hi Hiram, I see. Please try out Peter Belows' code from [here](https://groups.google.com/forum/?hl=de#!topic/borland.public.delphi.winapi/vKjwHUB96FI), more specific the `GetPaperInfo` procedure. – whosrdaddy Aug 27 '19 at 21:26
  • @whosrdaddy I will try it and let you know, thanks a lot for helping me. – Hiram Aug 27 '19 at 21:34

1 Answers1

2

Here is an example that calls DeviceCapabilities for the currently selected printer and outputs supported paper names for "the current default initialization values for the specified printer driver" to a memo. The quoted part in the previous sentence is from the documentation of the function and I'm not absolutely positive that I understand what it means. That happens because a DevMode is not passed.

procedure TForm1.Button1Click(Sender: TObject);
var
  PrinterName: string;
  HPrinter: THandle;
  Ret: DWORD;
  Buf: array of array [0..63] of Char;
  i: Integer;
begin
  PrinterName := Printer.Printers[Printer.PrinterIndex];
  if OpenPrinter(PChar(PrinterName), HPrinter, nil) then begin
    Ret := DeviceCapabilities(PChar(PrinterName), nil, DC_PAPERNAMES, nil, nil);
    if Ret > 0 then begin
      SetLength(Buf, Ret);
      DeviceCapabilities(PChar(PrinterName), nil, DC_PAPERNAMES, Pointer(Buf), nil);
      for i := 0 to Ret - 1 do
        Memo1.Lines.Add(Buf[i]);
    end;
    ClosePrinter(HPrinter);
  end;
end;

Explaining the code is kind of pointless, I'd be duplicating the documentation. I included the link above.

Sertac Akyuz
  • 54,131
  • 4
  • 102
  • 169
  • I tried the code but the memo fills with numbers instead of names and they go like this: | 1 | 1 | 2 | 2 | 2 | 3 | 3 | 5 | 5 | 6 | 6 | 6 | 1 | 2 | 5 | 1 | 2 | 3 | 5 | 5 | 6 | 1 | 2 | 3 | 5 | 5 | 6 | 1 | I just changed the `PrinterName` to my printer, which does exist. – Hiram Aug 28 '19 at 16:54
  • @Hiram the PAnsiChar cast should be PChar, in memo.lines.add. Still seems to be a problem though, I'll have a look. – Sertac Akyuz Aug 28 '19 at 17:06
  • thank you so much for taking the time. And yes, I also got an Access Violation if I close the program after clicking the button. – Hiram Aug 28 '19 at 17:11
  • @Hiram - I modified string extraction code, please try it again with the update. – Sertac Akyuz Aug 28 '19 at 17:24
  • It worked perfect! is it possible to use this code in a similar way to get the paper's width and height in millimeters? – Hiram Aug 28 '19 at 17:32
  • Yes. Instead of a [0..63] char array, you need to pass a point array. And the appropriate flag of course - need to read DC_PAPERSIZE in docs. Please notify if you get stuck... – Sertac Akyuz Aug 28 '19 at 17:36
  • Alright, I will try that and let you know and then I'll mark it as the correct answer. you have truly helped me a lot, Thanks! – Hiram Aug 28 '19 at 17:39
  • I think I got it. Only one last question, for papers like 62mm x 100mm when filling the memo I get 62 x 99, I am showing `Buf[i].X div 10;` and `Buf[I].Ydiv 10;` so that I get mm and not 10th of mm. do you see any problem if I round those numbers up so that they match the same value as the one the paper name says? – Hiram Aug 28 '19 at 18:41
  • Yeah, how would you know if you have to round up a number or not. I think I'd use `Round(Buf[i].X/10)` or perhaps `Trunc(SizeBuf[i].X/10` – Sertac Akyuz Aug 28 '19 at 19:03
  • I'll do some tests with both. Thanks Sertac, you have helped me a lot with the problem and also understanding `DeviceCapabilities`. – Hiram Aug 28 '19 at 19:26
  • The latter (trunc) is an error on my part, it would be identical with div. I don't understand how you can end up with 99 from (100# div 10). You're welcome. – Sertac Akyuz Aug 28 '19 at 19:46
  • the thing is that the point has a value of 998, and I do 998 div 10 and that is where I get the 99, I don't get the full 1000 from the point.Y. in other paper instead of getting Y 540 I get Y 539 – Hiram Aug 28 '19 at 20:12