Как перерисовать содержимое окна до того как оно переместилось?
От: C0x  
Дата: 03.02.17 17:41
Оценка:
Перемешаю мышкой child окно над другим parent окном.
Хочу добиться эффекта прозрачности child окна относительно parent окна.
Дебагом обнаружил, что OnPaint child окна вызывается после того как окно появляется в новом месте.
То есть получается, сначала окно перемещается в новое место, там рисуется со старым содержимым, а потом перерисовывается его содержимое.
Вопрос: Как перерисовать содержимое до того как окно возникнет в новом месте?


Немного предыстории:

Есть окно в котором нарисована большая картинка. Задача на этом окне вводить текст в любой позиции. Этот текст потом добавляется к картинке и сохраняется.
Решил сделать с помощью дополнительного окна с прозрачным CEdit для ввода текста (чтобы не реализовывать все штуки по работе с текстом самостоятельно).

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

Для перерисовки дочернего окна-рамки я делаю следующее:


void CTextBoxDlg::OnWindowPosChanging(WINDOWPOS* lpwndpos)
{

    CDialog::OnWindowPosChanging(lpwndpos);

    Invalidate();
}


А Вот OnPaint который берет содержимое parent окна и рисует нужную область из него.

void CTextBoxDlg::OnPaint()
{

    CPaintDC dc(this); // device context for painting
                       //CDC      MemDC;
                       //BITMAP   bit;

    CDC* pParentDC = m_pParentWnd->GetDC();

    CRect rect;
    GetWindowRect(&rect);
    dc.BitBlt(0, 0, rect.Width(), rect.Height(), pParentDC, rect.left, rect.top, SRCCOPY);


    dsc.Draw(dc);

    CDialog::OnPaint();
}
Re: Как перерисовать содержимое окна до того как оно переместилось?
От: VladFein США www.FeinSoftware.com
Дата: 03.02.17 22:22
Оценка:
Здравствуйте, C0x, Вы писали:

C0x>
C0x>void CTextBoxDlg::OnWindowPosChanging(WINDOWPOS* lpwndpos)
C0x>{
C0x>    CDialog::OnWindowPosChanging(lpwndpos);
C0x>    Invalidate();
C0x>}
C0x>


1. WM_WINDOWPOSCHANGING посылается ДО ТОГО как позиция окна изменилась, что бы Вы могли поправить кекие-нибудь параментры или вообще предотвратить перемещение. Ловите WM_WINDOWPOSCHANGED.
2. Ваш Invalidate(); просто помечает окно как нуждающееся в перерисовке; добавьте после этого UpdateWindow();
Re[2]: Как перерисовать содержимое окна до того как оно переместилось?
От: C0x  
Дата: 04.02.17 21:37
Оценка:
Здравствуйте, VladFein, Вы писали:

VF>Здравствуйте, C0x, Вы писали:


C0x>>
C0x>>void CTextBoxDlg::OnWindowPosChanging(WINDOWPOS* lpwndpos)
C0x>>{
C0x>>    CDialog::OnWindowPosChanging(lpwndpos);
C0x>>    Invalidate();
C0x>>}
C0x>>


VF>1. WM_WINDOWPOSCHANGING посылается ДО ТОГО как позиция окна изменилась, что бы Вы могли поправить кекие-нибудь параментры или вообще предотвратить перемещение. Ловите WM_WINDOWPOSCHANGED.

VF>2. Ваш Invalidate(); просто помечает окно как нуждающееся в перерисовке; добавьте после этого UpdateWindow();

Всеравно остается мелькание. Проблема в том, что если делать так:

void CTextBoxDlg::OnWindowPosChanged(WINDOWPOS* lpwndpos)
{
    CDialog::OnWindowPosChanged(lpwndpos);

    Invalidate();
    UpdateWindow();
}


