TToolBar неправильно рисует в нетематических Windows

Недавно я обратил внимание на то, что одно из наших приложений неправильно рисует в нетематической Windows.

Панель инструментов построена из TSpeedButtons, вложенных в TToolbar, который, в свою очередь, находится внутри элемента управления страницы.

На тематической винде все выглядит красиво. Ну, не красиво, но ладно.

TToolbar в тематических Windows

Однако в нетематических Windows внутри кнопок появляются странные вертикальные линии.

Панель инструментов в нетематических Windows

Я искал вокруг, но не могу найти ни одного сообщения о такой проблеме. (Скорее всего, просто мой поиск кунг-фу отстой.) Кто-нибудь знает описание этой проблемы или, что еще лучше, решение?


person gabr    schedule 20.07.2011    source источник
comment
Извините, а что именно с ними не так?   -  person mj2008    schedule 20.07.2011
comment
@ mj2008: См. кнопки «Добавить», «Редактировать», «Удалить» и «Копировать» — они нарисованы вертикальной линией посередине, которой там быть не должно.   -  person gabr    schedule 20.07.2011
comment
Я помню, что несколько лет видел что-то похожее: попробуйте добавить кнопку-разделитель и переключить ее стиль между tbsDivider и tbsSeparator. В тематическом приложении строка появляется или исчезает соответственно, а в нетематическом приложении вместо этого она переключается между одной и двумя строками.   -  person Uli Gerhardt    schedule 20.07.2011
comment
Не можете ли вы заменить кнопки скорости на TToolButtons в качестве обходного пути?   -  person Uli Gerhardt    schedule 20.07.2011
comment
Похоже на ошибку, когда для свойства Flat панели инструментов установлено значение True. Случается с любым не оконным потомком TGraphicControl.   -  person Ondrej Kelle    schedule 20.07.2011
comment
У нас точно такая же проблема с нашим внутренним инструментом управления проектами, так как мы переключили его сборки с Delphi 5 на Delphi 2010. Решения нет (но и не искал, только для внутреннего использования).   -  person Paul-Jan    schedule 20.07.2011
comment
Это не работает в D2007; вполне возможно, это работало в D5.   -  person gabr    schedule 20.07.2011
comment
Проявляется ли это на вашей машине разработки? Есть ли у вас легкий доступ к машине, на которой проявляется проблема? Если это так, просто начните комментировать большие участки кода из TSpeedButton.Paint, пока вертикальная линия не исчезнет. Когда это произойдет, вы обнаружите ошибочный код и узнаете, какое свойство нужно настроить (или какой код нужно исправить). Я попытался поместить большую кнопку TSpeedButton в форму и запустить приложение без их отображения, но для меня это выглядело так, как ожидалось.   -  person Cosmin Prund    schedule 20.07.2011
comment
Эффект исчезает, когда вы заменяете CDRF_DODEFAULT на CDRF_SKIPDEFAULT в NM_CUSTOMDRAW при обработке в TToolBar.CNNotify. Но, вероятно, это сложнее, вам нужно исследовать все возможные комбинации с пользовательским рисунком и темами.   -  person Ondrej Kelle    schedule 20.07.2011
comment
@Cosmin Вероятно, это не имеет ничего общего с TSpeedButton; это влияет на все (не оконные) графические элементы управления.   -  person Ondrej Kelle    schedule 20.07.2011
comment
Воспроизведено в D6 и D2010, плоская кнопка скорости внутри плоской панели инструментов.   -  person David Heffernan    schedule 20.07.2011
comment
@TOndrej, что-то должно рисовать эти вертикальные линии, если это не TSpeedButton, то TToolBar, и, будучи разработчиками Delphi, у нас есть источники для обоих. Я знаю, что я бы сделал именно так, я бы попытался найти точную строку кода, которая рисует это.   -  person Cosmin Prund    schedule 20.07.2011
comment
Я вижу, что происходит, я просто не знаю, как это исправить.   -  person David Heffernan    schedule 20.07.2011
comment
@Cosmin Я просто имел в виду, не тратьте время на отладку TSpeedButton, вот и все.   -  person Ondrej Kelle    schedule 20.07.2011
comment
@gabr: TToolbar не предназначен для хранения TSpeedButtons. Он предназначен для хранения TToolButtons, которые созданы не только для размещения на панели инструментов, но и специально написаны для правильного поведения на панели. Проблема, с которой вы столкнулись (особенно с разделителями, нарисованными так, как они есть), заключается в том, что вы используете несовместимый SpeedButton и разделяете их с помощью кнопок инструментов. TSpeedButton хорошо работает на TPanel, и IIRC были разработаны именно для этого до того, как MS предоставила пару TToolBar/TToolButton в ComCtl. Быстрое тестовое приложение с TToolBar с TToolButtons и TPanel с Speedbuttons покажет.   -  person Ken White    schedule 20.07.2011
comment
TToolBar.UpdateItem включает TBSTYLE_SEP в fStyle для сообщения TB_INSERTBUTTON. Кажется, это место, где проходит вертикальная линия. Однако я понятия не имею, как работают панели инструментов!   -  person David Heffernan    schedule 20.07.2011
comment
@Ken: Напиши это как ответ, и я с радостью его приму. Кроме того, у меня были веские причины использовать TSpeedButton в этом приложении, но я забыл, какие они были — это приложение родилось в 1999 году.   -  person gabr    schedule 20.07.2011
comment
@gabr: я забыл, когда MS добавила TToolBar в общую библиотеку элементов управления. Однако я помню, как кропотливо создавал эквивалент с помощью TPanel/TSpeedButton, вручную расставляя интервалы для создания разделителей (или, что еще хуже, используя небольшой TBevel). Не самые приятные воспоминания, кстати. :)   -  person Ken White    schedule 20.07.2011
comment
@David: TB_INSERTBUTTON не применяется, если вы не используете TToolButtons. Для TSpeedButton такого сообщения не создано. ;)   -  person Ken White    schedule 21.07.2011


