Плавное появление окна с помощью AnimateWindow
От: programme-soul  
Дата: 28.04.10 07:13
Оценка:
Здравствуйте!

У меня возникли проблемы с использованием функции AnimateWindow. Я прочитала все в MSDN и RSDN, что нашла про AnimateWindow. В результате ни один из способов непонятно как правильно использовать (т.к. неправильно работает для моего случая) и какой-то сумбур в голове...

Задача:
сделать плавное появление главного окна, используя AnimateWindow. После этого на главном окне должна отрисоваться картинка (средствами GDI+).

Проблема:
какой бы способ ни пробовала, изображение отрисовывается только после сворачивания/разворачивания окна, в то время, как если вместо AnimateWindow использовать ShowWindow, то такой проблемы нет.

Функция создания главного окна
bool 
CImageViewer::CreateMainWindow()
{
    m_hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, (const char*)"Image Viewer main window class", 
                            (const char*)"Image Viewer v.1.0.0", WS_OVERLAPPEDWINDOW, 
                            0, 0, 
                            1024, 768,
                            NULL, NULL, 
                            m_hInstance, this);

    if (m_hWnd == NULL)
        return false;

    if (!AnimateWindow(m_hWnd, 500, AW_BLEND))
        return false;

    if (!UpdateWindow(m_hWnd))
        return false;

    return true;
}


Оконная процедура
LRESULT CALLBACK 
CImageViewer::WndProc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    PAINTSTRUCT ps;
    HDC         hdc;

    switch (msg)
    {
    case WM_PRINTCLIENT:
    // в MSDN написано, что нужно обрабатывать это сообщение, но как?
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        if (hdc == NULL) break;
        OnPaint(hdc);
        EndPaint(hWnd, &ps);
        break;
    case WM_CLOSE:
        AnimateWindow(hWnd, 500, AW_BLEND|AW_HIDE);
        DestroyWindow(hWnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, msg, wparam, lparam);
    }

    return 0;
}


Функция прорисовки (использует GDI+)

void 
CImageViewer::OnPaint(HDC hdc)
{
    Graphics graphics(hdc);

    Image image(L"g:\\_project\\image viewer\\ipcamera.jpg");
    graphics.DrawImage(&image, 0, 0);
}
Just programming soul
...who wants to know more
Re: Плавное появление окна с помощью AnimateWindow
От: kvasya  
Дата: 28.04.10 07:29
Оценка:
Здравствуйте, programme-soul, Вы писали:

Небольшой ремарк:
PS>Оконная процедура
PS>
PS>...
PS>    case WM_PRINTCLIENT:
PS>    // в MSDN написано, что нужно обрабатывать это сообщение, но как?
PS>        break;
PS>    case WM_PAINT:
PS>...
PS>

..если нет необходимости — не обрабатывайте.

По вопросу, форсируйте прорисовку просто WM_PAINT, например, RedrawWindow.
Re[2]: Плавное появление окна с помощью AnimateWindow
От: programme-soul  
Дата: 28.04.10 08:52
Оценка:
Здравствуйте, kvasya, Вы писали:

K>По вопросу, форсируйте прорисовку просто WM_PAINT, например, RedrawWindow.


Спасибо за совет!
Я пробовала RedrawWindow, но видимо, не в такой комбинации. Сейчас все работает. Обработку WM_PRINTCLIENT убрала, т.к. действительно, вроде пока не нужно.

По идее UpdateWindow должна была посылать WM_PAINT... Видимо не посылала почему-то (неужели считала, что область для обновления была пустой?). А RedrawWindow сработала, т.к. это принудительное обновление и область для обновления была задана как клиентская область целиком.

bool 
CImageViewer::CreateMainWindow()
{
    m_hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, (const char*)"Image Viewer main window class", 
                            (const char*)"Image Viewer v.1.0.0", WS_OVERLAPPEDWINDOW, 
                            0, 0, 
                            1024, 768,
                            NULL, NULL, 
                            m_hInstance, this);

    if (m_hWnd == NULL)
    {
        MessageBox(NULL, "Window creation failed!", "Error", MB_ICONEXCLAMATION|MB_OK);
        return false;
    }

    if (!AnimateWindow(m_hWnd, 500, AW_BLEND))
        return false;

    if (!RedrawWindow(m_hWnd, NULL, NULL, RDW_INVALIDATE))
        return false;

    return true;
}
Just programming soul
...who wants to know more
Re[3]: Плавное появление окна с помощью AnimateWindow
От: Guard_h4s Россия  
Дата: 28.04.10 09:36
Оценка:
Здравствуйте, programme-soul, Вы писали:

