Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Прикольный баг в шестой студии...  (Прочитано 24802 раз)
0 Пользователей и 3 Гостей смотрят эту тему.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« : 03-11-2005 12:12 » 

Програмлю внутреннюю программку в студии 6.
Сделал ее на основе диалога, вставил менюшку и поставил в OnDestroy() проверку - сохранен ли текущий профиль или нет.


На основе проверки идет вопрос - а не сохраниться ли нам?

Примерно такой код

void CMainDlg::OnDestroy()
{
   CDialog::OnDestroy();
   if (!IsSavedProfile())
   {
      
      if (IDYES == AfxMessageBox("Current profile changed, but not saved. Save?",MB_YESNO) )
      {
         SaveProfile(NULL);
      }
   }
}


Смотрю, а сообщеньица то и нет, при этом профиль сохраняется ... Жаль


У думаю, злоебучая скотинка, взял и создал простую заготовку, в кнопку вставил PostQuitMessage(0);
А в тот же OnDestroy() проставил простой вызов сообщеньица.

Ответ - фиг вам, а не сообщение.

Короче говоря, после всех проверок - выясняется, что именно в случае - когда убивается диалог через PostQuitMessage получается вот такой провал.
А вот если просто вызвать вместо нее CDialog::OnOK(); то все в порядке.

Винда 2000 студия 6.
Записан

А птичку нашу прошу не обижать!!!
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #1 : 03-11-2005 12:33 » 

Хм... странно - ща проверил всё работает - 6я на 2000ой винде. Правда у меня 6ой сервис пак стоит.
Может в этом дело?

* TestOnDestroy.zip (12.21 Кб - загружено 1044 раз.)
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #2 : 03-11-2005 12:38 » 

Джон - при нормальном выхове при закрытии окна крестиком - тоже все работает - не работает если вставить кнопку и из нее вызвать PostQuitMessage - я ж написал....
Записан

А птичку нашу прошу не обижать!!!
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 03-11-2005 12:41 » 

поставь вызов

CDialog::OnDestroy();

в конце

мож поможет Улыбаюсь
Записан

Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #4 : 03-11-2005 12:59 » 

Леш - я ж написал, что если вызвать OnOK  вместо PostQuitMesage то все работает .....
Записан

А птичку нашу прошу не обижать!!!
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 03-11-2005 13:00 » 

Улыбаюсь
я те посты не видел, когда постил - шустро появились Улыбаюсь)))
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #6 : 03-11-2005 13:23 » 

Гром, нельзя вызывать из проги PostQuitMessage. Это прерагатива только обработчика сообшения WM_DESTROY. Ты если хочеш выйти должен послать сообшение WM_CLOSE.
Функция PostQuitMessage Помешает в очередь сообшений сообшение WM_QUIT. И когда в данном обработчике:
Код:
    while (GetMessage(&Msg,NULL,0,0))
    {
       TranslateMessage(&Msg);
       DispatchMessage(&Msg);
    }
GetMessage вытаскивает сообшение из очереди WM_QUIT, то происходит выход из цикла обработки очереди.

Вот вырезка из MSDN
Цитата
he PostQuitMessage function indicates to Windows that a thread has made a request to terminate (quit). It is typically used in response to a WM_DESTROY message.
Цитата
The PostQuitMessage function posts a WM_QUIT message to the thread's message queue and returns immediately; the function simply indicates to the system that the thread is requesting to quit at some time in the future.
When the thread retrieves the WM_QUIT message from its message queue, it should exit its message loop and return control to Windows. The exit value returned to Windows must be the wParam parameter of the WM_QUIT message.
« Последнее редактирование: 20-12-2007 21:14 от Алексей1153++ » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #7 : 03-11-2005 13:38 » 

Finch  попробуй то же самое сделать в обычном окне.
Поймешь, что все можно.

Я активирую процесс который активируется WM_DESTROY т.е. делаю то же самое - нигде нет запрета на вызов этой функции, есть только пояснения.

Выход из кольца обработчкиа никак не объсняет почему я не могу создать модальное окно после выхода....

