Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I change the caption of a modal form without access to the source?

I have a third party component that displays a print preview form. I would like to change the caption of the preview form to something more appropriate. Unfortunately I do not have the source for the third party component and the component does not provide the functionality.

Is it possible to somehow catch the modal form as it is being displayed and set it's properties before it is shown?

like image 275
norgepaul Avatar asked Oct 23 '12 20:10

norgepaul


3 Answers

The modal form will cause the calling form to deactivate, you can listen for WM_ACTIVATE messages on the form that is active before the modal form is shown. You'll have the activating window's handle in the message handler, you can test that if it is of a form of the type of the modal form. Below example tests for the class name, which you can get with something like Spy++. Note that deactivation happens briefly after the modal form has become visible, but I don't think it would be possible to notice the differing caption.

type
  TForm1 = class(TForm)
    ..
  protected
    procedure WMActivate(var Message: TWMActivate); message WM_ACTIVATE;
  end;

procedure TForm1.WMActivate(var Message: TWMActivate);
var
  Form: TWinControl;
begin
  if Message.Active = WA_INACTIVE then begin
    Form := FindControl(Message.ActiveWindow);
    if Form is TCustomForm then begin
      if TCustomForm(Form).ClassName = 'TThirdPartyModalForm' then
        TCustomForm(Form).Caption := 'My caption';
    end;
  end;
  inherited;
end;
like image 155
Sertac Akyuz Avatar answered Sep 30 '22 16:09

Sertac Akyuz


Try using the TScreen.OnActiveFormChange event, using the TScreen.ActiveCustomForm or TScreen.ActiveForm property to know which TForm has the focus:

procedure TMainForm.DoSomething; 
begin 
  Screen.OnActiveFormChange := ActiveFormChanged;
  try
    // do something that triggers the modal form ...
  finally
    Screen.OnActiveFormChange := nil;
  end;
end;

procedure TMainForm.ActiveFormChanged(Sender: TObject);
var
  Form: TCustomForm;
begin
  Form := Screen.ActiveCustomForm; 
  if (Form <> nil) and (Form.ClassName = 'TModalFormClassName') then 
    Form.Caption := 'My caption'; 
end;
like image 21
Remy Lebeau Avatar answered Sep 30 '22 16:09

Remy Lebeau


You can install a WH_CBT hook using the SetWindowsHookEx function.

var
 hhk: HHOOK;


function CBT_FUNC(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
const
  ClassNameBufferSize = 1024;
var
 hTemp  : HWND;
 i      : Integer;
 RetVal : Integer;
 ClassNameBuffer: Array[0..ClassNameBufferSize-1] of Char;
begin
   case nCode of
     HCBT_ACTIVATE:
     begin
       hTemp := HWND(wParam);
       if (Screen<>nil) and (hTemp>0) then
       begin
          RetVal := GetClassName(wParam, ClassNameBuffer, SizeOf(ClassNameBuffer));
          //check for the class 
          if (RetVal>0) and SameText(ClassNameBuffer,'TForm2') then
          begin
             Assert(RetVal < ClassNameBufferSize, 'Class name larger than fixed buffer size');
            for i := 0 to Screen.FormCount-1 do
             if Screen.Forms[i].Handle=hTemp then
               begin 
                  //set the caption
                  Screen.Forms[i].Caption:='Hello';
                  Break;
               end;
          end;
       end;
     end;
   end;
  Result := CallNextHookEx(hhk, nCode, wParam, lParam);
end;

Procedure InitHook();
var
  dwThreadID : DWORD;
begin
  dwThreadID := GetCurrentThreadId;
  hhk := SetWindowsHookEx(WH_CBT, @CBT_FUNC, hInstance, dwThreadID);
  if hhk=0 then RaiseLastOSError;
end;


Procedure KillHook();
begin
  if (hhk <> 0) then
    UnhookWindowsHookEx(hhk);
end;


initialization
  InitHook();

finalization
  KillHook();
end.
like image 20
RRUZ Avatar answered Sep 30 '22 14:09

RRUZ