Определить, имеет ли сфокусированное окно активную каретку

#delphi #winapi #controls #caret #delphi-6

#delphi #winapi #элементы управления #курсор #delphi-6

Вопрос:

Следующая _isEdit функция определяет, можно ли применить ввод к текущему сфокусированному элементу управления:

 class function TSpeedInput._getFocusedControlClassName(): WideString;
var
  lpClassName: array[0..1000] of WideChar;
begin
  FillChar(lpClassName, SizeOf(lpClassName), 0);
  Windows.GetClassNameW(GetFocus(), PWideChar(@lpClassName), 999);
  Result := lpClassName;
end;

class function TSpeedInput._isEdit(): Boolean;
const
  CNAMES: array[0..3] of string = ('TEdit', 'TMemo', 'TTntMemo.UnicodeClass',
    'TTntEdit.UnicodeClass');
var
  cn: WideString;
  i: Integer;
begin
  Result := False;
  cn := _getFocusedControlClassName();
  for i := Low(CNAMES) to High(CNAMES) do
    if cn = CNAMES[i] then begin
      Result := True;
      Exit;
    end;
  //MessageBoxW(0, PWideChar(cn), nil, 0);
end;
  

Что мне в этом не нравится, так это жесткое кодирование списка имен классов. Можно ли обнаружить, что текущее сфокусированное окно принадлежит к семейству редакторов или, лучше сказать, что оно имеет активную каретку? (в порядке, который _isEdit возвращает False для WhateverItIsControl, который находится в режиме только для чтения).

Комментарии:

1. Посмотрите на: codeproject.com/Articles/34520 /…

2. Элемент управления, доступный только для чтения, может отображать курсор. Действительно, обычно это так, чтобы вы могли копировать текст.

3. В любом случае, вы можете попробовать скрыть курсор. Если это удастся, покажите его снова и обратите внимание, что отображался курсор.

Ответ №1:

Если Handle элемент управления выделен, вы можете использовать этот хак:

 function IsEdit(AControl: TWinControl): boolean;
begin
    if AControl.HandleAllocated then
    begin
        Result := SendMessage(AControl.Handle, EM_SETREADONLY,
            WPARAM(Ord(AControl.Enabled)), 0) <> 0;
    end
    else
    begin
        Result := AControl is TCustomEdit;
    end;
end;
  

Ответ №2:

Если интересующие вас элементы управления находятся в определенной форме и принадлежат этой форме (и являются стандартными элементами управления Delphi), вы можете использовать следующее:

 function TFormML2.FocusIsEdit: boolean;
var
  i : integer;
begin
  Result := FALSE;
  for i := 0 to ComponentCount - 1 do
  begin
    if Components[ i ] is TCustomEdit then
    begin
      if (Components[ i ] as TCustomEdit).Focused and not (Components[ i ] as TCustomEdit).ReadOnly  then
      begin
        Result := TRUE;
        break;
      end;
    end;
  end;
end;
  

Если вы знаете форму и можете передать ее в качестве параметра, вы могли бы сделать что-то подобное.

TCustomEdit является предком всех полей редактирования, заметок и т. Д.

Комментарии:

1. Несколько замечаний: (1) При этом будут найдены только элементы управления, принадлежащие TFormML2 . Эта форма вполне может содержать элементы управления, не принадлежащие ей. (2) Не проще ли использовать FindControl функцию? (3) Не все элементы управления редактированием являются производными от TCustomEdit . Например, мой собственный TTextEditor происходит от TCustomControl .

2. @AndreasRejbrand Спасибо за ваши комментарии. Я знал, что это может быть не совсем то, чего хочет OP, но опять же это может быть. Он, например, специально запрашивает, доступно ли оно только для чтения. Но я согласен, это только все собственные элементы управления Delphi VCL, которые являются производными от TCustomEdit. Я думал, что упоминал, что форма должна владеть элементами управления, но при чтении назад я вижу, что я этого не сделал. Я отредактирую..

3. OP использует Application.OnMessage , чтобы элемент управления редактированием мог быть в любой форме. Все, что у меня есть, это дескриптор.