Кстати - если ты говоришь о том, что PostQuitMessage ответ на WM_DESTROY и я с тобой согласен, что в обычном окне так и происходит, потому, как при работе с ней нет вызова OnDestroy то тогда ответь мне как объяснить факт вызова ее в диалоговой апликации, которая запускает обработчик WM_DESTROY после PostQuitMessage Не понял
Записан

А птичку нашу прошу не обижать!!!
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #8 : 03-11-2005 13:43 » 

Гром в Чистом WinAPI это не прокатит, и не будет вызвано ни одно сообшение по уничтожению ресурсов. Какие есть навороты в MFC я не разбирал. Кнопочки закрытия программ вызывают именно сообшение WM_CLOSE.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #9 : 03-11-2005 14:18 » 

Програмлю внутреннюю программку в студии 6.
Сделал ее на основе диалога, вставил менюшку и поставил в OnDestroy() проверку - сохранен ли текущий профиль или нет.

На основе проверки идет вопрос - а не сохраниться ли нам?

Примерно такой код

void CMainDlg::OnDestroy()
{
   CDialog::OnDestroy();
   if (!IsSavedProfile())
   {
      
      if (IDYES == AfxMessageBox("Current profile changed, but not saved. Save?",MB_YESNO) )
      {
         SaveProfile(NULL);
      }
   }
}
Смотрю, а сообщеньица то и нет, при этом профиль сохраняется ... Жаль

Я только вот это проверил. Или я что-то не так понял? Это у тебя работает?

А про остальное - думаю тебе надо кодом в нас кинуть. Ага

Я только не понимаю зачем ты вызываешь именно PostQuitMessage?
Насколько я знаю - это сообщение системе, что тред заканчивает работу. ПОчему она должна OnDestroy вызывать? ЭТо следствие WM_DESTROY. Попробуй вместо PostQuitMessage(0); вызвать PostMessage(WM_DESTROY);
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #10 : 03-11-2005 15:57 » 

Я наверное чего то не понял но....

Функция PostQuitMessage инициирует процесс окончания потока. Вызванная в главном потоке апликации вызовет закрытие всей программы включая дочерние потоки...

Что не нравится...
Если послать просто WM_DESTROY  поверь ничерта нормально не отработает.

Нужно посылать либо WM_CLOSE которая закрывает программу либо вышеназванную функцию...

Теперь еще раз.
В НОРМАЛЬНОЙ ОКОННОЙ ПРОГРАММЕ вызова OnDestroy правильно не происходит в результате чего бага нет.

В диалоге как главном окне программы ВЫЗЫВАЕТСЯ OnDestroy что дает баг.
Он сопровождается и отсутствием сообщения которое там может быть инициировано.

Судя по "я те посты не видел, когда постил - шустро появились" - интересно как можно не видеть ПЕРВОЕ сообщение в теме, которое написано, его мало кто читал внимательно.
Повторяю - перечитайте сообщение.
Там нету:
1. Никаких упоминаний о спец сообщениях.
2. Нет упоминания об ВинАПИ - к этому вообще все вышесказанное не относится.
3. Есть указание, что баг наблюдается ТОЛЬКО в случае если главное окно программы - диалог.


Теперь вопросы:
1. Финч - где написано, что PostQuitMessage нельзя вызывать для завершения главного потока?

2. Фраза It is typically used in response to a WM_DESTROY message. говорит о том, что в ответ на такое сообщение в потоке дочернем чаще всего пользуют именно такую функцию для самоуничтожения, но я не вижу там никакого противоречия с фактом, что я в ручную когда хочу убить главный поток корректно вызываю именно ее, которая и посылает код возврата и отрабатывает как нормальный выход из потока. Где крамола?

Условия как повторить баг.
1. Создать МФС программу на основе диалогового окна.
2. Создать обработчик сообщения WM_DESTROY
3. Вызввать в 2-м AfxMessageBox с любым сообщением.
4. Поставить на форму окна кнопку.
5. Создать обработчик нажатия кнопки.
6. В нем вызвать функцию PostQuitMessage(0); при этом вместо 0 можно ставить любой число.
7. Запустить программу в режиме дебаг и поставив точку останова в обработчике DESTROY убедится что туда есть заход.
8. Запустить программу и нажать на кнопку которю вы поставили в 4-м пункте.
9. Полюбоваться на отсутствие сообщения.
10. Для любителей - повторить пункт 7 для поной картины, что проход по вызову сообщения есть а самого сообщения нет.
11. В качестве интереса поставить для вызова не простое сообщение а с выбором Да или Нет и убедиться что нет никакой разницы в типе.

