Версия для печати


VCL.TRadioButton.Автовыбор при получении фокуса в момент показа формы
http://www.delphikingdom.com/asp/viewitem.asp?catalogID=1187

Cepгей Poщин
дата публикации 26-12-2005 06:51

КАТЕГОРИЯБИБЛИОТЕКА.VCL.TRadioButton.Автовыбор при получении фокуса в момент показа формы
ПРОДУКТDelphi
ПЛАТФОРМАWindows


При получении фокуса ввода контролом TRadioButton в момент отображения формы свойство Checked принимает значение True.

Проверено в Delphi 7 (SP1), Delphi 2005 (SP3), Windows 2000, Windows 98.

В приведенном примере в момент закрытия окна диалога все TRadioButton принимают ранее сохраненные значения поля Checked. Если изменить RadioButton.Checked, используя мышь, и кнопку "Отмена" тоже нажать мышью — форма закроется и при следующем открытии все TRadioButton будут находиться в нужном состоянии. Если нажать клавишу Esc, то при следующем открытии тот RadioButton, в котором находится фокус ввода — будет выбран, чего быть не должно.


Типовые решения


  1. При закрытии формы надо поменять фокус ввода, если он находится в RadioButton.
  2. При изменении свойства Checked изменять фокус ввода. Если новое значение True, то этот орган управления получает фокус ввода, в противном случае проверяется, есть ли хоть один RadioButton у которого Checked=true, и если таковых нет, то эмулируется потеря фокуса всеми RadioButton. Для этого следует исправить метод TRadioButton.SetChecked (см. модуль StdCtrls):
    procedure TRadioButton.SetChecked(Value: Boolean);
    
      procedure TurnSiblingsOff;
      var
        I: Integer;
        Sibling: TControl;
      begin
        if Parent <> nil then
          with Parent do
            for I := 0 to ControlCount - 1 do
            begin
              Sibling := Controls[I];
              if (Sibling <> Self) and (Sibling is TRadioButton) then
                with TRadioButton(Sibling) do
                begin
                  if Assigned(Action) and
                     (Action is TCustomAction) and
                     TCustomAction(Action).AutoCheck then
                    TCustomAction(Action).Checked := False;
                  SetChecked(False);
                end;
            end;
      end;
    
      //Эта процедура устанавливает фокус ввода на выбраный переключатель
      procedure FocusChanged;
      var i:integer;
          Sibling: TControl;
          NoChecked:boolean;
      begin
        if Value then begin    //Когда устанавливается свойство Checked
          if HandleAllocated then
                 Windows.SetFocus(Handle); //Этот переключатель просто получает фокус ввода
        end else begin         //Когда сбрасывается свойство Checked, несколько сложнее
          if (parent<>nil) then begin
           //Проверяем, есть ли хоть один TRadioButton у которого свойство Checked=true
           NoChecked:=true;
           for i:=0 to Parent.ControlCount - 1 do begin
              Sibling := Parent.Controls[I];
              if (Sibling is TRadioButton) and
                 Sibling.Visible and
                 Sibling.Enabled and
                 TRadioButton(Sibling).Checked then begin
               NoChecked:=false;
               break;
              end;
           end;
           //Если таких TRadioButton нет, то эмулируем для них потерю фокуса ввода
           if NoChecked then for i:=0 to Parent.ControlCount - 1 do begin
              Sibling := Parent.Controls[I];
              if (Sibling is TRadioButton) and
                 Sibling.Visible and
                 Sibling.Enabled and
                 TRadioButton(Sibling).HandleAllocated then begin
               //Чтобы TRadioButton потерял фокус ввода, делаем его
               //сначала неактивным, а потом активным
               //Возможно есть другие варианты
               TRadioButton(Sibling).Enabled:=false;
               TRadioButton(Sibling).Enabled:=true;
              end;
           end;
          end;
        end;
      end;
    begin
      if FChecked <> Value then
      begin
        FChecked := Value;
        TabStop := Value;
        if HandleAllocated then
          SendMessage(Handle, BM_SETCHECK, Integer(Checked), 0);
        if Value then
        begin
          TurnSiblingsOff;
          inherited Changed;
          if not ClicksDisabled then Click;
        end;
        FocusChanged; //Добавлено
      end;
    end;
    
    



Дополнительные ссылки и прилагаемые файлы

Вопрос на Круглом столе Королевства Delphi:

http://www.delphikingdom.com/asp/answer.asp?IDAnswer=35572

Скачать пример:StoneTest_90.zip