2

Most TWinControl descendant in Delphi has an override method CreateParams to define it's subclass such as: 'EDIT', 'COMBOBOX', 'BUTTON', 'RICHEDIT' and etc.

CreateSubClass(Params, 'EDIT');
CreateSubClass(Params, 'COMBOBOX');
CreateSubClass(Params, 'BUTTON');

There are quite a number of rich edit control for Delphi including controls from third party vendors. All those controls are sub class of RichEdit.

I am wondering if there is a way to test a control is RichEdit regardless of it's original vendor by testing the SubClass defined in CreateParams?

Chau Chee Yang
  • 18,422
  • 16
  • 68
  • 132

4 Answers4

2

Use the Win32 API GetClassName() or RealGetWindowClass() function (see What makes RealGetWindowClass so much more real than GetClassName? for the difference between them), and then check the result for the various RichEdit class names that are available:

  • 'RICHEDIT' (1.0)
  • 'RICHEDIT20A' or 'RICHEDIT20W' (2.x+)
  • 'RICHEDIT50W' (4.1)
  • 'TRichEdit' (VCL wrapper)
  • and so on for other 3rd party wrappers
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
1

Thanks for all the feedback. I think there is no way to get the windows class name for the TWinControl.

Here is another version of IsRichEdit modified from JamesB's version:

type TWinControlAccess = class(TWinControl);

function IsRichEdit(C: TWinControl): boolean;

const A: array[0..8] of string = (
           'RICHEDIT',
           'RICHEDIT20A', 'RICHEDIT20W',
           'RICHEDIT30A', 'RICHEDIT30W',
           'RICHEDIT41A', 'RICHEDIT41W',
           'RICHEDIT50A', 'RICHEDIT50W'
          );

var Info: TWNDClass;
    p: pointer;
    s: string;
begin
  p := TWinControlAccess(C).DefWndProc;

  Result := False;

  for s in A do begin
    if GetClassInfo(HInstance, PChar(s), Info) and (Info.lpfnWndProc = p) then begin
      Result := True;
      Break;
    end;
  end;
end;

We may modify array A if there is newer version of RichEdit class from Windows.

Another possible but risky solution is I just check if the control's VCL class name contain 'RichEdit' string as almost rich edit VCL class from Delphi or 3rd party vendors name the controls that way.

Chau Chee Yang
  • 18,422
  • 16
  • 68
  • 132
0

Am I missing something? Is it not simply a case of testing:

if (MyControl is TRichEdit)

or

if (MyControl is TCustomRichEdit)
J__
  • 3,777
  • 1
  • 23
  • 31
  • These are the Delphi's VCL rich edit controls. There are TcxRichEdit, TRxRichEdit, and more... – Chau Chee Yang Feb 19 '10 at 08:51
  • 1
    That only works for controls that derive from T(Custom)RichEdit. It will not work for controls that derive from TWinControl or TCustomControl instead. – Remy Lebeau Feb 19 '10 at 08:57
  • Yes but in your question you said, "There are quite a number of rich edit control for Delphi including controls from third party vendors. All those controls are sub class of RichEdit." If they're a subclass of TRichEdit then the `is` test works. – J__ Feb 19 '10 at 09:21
  • @_J_: No, it doesn't, subclassing in this context has nothing to do with Delphi's inheritance. – Ondrej Kelle Feb 19 '10 at 09:27
  • cxControls inherit from TcxControl which in turn comes from TCustomControl so this wont work for those. – James Feb 19 '10 at 09:30
  • The "sub class" is not meant for Delphi class inheritance. It is CreateSubClass invoke in method CreateParams. – Chau Chee Yang Feb 19 '10 at 09:34
0

You could use

 function GetClassInfo(hInstance: HINST; lpClassName: PChar;  var lpWndClass: TWndClass): BOOL;

I think this is what Remy was trying to do.

something like:

Function IsRichEdit(MyControl : TWinControl):Boolean;
var 
    Info : TWNDClass;
begin
    Result := False;
    if GetClassInfo(HInstance,PCHAR('RICHEDIT'),Info) and (Info.lpfnWndProc = MyControl.DefWndProc) then 
        Result := True
    else if GetClassInfo(HInstance,PCHAR('RICHEDIT20A'),Info) and (Info.lpfnWndProc = MyControl.DefWndProc)  then 
        Result := True
    else if GetClassInfo(HInstance,PCHAR('RICHEDIT30A'),Info) and (Info.lpfnWndProc = MyControl.DefWndProc)  then 
        Result := True
    else if GetClassInfo(HInstance,PCHAR('RICHEDIT41A'),Info) and (Info.lpfnWndProc = MyControl.DefWndProc)  then 
        Result := True
    else if GetClassInfo(HInstance,PCHAR('RICHEDIT50A'),Info) and (Info.lpfnWndProc = MyControl.DefWndProc)  then 
        Result := True
end;

If you are using Delphi > 2007 then you might need to test for the 'W'(unicode) versions as well e.g 'RICHEDIT20W'

Edit: added Info.WndProc test to match the control.

Oddly enough this won't work for the cxControls since the cxRichEdit isn't the control using the rich edit window (It's a containing so you would need to pass cxControl.InnerControl for this to return true).

Edit I couldn't get this to work for more than the first richedit control created.

James
  • 9,774
  • 5
  • 34
  • 58
  • 1
    Almost. Except your function will return True for *any* control you pass to it, as long as your application has created a subclass for one of those classes. The first parameter to GetClassInfo is supposed to be application instance (HInstance, or 0 for system classes), not the control's handle. The correct test would probably be: if GetClassInfo(HInstance, 'RICHEDIT', Info) and (Info.lpfnWndProc = THackWinControl(MyControl).DefWndProc) then ... – Ondrej Kelle Feb 19 '10 at 11:20
  • Your code works. Is this the only way to test if a control a rich edit? There seems to have few RichEdit window class (e.g: RICHEDIT, RICHEDIT20A, RICHEDIT20W, ...). Do you know how many of them? Is there anyway to return the window class name of TWinControl instance? Then I can check if window class name contain 'RICHEDIT'. – Chau Chee Yang Feb 19 '10 at 12:27