Форум: "Основная";
Текущий архив: 2004.02.25;
Скачать: [xml.tar.bz2];
ВнизDelphi + WinApi Найти похожие ветки
← →
Тимохов (2004-02-10 12:26) [0]1.5 месяца назад был топик о методе Application.ProcessMessages.
Вопрос автора был такой, что мы думаем о мнении некоего чела о том, что данный метод вообще не надо использовать. Мое утверждение было, что надо стараться избегать его использование. Утверждение многоуважаемого АП - если руки не кривые, то использовать можно.
Меня в конец достал этот Application.ProcessMessages. Я решил от него избавиться. Т.е. наконец я решил избавить свои руки от кривизны.
Ситуация в которой я использую метод Application.ProcessMessages.
В настоящее время этот метод используется для того, чтобы перед долгой операцией обновилась информация в окошечке "Подождите, идет расчет", а также для того, чтобы в этом окошечке двигался progressbar. Более ни для чего я его не использую. Вызов этого метода приводит к тому, что если при долгом рассчете нажать крестик на форме, то форма закроется и будет AV.
Предполагаемое мной решение проблемы.
Вариант 1. Переползти на вывод этого окошечка с сообщением и progressbar"ом, а также его обновления в процессе расчета, средствами WinApi. Насколько я понимаю (возможно, могу ошибаться, т.к. никогда не писал на чистом WinApi) в этом случае такое окошко будет жить независимо от VCL и окошко можно обновлять не вызывая Application.Processmessages.
По сему вопрос 1. Где в сети почитать про программирование (желательно на Дельфи) на чистом WinApi? Знаю, что здесь есть люди, пишушие в дельфи на WinApi. Буду благодарен за такую помощь. Эта информация нужна, как страртовая, далее сам все выясню, но начать то с чего-то надо?
Вариант 2. Оставить обсуждаемое информационное окошечко в рамках VCL (т.е. класса TForm) и научится в дельфи обрабатывать не все сообщения моему приложению (т.е. как это делает ProcessMessages) а только данному информационному окну. Как это делать я не представляю совсем. Вопрос 2. Возможно ли это вообще?
← →
panov (2004-02-10 12:31) [1]AV вылетает при попытке терминировать активный дополнительный поток, а не при обновлении формы.
← →
Тимохов (2004-02-10 12:33) [2]
> AV вылетает при попытке терминировать активный дополнительный
> поток, а не при обновлении формы.
У меня нет дополнительного потока.
Почему вылетает АВ я знаю - т.к. работа метода формы прерывается по середине, т.к. форма дестроится.
← →
Семен Сорокин (2004-02-10 12:34) [3]panov © (10.02.04 12:31) [1]
имхо тут о потоке небыло речи.
Тимохов
или все-таки поток?
← →
panov (2004-02-10 12:37) [4]>Семен Сорокин © (10.02.04 12:34) [3]
Да о потоке не было речи. Но тогда нужно код смотреть.
← →
Семен Сорокин (2004-02-10 12:37) [5]Тимохов © (10.02.04 12:33) [2]
Почему вылетает АВ я знаю - т.к. работа метода формы прерывается по середине, т.к. форма дестроится.
а если в обработчике метода перед Application.ProcessMessages проверять нажимал ли юзер крестик?
← →
Тимохов (2004-02-10 12:37) [6]Хочу сказать всем, что аналогичную ошибку можно получить практически всегда, где используется Application.Processmessages.
Т.е. имхо здесь нет откровенной кривизны рук.
Оба вопроса были сформулированы на основе долгих изысканий и приыину проблем я знаю хорошо.
Заранее спасибо :)))))
← →
Семен Сорокин (2004-02-10 12:38) [7]+
дестроить ее посылкой PostMessage(Handele, CM_RELEASE..)
← →
Тимохов (2004-02-10 12:39) [8]Семен Сорокин © (10.02.04 12:37) [5]
В проекте из 1 млн строк с навернутой функциональностью и взаимосвязями не напроверяешься - сдохнешь :)))))
При том не только крестик страшен - есть другие команды, которые вызываются по горячим клавишам и могут приводить к ошибкам.
← →
Плохиш (2004-02-10 12:49) [9]>Тимохов © (10.02.04 12:39) [8]
OnCloseQuery использовать не пробовал? Хорошо знаешь ли руки выправляет ;-)
← →
Digitman (2004-02-10 12:50) [10]
> Тимохов
> нажать крестик на форме, то форма закроется и будет AV
ну форма-то, наверно, разрушается при этом у тебя... а ты, очевидно, продолжаешь после этого обращаться к ее доч.контролам ... вот тебе и AV
← →
Тимохов (2004-02-10 12:57) [11]Граждане.
Еще раз. Почуму бывает АВ я знаю.
Вопрос бы в другом. См. в оригинальном посте вопрос 1 и 2.
> Плохиш (10.02.04 12:49) [9]
Пример с закрытием формы был приведен в качестве примера. В данном случае скорее все этот ивент спасет. См. также [8].
← →
Digitman (2004-02-10 13:14) [12]Вариант 3: как ни странно, но таки выпрямляющий руки , при том что все остается "как есть", т.е. использование VCL и App.Processmessages
перед тем как обновлять контролы в окошке проверять ссылку на объект формы
при конструировании ссылка записывается в объектную переменную, при разрушении объектная переменная обнуляется
код, обновляющий контролы в цикле
MyForm := TMyForm.Create(...);
while условие_выхода_из_цикла do
begin
... что-то делаем
if not Assigned(MyForm) Break;
MyForm.ProgressBar.Position := ...;
... еще что-то делаем
Application.Processmessages;
end;
MyForm.Free;
procedure TMyForm.FormDestroy(...);
begin
MyForm := nil;
end;
← →
Тимохов (2004-02-10 13:22) [13]
> Digitman © (10.02.04 13:14) [12]
Вариант, основанный на проверке хорош, когда этих проверок не много.
Я уже говорил, что причин возникновения ошибок много. Например, по горячей клавише форма меняет состояние на то, в котором обращаться из цикла тем образом, которым обращаюсь, становится невозможно. Да. В этом случае делаю именно проверку. Ясно, что в этом случае перед циклом можно вставить флажок, запрещающий TAction, вызванному по горячей клавише, менять состояние. И т.д. и т.п.
Но, опять же как сказал выше, это задолбало - не много ли чести маленькому окошечку с информацией?
В общем все-таки хотелось бы услышать про программирование на winapi в чистом виде.
← →
Radionov Alexey (2004-02-10 13:28) [14]> Digitman © (10.02.04 13:14) [12]
Принципы ООП съехали несколько:
А если работа будет с Form : TMyForm или Form : array of TMyForm? ;-)
← →
Verg (2004-02-10 13:29) [15]Я тебя понимаю. Когда на форме много разных контролов, то перед уходом в "глубокий" цикл с ProcessMessages надо как бы установить всем (или группе) им Enable:=false; а в обработчике OnCloseQuery устанавливать флаг, который будет проверяться в том "глубоком" цикле как признак его досрочного прекращения.
примерно так
Application.Processmessages;
if StopFlag then Exit;
А для блокирования контролов помнится применял что-то типа этого:
procedure SetControlEnabled(C : TWincontrol;
E : boolean);
var I : integer;
begin
for I:=0 to C.ControlCount-1 do
begin
if C.Controls[I] is TWinControl then
SetControlEnabled(C.Controls[I] as TWinControl, E);
C.Controls[I].Enabled:=E
end;
C.Enabled:=E;
end;
Веселые времена были :))
← →
Тимохов (2004-02-10 13:33) [16]
> Веселые времена были :))
Да они и сейчас остались. :(((((
← →
Verg (2004-02-10 13:34) [17]
> OnCloseQuery
Да, забыл и при этом он должен возвращать в CanClose false до тех пор, пока цикл не прекратит свою работу, обнаружив StopFlag
← →
Anatoly Podgoretsky (2004-02-10 13:49) [18]ProcessMessages не причем, а причины смотри выше.
← →
Тимохов (2004-02-10 13:54) [19]Anatoly Podgoretsky © (10.02.04 13:49) [18]
Ну конечно ни при чем. При чем мои кривые руки. Вашу позицию я запонил еще с прошлого топика по теме ProcessMessages. :)))))))
Насколько я понимаю то, к чему Вы меня отослали, говорит о том, что мне надо на каждый чих делать проверки. Вы считаете правильным делать такие проверки?
Все-таки я предложил себе вариант решения проблемы через winapi. Хотелось бы услашать мнение любителей чистого WinApi, где они брали стартовую для своего образования информацию? Только из MSDN? Или что-то еще?
← →
Тимохов (2004-02-10 13:56) [20]Коррекция на вопрос
> Вы считаете правильным делать такие проверки?
Надо "Вы считаете правильным делать таким способом или лучше сделать обходной маневр, например, через winapi?"
← →
Игорь Шевченко (2004-02-10 13:56) [21]
TForm1 = class(TForm)
private
FCantClose : Boolean;
....
end;
procedure TForm1.RunFoo;
begin
FCantClose := true;
try
Foo;
finally
FCantClose := false;
end;
end;
procedure TForm1.FormCloseQuery (Sender: TObject; var CanClose: Boolean);
begin
CanClose := not FCantClose;
end;
Ку?
← →
Тимохов (2004-02-10 13:58) [22]Игорь Шевченко © (10.02.04 13:56) [21]
Эх...
Вроде я старался ставить вопрос корректно... :(((((
Все равно спасибо...
← →
Anatoly Podgoretsky (2004-02-10 14:03) [23]Тимохов © (10.02.04 13:54) [19]
Э я тебя не к этому отослал, а отослал к тому, что программы нужно делать надежные, если для это надо сделать проверку, то ее надо сделать, а не списовать на ту или иную функцию.
Жаль, что ты меня неправильно понял.
Ну а причина все таки наши руки.
← →
Verg (2004-02-10 14:04) [24]Тимохов © (10.02.04 13:56) [20]
Дык, VCL же и работает через WinApi. (А через чего ж ей еще работать?)
← →
Тимохов (2004-02-10 14:07) [25]Ставлю вопрос по другому (совсем).
Вопрос 1. Возможно ли в рамках VCL делать 99 процентов через VCL, а определенные окна не через winapi? Т.е. мозможно ли такое сочетание?
Вопрос 2. Где про это сочетание почитать?
← →
Verg (2004-02-10 14:08) [26]
> Вопрос 2. Где про это сочетание почитать?
DDK
← →
Игорь Шевченко (2004-02-10 14:09) [27]Тимохов © (10.02.04 14:07)
Возможно. А зачем ? Очень хочется помучиться ? :)) VCL придумана именно для того, чтобы избавить программиста от рутинных операций
← →
Тимохов (2004-02-10 14:12) [28]
> Verg © (10.02.04 14:08) [26]
>
> > Вопрос 2. Где про это сочетание почитать?
>
>
> DDK
DDK - это что?
← →
Игорь Шевченко (2004-02-10 14:15) [29]Тимохов © (10.02.04 14:12)
> DDK - это что?
Это к сабжу не относится :)
← →
jack128 (2004-02-10 14:37) [30]
> Вопрос 1. Возможно ли в рамках VCL делать 99 процентов через
> VCL, а определенные окна не через winapi?
То есть? Все окна делаются через, даже если они делаются через VCL.
И использование непосредственно апи не спасет тебя от необходимости использовать Application.ProcessMessages..
← →
Тимохов (2004-02-10 14:49) [31]
> И использование непосредственно апи не спасет тебя от необходимости
> использовать Application.ProcessMessages..
Разве?
Я, к моему стыду, плохо знаю архитектуру windows, только начал изучать рихтера. Но! Насколько я понимаю я могу сделать поток с обработчиком очереди сообщений моего нового окна на winapi. При это, опять же, насколья я понимаю, от vcl я вообще зависеть не буду: свое окно, свой поток с обработкой собщений. Разве нет?
← →
Игорь Шевченко (2004-02-10 15:00) [32]Тимохов © (10.02.04 14:49)
> Я, к моему стыду, плохо знаю архитектуру windows, только
> начал изучать рихтера
Лучше Петцольда.
> Насколько я понимаю я могу сделать поток с обработчиком
> очереди сообщений моего нового окна на winapi.
Да, только окно должно быть создано в том же потоке.
← →
Тимохов (2004-02-10 15:03) [33]
> Да, только окно должно быть создано в том же потоке.
Это-то понятно. Спасибо.
Будем читать Петцольда...
← →
jack128 (2004-02-10 15:09) [34]
>Насколько я понимаю я могу сделать поток с обработчиком
> очереди сообщений моего нового окна на winapi.
> Да, только окно должно быть создано в том же потоке
Гм. Смысл? Не проче вынести математику в доп поток, а окно написать на VCL и оставить в основном потоке??
← →
Юрий Зотов (2004-02-10 15:13) [35]> Тимохов © (10.02.04 14:07) [25]
> Вопрос 1. Возможно ли в рамках VCL делать 99 процентов через
> VCL, а определенные окна не через winapi? Т.е. мозможно ли
> такое сочетание?
Движущим механизмом любого оконного приложения Windows является так называемый цикл выборки сообщений. Он выбирает сообщения из очереди (которая для каждого потока своя) и перенаправляет их окнам - адресатам, а там уже сообщения обрабатываются их оконными функциями.
В VCL цикл выборки сообщений главного потока (и тольео его одного) реализован в объекте Appication. Оттуда сообщения поступают формам, проходя сначала через обработчик Application.OnMessage.
В принципе, ничто не мешает создать в программе "чистое" окно Windows (не форму VCL) и задача состоит лишь в том, чтобы заставить его получать сообщения. Для этого можно попробовать создать это окно в главном потоке и диспетчировать сообщения в обработчике Application.OnMessage, но можно и создать его в отдельном потоке, написав в нем же свой цикл выборки сообщений (тогда, если создавать не объект TThread, а прямой поток Windows, то этот поток сможет работать вообще независимо от VCL).
> Вопрос 2. Где про это сочетание почитать?
Про сочетание - не знаю, а про работу с окнами Windows - в любой книжке по программированию для Windows (классическому, а не в RAD-средах, разумеется). Для примера привожу знаменитую "Hello, world!", написанную на "чистом API".
program HelloWorld;
uses
Windows, Messages;
// Оконная функция - обрабатывает все поступающие окну сообщения.
function WndFunc(Wnd, Msg: DWord; wParam, lParam: integer): integer; stdcall;
var
DC: HDC;
PaintStruct: TPaintStruct;
Rect: TRect;
begin
case Msg of
WM_Paint:
begin // Если поступило сообщение WM_Paint,
DC := BeginPaint(Wnd, PaintStruct); // то подготовить отрисовку,
GetClientRect(Wnd, Rect); // получить клиентскую область и в ее центре отрисовать текст,
DrawText(DC, "Hello, World!", -1, Rect, DT_SINGLELINE or DT_CENTER or DT_VCENTER);
EndPaint(Wnd, PaintStruct); // затем сообщить системе, что рисование завершено
Result := 0 // и что сообщение WM_Paint обработано.
end;
WM_Destroy:
begin // Если поступило сообщение WM_Destroy,
PostQuitMessage(0); // то послать в очередь потока сообщение WM_Quit
Result := 0 // и сообщить системе, что WM_Destroy обработано.
end
else Result := DefWindowProc(Wnd, Msg, wParam, lParam) // Для других сообщений вызвать стандартную оконную функцию.
end
end { of WndFunc };
const
AppName = "HelloWorld";
var
Msg: TMsg;
WndClass: TWndClassEx;
begin { main }
// Заполняем запись WndClass и регистрируем в системе класс окна
with WndClass do
begin
cbSize := SizeOf(WndClass);
Style := CS_HRedraw or CS_VRedraw;
lpfnWndProc := @WndFunc;
hIcon := LoadIcon(0, IDI_Application);
hCursor := LoadCursor(0, IDC_Arrow);
hbrBackground := hBrush(Color_Window);
lpszMenuName := nil;
lpszClassName := AppName;
hIconSm := hIcon
end;
WndClass.hInstance := hInstance;
RegisterClassEx(WndClass);
// Создаем и показываем окно заданного класса
CreateWindowEx(0, AppName, AppName, WS_OverlappedWindow or WS_Visible,
CW_UseDefault, CW_UseDefault, CW_UseDefault, CW_UseDefault, 0, 0, hInstance, nil);
// Цикл обработки сообщений (работает, пока не поступит сообщение WM_Quit).
while GetMessage(Msg, 0, 0, 0) do // Выбрать сообщение из очереди потока
begin // и, если это сообщение не WM_Quit, то
TranslateMessage(Msg); // преобразовать сообщение клавиатуры
DispatchMessage(Msg) // и вызвать функцию окна Msg.hWnd
end;
// Передаем системе код завершения программы
Halt(Msg.wParam)
end.
← →
Тимохов (2004-02-10 15:19) [36]Юрий Зотов © (10.02.04 15:13) [35]
Ваш талант и способность отвечать на реально интересущий вопрощающего вопрос меня всегда восхищали:)))
Спасибо. Хороший пример и хорошая информация - будем копать.
← →
KSergey (2004-02-11 09:24) [37]> [31] Тимохов © (10.02.04 14:49)
> Но! Насколько я понимаю я могу сделать
> поток с обработчиком очереди сообщений моего нового окна
> на winapi. При это, опять же, насколья я понимаю, от vcl
> я вообще зависеть не буду: свое окно, свой поток с обработкой
> собщений. Разве нет?
Не далее как дня 2-3 назад я, задравшись с некоторыми проблемами собственного модуля индикатора
длинных процессов, обдумывал как раз такой же вариант, который я условно назвал для себя "через
жопу".
(впрочем, проблемы были совершенно иными: он либо проваливался под главную форму при клике на
ней, либо висел вообще всегда поверх всего)
Кратко предысторию вопроса, объясняющую за одно такое название.
Какие проблемы имеем в случае некоего долгого процесса? (здесь под процессом буду понимать некий
цикл, например, который выполняется продолжительное время; шаблон (пока пустой) for i=0 to 300000
do; - использован был мною как полигон)
а) главное окно "замирает", не переписовывается (при переключении на другую задачу и обратно),
никакие контролы не реагируют ни на что.
б) некоторые контролы даже при выводе на них информации (изменяя "визуальные" их свойства) нифига
ничего не выводят. Да, именно не все, но многие.
Как известно, причиной всему то, что во время этого цикла сообщения, поступающие в очередь
приложения, не диспетчерезируются контролам (а точнее, конечно же - окнам). А сообщения эти как
раз и есть - "перерисуйся". Почему не диспетчерезируются - да потому, что кроме нашего кода не
работает нифига.
И поверьте на слово, такое поведение не есть "глюки VCL" - хоть на WinAPI хоть ты как - а ничего
тут не поделаешь.
Чтобы эту ситуацию как-то "разрулить" - надо давать иногда проталкиваться очереди сообщений. Как?
Ну, например, вызвать пресловутый ProcessMessages.
Как правило, все "проблемы" ProcessMessages происходят, по моим наблюдениям, от слишком частого
его вызова. "Ох, мое приложение тормозит, опять этот триклятый корявый ProcessMessages, а вместе
с ним и дельфи и борланд и все остальные". Ну так вызывай его реже! (это не обязательно в адрес
автора, не принимайте близко к сердцу ;)
Тут возникает и другая проблема: если пользователь при этом с дуру начнет тыкаться куда попало (в
меню, например), пока цикл наш идет - то получатся повторные ("параллельные") вызовы других
обработчиков, что вообще ужасно. конечно же, и недопустимо.
Есть ли выход? Да! ;)
Классический выход: выводим модальную форму (с прогресс-баром или без - по вкусу), создаем доп.
поток и ждем в этой модальной форме его завершения (вернее, видимо, по завершении потока
закрываем форму посылкой подходящего сообщения через PostMessage, например). Работает все -
изумительно! Можно и кнопочку "прервать" легко организовать, и прогресс бар (посылая в форму свои
(пользовательские) сообщения через PostMessage, например), и формочка (а вместе с ней и все
приложение) отлично прорисовываются по необходимости.
Все здорово? В принципе да, но есть и некоторые проблемы.
Основной из них считаю то, что поточную функцию писать несколько сложнее, во всяком относиться к ее написанию надо более аккуратно, постоянно себя одергивая от всяких желаний нехороших. ;) Да и вероятность напороться на какие-либо странноватые глюки (вернее неожиданные, возникающие по неопытности или недостаточно тщательного проектирования) намного проще, нежели в "обычном" коде.
Да и как сказал мой старший коллега "Потоки - это пижонство". Во всяком случае для случая улучшения лишь визуального интерфейса программы (что и имелось в виду) я с ним полностью согласен.
Хотя, конечно, держать на примете этот способ надо: для частной задачи, где таких долгих циклов 1-2,
И вот крутя эту задачку так и сяк, я вдруг подумал: а что если взять, и организовать все наоборот по сравнению с классическим вариантом? Долгий цикл пишем в основном потоке, а формочку вешаем в дополнительном? (отсюда и вышеозвученное название сего метода).
Ну именно формочку (дельфийскую) не получится - визуальные компоненты только в основном потоке допустимы, либо через synhronize, которая опять же на сообщениях держится. Но накидать окошко из пары-тройки контролов на WinAPI разве не сможем? Да легко! ;) А то и вообще диалог из ресурса модально отобразить - еще проще. (Надо отметить, если кто еще не знает, ничего загадочно-мистического в буквосочетании "WinAPI" конечно же нету и бояться его никому не надо.)
Тогда эта отдельная формочка (по задаче требовалась она с ProgressBar и кнопкой "прервать") будет отлично отрисовываться, оперативно (визуально!) реагировать на действия пользователя - и т.д...
К счастью, до реализации я так и не дошел, т.к. понял, что доп. окошко конечно будет вести себя хорошо, но вот окна основной программы - нифига. Сообщения я не проталкиваю для основного потока - отрисовываться ничего не будет! А чтобы протолкнуть - опять надо ProcessMessages вызывать! А тогда стоит ли вообще овчинка выделки??
По-моему - нет.
← →
KSergey (2004-02-11 09:25) [38]Наступает часть последняя, заключительная.
Но формочка-то с прогрессом нам нужна! Что же делать? С потоками связываться не хотелось, "долгих" циклов в программе будет много. Ладно, будем периодически вызывать Application.ProcessMessages (что, надо заметить, очень даже не сложно ;). Однако формочка эта должна быть с одной стороны выше приложения, с другой - не StayOnTop (это вообще ужасный случай, выше нее даже Exception"ы не всегда прорываются). Но и проваливаться под главную форму при клике на последней не должна!
В общем вести себя должна так, как обычно ведет себя модальная форма.
Так и может и подсмотреть как же модальный формы устроены? но вот незадача: для виндовских ф-ций, связанных с отображением модальных диалогов, исходников-то нет... Но как же устроена борландовская ShowModal? Задавшись наконец таким вопросом внимательно изучаю TCustomForm.ShowModal и с удивлением обнаруживаю, что в VCL данная ф-ция реализована от и до руками борландовцев! Т.е. никаких "секретных" (в смысле начинки) WinApi-шных ф-ций там не используется!
Так это то, что надо!
Берем начальный код из ShowModal; вместо цикла обработки сообщений (который, разумеется, всегда организуется свой для модальных форм) вставляем свой "долгий" цикл, в котором не забываем хоть иногда вызывать ProcessMessages; под завязку - финальную часть из ShowModal - и наши, как это водится, победили! ;)
Не все, конечно, из ShowModal удалось скопировать (многое, что там сохраняется/восстанавливается из приватных секций), однако функциональность шаблона вполне устраивает.
Вот собственно и все, что хотелось мне сказать.
← →
jack128 (2004-02-11 09:44) [39]
> KSergey ©
Упрощенно ShowModal выглядит так
WndList := DisableTaskWindows(0);//дизаблим все окна (кроме нашего)
Show;
repeat
Application.HandleMessage;//обрабатываем сообщение из очереди
until ModalResult <> mrNone;
Hide;
EnableTaskWindows(WndList);
Но к вопросу автора, как мне кажется, это не какого отнашения не имеет ;-) По сути
while ModalResult = 0 do Application.ProcessMessages; - хрен редьки не слаще..
← →
KSergey (2004-02-11 10:49) [40]> [39] jack128 © (11.02.04 09:44)
> Упрощенно ShowModal выглядит так
> WndList := DisableTaskWindows(0);//
Да теперь я тоже это знаю ;)
Но до того вот до этих DisableTaskWindows/EnableTaskWindows я и не догадывался!
Ранее же я думал, что в цикле обработки сообщений, организуемого внутри ShowModal, сообщения, предназначенные другим окнам, просто фильтруются хитрым образом, дабы не пропустить сообщения от клавы/мыши или еще чего-то там, чтобы эти окна не активизировались.
А все оказалось проще: запретил их все - и пусть уже система разбирается как им не дать активизироваться ;)
← →
KSergey (2004-02-11 10:55) [41]> [39] jack128 © (11.02.04 09:44)
> Но к вопросу автора, как мне кажется, это не какого отнашения не имеет ;-)
А по-моему, очень даже имеет.
Собственно взялся я за сей опус лишь потому, что автор предполагал, что все проблемы кроются как раз в VCL, и применив мистическое WinAPI, где все хорошо и здорово, от проблем удасться избавиться очень легко и просто (см. первый пост с вопросом).
Вот я и попытался подробно показать, что ничего от этого не изменится.
Более того, я усмотрел в вопросе автора надежду на то, что описанный мною метод "через жопу", который, как мне показалось, и ему казался панацей и который в общих чертах он тоже описывал (как мне показалось на основании вопроса), ни к чему полезному не приведет.
← →
Плохиш (2004-02-11 11:02) [42]Может вместо ProcessMessage, Refresh для формы вызывать?
← →
Тимохов (2004-02-11 11:09) [43]
> KSergey © (11.02.04 10:55) [41]
Большое спасибо за столь развернутый "опус".
Скопировал его себе - буду обдумывать.
В [40] Вы упомянули про фильтрацию сообщений. ЗдОрово было бы научиться это делать. Например, пропускать только те сообщения, которые отвечают за перерисовку. Все остальные (например, клики мышкой куда душе будет угодно) просто игнорировать - разрешать только кликать на кнопку "Прервать" на маленьком окошке. У меня есть ощущение, что этот путь вполне реален. Интересно пытался ли кто-нибудь такое сделать (и упешно реализовал:)))?
← →
Тимохов (2004-02-11 11:11) [44]
> Плохиш (11.02.04 11:02) [42]
> Может вместо ProcessMessage, Refresh для формы вызывать?
Вы имеет в виду для информационного окошка?
Как правильно заметил KSergey, хочется все-таки, чтобы другие формфы моего приложения, а не только информационное окошко, реагировали на сообщения о перерисовке...
← →
jack128 (2004-02-11 11:22) [45]
> хочется все-таки, чтобы другие формфы моего приложения,
>
Ну так перерисовывай все.
хинт: Screem.Forms[]
Но, повторюсь, имхо, не тем путем идешь..
← →
KSergey (2004-02-11 12:05) [46]> [42] Плохиш (11.02.04 11:02)
> Может вместо ProcessMessage, Refresh для формы вызывать?
Первый вопрос: как часто это надо делать? Т.е. упираемся в ту же проблему "как часто вызывать ProcessMessages"
Но это бы все ничего, но есть другой огромный косяк: при вызове ProcessMessages обрабатываются только те сообщения, которые есть в очереди. В частности, если там есть WM_PAIT - требуемые окна перерисуются. Если ничего нет - выход произойдет довольно быстро.
Refresh же в любом случае заставит контрол принудительно перерисовываться, даже если этого и не требуется (пользователь никуда и не думал переключаться), что может занять продолжительное время.
> [43] Тимохов © (11.02.04 11:09)
> В [40] Вы упомянули про фильтрацию сообщений. ЗдОрово было
> бы научиться это делать. Например, пропускать только те
> сообщения, которые отвечают за перерисовку. Все остальные
> (например, клики мышкой куда душе будет угодно) просто игнорировать
> - разрешать только кликать на кнопку "Прервать" на маленьком
> окошке. У меня есть ощущение, что этот путь вполне реален.
> Интересно пытался ли кто-нибудь такое сделать (и упешно
> реализовал:)))?
Проблема как раз в том, чтобы определиться что пропускать, а что нет.
В общем случае, как я понимаю, надо приложить весьма серьезные усилия для изучения всех сообщений, кроме того необходимо четко понимать какое из них что делает и в каком порядке они должны идти. А сообщений этих - туева хуча, доложу я вам.
Однако в системе есть готовая ф-ция EnableWindow, которая и так делает все что надо (а что надо - только в MS знают точно ;), а на ее основе мы имеем счатье лицезреть готовую реализацию DisableTaskWindows/EnableTaskWindows. Так стоит ли изобретать велосипед, все элементы которого мы к тому же не знаем?
← →
Тимохов (2004-02-11 12:07) [47]Вот с этим
> В общем случае, как я понимаю, надо приложить весьма серьезные
> усилия для изучения всех сообщений, кроме того необходимо
> четко понимать какое из них что делает и в каком порядке
> они должны идти. А сообщений этих - туева хуча, доложу я
> вам
и с этим
> (а что надо - только в MS знают точно ;
Побностью согласен - будем копать. :((((
← →
KSergey (2004-02-11 12:11) [48]> [45] jack128 © (11.02.04 11:22)
> Но, повторюсь, имхо, не тем путем идешь..
А, к стати, каким надо? Или хотя бы какие есть еще варианты, кроме мною описанных?
← →
KSergey (2004-02-11 12:14) [49]> [47] Тимохов © (11.02.04 12:07)
> Побностью согласен - будем копать. :((((
Копать куда? В сторону изучения всех сообщений?
Дохлое дело. Хотя бы так: что делать с пользовательскими сообщениями (начиная от WM_USER и далее)? Глушить? Пропускать? А что задумывалось разработчиком под ними? А ведь библиотека VCL этими сообщениями просто изобилует! Еще и их изучать? А зачем, если все уже сделано?
← →
Тимохов (2004-02-11 12:17) [50]
> Еще и их изучать? А зачем, если все уже сделано?
Копать в сторону решения проблемы - несколько ямок уже есть. Еще десяток будет - будем выбирать, которую копать дальше :))))
← →
Barbarian five (2004-02-11 14:02) [51]Долгие операции надо засовывать исключительно в потоки. Сделать это совсем не сложно. А вот если использовать ProcessMessages, то можно вообще зависнуть в случае, если в этот момент будет запущен другой долгий цикл (после нажатия на кнопку, например), т.е. не выйти из него. Это все не есть гуд, и для параллельных операций (цикл и отображение на форме) специально придумали многозадачность. Так воспользуемся же ею!
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2004.02.25;
Скачать: [xml.tar.bz2];
Память: 0.63 MB
Время: 0.036 c