Вот уж не думал, что на своем форуме придется так разжевывать. Жаль
Записан

А птичку нашу прошу не обижать!!!
PooH
Глобальный модератор

ru
Offline Offline
Пол: Мужской
... и можно без хлеба!


« Ответ #11 : 03-11-2005 17:10 » 

ИМХО (под рукой нет Студии, проверить не могу, но как вариант)
"10. Для любителей - повторить пункт 7 для поной картины, что проход по вызову сообщения есть а самого сообщения нет."

А может он диалог просто не прорисовывает? тут не до прорисовки диалогов.
может быть после создания диалога его принудительно прорисовать, а после этого поставить брикпоинт и продебагить
« Последнее редактирование: 03-11-2005 17:12 от PooH » Записан

Удачного всем кодинга! -=x[PooH]x=-
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #12 : 03-11-2005 21:50 » 

Гром, спокойно - "Сядем усе" Улыбаюсь в первой "неработающей" части твоего поста ни слова не говорилось о PostQuitMessage. Ты написал о ней как о решениии проблемы в первой части.
Поэтому я это и проверил.

Все твои пункты с 1 по 6 соответствуют действительности - я именно это и проверил после твоего уточнения.

Насчёт "нет разницы" - на самом деле разница есть - если поставить тип MB_RETRYCANCEL, то получишь не 6 а 4, те как если бы была нажата кнопка IDRETRY - те получается, что MessageBox в данной ситуации просто возвращает значение кнопки, которая находится в фокусе - при стиле MB_YESNO - это кнопка IDYES. Поэтому у тебя всегда сохранялся профиль.

Для чистоты эксперимента я использовал не МФЦшную, а "нормальную" ф-ю

int i = ::MessageBox(NULL,_T("Hallo"),_T("123"),MB_RETRYCANCEL);

В данном случае мы имеем дело с багом - если это конечно баг, а не безграмотность программера - с которым я тоже один раз сталкивался - в одном pop-up окошке необходимо было показать MessageBox - и всё было один в один - к тому моменту, когда MessageBox должна была появится окошко уже не сушествовало и MessageBox я не видел. GetLastError возвращал 0. Всё было хокей - только MessageBox небыло. Насколько я помню - причину я так и не нашёл (иначе не мучил бы себя и вас). Но она кроется в природе MessageBox при оконченных тредах (или, как теперь выяснилось, тредах находящихся в стадии завершения).

Попробую покопать в этом направлении.

зы Сначала я предположил, что остаётся в очереди OnButtonClick - и именно он отрабатывает в MessageBox - нифига подобного. Если отправлять PostQuitMessage например при OnChangeEdit, то всё работает точно так же.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #13 : 03-11-2005 23:13 » 

Гы, во чего нашёл - просто и понятно

Цитата: MSDN
The PostQuitMessage function indicates to Windows that a thread has made a request to terminate.
Any window that is created after calling the PostQuitMessage function will be immediately destroyed.

Всё ясно.

зы Кстати этом метод рекомендуется для убивания "несвоих" модальных окон - например для организации MessageBox с таймером - или сформулировать по другому - как закрыть MessageBox программно:

Код:
 void CALLBACK  MessageBoxTimer(HWND hwnd, UINT uiMsg, UINT idEvent, DWORD dwTime)
   {
       PostQuitMessage(0);
   }

   UINT   TimedMessageBox( HWND hwndParent,  LPCTSTR ptszMessage, LPCTSTR ptszTitle, UINT flags,       DWORD dwTimeout)
   {
       UINT idTimer;
       UINT uiResult;
       MSG msg;
       idTimer = SetTimer(NULL, 0, dwTimeout, (TIMERPROC)MessageBoxTimer);

       uiResult = MessageBox(hwndParent, ptszMessage, ptszTitle, flags);
       KillTimer(NULL, idTimer);
       if (PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE))
      {
           uiResult = 0;
       }
       return uiResult;
   }
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #14 : 06-11-2005 08:05 » 

