Recent

Author Topic: Change the class name of TForm on win32 ?  (Read 29859 times)

Thaddy

  • Hero Member
  • *****
  • Posts: 16770
  • Ceterum censeo Trump esse delendam
Re: Change the class name of TForm on win32 ?
« Reply #15 on: June 06, 2017, 07:15:54 am »
I thought overriding CreateParams as in Delphi might be enough. Thank you for your answer and clarifying my doubts.
Summarize:
- If you are a component writer, plz feel free to use CreateParams, you need it...But you need a whole lot more... And you allow for testing, etc, overriding paint, add your message handling etc.. Object Pascal, not only Delphi but also Lazarus/fpc  can help a little.
- If you just want it ad-hoc in a program, don't...
Changing servers. thaddy.com may be temporary unreachable but restored when the domain name transfer is done.

chris_laz

  • New Member
  • *
  • Posts: 16
Re: Change the class name of TForm on win32 ?
« Reply #16 on: March 14, 2025, 01:16:54 pm »
Just in case anyone is still interested in this, I have found a decent workaround.
We used the Window classname in Delphi to find windows in other apps, and to enumerate windows in the current app from a thread, when it isn't safe to use Screen.Forms or Application.Forms.

It is quite inconvenient that Lazarus uses the same classname of 'Window' for all forms, but it is possible to intercept the window handle creation and add a custom property to the window handle as a global atom:

Code: Pascal  [Select][+][-]
  1. // add these overrides into your base form ancestor, for use in all your forms
  2. procedure TBaseForm.CreateWnd; override;
  3. begin
  4.    inherited CreateWnd;
  5.    Windows.SetProp(Handle, 'My_Window_Prop_ClassName', GlobalAddAtom(pchar(string(ClassName))));
  6. end;
  7.  
and then destroy the atom (atoms have built-in reference counting) and remove the property when the window handle is destroyed

Code: Pascal  [Select][+][-]
  1. procedure TBaseForm.DestroyWnd; override;
  2. var
  3.    atom: TAtom;
  4. begin
  5.    atom := Windows.RemoveProp(Handle, 'My_Window_Prop_ClassName');
  6.    if (atom<>0) then GlobalDeleteAtom(atom);
  7.    inherited DestroyWnd;
  8. end;
  9.  

Then you can enumerate all windows to find the one you are looking for with something like this:

Code: Pascal  [Select][+][-]
  1. type
  2.    TEnumInfo = record
  3.       ClassName: string;
  4.       Found: boolean;
  5.    end;
  6. var
  7.    info: TEnumInfo;
  8.  
  9. info.ClassName := 'class name to look for';
  10. info.Found := false;
  11. EnumThreadWindows(MainThreadId, @EnumThreadCallback, LPARAM(@info));
  12.  

where EnumThreadCallback is defined as:
Code: Pascal  [Select][+][-]
  1. function EnumThreadCallback(hwnd: THandle; var info: TEnumInfo): bool; stdcall;
  2. var
  3.    atom: TAtom;
  4.    cls: array[0..MAX_PATH] of char;
  5. begin
  6.    atom := Windows.GetProp('My_Window_Prop_ClassName');
  7.    if (atom<>0) then begin
  8.       if GlobalGetAtomName(atom, cls, MAX_PATH)>0 then begin
  9.          if (StrComp(cls, pchar(info.ClassName)=0 then begin
  10.             info.Found := true;
  11.             break;
  12.          end;
  13.       end;
  14.    end;
  15.    Result := not info.Found; // return TRUE to continue enum, FALSE to stop
  16.  



 

TinyPortal © 2005-2018