Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 2 августа!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

ПРОГРАММИРОВАНИЕ НА C и С++



Давно заметил, что всё-таки языки С/C++ это не самый лучший вариант программирования под Windows. Сейчас появилась масса более современных и удобных языков, например тот же Python - кроссплатформенный язык, очень легок в изучение. Я его изучил буквально за несколько дней по этому курсу - ссылка. Автор постарался, там видеоуроки на удивление легкие и понятные.

Таймер закрывает Message box.

Автор: Markus Loibl

  • Скачать демонстрационный проект - 17 Kb
  • Скачать исходник - 3 Kb

    Цель этого примера

    Иногда возникает необходимость показать пользователю стандартное диалоговое
    окошко типа Yes/No , и, если пользователь не даёт ответа, то по истечении определённого
    интервала времени закрыть этот диалог.

    Основы

    Перед вызовом MessageBox, необходимо проинсталировать таймер. Когда окно закрывается,
    то в окно MessageBox поступает сообщение WM_COMMAND .

    Timer-Callback

    Я решил собрать всю информацию передающуюся в MessageBox (Заголовок, Текст, Флаги ...) в классе.
    Но есть одна проблемма: с функцией  SetTimer()может быть инсталлирована только статическая
    timer-callback-процедура: которая не может получить доступа к членам класса (так как статическая).

    Для решения этой проблеммы я вставил мап(Map) для хранения сообщения класса для timer-id:

    Заголовок:

    class CDlgTimedMessageBox
     
     {
     
     public:
     
         // ...
     
         UINT         ShowMessageBox(BOOL *pbStoppedByUser=NULL);
     
         // ...
     
         static void  GlobalTimerProc(HWND hwnd, UINT uiMsg, UINT idEvent, DWORD dwTime);
     
         void         LocalTimerProc(void);
     
         // ...
     
         static       CMapPtrToPtr        m_mapTimerIdToClassMe;
     
     
     
     protected:
     
         UINT         m_idTimer;
     
     };
     
     

    Исходник:

    UINT CDlgTimedMessageBox::ShowMessageBox(BOOL *pbStoppedByUser)
     
     {
     
         // ...
     
         m_idTimer = ::SetTimer(NULL, 0, 1000, (TIMERPROC) CDlgTimedMessageBox::GlobalTimerProc);
     
         CDlgTimedMessageBox::m_mapTimerIdToClassMe.SetAt((void*)m_idTimer, this);
     
         // ...
     
         ::MessageBox(...)
     
         // ...
     
     }
     
     
     
     void CDlgTimedMessageBox::GlobalTimerProc(HWND hwnd, UINT uiMsg, UINT idEvent, DWORD dwTime)
     
     {
     
         CDlgTimedMessageBox    *pMe = NULL;
     
     
     
         // Находим timer-id сообщения для класса
     
         CDlgTimedMessageBox::m_mapTimerIdToClassMe.Lookup((void*)idEvent, (void *&) pMe);
     
     
     
         if( pMe!=NULL )
     
             pMe->LocalTimerProc();
     
     }
     
     
     
     void CDlgTimedMessageBox::LocalTimerProc(void)
     
     {
     
         // находим Message-Box-окно
     
     
     
         // Calculate time since start
     
     
     
         if( too long running )
     
         {
     
             // Закрываем MessageBox
     
         }
     
         else
     
         {
     
             // изменяем текст MessageBox
     
         }
     
     }

    Находим MessageBox

    hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
     
     while( (hWnd!=NULL) && (m_hMsgBox==NULL) )
     
     {
     
         pWnd = CWnd::FromHandle(hWnd);
     
         pWnd->GetWindowText(title);
     
     
     
         if( AfxIsDescendant(m_hParent, hWnd) && ::IsWindowVisible(hWnd) &&
     
             (m_Title.CompareNoCase(title)==0) )
     
         {
     
             m_hMsgBox = hWnd;
     
             break;
     
         }
     
     
     
         hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
     
     }

     

    Добавляем всё это в одну функцию

    UINT TimedMessageBox(UINT flags, LPCTSTR ptszMessage, LPCTSTR ptszTitle,
     
                               DWORD dwTimeout, UINT dDefaultReturn,
     
                               LPCTSTR ptszMessageTimer, HWND hwndParent, BOOL *pbStoppedByUser)
     
     {
     
         CDlgTimedMessageBox    msgBox(flags, ptszMessage, ptszTitle, dwTimeout,
     
                                       dDefaultReturn, ptszMessageTimer, hwndParent);
     
     
     
         return msgBox.ShowMessageBox(pbStoppedByUser);
     
     }

     

    Потокозащищённость

    Доступ к карте включён через CCriticalSection.

    Пример

    BOOL	stoppedByUser;
     
     UINT	erg;
     
     
     
     erg  = ::TimedMessageBox(MB_YESNO|MB_ICONHAND,
     
     		"Please press a button",
     
     		"box-title",
     
     		5000, IDYES,
     
     		"\nin the next %lu sec !",
     
     		NULL, &stoppedByUser);

     

 
 




<< ВЕРНУТЬСЯ В ПОДРАЗДЕЛ

<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ




Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU Проект ReactOS