Джон - вот ответ не мальчика но мужа.
Я так глубоко не копал.
Если не трудно на ссылку про то, что все окна будут уничтожены в MSDN в студию....

Прошу прощения - Джон углядел - действительно в первом сообщении не написал, что баг возник сам из-за ПостКуитМессаджа Улыбаюсь

Прошу поставить мне минус за неправильное изложение материала Жаль каюсь погарячился...

Записан

А птичку нашу прошу не обижать!!!
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #15 : 07-11-2005 09:32 » 

Прошу поставить мне минус за неправильное изложение материала Жаль каюсь погарячился...

Раскаяния достаточно Ага

Задай поиск в MSDN - Q138681 (это в старой - в новой - PSS ID Number: 138681)
Или тема
"Knowledge Base
 PRB: Windows Flash and Disappear in Dialog-Based Applications"

В описании причины - второй абзац.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #16 : 20-12-2007 21:34 » 

Джон, прикольный трюк с модальным окном )

насколько я понял, делается следующее:

1) запуск таймера на N мс
2) открытие модального диалога ()
3) через N мс сработал таймер, поместил сообщение WM_QUIT в конец очереди
4) вышли из модального диалога
5) убили таймер
6) удалили из очереди WM_QUIT

Только объясни одну вещь, не могу понять -
Цитата
Any window that is created after calling the PostQuitMessage function will be immediately destroyed.

но ведь диалог выведен раньше вызова PostQuitMessage!

как же так ? Улыбаюсь

ps Кстати , нет ли опасности вылететь из программы ? (если задержимся между пунктами 4-5 или 5-6) ?
« Последнее редактирование: 20-12-2007 21:36 от Алексей1153++ » Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #17 : 21-12-2007 08:48 » 

Это вобще я тот Джон, который это всё написал? Нифига не помню. Да давненько я уже теорией не занимался.

Не совсем так... У тебя же есть dwTimeout.

Приведённый код просто показывает как закрыть модальный MressageBox через определённое время.
Те если пользователь не закроет его скажем в течении 10 сек.

Запускаем таймер и открываем MessageBox. Через 10 сек приходит OnTimer и вызывает callback ф-ю. Посылается PostQuitMessage и MessageBox закрывается. Если же пользователь раньше закроет, то таймер сразу убивается и PostQuitMessage не отправляется.


но ведь диалог выведен раньше вызова PostQuitMessage!

как же так ? Улыбаюсь

Именно так. Сначала диалог потом спустя dwTimeOut для unattended (не знаю как лучше перевести) закрытия PostQuitMessage.

Цитата
ps Кстати , нет ли опасности вылететь из программы ? (если задержимся между пунктами 4-5 или 5-6) ?

КиллТаймер приходит сразу после закрытия. Там задержи быть не может. Так же как и после него. Так что всё чисто.

зы А кстати - почему в "Общении"?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #18 : 21-12-2007 09:20 » 

тот, тот, и не отпирайся Улыбаюсь)


всё равно не ясно:
Цитата
Any window that is created after calling the PostQuitMessage function will be immediately destroyed.
любое окно, созданное ПОСЛЕ вызова PostQuitMessage будет немедленно уничтожено.

а тут то порядок наоборот! Создано окно , потом вызвано PostQuitMessage (если юзер протупил эти 10 секунд)

-----------------
Цитата
КиллТаймер приходит сразу после закрытия. Там задержи быть не может. Так же как и после него. Так что всё чисто.
а при чём тут киллтаймер то , сообщение WM_QUIT лежит в очереди , а тут , скажем , написано так
Код:
uiResult = MessageBox(hwndParent, ptszMessage, ptszTitle, flags);
KillTimer(NULL, idTimer);

