Возникла такая проблема: Я создаю обычное Win32 приложение, но окно хочу вызывать через класс с методами: 1. CreateWindow, где будем регистрировать, создавать класс окна и запускать цикл с GetMessage 2. static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM), функция обработки сообщений окна Таким образом из созданного нами приложения убиваем все кроме _tWinMain в которой пишем: CMyWindow w; w.CreateWindow(TEXT("Title")); Всё работает почти замечательно если не считать того что кроме всего прочего мне нужно запустить таймер. Добавляем if в CreateWindow : while (GetMessage(&msg, NULL, 0, 0)) { if (msg.message == WM_TIMER) { MessageBox(NULL, TEXT("Title"), TEXT("message"), MB_OK); } TranslateMessage(&msg); DispatchMessage(&msg); } Если SetTimer вызвать перед этим циклом в if можно попасть только после того как закрывается окно, а если SetTimer вызвать в WM_CREATE, то приложение просто висит. Подскажите как правильно реализорвать то что я хочу: класс окна с таймером?
А что если обрабатывать таймер в самой оконной процедуре? Или же просто проставить ему функцию-обработчик?
Ты не там обрабатывать пытаешься сообщения. Сообщения обрабатываются в WinMain. И что за код, какой язык программирования? Пиши в другой раз лучше в WASM.LANG.C
C функцией обработчиком та же ситуация А в самой оконоой процедуре ето я так понимаю в WndProc? Если да то сообщения WM_TIMER она не получает, а если после WM_CREATE идет SetTimer и далее цикл c GetMessage, то он действительно обрабатывает там таймер, но тогда он из этого цикла не уходит в цикл GetMessage окна и окно просто висит.
Хорошо тогда как мне реализовать таймер+окно без WinMain? С++ ОК. Но в данном случае писал сюда потому, что именно проблема не в языке а в работе с WinAPI
Так проблема именно в том как спрятать работу в классе ( именно тогда всё и перестаёт работать), ведь судя по моим скромным знаниям ассемблера у тебя цикл с GetMessage находится именно там где и и должен (в WinMain), а я хочу перенести WinMain в класс и потом из настоящего WinMain запускать классовый (CreateWindow у меня)
Изначально мой класс окна я хотел использовать в консольном приложении, но там была таже ситуация, что и сейчас. Прочитав вот это - "SetTimer() не должна использоваться в консольных приложениях, так как консольные приложения не поддерживают разделения потоков." просто перенес всё в созданное окнонное Win32 приложение и в место main теперь класс создается в _tWinMain. Так может ктото объяснит как именно работает таймер? Потому, что после вызова SetTimer я не нашел нового потока в моем процессе.
Хм, ну ладно, обычные таймеры не катят. А что если пользовать timeSetEvent/timeKillEvent из модуля WinMM? Там другой механизм отсчёта (вытесняющая многопоточность, если интересно). Может оно не будет подвешивать?
Для таймера нет нового потока. По вызову SetTimer() - Windows записывает HWND окна во внутренний список и когда время течет внутенним образом в Windows - система посылает сообщения WM_TIMER.
Вообщем я думал, что что-то не допонимаю в таймерах, а как оказалось проблема была в другом. Кстати кроме неправильной работы таймера, мое приложение со включённым окном грузило процессор примерно на 50%. Для избавления от этих 2-х проблем, как оказалось надо было добавить в обработчик сообщений окна: case WM_PAINT: hdc = BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); break; До этого, секция WM_PAINT у меня вообще отсутсвовала, но как оказалось именно без BeginPaint и EndPaint таймер не правильно работает и приложение со включённым окном грузит процессор на 50%. Судя по тому, что я прочитал в MSDN'е и всегда знал - сообщение WM_PAINT и не обязательно обрабатывать, если сам ничего в окне выводишь. Кто может объяснить почему именно нехватка BeginPaint и EndPaint в WM_PAINT так влияет на работу приложения - просьба отписаться
Ох, что-то странное у тебя происходит. Я размышляю... Можно посмотреть код? Конкретно нас интересуют связи между оконной процедурой [WndProc], функцией, в которой создаётся окно, функцией с циклом обработки сообщений и то, с какими параметрами вызывалась SetTimer. ). Короче говоря, хотелось бы получить код для воспроизведения ситуации с высокой загрузкой ЦП.
С WM_PAINT-ом такая вот петрушка: если у тебя нет "case WM_PAINT:" вообще - тогда ничего не надо делать, потому что если какого-то обработчика нет, то должен быть вызов DefWindowProc() в "default" случае - в твоёй процедуре окна.. Если "case WM_PAINT:" есть - тогда надо обязательно пара BeginPaint()/EndPaint() или без пары, но опять вызов DefWindowProc(): Код (Text): // // No handling! Bad code! // switch (message) { case WM_PAINT: break; default: DefWindowProc (...); } // // OK // switch (message) { case WM_PAINT: DefWindowProc (...); break; default: DefWindowProc (...); } // // OK // switch (message) { case WM_PAINT: BeginPaint (...); EndPaint (...); break; default: DefWindowProc (...); } Дело в том, что WM_PAINT изымается из очереди сообщений окна функцией EndPaint() и если такого вызова нет, то сообщение стоит в очереди навсегда и происходит замкнутый цикл - т.е. постоянный вызов твоей оконной процедуры.
Ну и так, на всякий случай: таймер не работал, потому что сообщения WM_TIMER имеют наименьший приоритет и доходят до оконной процедуры только после того, как из очереди сообщений будут изъяты другие сообщения (в том числе и WM_PAINT).