C ++ - вопрос о диалоговом окне - PullRequest
1 голос
/ 21 мая 2010

Это более конкретный вопрос, связанный с моим предыдущим.

У меня есть приложение, которое использует таймер. Код написан так, как обработчик my WM_TIMER вызывает DialogBoxParam(...) с некоторым пользовательским обработчиком сообщений (назовем его DlgProc).

Это делается следующим образом:

case WM_TIMER: { // Рутина, которая отображает специальное окно сообщения DisplayMessageBox (...); вернуть 0; } * +1010 *

Теперь, если я заставлю DlgProc обрабатывать подобные сообщения (см. Код), это приведет к множеству диалоговых окон (по одному на WM_TIMER вызов).

   switch (msg)
   {
   case WM_INITDIALOG:
      // (...)
      return TRUE;
   case WM_COMMAND:
      // (...)
      return TRUE;
   return FALSE;
   }

Но если я добавлю фиктивный обработчик WM_PAINT (return TRUE;) к своему DlgProc, это приведет к ровно одному показанному DialogBox и 100% загрузке ЦП (потому что я получаю тонны WM_PAINT сообщений).

Q:

Что можно сделать здесь, если я хочу, чтобы мое приложение показывало ровно ОДНО диалоговое окно и не загружало ЦП для обработки WM_PAINT? (я имею в виду подобное поведение, похожее на рисование уникального диалогового окна и полное приостановление родительского окна) .

Также было бы замечательно, если бы кто-то объяснил, что на самом деле происходит в этой ситуации и почему я получаю gazillions WM_PAINT сообщений в мое диалоговое окно и почему их обработка (с return TRUE) приводит к предотвращению создания других диалоговых окон ,

Спасибо.

Ответы [ 2 ]

3 голосов
/ 21 мая 2010

1) Вы должны отключить таймер после того, как первый сигнал WM_TIMER пойман, если вы хотите показать только одно диалоговое окно. Вы можете сделать это, используя KillTimer () .

2) Windows хочет поддерживать графический интерфейс в актуальном состоянии. Всякий раз, когда область на экране должна быть обновлена, она становится недействительной с помощью InvalidateRect или InvalidateRgn. Теперь для каждой «недействительной» части экрана вызывается WM_PAINT, чтобы снова сделать «действительным».

Если вы этого не сделаете (или только его части), Windows снова вызовет WM_PAINT ... и снова. Одним из способов является вызов ValidateRect . Во многих случаях BeginPaint () и EndPaint () используются для выполнения этой работы.

3) Может быть, самое важное: вы не должны просто возвращать ЛОЖЬ! Попробуйте DefWindowProc () для окон и DefDlgProc () для диалогов. Они также позаботятся о WM_PAINT надлежащим образом.

0 голосов
/ 24 мая 2010

Дело не в том, что вы зарегистрированы для WM_PAINT, что-то должно вызывать это (даже если вы не добавляете WM_PAINT: обработчик), ищите функции перерисовки / рисования (например, InvalidateRect ())

...