Ответы (2)


TToolbar не предназначен для хранения TSpeedButtons. Он предназначен для удержания TToolButtons, которые созданы не только для того, чтобы сидеть на TToolBar, но и специально написаны для правильного поведения на перекладине.

Проблема, с которой вы столкнулись (особенно с разделителями, нарисованными такими, какие они есть), заключается в том, что вы используете несовместимые TSpeedButton и разделяете их разделителями TToolButton. TSpeedButton хорошо работает на TPanel, и IIRC были разработаны именно для этого до того, как MS предоставила пару TToolBar/TToolButton в ComCtl.

Приложение для быстрого тестирования с TToolBar с TToolButtons и TPanel с TSpeedButtons должно проверить, решит ли это проблему.

РЕДАКТИРОВАТЬ: Ваш комментарий не совсем правильный. :)

введите здесь описание изображения

Установите для параметра TToolBar.AllowTextButtons значение True, а затем установите для кнопки, которую вы хотите расширить, стиль tbsTextButton. Как видите, я использовал обычную кнопку, разделитель, текстовую кнопку (с текстом и изображением), разделитель и еще одну обычную кнопку.

person Ken White    schedule 20.07.2011
comment
TToolButton действительно работает, но есть другая проблема - изменение ширины TToolButton меняет ширину всех остальных кнопок на той же панели инструментов, что в моем случае совершенно неприемлемо. - person gabr; 20.07.2011
comment
@Sertac: я не понимаю вашего комментария. Это просто изображения, которые я взял из одной из папок изображений Glyfx и добавил в список изображений для тестирования. Захват был сделан на WinXP с использованием Delphi XE. Я не пытался ничего делать с изображениями - это не было целью ответа (или каким-либо образом связанным с вопросом). - person Ken White; 21.07.2011
comment
@ Кен - я знаю, что это не связано с вопросом. Я смутно припоминаю проблему с черным фоновым изображением на форумах, просто я надеялся, что для Габра не проблема переключиться на кнопки инструментов. Я не критиковал ответ, AAMOF, я проголосовал за него. :) - person Sertac Akyuz; 21.07.2011
comment
@Sertac: Просто убедился, что ничего не упустил. IIRC, есть проблема с прозрачностью изображения PNG, TImageList и WinXP, но это не то, что я изучал. :) Спасибо за голос. :) - person Ken White; 21.07.2011
comment
@Ken: Спасибо за это дополнение к вашему ответу. Может быть, теперь я изменю свое приложение, чтобы использовать TToolButtons. - person gabr; 21.07.2011

Как сказал в комментариях TOndrej, это происходит, когда для TSpeedButton.Flat и .Transparent установлено значение True. Как выяснил Дэвид, TToolbar также должен иметь .Flat значение True, чтобы возникла проблема.

Обходной путь, не требующий изменения исходного кода VCL, — установить для .Transparent значение False.

person gabr    schedule 20.07.2011
comment
Я не упомянул Transparent, но вы правы, установка False помогает. Нет тем, Windows XP, Delphi XE. +1 за простой обходной путь. - person Ondrej Kelle; 20.07.2011
comment
Очень некрасивый обходной путь. Как насчет прекращения использования TToolbar с кнопками скорости. Не требует изменения исходного кода VCL. Если вам нужна панель с кнопками скорости, используйте панель с кнопками скорости и забудьте о панелях инструментов. - person Warren P; 20.07.2011
comment
@Warren: Не уродливо. В нетематических Windows прозрачность все равно не дает ничего полезного. - person gabr; 20.07.2011
comment
Есть больше проблем с размещением элементов управления кнопками скорости на панелях инструментов, чем просто этот забавный рендеринг линий и проблема с прозрачностью. - person Warren P; 21.07.2011
comment
@Warren: Никогда ни с кем не сталкивался, а приложение живет 12 лет. - person gabr; 21.07.2011