..........тут - длительные вычисления........

 if (PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE))
 {

а во время длительных вычислений оконная процедура (в которой тоже ведь есть PeekMessage ) взяла и добралась до WM_QUIT
?


-----------------
в словаре:
unattended - оставленный (оставлен) без присмотра.
Отлично

Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #19 : 21-12-2007 09:43 » 

unattended - короче говоря, я это использую для обозначения прог или ф-ций, в которых не требуется участие человека. Инсталляция, конфигурация и тп. unattended_setup, unattended_config etc.

Не Лёш, МСДН только говорит, что если ты вдруг ни с того ни с сего попытаешься создать окно ПОСЛЕ вызова PostQuitMessage (например у тебя бежит независимый тред или ты из этого диалога ещё один открыть задумаешь в этот момент), то оно будет сразу (те по получению им PostQuitMessage) уничтожено. Это было объяснение сашкиной проблемы. К данному примеру закрытия MessageBox это никак не относится.

Просто используется PostQuitMessage. А как иначе ты ещё закроешь чужое окно?

Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #20 : 21-12-2007 10:01 » 

Хорошо, эт понятно.

тогда ещё не понятно вот что - просто по PostQuitMessage процесс ещё не умер , а все его окна закрылись. Я правильно понимаю ? То есть сей приём годится только для выполнения программ , которых на экране не видать и которые изредка показывают на экране модальное окошко

-------------------
а про это всё равно не объяснил Улыбаюсь  Ждём-с. Отлично

Цитата
КиллТаймер приходит сразу после закрытия. Там задержи быть не может. Так же как и после него. Так что всё чисто.
а при чём тут киллтаймер то , сообщение WM_QUIT лежит в очереди , а тут , скажем , написано так
Код:
uiResult = MessageBox(hwndParent, ptszMessage, ptszTitle, flags);
KillTimer(NULL, idTimer);

..........тут - длительные вычисления........

 if (PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE))
 {

а во время длительных вычислений оконная процедура (в которой тоже ведь есть PeekMessage ) взяла и добралась до WM_QUIT
?

Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #21 : 21-12-2007 11:10 » 

тогда ещё не понятно вот что - просто по PostQuitMessage процесс ещё не умер , а все его окна закрылись. Я правильно понимаю ? То есть сей приём годится только для выполнения программ , которых на экране не видать и которые изредка показывают на экране модальное окошко

Не однозначно, что процесс не умер. И потом - сделай таймаут 30 мин и можешь полчаса любоваться на это окошко. В чём проблема? Ещё раз - задайся вопросом:

А как иначе ты ещё закроешь чужое окно?

... ведь тебе о нём практически ничего не известно.

Цитата
а про это всё равно не объяснил Улыбаюсь  Ждём-с. Отлично

Я не понял - где так написано? Какие должны быть длительные вычисления?

После KillTimer сразу вызывается PeekMessage для того чтобы проверить, закрыл пользователь окно или же сработал таймаут. Если в очереди стоит WM_QUIT. В противном случае WM_QUIT будет отработана при нажатии кнопки и покинет очередь. В этом случае надо вернуть оригинальный результат MessageBox. Конечно 0 не попадает ни в какое условие, тут можно самому выбрать, что возвращать.
Это только, как ты любишь говорить, - идея. Ведь MEssageBox может возвращать IDOK, IDCANCEL, IDIGNORE и тд
Как анализируется это значение - решать уже тебе. Я бы наверное возвращал IDCANCEL, если конечно он стоит в списке флажков. Короче для идеала ф-ю надо доработать.

Но я никак в толк не возьму, почему ты там ещё что-то хочешь длительно вычислять? Зачем?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #22 : 21-12-2007 11:32 » 

я вычислять ничего не хочу Улыбаюсь  Просто некоторые моменты описанного трюка непонятны, а значит я не смогу его применять , а так хочется разобраться ))

следующий вопрос:
Цитата
После KillTimer сразу вызывается PeekMessage для того чтобы проверить, закрыл пользователь окно или же сработал таймаут.

кто это сказал ? я этого вот так сразу не вижу.
Предположу, что чтобы это было верно, выход из процедуры PostQuitMessage должен произойти позднее , чем выход из модального диалога. То есть структура PostQuitMessage должна примерно такая:

Код:
PostQuitMessage ()
{
   кладём WM_QUIT в конец очереди сообщений

   ищем открытые окна потока

   while(нашли очередное окно?)
   {
      найденное_окно->EndDialog(); // или Destroy ?
   }

}
« Последнее редактирование: 21-12-2007 11:34 от Алексей1153++ » Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #23 : 24-12-2007 00:37 » 

