Форум: "Прочее";
Текущий архив: 2011.08.07;
Скачать: [xml.tar.bz2];
ВнизНежелательная обработка сообщений Найти похожие ветки
← →
Дмитрий Тимохов (2011-04-18 10:50) [0]Приветствую всех!
У меня есть некий проект, который А) давнишний (> 10 лет); Б) большой; В) сложный; Г) активно развивается и эксплуатируется.
Изначально в программу заложена модель: все обращения к БД выполняются в главном потоке (так уж получилось - см. п. А, а переделывать сложно - см. п.п. Б и В). Переделать то и можно, но некогда - см. п. Г.
Следствием одного потока является то, что периодически приходится вызывать Application.ProcessMessages, чтобы перерисовать окно перед долгой операцией. Или, например, может быть прогресс бар, который должен ползти по ходу выполнения операции.
Цель вызова - перерисовка! Но в очереди могут быть и другие события: например, клик мышкой на закрытии формы или ALT+F4 и т.д., обработка которых в ходе выполнения запроса недопустима.
Кликаньем на разные части программы в момент ее задумчивости страдают многие пользователи.
Естественным выходом из подобной ситуации - на время выполнения запросов и других действий, в ходе которых недопустима обработка пользовательского ввода, блокировать обработку всего и вся. Например, в OnCloseQuery сразу давать CanClose := False, если выполняется запрос.
Полагаю, что подобная ситуация знакома многим.
Если не говорить о том, что "у тебя все не так, надо все делать иначе - в отдельном потоке" (в модели - отдельный поток на обращение к БД - тоже требует блокировки GUI, кстати), то у меня такой вопрос:
Кто и как справляется с подобным? Кто как блокирует нежелательные события (вернее, их обработку) в ходе долгих операций?
← →
brother © (2011-04-18 10:56) [1]> например, клик мышкой на закрытии формы или ALT+F4 и т.д
что-то ты не договариваешь...
procedure TForm1.Button1Click(Sender: TObject);var
i: integer;
begin
i:= 0;
repeat
inc(i);
label1.Caption:= inttostr(i);
sleep(1);
application.ProcessMessages;
until i> 3000;
end;
запусти и попробуй кликнуть "крестик" или ALT+F4...
← →
Юрий Зотов © (2011-04-18 10:56) [2]Вариант навскидку: на время операции отключать собщения клавы и мыши через Application.OnMessage.
← →
KilkennyCat © (2011-04-18 10:57) [3]ну я создавал флаг енабле-неенабле... и перед каждым чихом его проверял.
а если тебе только перерисовка нужна, то вызови ее непосредственно, вовсе необязательно для этого Application.ProcessMessages юзать.
← →
brother © (2011-04-18 10:58) [4]> енабле-неенабле
называется boolean :)
← →
И. Павел © (2011-04-18 10:58) [5]В одной программе был подобный случай (жали на доработку сразу как устроился на работу, и я еще не мог понять, почему в одном потоке параллельно обрабатывались два нажатия кнопки :). Решал в лоб: добавлял переменную, которая определяла - выполняется ли сейчас какая-то операция, и если выполняется, то другие обработчики ничего не делали. Но сейчас я уже нашел в той программе ProcessMessages (там достаточно было обычного refresh).
← →
KilkennyCat © (2011-04-18 11:00) [6]
> brother © (18.04.11 10:58) [4]
буулеан - это банально :)
енабле-неенабле звучит лучше.
← →
brother © (2011-04-18 11:01) [7]> звучит лучше.
вынос мозга!)
← →
Anatoly Podgoretsky © (2011-04-18 11:06) [8]> KilkennyCat (18.04.2011 11:00:06) [6]
Деза абле
← →
Дмитрий Тимохов (2011-04-18 11:30) [9]
> brother © (18.04.11 10:56) [1]
>
> > например, клик мышкой на закрытии формы или ALT+F4 и т.
> д
>
> что-то ты не договариваешь...
Интересно, не замечал кстати, что закрыть нельзя...
Ну не важно - все равно на кнопку то нажать можно еще раз.
Тоже весело получается.
← →
Дмитрий Тимохов (2011-04-18 11:47) [10]
> Юрий Зотов © (18.04.11 10:56) [2]
>
> Вариант навскидку: на время операции отключать собщения
> клавы и мыши через Application.OnMessage.
А как, Юра? Я так понял, что имеется в виду выставлять Handled для определенных сообщений?
← →
Юрий Зотов © (2011-04-18 12:05) [11]> Дмитрий Тимохов (18.04.11 11:47) [10]
> выставлять Handled для определенных сообщений?
Конечно. Сообщения мыши и клавы идут непрерывными диапазонами (загляни в Messages.pas - увидишь), поэтому что-то вроде этого:
Handled := операция_еще_продолжается // булевский флаг
and
(Message >= мышь.MIN and Message <= мышь.MAX)
or
(Message >= клава.MIN and Message <= клава.MAX)
or
(и что-то подобное для сообщений WM_NCxxx)
or
(и что-то подобное для сообщений WM_SYSxxx)
Короче, загляни в Messages.pas. Еще можно попробовать копнуть в сторону хука WH_GETMESSAGE
← →
Юрий Зотов © (2011-04-18 12:10) [12]Удалено модератором
← →
sniknik © (2011-04-18 12:14) [13]> Кто как блокирует нежелательные события
aОбработка: TAction;
procedure TForm1.aОбработкаExecute(Sender: TObject);
begin
aОбработка.Enabled:= false;
try
...
finally
aОбработка.Enabled:= true;
end;
end;
и все, второй раз до завершения не нажмут (кнопки/меню/горячие клавиши все "повешено" на "акцию" и дизейблится получается одновременно) + в том, что это еще и визуально видно, куда можно нажимать, а куда нельзя.
← →
OW © (2011-04-18 13:33) [14]
> Кто как блокирует нежелательные события (вернее, их обработку)
> в ходе долгих операций?
предотвращать логичнее
на входе, если флаг не поднят, флаг поднять и работать, на выходе опустить
и предупреждать, что операция вызовет подвисание
← →
MsGuns © (2011-04-18 14:10) [15]Нетерпеливых юзверей - на гилку (дефок - в клуню)
← →
ттест (2011-04-18 14:48) [16]
> на гилку (дефок - в клуню)
куда-куда?
← →
Jeer © (2011-04-18 22:32) [17]
> куда-куда?
"За пицунду и на кукан" (С) известно чей.
← →
oxffff © (2011-04-19 09:40) [18]
> Следствием одного потока является то, что периодически приходится
> вызывать Application.ProcessMessages, чтобы перерисовать
> окно перед долгой операцией. Или, например, может быть прогресс
> бар, который должен ползти по ходу выполнения операции.
>
> Цель вызова - перерисовка!
А?
Tcontrol. Update;
Processes any pending paint messages immediately.
Tcontrol. Repaint
Call Repaint to force the control to repaint its image immediately.
Tcontrol.Perform(Msg: Cardinal; WParam, LParam: Longint): Longint;
Responds as if the control received a specified Windows message.
Call Perform to bypass the Windows message queue and send a message directly to the control’s window procedure.
← →
oxffff © (2011-04-19 09:46) [19]Для всех дочерних.
Broadcast method (TWinControl)
← →
oxffff © (2011-04-19 11:01) [20]Естественно есть и другие методы.
Да, да. Мои самые любимые.
← →
OW © (2011-04-20 11:41) [21]
> Да, да. Мои самые любимые.
>
какие это?
← →
brother © (2011-04-20 11:56) [22]ректальные)
← →
oxffff © (2011-04-20 12:02) [23]
> OW © (20.04.11 11:41) [21]
>
> > Да, да. Мои самые любимые.
> >
>
> какие это?
Динамический патч.
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2011.08.07;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.003 c