问题
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?
回答1:
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
回答2:
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.
回答3:
Am I missing something? Is it not simply a case of testing:
if (MyControl is TRichEdit)
or
if (MyControl is TCustomRichEdit)
回答4:
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.
来源:https://stackoverflow.com/questions/2294962/how-to-test-if-a-control-is-a-richedit-control