То окно сначало рисуется в новой позиции со старым контентом, после чего, дергается OnPaint и рисует новый контент. Но OnWindowPosChanging то же не вариант, т.к. он срабатывает еще до того как
окно исчезнет в старой позиции. Поэтому новый контент рисуется в старой позиции, а потом только оно перемещается в новую.
Нужно как-то обновить контент еще до того как окно появится в новой позиции, но уже исчезнет в старой.
Re: Как перерисовать содержимое окна до того как оно переместилось?
От: kov_serg Россия  
Дата: 05.02.17 09:47
Оценка:
Здравствуйте, C0x, Вы писали:

C0x>Перемешаю мышкой child окно над другим parent окном.

C0x>Хочу добиться эффекта прозрачности child окна относительно parent окна.
https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms633540(v=vs.85).aspx

C0x>Дебагом обнаружил, что OnPaint child окна вызывается после того как окно появляется в новом месте.

Это еще фигня пока тащишь тебе события могут не приходить даже PeekMessage может не возвращать управление секундами.

C0x>То есть получается, сначала окно перемещается в новое место, там рисуется со старым содержимым, а потом перерисовывается его содержимое.

C0x>Вопрос: Как перерисовать содержимое до того как окно возникнет в новом месте?
Самый простой и варворский метод иметь еще одно окно, в своём потоке, которое таскать нельзя, но на нём правильная картинка и синхронизировать его положение с тем то таскают, примерно как в directshow. И в нужный момент прятать.
Re[3]: Как перерисовать содержимое окна до того как оно переместилось?
От: VladFein США www.FeinSoftware.com
Дата: 06.02.17 20:33
Оценка:
Здравствуйте, C0x, Вы писали:

C0x>Нужно как-то обновить контент еще до того как окно появится в новой позиции, но уже исчезнет в старой.


Два предложения:

1. На WM_WINDOWPOSCHANGING уменьшаете высоту окна до высоты Caption Bar; на WM_WINDOWPOSCHANGED (пере-)запускаете короткий таймер; на WM_TIMER прорисовываете нужное окно и восстанавливаете его размер.

2. Используете Layered Windows
Re[4]: Как перерисовать содержимое окна до того как оно переместилось?
От: C0x  
Дата: 07.02.17 10:07
Оценка:
Здравствуйте, VladFein, Вы писали:

VF>Здравствуйте, C0x, Вы писали:


C0x>>Нужно как-то обновить контент еще до того как окно появится в новой позиции, но уже исчезнет в старой.


VF>Два предложения:


VF>1. На WM_WINDOWPOSCHANGING уменьшаете высоту окна до высоты Caption Bar; на WM_WINDOWPOSCHANGED (пере-)запускаете короткий таймер; на WM_TIMER прорисовываете нужное окно и восстанавливаете его размер.


Скорее всего это приведет к тому, что будет постоянно блинкать рамка окна, либо во время перетаскивания её не будет видно. Но стоит попробовать. Спасибо.

VF>2. Используете Layered Windows


Не могу придумать как поверх layered окна рисовать прозрачный Edit так, чтобы во всей этой совокупной конструкции (Dialog + Transparent Edit) только текст, рисуемый
Edit контролом был не прозрачным. Наверняка это как-то можно сделать, но мои попытки не привели к успеху.
Re[3]: Как перерисовать содержимое окна до того как оно переместилось?
От: MasterZiv СССР  
Дата: 13.02.17 13:23
Оценка:
Здравствуйте, C0x, Вы писали:

C0x> Invalidate();

C0x> UpdateWindow();
C0x>}
C0x>[/code]

C0x>То окно сначало рисуется в новой позиции со старым контентом, после чего, дергается OnPaint и рисует новый контент. Но OnWindowPosChanging то же не вариант, т.к. он срабатывает еще до того как

C0x>окно исчезнет в старой позиции. Поэтому новый контент рисуется в старой позиции, а потом только оно перемещается в новую.
C0x>Нужно как-то обновить контент еще до того как окно появится в новой позиции, но уже исчезнет в старой.

Наоборот, UpdateWindow(); не нужно вызывать явно. А то получается ты делаешь это 2 раза.
И желательно инвалидировать не всю client area окна, а только то, что нужно обновить (RECT).

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