Читаем О чём не пишут в книгах по Delphi полностью

Метод TComboBoxStrings.GetObject, через который читается значение свойства Objects, в Delphi 7 и более ранних версиях интерпретирует получение CB_ERR однозначно: генерирует исключение EStringListError с комментарием "List index out of bounds".

Проблема заключается в том, что константа CB_ERR имеет численное значение -1. Поэтому и в случае ошибки, и в случае, когда строке сопоставлено значение -1, системный обработчик сообщения CB_GETITEMDATA вернет одинаковый результат. И метод TComboBoxStrings.GetObject интерпретирует его как ошибку. (А что ему еще остается делать?)

Аналогичная проблема по тем же причинам возникает и для ListBox (аналогичная по смыслу константа LB_ERR также имеет значение -1). Это прямое следствие документированных особенностей работы Windows и модели работы VCL встречается во всех версиях Windows. Та же проблема возникает при попытке указать значение 4 294 967 295, т. к. на двоичном уровне это число записывается той же комбинацией битов, что и -1.

При использовании свойства Objects по прямому назначению, т. е. для хранения объектов, эта проблема не может возникнуть, потому что $FFFFFFFF — это адрес самого старшего байта в четырехгигабайтном виртуальном адресном пространстве программы. Эта область адресного пространства зарезервирована системой, и менеджер памяти Delphi не может выделить память для объекта в этой области. Рекомендуемые способы решения проблемы:

1. Пересмотреть алгоритм и отказаться от связывания значения -1 со строками.

2. Напрямую посылать CB_GETITEMDATA окну ComboBox, а попадание индекса в диапазон контролировать самостоятельно другими методами. Приведенный в листинге 3.57 код иллюстрирует последний совет.

Листинг 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-байтного значения) не приводит к аналогичным проблемам.

<p>3.4.7. Неправильное поведение свойства <emphasis>Anchors</emphasis></p>
Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных