Листинг 3.57. Получение связанного с элементом значения вручную
procedure TForm1.Button2Click(Sender: TObject);
var
I: Integer;
begin
ComboBox1.Items.Clear;
ComboBox1.Items.AddObject('Text', TObject(-1));
I := SendMessage(ComboBox1.Handle, CB_GETITEMDATA, 0, 0);
Label1.Caption := IntToStr(I);
end;
Как уже было отмечено ранее, в BDS 2006 и более поздних версиях исключение не возникает. Это связано с новой реализацией метода TCustomComboBoxStrings.GetObject
, который отвечает за получение значения свойства Items.Object
(листинг 3.58).
Листинг 3.58. Получение значения свойства Items.Object
в BDS 2006 и выше
function TCustomComboBoxStrings.GetObject(Index: Integer): TObject;
begin
Result := TObject(SendMessage(ComboBox.Handle, CB_GETITEMDATA, Index, 0));
// Do additional checking on Count and Index here is so in the event
// the object being retrieved is the integer -1 the call will succeed
if (Longint(Result) = CB_ERR) and ((Count = 0) or
(Index < 0) or (Index > Count)) then
Error(SListIndexError, Index);
end;
Решение спорное, т.к. проверка корректности системой дополняется собственной проверкой индекса, и не совсем понятно, что делать в том случае, если система фиксирует какую-либо ошибку, не связанную с индексом. Но здесь Windows ставит разработчика в такие условия, что любое решение будет спорным, так что упреком по отношению к разработчикам VCL такая оценка их решения не является.
В таких элементах управления, как TListView
и TTreeView
, тоже существует возможность связывания 4-байтного значения с элементом (см. свойства TTreeNode.Data
, TListItem.Data
), но сообщения TVM_GETITEM
и LVM_GETITEM
, через которые можно получить значения этих свойств, устроены иначе, поэтому связывание с элементом значения -1 (а также любого другого 4-байтного значения) не приводит к аналогичным проблемам.
3.4.7. Неправильное поведение свойства Anchors
Свойство Anchors
, появившееся в Delphi 5, является очень удобным средством управления положением и размерами визуальных компонентов при изменении размера родителя. Однако в тех случаях, когда начальные размеры формы по каким-то причинам не совпадают с установленными при проектировании, задание значения свойства Anchors
не приносит желаемого эффекта: первоначальное расположение визуальных компонентов на форме соответствует размерам, установленным при проектировании, а не тем, которые реально получила форма. Примеры такого некорректного поведения демонстрирует программа WrongAnchors на компакт-диске.
Программа WrongAnchors — это MDI-приложение, в котором открываются две дочерние формы разных классов: ChildForm1
(класс TChildForm1
) и ChildForm2
(класс TChildForm2
). Во время проектирования эти две формы выглядят совершенно одинаково, но при запуске программы только вторая форма сохраняет заданные при проектировании размеры, а первая становится больше. При этом панель, лежащая на ней, не адаптирует свои размеры к изменившемуся размеру формы, хотя свойство Anchors обязывает ее к этому (это легко видеть, изменяя размеры формы после ее создания). Самый простой способ борьбы с этой неприятностью — заставить дочернюю MDI-форму иметь такой же начальный размер, какой задан при проектировании.
Дочерняя MDI-форма приобретает отличный от заданного размер потому, что метод CreateParams
для ширины и высоты окна устанавливает не те значения, которые хранятся в свойствах Width
и Height
, а значение CW_USERDEFAULT
. Это значение говорит системе, что она должна выбрать размеры окна на свое усмотрение. Чтобы этого не происходило, нужно вновь вернуть установленные при проектировании значения ширины и высоты в перекрытом методе CreateParams
. Именно этим класс TChildForm2
отличается от TChildForm1
(листинг 3.59).
Листинг 3.59. Установка значений ширины и высоты, заданных при проектировании
procedure TChildForm2.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.Width := Width;
Params.Height : = Height;
end;
Значение CW_USERDEFAULT
присваивается ширине и высоте окна не только в том случае, если это дочерняя MDI-форма, но и когда значение свойства Position
формы равно poDefault
или poDefaultSizeOnly
. Но в этом случае перекрывать CreateParams
нет нужды, достаточно просто изменить значение свойства Position
на другое. Просто необходимо помнить, что если свойство Position
формы имеет одно из этих значений, свойства Anchors
лежащих на форме компонентов должны иметь значения по умолчанию.
Другой случай, когда окно может при создании иметь размеры, отличные от заданных при проектировании, — это когда свойство WindowState
равно wsMaximized
. При этом окно растягивается на весь экран. В примере WrongAnchors в главном меню есть пункты Развернутое окно 1и Развернутое окно 2, которые открывают диалоговые окна, развернутые на весь экран. Но в первом из этих окон панель опять не адаптируется к новым размеру окна, в то время как во втором — адаптируется, хотя значения свойства Anchors
у обеих панелей одинаковые. Это происходит потому, что в первом случае значение wsMaximized
присваивается свойству WindowState
во время проектирования, и поэтому окно сразу создается развернутым. А во втором случае значение wsMaximized
присваивается свойству WindowState
только при обработке события OnShow
формы, т.е. тогда, когда форма уже создана с заданными при проектировании размерами, но еще не видна на экране. При этом свойство Anchors
работает так, как требуется. Это и есть решение проблемы — значение свойству WindowState нужно присваивать не во время проектирования, а в обработчике события OnShow
.
Читать дальше
Конец ознакомительного отрывка
Купить книгу