Пытался озвучить нажатия клавиш - в окне ричедит. Периодически появлялись - "error - программа будет закрыта" Не из-за этого случайно?
Veter Эта ситуация невозможна. Просто если бы была - были бы такие последствия У Вас скорей всего самая распространённая ошибка доступа к памяти. Но это не точно и надо её смотреть.
Wsd стэки могут быть разными, доступ к памяти возможно – об этом я и думал Пробовал критическую секцию ставить не помогло, наверно дело не в этом
Ребя, давно известно что окно ассоциируется с потоком. Также существует такое понятие как "очередь сообщений окна".
Perre Причём тут критическая секция? Я ж написал что это тех невозможно. При обработке мессажей для каждого поток не создаётся а несколько сразу в одном быть неможет. Mental_Mirror проще объяснил но смысл тот же НЕМОЖЕТ
Mental_Mirror wsd Подробнее, плиз. необработанные сообщения в очереди объединяются - это факт. А DispatchMessage ждет возврата из callback-процедуры, возвращая именно то, что мы в этой процедуре вернули. Но в некоторых случаях ... - то есть у нас там что-то обрабатывается и еще (возможно) не завершилось, а оконная процедура вызвана еще раз, и ей передано WM_PAINT, без всяких GetMessage (или я как-то не так понял смысл процитированной фразы?) ...и еще в случае создания других окон при обработке событий в нашем - например диалога или мессажбокса - наша процедура продолжает принимать события! Хотя по логике должна полностью заморозится. (угу, это все потому, что очередь сообщений не окна, а потока, и что у мессаджбокса или другого диалога вызывается при инициализации своя callback-функция, и потом при возврате система немного путает, кто именно и что вернул /я так думаю.../- DispatchMessage возвращает то, что вернула та, другая, и цикл обработки сообщений продолжается... Но в стеке нормально продолжает лежать адрес возврата в нашу ветку, и по завершению вызванного диалога или мессаджбокса, попадаем куда надо - в продолжение обработки того самого события, например нажатия на кнопку...) Так что что-то тут совсем не ясно! То есть мне было ясно до этого топика, что окну МОЖЕТ придти следующее сообщение, несмотря на необработанность текущего. ) Вот если бы вы сказали "Оконная/диалоговая процедура не может обрабатывать 2 и более сообщений одновременно" ... (если никто не понял, что я имел в виду - под одновременностью в данном случае понимается отсутствие API вызовов в момент выполнения обработки обоих сообщений) короче, я понимаю, что ничего не понимаю!
исходя из цитаты проца можед обрабатывать несколько сообщений сразу в разных тредах. для проверки можно в обработчик wmpaint'a кинуть проверку текущего хендла треда и запустить паралель но тред с вызовом updatewindow
Не, то что в разных тредах может быть, это даже не интересно. А вот если UpdateWindow вызывать из обработки WM_COMMAND, а после вызова еще выполнять какой-то не очень быстрый код... Итак, внимание! Код (Text): ... switch (uMsg) { case WM_PAINT: printf("=== WM_PAINT: hwnd = %#0lx, message = %#0lx\n",hwnd, uMsg); // Paint the window's client area. return DefWindowProc(hwnd, uMsg, wParam, lParam); case WM_KEYDOWN: printf("=== WM_KEYDOWN start: wparam = %#0lx, lparam = %#0lx\n",wParam, lParam); InvalidateRect(hwnd,NULL,TRUE); UpdateWindow(hwnd); Sleep (500); printf("=== WM_KEYDOWN end ==="); return 0; case WM_DESTROY: case WM_CLOSE: // Clean up window-specific data objects. printf("from WndProc (Close) hwnd = %#0lx, message = %#0lx\n",hwnd, uMsg); PostQuitMessage(0); break; // // Process other messages. // default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } ... И что имеем на выходе при нажатиях на клавиши? (оконное приложение скомпилировано как консольное, выход перенаправлен в текстовый файл, ниже кусок из него) То есть мы продолжаем обрабатывать одно из событий (нажатие на клавишу), а в это время вклинивается WM_PAINT и успешно выполняется. Вопросы? Объяснения?
sendmessage как раз и вызывает процедуру окна напрямую, а в очередь сообщений помещает postmessage. при этом если sendmessage выполняется внутри одного потока, то это равносильно вызову оконной процедуры как подпрограммы. а если из другого потока - там есть своя синхронизация (см. Remarks k SendMessage b MSDN):
shoo Угу, 100% так оно и есть. UpdateWindow так же не возвращает управления до завершения обработки WM_PAINT, вызов Sleep в данном случае совершенно не нужен. Но так значит, окну МОЖЕТ придти следующее сообщение, даже если оно не обработало предыдущее?
ну, в принципе, если в оконной процедуре сделать UpdateWindow себя - то такой вариант возможен. (в каждом заборе найдется дырка ---------- в том числе никто не запрещает посылать сообщения окну из собственно оконной процедуры.
Прорезюмирую - если оконная процедура вызывает что-то, приостанавливающее выполнение кода и инициирующее другие события окна (не обязательно данного), как-то: UpdateWindow, MessageBox, SendMessage, DialogBoxParam/Indirect - то окну могут приходить другие сообщения, хотя событие, в котором была вызвана подобная функция, останется еще недообработанным. Это не означает, что будет выполняться несколько потоков оконной процедуры - просто выполнение первого обработчика будет приостановлено. не наврал?
смотря что иметь в виду под приостановкой выполнения кода: приостановку потока или перенос выполнения данного потока в код за пределами данной процедуры (т.е. выполнение какой-либо функции). если поток приостановлен - то окно не может получить сообщения ни из себя, ни из другого потока (см. синхронизацию). если поток продолжает выполняться - получение сообщений возможно. например, посылаем из процедуры главного окна сообщение дочернему окну, а дочернее окно, обрабатывая его, может послать какое-нибудь сообщение главному окну, и главное окно обработает его своей оконной процедурой до того, как первоначальный SendMessage "вернет" управление. Картина такого выполнения сродни рекурсии, при хранении промежуточных данных в локальных переменных или сохраняя регистры в стеке все должно быть прозрачно. но в некоторых случаях типа отрисовки нужно четко себе представлять что происходит, иначе можно или самовызов зациклить, или чего-то самому себе испортить следующим вызовом, и т.п.
Вот набросал примерчик: на диалоге два однострочных эдита. подготовка: субклассируем верхний эдит процедурой sub_proc. теперь самое интересное: нажимаем ОК: 1.оконная процедура диалога начала обрабатывать сообщение WM_COMMAND с кодом 1, о чем мы получаем уведомление "Начали" 2.далее: посылаем сообщение EM_GETHANDLE эдиту EDIT_1 3.эдит EDIT_1 обрабатывая это сообщение субклассирующей процедурой посылает родительскому окну сообщение WM_COMMAND с кодом 33 4.оконная процедура диалога обрабатывает сообщение WM_COMMAND с кодом 33, в результате чего в эдите EDIT_2 появляется надпись "Послание". 5.неявные события: возвращение в субклассирующую процедуру, которая передает управление родной оконной процедуре эдита, затем возвращает управление назад в оконную процедуру диалога. 6.оконная процедура заканчивает обработку WM_COMMAND с кодом 1, начатую в пункте №1, о чем мы получаем уведомление "Закончили". все предельно ясно. кому нет - можно натыкать дополнительных мессаджбоксов в разных местах до и после
Всем кто откликнулся спасибо, насколько я понял обработка некоторых сообщений может быть прервана более важными сообщениями (например: перерисовка окна) , но потом первый обработчик продолжит работу
да, кстати, еще один момент (или готовое решение) по этому вопросу (правда не с отрисовкой): одно мое приложение выполняет операции, некоторые из которых занимают длительное время. чтобы окно не было в это время "парализованным" эти операции я выполняю в отдельном потоке - при этом окно можно сворачивать, двигать и т.п. а чтобы пользователь не выполнил в это время какой-либо другой операции - высавляется флаг: единица в статической ячейке. пока она стоит - WM_COMMAND игнорируется (проверкой в оконной процедуре). Когда операция завершается - она сбрасывает единицу в ноль - можно работать дальше. такая вот синхронизация подручными средствами