кто это сказал ? я этого вот так сразу не вижу.

Ок всё по порядку.

Итак, имеем чужое окно - окно создаваемое вызовом ф-ции MessgaeBox. Ф-я возвращает результат - выбраную пользователем кнопку, он зависит от флажков переданных в ф-ю в качестве параметра.
Хэндл этого окна нам не известен, чтобы отправить ему сообщение WM_CLOSE. Ну можно конечно дать ему специфичное имя и потом искать окно с этим именем, но это не спортивно. Да и окно придётся запускать в треде, ведь оно модальное. Поэтому создаётся некая ф-я, которая параллельно с созданием модального окна запускает таймер, котрый должен отработать через время Тх.

Теперь возможны два варианта - 1. время Тх истекло и 2. пользователь нажал кнопку.

Если пользователь нажал кнопку, то ф-я возвращает ID этой кнопки в кач-ве результата - всё в порядке. И наша враппер-ф-я должна вернуть именно его. А если таймаут? Тоже надо вернуть некое значение. А какое? В примере возвращается просто 0. Его можно интртрепировать, например, как... таймаут. Тк нет ни одного значения результата с ID = 0. В этом случае вызывающий алгоритм должен обеспечить поддержку этого результата.

Вот и всё. Данный пример не некий хитрый трюк или единственно возможный способ использования PostQuitMessage. Это только пример использования PostQuitMessage для автоматического завершения модального окна хэндл которого нам не известен.

Конечно можно поиздеваться над этой ф-ей и добится её неработоспособности. Но зачем? ЭТо можно в принципе проделать с любым кодом.

И ещё одна неточность:
выход из процедуры PostQuitMessage должен произойти позднее , чем выход из модального диалога.

Причинноследственный принцип: в данном случае, при вызове PostQuitMessage в callback ф-ции таймера, закрытие модального диалога является следствием работы PostQuitMessage.

В "нормальной жизни" она не запускает никакие циклы, а просто ложит WM_QUIT в очередь сообщений текущего треда и тут же заканчивается. И уж конечно не вызывает никакие EndDialog или Destroy. Наоборот она обычно вызывается окном при получении им сообщения WM_DESTROY после чистки собственных (окна) ресурсов.

Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #24 : 24-12-2007 15:28 » 

aaaa. теперь , кажись понял, поправь , если нет :

Открыто же МОДАЛЬНОЕ окно , а значит - все сообщения , кроме WM_TIMER , WM_PAINT  (ну и каких то ещё может) , которые не предназначены ему, обрабатывает именно это окно.
А то есть , когда когда PostQuitMessage кладёт в очередь WM_QUIT , то сообщение обработается модальным окном и окно закрывается (и , наверное, пересылает сообщение и родительскому окну? )

Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #25 : 25-12-2007 12:01 » 

Да, в приниципе это моя вина. Я всё никак не мог понять, что же ты не понимаешь и должен был сделать акцент именно на модальности окна, которое перехватывает все сообщения.
Короче представь себе место, в котором ты вызваешь простой диалог CMyDialog dlg; dlg.DoModal();
Всё, в этом месте ты можешь только ждать. Те даже dlg.EndDialog() ты не можешь сделать.

Короче ты всё правильно понял. Ага

и , наверное, пересылает сообщение и родительскому окну?

Родительскому окну оно его не пересылает иначе бы оно тоже закрывалось, что поломало бы всю затею. Но WM_QUIT остаётся в очереди, тк не участвует в функции отрабатывающей по стандартному завершению модального диалога. Поэтому мы можем протестировать очередь и выяснить кто завершил диалог  - пользователь или таймаут.
Чтобы WM_QUIT не оставалось в очереди PeekMessage вызывается с флажком PM_REMOVE. Тк мы в этом месте абсолютно уверены, что сами его туда положили и стало быть всё прекрасно.
« Последнее редактирование: 25-12-2007 23:19 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #26 : 25-12-2007 15:07 » 

Цитата
Родительскому окну оно его не пересылает иначе бы оно тоже закрывалось, что поломало бы всю затею. Но WM_QUIT остаётся в очереди,
ну я это и имел в виду )
Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines