How To create custom InputQuery/MessageBox etc without pain.

Using a way that may look like a hack it is possible to modify generic message boxes and change the icon, edit, button, size, etc...

The idea behind this customization is to create a custom message, post it to the queue *before* calling the message box. In the message, you retrieve the handle of the window (if it's messagebox) or the form (if it's inputbox/inputquery/messagedlg) and you modify whatever you want. Let me give two examples, one for a regular api messagebox and another with a inputquery.

1st example: You need to change the default caption of the Yes/No button of a regular messagebox.

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure WMHackBox(var message: TMessage); message WM_USER + 1025;
  end;
...
implementation
...
procedure TForm1.Button1Click(Sender: TObject);
begin
  // Posting our custom message
  PostMessage(Handle, WM_USER + 1025, 0, 0);
  // Messagebox call
  Application.MessageBox('I'' completely stupid.', 'MyApplication', MB_YESNO or MB_ICONINFORMATION);
end;

procedure TForm1.WMHackBox(var message: TMessage);
var
  h: HWND;
begin
  // The message box is shown, let's retrieve its handle
  h := FindWindow(WC_DIALOG, 'MyApplication');
  // If this is the right messagebox, let's modify it
  if GetParent(h) = Application.Handle then
  begin
    SetDlgItemText(h, ID_YES, 'I &agree');


    SetDlgItemText(h, ID_NO, 'I &disagree');
  end;
end;

Note that if you use MessageDlg, it's not a regular API messagebox but a Form created dynamically by Delphi. See 2nd Example.

Result'

2nd example: You need to change the edit property of a InputQuery, for instance the PasswordChar.

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure WMHack(var message: TMessage); message WM_USER + 1024;
  end;
...
implementation
...
const
  ACaption = 'Caption';

procedure TForm1.Button1Click(Sender: TObject);
begin
  PostMessage(Handle, WM_USER + 1024, 0, 0);
  InputBox(ACaption, 'Prompt', 'Default');
end;

procedure TForm1.WMHack(var message: TMessage);
var
  i: Integer;
  j: Integer;
begin
  for i := 0 to Screen.FormCount-1 do
    if Screen.Forms[i].Caption = ACaption then
    begin
      for j := 0 to Screen.Forms[i].ControlCount-1 do
        if Screen.Forms[i].Controls[j] is TEdit then
        begin
          TEdit(Screen.Forms[i].Controls[j]).PasswordChar := '#';
          TEdit(Screen.Forms[i].Controls[j]).SelectAll;
          Exit;
        end;
    end;
end;
Result

 

Share this article!

Follow us!

Find more helpful articles: