TPrintDialog

Hello

How can I handel ONPrinterChange event when TPintDialog is executing?

I want to get Printer.PrinterIndex during the PrintDialog is appearing.

I want to get all printer's settings before Execute metod.

Thanks.
pmarkovAsked:
Who is Participating?
 
JaccoConnect With a Mentor Commented:
Hi pmarkov,

I posted the previous comment as an answer.

Regards Jacco

procedure TForm1.Button4Click(Sender: TObject);
begin
 PrintDialog1.Execute;
end;

var
 OldPDWndProc: Pointer;
 NewPDWndProc: Pointer;
 PrinterComboHandle: HWND;

procedure TForm1.PDWndProc(var Message: TMessage);
var
 liIndex: Integer;
begin
 // Check whether combobox changes
 if Message.Msg = WM_COMMAND then
   if TWMCommand(Message).NotifyCode = CBN_SELCHANGE then
   begin
     // get the current index
     liIndex := SendMessage(PrinterComboHandle, CB_GETCURSEL, 0, 0);
     // report the selected printer index
     Memo1.Lines.Add('Printer selected: ' + IntToStr(liIndex));
   end;
 // call the old WindowProc
 with Message do
   Result := CallWindowProc(OldPDWndProc, PrinterComboHandle, Msg, wParam, lParam);
end;

procedure TForm1.PrintDialog1Show(Sender: TObject);
var
 t: Pointer;
 p: PChar;
 h: HWND;
begin
 NewPDWndProc := MakeObjectInstance(PDWndProc);
 GetMem(p, 100);
 h := FindWindowEx(PrintDialog1.Handle, 0, nil, nil);
 while h <> 0 do
 begin
   GetClassName(h, p, 100);
   if p = 'ComboBox' then
   begin
     PrinterComboHandle := h;
     OldPDWndProc := Pointer(GetWindowLong(h, GWL_WNDPROC));
     SetWindowLong(h, GWL_WNDPROC, LongInt(NewPDWndProc));
   end;
   h := FindWindowEx(PrintDialog1.Handle, h, nil, nil);
 end;
 FreeMem(p);
end;
0
 
ITugayCommented:
Hi pmarkov,

sorry, have no time to write complete sample, here is only idea:

type
  TWindowProc = function (H, Msg, L, W: Integer): Integer; stdcall;
var
  OldPDWndProc: TWindowProc;

function PDWndProc(H, Msg, L, W: Integer): Integer; stdcall;
begin
  // here you can check some values of dailog
  // e.g. get text for printer's combobox
  Result := OldPDWndProc(H, Msg, L, W);
end;

procedure TForm1.PrintDialog1Show(Sender: TObject);
begin
  OldPDWndProc := Pointer(GetWindowLong(PrintDialog1.Handle, GWL_WNDPROC));
  SetWindowLong(PrintDialog1.Handle, GWL_WNDPROC, Integer(@PDWndProc));
end;

-----
Igor.
0
 
pmarkovAuthor Commented:
But I want handle ON printer Change event! :(
0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

 
JaccoCommented:
Hi pmarkov,

I have spent some hours trying to get things working. Igor was right. Here is the working code. The TPrintDialog does not have an OnPrinterChange event. That is why you need to bend the message handling chain so that you catch the windows messages send to the combobox. For that you first have to find the combobox.

To achieve this you implement the OnShow event of the TPrintDialog. There you have access to the Handle of the dialog. The you loop all WinControls on the dialog using FindWindowEx until you find one of ClassName "ComboBox" (you can get the ClassName of a HWND using GetClassName). Then you reroute the message handling chain for the found handle by GetWindowLong and SetWindowLong passing the object instance of your new window proc (which is made using MakeObjectInstance).

The message handler must do the following:

catch WM_COMMAND check if NotifyCode = 1 get the selected index of the combo and report it (or call an event...).

Good luck,

Regards Jacco

procedure TForm1.Button4Click(Sender: TObject);
begin
  PrintDialog1.Execute;
end;

var
  OldPDWndProc: Pointer;
  NewPDWndProc: Pointer;
  PrinterComboHandle: HWND;

procedure TForm1.PDWndProc(var Message: TMessage);
var
  liIndex: Integer;
begin
  // Check whether combobox changes
  if Message.Msg = WM_COMMAND then
    if TWMCommand(Message).NotifyCode = CBN_SELCHANGE then
    begin
      // get the current index
      liIndex := SendMessage(PrinterComboHandle, CB_GETCURSEL, 0, 0);
      // report the selected printer index
      Memo1.Lines.Add('Printer selected: ' + IntToStr(liIndex));
    end;
  // call the old WindowProc
  with Message do
    Result := CallWindowProc(OldPDWndProc, PrinterComboHandle, Msg, wParam, lParam);
end;

procedure TForm1.PrintDialog1Show(Sender: TObject);
var
  t: Pointer;
  p: PChar;
  h: HWND;
begin
  NewPDWndProc := MakeObjectInstance(PDWndProc);
  GetMem(p, 100);
  h := FindWindowEx(PrintDialog1.Handle, 0, nil, nil);
  while h <> 0 do
  begin
    GetClassName(h, p, 100);
    if p = 'ComboBox' then
    begin
      PrinterComboHandle := h;
      OldPDWndProc := Pointer(GetWindowLong(h, GWL_WNDPROC));
      SetWindowLong(h, GWL_WNDPROC, LongInt(NewPDWndProc));
    end;
    h := FindWindowEx(PrintDialog1.Handle, h, nil, nil);
  end;
  FreeMem(p);
end;
0
 
JaccoCommented:
Hi pmarkov,

Is this what you are looking for?

Regards Jacco
0
 
pmarkovAuthor Commented:
YES!
Thank you.

0
 
pmarkovAuthor Commented:
Hi Jacco

With this example I can get Printer Index in DropDownBox but it is DIFFERENT from Printer Index In Printer.Printers.

How Can I get real Printer Index ot Printer Name selected in drop-down?

Thanks
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.