Delphi 3. Библиотека программиста

Группы переключателей с индивидуальной блокировкой


Ничто так не радует во время конструирования форм, как элементы, которые автоматически выравниваются, масштабируются и выстраивают свое содержимое в аккуратные столбики. Возникает впечатление, будто у вас появились надежные союзники. Однако достоинства «умных» элементов вовсе не исчерпываются психологическим комфортом— подумайте, сколько строк программного кода вам сэкономило свойство Align панелей? Десятки, сотни? Теперь вы понимаете, почему мне так не хочется отказываться от удобного элемента TRadioGroup, когда возникает необходимость в блокировке отдельных переключателей. Класс TRadioGroup автоматически располагает переключатели в виде столбцов, выравнивает расстояния между ними и позволяет задать их имена в виде одного строкового списка.

Однако он не позволяет обращаться к отдельным переключателям группы — и наверняка для этого есть веские причины. Но я уверен в своей способности разумно блокировать тот или иной переключатель и поэтому написал улучшенный вариант TRadioGroup (см. листинг 9.12). Класс TRadioBtnGrp содержит новое свойство ItemEnabled, с помощью которого можно получать и задавать состояние блокировки для отдельных кнопок.

Листинг 9.12. Модуль RBTNGRPS.PAS

{ Группа переключателей с возможностью блокировки отдельных кнопок } unit RBtnGrps; interface uses StdCtrls, ExtCtrls, Classes; type TRadioBtnGroup = class( TRadioGroup ) private function GetItemEnabled( Index: Integer ) : Boolean; procedure SetItemEnabled( Index: Integer; Value: Boolean ); function GetButtons( Index: Integer ) : TRadioButton; protected function CheckAnyBut( NotThisIndex: Integer ): Boolean; property Buttons[ Index: Integer ] : TRadioButton read GetButtons; public property ItemEnabled[ Index: Integer ] : Boolean read GetItemEnabled write SetItemEnabled; end; procedure Register; implementation function TRadioBtnGroup.CheckAnyBut; var Index: Integer; begin Result := True; for Index := NotThisIndex + 1 to Items.Count - 1 do if Buttons[ Index ].Enabled then begin Buttons[ Index ].Checked := True; Exit; end; for Index := 0 to NotThisIndex - 1 do if Buttons[ Index ].Enabled then begin Buttons[ Index ].Checked := True; Exit; end; Result := False; end; function TRadioBtnGroup.GetItemEnabled; begin Result := Buttons[ Index ].Enabled; end; procedure TRadioBtnGroup.SetItemEnabled; begin if ( not Value ) and ( Index = ItemIndex ) and Buttons[ Index ].Checked and ( not CheckAnyBut( Index )) then ItemIndex := -1; Buttons[ Index ].Enabled := Value; end; function TRadioBtnGroup.GetButtons; begin Result := Components[ Index ] as TRadioButton; end; procedure Register; begin RegisterComponents('HP Delphi 3', [ TRadioBtnGroup ]); end; end.

Во внутренней реализации TRadioBtnGroup метод GetButtons используется для получения доступа к отдельным переключателям. GetButtons использует тот факт, что входящие в группу переключатели хранятся в массиве Components. Все, что требуется от GetButtons — индексировать массив Components и выполнить безопасное преобразование типа для результата.

Новый элемент стремится работать как можно разумнее. При блокировке установленного переключателя он пытается установить другой переключатель; если заблокированы все переключатели, он ничего не устанавливает. Если такое поведение вас не устраивает, его можно изменить.



Содержание раздела