PS>По идее UpdateWindow должна была посылать WM_PAINT... Видимо не посылала почему-то (неужели считала, что область для обновления была пустой?).

Перед вызовом желательно вызывать Invalidate, иначе область обновления действительно может быть пустой.
Re[4]: Плавное появление окна с помощью AnimateWindow
От: programme-soul  
Дата: 28.04.10 12:56
Оценка:
Здравствуйте, Guard_h4s, Вы писали:

PS>>По идее UpdateWindow должна была посылать WM_PAINT... Видимо не посылала почему-то (неужели считала, что область для обновления была пустой?).

G_>Перед вызовом желательно вызывать Invalidate, иначе область обновления действительно может быть пустой.

Действительно, связка InvalidateRect и UpdateWindow работает! Спасибо вам!
Just programming soul
...who wants to know more
Re[5]: PS
От: CEMb  
Дата: 29.04.10 05:22
Оценка:
WM_PRINT и WM_PRINTCLIENT используются так же для отрисовки при AnimateWindow. Обычно все стандартные контролы автоматически поддерживают обработку этих сообщений, но если есть что-то нестандартное, обработку лучше добавить. Так же, мне кажется, если бы в обработчике у ТС были бы обработаны эти сообщения, то надобности в жёстком апдейте онка не было бы, и код был бы более правильным.
Re[6]: PS
От: programme-soul  
Дата: 30.04.10 11:37
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>WM_PRINT и WM_PRINTCLIENT используются так же для отрисовки при AnimateWindow. Обычно все стандартные контролы автоматически поддерживают обработку этих сообщений, но если есть что-то нестандартное, обработку лучше добавить. Так же, мне кажется, если бы в обработчике у ТС были бы обработаны эти сообщения, то надобности в жёстком апдейте онка не было бы, и код был бы более правильным.


Дело в том, что я не знаю, как обрабатывать эти сообщения. И как их правильно обрабатывать тоже не знаю. Я пробовала найти примеры с обработкой этих сообщений, но тоже неудачно.
Может быть вы подскажете, как правильнее делать, чтобы все окно целиком не перерисовывать?
Just programming soul
...who wants to know more
Re[7]: PS
От: Guard_h4s Россия  
Дата: 30.04.10 12:52
Оценка:
Здравствуйте, programme-soul, Вы писали:

PS>Дело в том, что я не знаю, как обрабатывать эти сообщения. И как их правильно обрабатывать тоже не знаю. Я пробовала найти примеры с обработкой этих сообщений, но тоже неудачно.


Эти сообщения посылаются окну(опять же, не системой) для того чтобы окно отрисовало себя в предоставленном контексте. Если вы не пользуетесь, например, отрисовкой вашего контрола в картинку, то смысла реализовывать их нет. Они никак не повлияют на то, каким образом окно перерисовывается при обычном WM_PAINT.

To force a window to draw into a specific device context, use the WM_PRINT or WM_PRINTCLIENT message. Note that this requires the target window to support the WM_PRINTCLIENT message. Most common controls support the WM_PRINTCLIENT message.


PS>Может быть вы подскажете, как правильнее делать, чтобы все окно целиком не перерисовывать?

Инвалидировать не все окно, а только отдельный регион(например с помощью того же InvalidateRect). Но отрисовка ложится на ваши плечи в той же самой WM_PAINT
Re[8]: Небольшое уточнение
От: Guard_h4s Россия  
Дата: 30.04.10 12:58
Оценка:
В случае с AnimateWindow действительно есть условие чтобы окно имело обработку WM_PRINT или WM_PRINCLIENT

The AnimateWindow function requires that the window being animated implement the WM_PRINTCLIENT message.

The window procedures for the window and its child windows should handle any WM_PRINT or WM_PRINTCLIENT messages.

 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.