Как проверить, является ли элемент управления элементом RichEdit

Большинство потомков TWinControl в Delphi имеют метод переопределения CreateParams для определения его подкласса, например: 'EDIT', 'COMBOBOX', 'BUTTON', 'RICHEDIT' и т. Д.

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

Для Delphi существует множество разнообразных элементов управления редактированием, включая элементы управления от сторонних поставщиков. Все эти элементы управления являются подклассом RichEdit.

Мне интересно, есть ли способ проверить элемент управления RichEdit, независимо от его исходного поставщика, путем тестирования подкласса, определенного в CreateParams?


person Chau Chee Yang    schedule 19.02.2010    source источник


Ответы (4)


Используйте Win32 API GetClassName() или _ 2_ (см. Чем отличается RealGetWindowClass более реальным, чем GetClassName?), а затем проверьте результат для различных доступных имен классов RichEdit:

  • 'RICHEDIT' (1.0)
  • 'RICHEDIT20A' or 'RICHEDIT20W' (2.x+)
  • 'RICHEDIT50W' (4.1)
  • 'TRichEdit' (оболочка VCL)
  • и так далее для сторонних оболочек.
person Remy Lebeau    schedule 19.02.2010
comment
Я не могу найти GetWindowClass в Windows.pas. Я использую Delphi 2010. - person Chau Chee Yang; 19.02.2010
comment
Я думаю, это сработает, если вы можете получить доступ к ControlClassName, переданному в CreateSubClass. - person James Barrass; 19.02.2010
comment
Итак, как мне получить к нему доступ? Я не могу найти GetWindowClass в модуле windows.pas - person Chau Chee Yang; 19.02.2010
comment
Я пробую GetClassName, но он возвращает имя класса Delphi элемента управления. Например, он возвращает TRichEdit для элемента управления TRichEdit вместо RICHEDIT, RICHEDIT20A ИЛИ RICHEDIT20W, упомянутых Реми Лебо. - person Chau Chee Yang; 19.02.2010
comment
имя API - GetClassName, определенное в Windows.pas, а не GetWindowClass. - person vcldeveloper; 19.02.2010
comment
GetClassName возвращает имя класса VCL, а не имя подкласса окна. - person Chau Chee Yang; 19.02.2010
comment
Я не уверен, но, возможно, вы можете использовать RealGetWindowClass (в user32.dll) вместо GetWindowClass - person SimaWB; 19.02.2010
comment
Я пробовал RealGetWindowClass и, похоже, возвращает тот же результат, что и GetWindowClass. - person Chau Chee Yang; 19.02.2010
comment
Привет, Реми, можно ли узнать, вернул ли CreateSubClass (Params, 'RICHEDIT20A') элемент управления RichEdit 2.0 или 3.0? - person MtwStark; 01.09.2017
comment
@MtwStark: единственный способ, о котором я знаю, - это выполнить операцию 3.0 над элементом управления, который не работает в 2.0, и посмотреть, что произойдет - person Remy Lebeau; 01.09.2017

Спасибо всем за отзывы. Я думаю, что нет способа получить имя класса Windows для TWinControl.

Вот еще одна версия IsRichEdit, модифицированная по сравнению с версией JamesB:

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;

Мы можем изменить массив A, если есть более новая версия класса RichEdit из Windows.

Другое возможное, но рискованное решение - я просто проверяю, содержит ли имя класса VCL элемента управления строку RichEdit, поскольку класс VCL с почти расширенным редактированием от Delphi или сторонних поставщиков так называет элементы управления.

person Chau Chee Yang    schedule 20.02.2010

Я что-то упускаю? Разве это не просто тест:

if (MyControl is TRichEdit)

or

if (MyControl is TCustomRichEdit)
person J__    schedule 19.02.2010
comment
Это многофункциональные элементы управления редактированием VCL Delphi. Есть TcxRichEdit, TRxRichEdit и другие ... - person Chau Chee Yang; 19.02.2010
comment
Это работает только для элементов управления, производных от T (Custom) RichEdit. Вместо этого он не будет работать для элементов управления, производных от TWinControl или TCustomControl. - person Remy Lebeau; 19.02.2010
comment
Да, но в своем вопросе вы сказали, что для Delphi существует множество элементов управления расширенным редактированием, включая элементы управления от сторонних поставщиков. Все эти элементы управления являются подклассом RichEdit. Если они являются подклассом TRichEdit, тогда тест is работает. - person J__; 19.02.2010
comment
@_J_: Нет, создание подклассов в этом контексте не имеет ничего общего с наследованием Delphi. - person Ondrej Kelle; 19.02.2010
comment
cxControls наследуется от TcxControl, который, в свою очередь, происходит от TCustomControl, поэтому для них это не сработает. - person James Barrass; 19.02.2010
comment
Подкласс не предназначен для наследования классов Delphi. Это вызов CreateSubClass в методе CreateParams. - person Chau Chee Yang; 19.02.2010

Вы могли бы использовать

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

Я думаю, это то, что Реми пытался сделать.

что-то типа:

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;

Если вы используете Delphi> 2007, вам может потребоваться протестировать версии 'W' (unicode), например, RICHEDIT20W.

Изменить: добавлен тест Info.WndProc для соответствия элементу управления.

Как ни странно, это не сработает для cxControls, поскольку cxRichEdit не является элементом управления, использующим окно расширенного редактирования (это содержание, поэтому вам нужно будет передать cxControl.InnerControl, чтобы он вернул true).

Изменить. Я не мог заставить это работать больше, чем для первого созданного элемента управления richedit.

person James Barrass    schedule 19.02.2010
comment
Почти. За исключением того, что ваша функция вернет True для любого элемента управления, который вы ей передаете, если ваше приложение создало подкласс для одного из этих классов. Первым параметром GetClassInfo должен быть экземпляр приложения (HInstance или 0 для системных классов), а не дескриптор элемента управления. Правильный тест, вероятно, будет следующим: если GetClassInfo (HInstance, 'RICHEDIT', Info) и (Info.lpfnWndProc = THackWinControl (MyControl) .DefWndProc), то ... - person Ondrej Kelle; 19.02.2010
comment
Ваш код работает. Это единственный способ проверить, является ли элемент управления расширенным редактированием? Кажется, есть несколько оконных классов RichEdit (например: RICHEDIT, RICHEDIT20A, RICHEDIT20W, ...). Вы знаете, сколько их? Есть ли способ вернуть имя класса окна экземпляра TWinControl? Затем я могу проверить, содержит ли имя класса окна «RICHEDIT». - person Chau Chee Yang; 19.02.2010