Delphi programming blog
Источник: http://teran.karelia.pro/articles/item_4463.html
 

TForm, TFrame, TUpDown, ShowMessage.

Опубликовано 25.03.2011 г. 18:57

Говорят "понедельник - день тяжелый", но складывается впечатление, что для мозга программиста, тяжелым является пятница. Опять на ровном месте столкнулся с проблемой.

Ситуация весьма проста. Имеется главная форма приложения. В процессе работы мы создаем фрейм, и размещаем его на этой форме. На фрейме есть элемент TUpDown. При изменении значения updown показываем сообщение. с точки зрения кода имеем:
  1. Создаем новую форму TTestForm,
  2. Создаем фрейм TTestFrame, добавляем на него updown : TUpDown;
  3. Теперь при создании формы создаем фрейм, и размещаем его непосредственно на форме:
    procedure TTestForm.FormCreate(Sender: TObject);
    var f  : TTestFrame;
    begin
        f := TTestFrame.Create(self);
        f.parent := self;
    
    При изменении значения updown показываем сообщение:
    procedure TTestFrame.UpDownClick(Sender: TObject; Button: TUDBtnType);
    begin
        ShowMessage('Changed!');
    end;
Запускаем приложение. жмем стрелку вверх на updown, видим сообщение. Все как и ожидалось. А теперь самое интересное: с этого момента куда бы мы ни кликали, в форму, в кнопку закрытия формы, в заголовок формы - всегда показывается сообщение. В конце рабочего дня в пятницу, подобные вещи могут поставить в тупик. С таким поведением кто либо сталкивался? (: При этом без разницы, создаем мы фрейм во время выполнения, или добавляет на форму во время проектирования, так что код для динамического создания можно не писать, а просто добавить фрейм, с помощью стандартного элемента Frames палитры инструментов Standart. Можно также заметить, как при движении мыши над формой, меняется фокус кнопок UpDown. Однако вернемся к коду, давайте добавим на фрейм тестовую метку - label : TLabel, и вместо показа сообщения, будем обновлять метку.
procedure TTestFrame.UpDownClick(Sender: TObject; Button: TUDBtnType);
begin
    label1.Caption := Format('position: %d', [updown.Position]);
end;
как мы видим все работает так, как и ожидалось. Следовательно виной всему ShowMessage(), т.е по сути отображение модального окна. Причины сего поведения мне пока не понятны, но может быть я попробую в этом разобраться. Урок который можно извлечь - не стоит увлекаться использованием ShowMessage для проверки работоспособности участков кода, это может сбить с пути истинного (: ------------------ update: для достижения эффекта не обязательно использовать TFrame, можно просто разместить на форме TUpDown и при клике на него показать любое модальное окно.

Комментарии

Vlad
26.03.2011 в 11:09
Интересно, а если вместо ShowMessage использовать MessageBox()? Сработает правильно?
ter
26.03.2011 в 19:27
нет, при любом модальном окне косяк выползает. и фрейм для этого не нужен.
DetSimen
24.06.2011 в 10:05
В этой проблеме виновата сама VCL, которая зачем-то назначает этому компоненту стиль csCaptureMouse. Компонент захватывает мышь, обрабатывает сообщение WM_ButtonDown, вызывает диалоговое окно (модальное), и сообщение WM_ButtonUp, которое должно отменять захват мыши, приходит уже в диалоговое окно, которому от него ни холодно, ни жарко. После окончания работы модального окна, захват восстанавливается и любой клик в любом месте оконной процедурой перенаправляется снова в компонент UpDown. :) Такая вот ошибка у Борланда. :)
Можно сгородить подпорку, если где-нибудь в конструкторе формы написать такой костыль:

UpDown1.ControlStyle:= UpDown1.ControlStyle - [csCaptureMouse];

:)))
Marat
09.11.2011 в 14:50
Читайте добрые хорошие книжки по Делфи :) "О чём не пишут в книгах по Delphi" автор А.Б. Григорьев, там эта проблема описана, и вообще там много подобных проблем описано.
ter
09.11.2011 в 15:06
спасибо за совет (: будет возможность почитаю (:
Marat
09.11.2011 в 15:41
Простите за спамерство, но может кому то интересно, вот здесь http://delphikingdom.com/asp/viewitem.asp?catalogid=1085 более детально расписано по данной проблеме.
- Имя
- e-mail*
- Сайт
вы можете использовать теги [i],[b],[code],[quote]
Дополнительно