![]() |
| Главная »Статьи » |
|
Этот эффект был замечен при работе в WindowsXP SP3 приложения, скомпилированного Delphi 7. Возможно, что он проявляется и в других версиях ОС. Эффект заключается в неправильном вертикальном позиционировании DropdownMenu для TToolButton относительно ее границ, что наглядно демонстрирует прилагаемый пример.
Причина этого в том, что при подсчете высоты меню в функции TToolBar.CheckMenuDropdown в расчет принимаются все пункты меню (FTempMenu.Items.Count), т.е. без учета уменьшения высоты меню за счет разбивки его на столбцы: if (GetSystemMetrics(SM_CYMENU) * FTempMenu.Items.Count) + APoint.Y > Screen.MonitorFromPoint(APoint).Height then Dec(APoint.Y, Button.Height); Высота 12-ти пунктов меню кнопки pmOpen + координата нижней кромки кнопки (APoint.Y) меньше высоты экрана, поэтому ее меню позиционируется верно. Для меню кнопки pmSave суммарная высота превышает высоту экрана и позиционирование ее меню неверное. Если сместить окно приложения вверх, чтобы меню "хватало места" эффект исчезнет.
Для устранения эффекта необходимо, чтобы расчет высоты меню осуществлялся корректно, т.е. с учетом разбивки меню на столбцы. Это делает следующая функция:
function GetMenuHeight(AMenu: TMenu): Integer;
var
I, H: Integer;
begin
H:= 0;
Result:= 0;
for I:= 0 to AMenu.Items.Count - 1 do
begin
if AMenu.Items[I].Break <> mbNone then
begin
Result:= Max(Result, H);
H:= 0;
end;
Inc(H);
end;
Result:= Result * GetSystemMetrics(SM_CYMENU);
end;
При использовании функции следует иметь ввиду, что, как видно из кода, высота пункта берется из настроек системы. Это значит, что если высота пункта была изменена в OnMeasureItem, то функция вернет неправильное значение!
Чтобы не создавать новый компонент пришлось скопировать все относящееся к TToolBar в новый модуль, который прилагается к примеру. Для использования модуля, необходимо просто добавить его в оператор uses интерфейсной секции. Как оказалось в Delphi 2010 этот эффект так же присутствует. Для его исправления подходит описанный модуль, надо только в procedure TToolBarDockObject.AdjustDockRect(ARect: TRect); исправить строки:
Inc(Left, CX); Inc(Top, CY); Inc(Right, CX); Inc(Bottom, CY);на DockRect := Rect(Left + CX, Top + CY, Right + CX, Bottom + CY); К статье прилагаются файлы с исходным кодом на Delphi. Внимание! Запрещается воспроизведение
данной статьи или ее части без согласования с автором. Если вы желаете разместить
эту статью на своем сайте или издать в печатном виде, свяжитесь с автором. |