Sleep() не работает в winapi32?

Я все еще новичок в программировании графического интерфейса с помощью c++ winapi32, и я обнаружил кое-что странное. Вот часть моего кода:

        InvalidateRect(hwnd,&rect, true);
        //Sleep(delay);
        MessageBox(hwnd, "Blahblah!", "blahblah",MB_OK | MB_ICONINFORMATION);
        InvalidateRect(hwnd,&rect, true);
        //Sleep(delay);
        MessageBox(hwnd, "Blahblah!", "blahblah",MB_OK | MB_ICONINFORMATION);

Я использую Invalidaterect для перерисовки части своих окон, и я пытаюсь перекрашивать окна каждую секунду или около того, чтобы изменения были очевидны для глаз пользователя. Странно то, что Sleep, кажется, не влияет на мои окна, если за ним не следует команда MessageBox, хотя на самом деле я не хочу иметь какую-либо команду MessageBox для каждой перерисовки, потому что это слишком мешает.

Пробовал 1000,2000, даже 10000 за задержку. Windoes действительно зависал во сне, но кажущаяся перерисовка выполняется только 1 раз в последней команде Sleep...

Этот код является частью, скажем, void A(). А void A() вызывается void B().

       //Message loop
       if(turn == 0)
       {
       B();
       }           

Есть ли альтернатива, которую я могу сделать, чтобы решить эту проблему?

Ах да, кстати, я использую MS Visual C++ 2008 Express.

Заранее спасибо за любую помощь в этом вопросе :)


person zia    schedule 03.09.2011    source источник
comment
Какое значение delay вы пробовали?   -  person wallyk    schedule 03.09.2011
comment
1000, 2000, даже 10000 не имеют никакого эффекта, если нет команды MessageBox... Что я имею в виду под «без эффекта»: предположим, что есть 3 команды перерисовки, за которыми следуют 3 команды сна для каждой из них, окна просто зависание для 3-кратной задержки, а перерисовка выполнялась только 1 раз в последний раз .... но если я также добавлю команду MessageBox для каждой команды Sleep, очевидно, что окна действительно перерисовывались 3 раза ... любая помощь?   -  person zia    schedule 03.09.2011
comment
Это действительно фундаментально для программирования графического интерфейса Windows. Отрисовки не возникают, пока вы не прокачаете цикл сообщений. Отложите клавиатуру и почитайте книгу.   -  person Hans Passant    schedule 03.09.2011
comment
Куда вы вставили этот код? Если он находится в обработчике, который косвенно выполняется перерисовкой окна, он может войти в цикл, в котором новые события перерисовки сохраняются каждый раз, когда начинается перерисовка.   -  person Diego Sevilla    schedule 03.09.2011
comment
@Hans Passant: я использовал цикл сообщений. Перерисовка действительно произошла, но это делается только 1 раз, по-видимому, в последней команде сна, хотя я вызывал ее 2 раза.   -  person zia    schedule 03.09.2011
comment
@Diego Sevilla: в цикле сообщений я вызвал void B(), а void B() вызвал void A(), и этот код является частью void A().   -  person zia    schedule 03.09.2011
comment
Цикл сообщений не запускается, когда вы вызываете Sleep! Сон — правильное решение исчезающе малого числа проблем. Это не одна из тех проблем. Прислушайтесь к мудрому совету Ганса. Возьмите книгу Петцольда и прочитайте.   -  person David Heffernan    schedule 03.09.2011


Ответы (1)


Важно то, что InvalidateRect ничего не рисует. Он только планирует отрисовку содержимого окна (помещает сообщение WM_PAINT в очередь сообщений). Фактическое рисование не происходит до тех пор, пока вы не вернетесь к циклу обработки сообщений, и окно фактически не обработает сообщение о рисовании. Итак, после последнего Sleep/MessageBox вы, наконец, возвращаетесь из своей функции, чтобы снова попасть в цикл сообщений, и в цикле сообщений вы, наконец, получаете сообщение WM_PAINT, которое представляет фактическое событие рисования, и обрабатываете это сообщение, чтобы перерисовать содержимое окна.

person Christian Rau    schedule 03.09.2011
comment
Понятно, но когда я ставлю Sleep в первой строке WM_PAINT case, почему программа ведет себя так же? Я имею в виду, что я могу видеть только последнюю перекраску, хотя она вызывалась бесчисленное количество раз. Заранее спасибо :) - person zia; 03.09.2011
comment
@zia InvalidateRect только планирует закрашивание окна (сообщает Win32, что содержимое этого окна недействительно). На самом деле событие рисования имеет очень низкий приоритет, чтобы не спамить события перерисовки, когда окно должно делать более важные вещи. А Win32 достаточно умен, чтобы поместить в очередь сообщений только одно сообщение с краской. Поэтому, когда вы вызываете InvalidateRect и уже имеете WM_PAINT в очереди сообщений, Win32 объединяет этот запрос с предыдущим (объединяет прямоугольники в, возможно, больший прямоугольник, содержащий оба), поэтому у вас всегда будет только одно событие рисования, пока вы его не обработаете. - person Christian Rau; 03.09.2011