TEdit focus & caret

У меня есть два элемента управления TEdit. Когда я выхожу из edit1, edit2 получает фокус. В моем событии OnExit Edit1 у меня есть следующий код:

procedure TForm1.Edit1Exit(Sender: TObject);
begin
  edit2.Enabled := false;
  edit2.Enabled := true;
  edit2.setfocus;
end;

Edit2 имеет фокус. Однако в нем нет каретки. Я могу начать печатать, но это сбивает с толку, так как я не знаю, какой элемент управления находится в фокусе.

Меня больше интересует, что происходит с изменением свойства Enabled, из-за которого некоторые сообщения не запускаются должным образом? Например, событие OnEnter edit2 не запускается.

Это на D2006, если это вообще имеет значение.

Спасибо за ответ.


person Rick    schedule 05.09.2011    source источник
comment
есть куча кодов между отключением и включением edit2. это не обязательно edit2, но то, что является активным элементом управления. поэтому после повторного включения активного элемента управления я хотел бы сбросить в нем фокус. ну, конечно, это активный элемент управления, но там нет каретки.   -  person Rick    schedule 05.09.2011


Ответы (4)


Я не понимаю, почему вы отключаете и включаете edit2, но вы делаете это:

procedure TForm1.Edit1Exit(Sender: TObject);
begin
  edit2.Enabled := false;
  edit2.Enabled := true;
  edit2.setfocus;
  PostMessage(edit2.Handle, WM_SETFOCUS, 0, 0);
end;

Кстати, я согласен с Андреасом Рейбрандом.

person Whiler    schedule 05.09.2011
comment
Я лично предпочитаю этот подход, если Assigned (ActiveControl), затем PostMessage (ActiveControl.Handle, WM_SETFOCUS, 0,0); после установки фокуса на другой элемент управления. После определенных операций кажется, что Windows api не распознает активный элемент управления, и поэтому события OnExit / OnEnter не срабатывают должным образом. Эта строчка исправляет это. - person ertx; 05.09.2011
comment
Это работает, спасибо! Я попытался проследить цепочку событий, выясняя, почему он не перерисовывает фокус и курсор. Ударьте по стене на WndProc, и он просто зациклится, и я потерял отслеживание, какое сообщение его обрабатывает. - person Rick; 06.09.2011

Я серьезно подозреваю, что вы делаете что-то не так, и лучшим решением, скорее всего, будет редизайн. Вы не должны отключать, а затем включать элемент управления, пока он получает фокус.

person Andreas Rejbrand    schedule 05.09.2011
comment
Согласен, не идеально. И конечно, есть обходные пути. Но мне интересно только то, что требуется для отображения курсора и фокуса. Что-то об отключении активного элемента управления в событии OnExit, которое разрывает цепочку сообщений Windows. - person Rick; 06.09.2011

Между отключением и включением edit2 есть несколько кодов.

Наличие большого количества кода в обработчике событий OnExit предыдущего активного элемента управления не требует отключения следующего активного элемента управления. Этот код будет выполнен до того, как следующий активный элемент управления покажет курсор и сможет принимать вводимые пользователем данные. Просто убедитесь, что он не передает выполнение чем-то вроде запуска нового потока или использования Application.ProcessMessages.

Установите Screen.Cursor в crHourGlass, чтобы дать понять пользователю, что следующий активный элемент управления еще не готов.

person NGLN    schedule 05.09.2011

Обнаружена проблема, когда OnActive для MainForm активирует другую форму.

TMainForm.OnActivate;
begin
ChildForm.ShowModal;
end;

Фокус управления установлен, но не работает. Работа, которую я обнаружил, заключалась в отправке PostMessage (Handle, WM_SETFOCUS, 0, 0); к дескриптору формы.

procedure TChildForm.FocusControl(AWinControl: TWinControl);
begin
  try
    // http://stackoverflow.com/questions/7305296/tedit-focus-caret
    PostMessage(Handle, WM_SETFOCUS, 0, 0);
    PostMessage(AWinControl.Handle, WM_SETFOCUS, 0, 0); 
    if AWinControl.CanFocus then
       AWinControl.SetFocus;
  except
    on E: Exception do
    begin
      Error(Self, E);
    end;
  end;
end;
person Tristan Marlow    schedule 12.10.2016