Я прочитал, что я никогда не должен отправлять WM_PAINT
вручную и должен позвонить InvalidateRect
но не нашел ничего, почему бы и нет. Так почему не?
Обновить работает с InvalidateRect
но не с SendMessage(WM_PAINT)
LRESULT CALLBACK window_proc(HWND wnd, UINT msg, WPARAM w_param, LPARAM l_param)
{
switch (msg)
{
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc = BeginPaint(wnd, &ps);
Polyline(..);
EndPaint(wnd, &ps);
return 0;
case WM_USER:
// SendMessage(wnd, WM_PAINT, NULL, NULL);
// InvalidateRect(wnd, NULL, FALSE);
return 0;
}
}
Официальные документы для WM_PAINT
заявите, что вы не должны в самом первом предложении раздела замечаний. Серьезно, этого должно быть достаточно, чтобы не делать этого.
Что касается технических причин, почему, я думаю, это один из них, взятый из BeginPaint
раздел замечаний:
Регион обновления задается InvalidateRect или же InvalidateRgn функции и системой после изменения размера, перемещения, создания, прокрутки или любой другой операции, которая влияет на клиентскую область.
таким образом BeginPaint
может не работать правильно, если вы отправите WM_PAINT
вручную.
Там может быть больше причин / сюрпризов.
Если вы хотите запустить немедленную перерисовку, правильный подход заключается в следующем:
использование InvalidateRect()
с последующим UpdateWindow()
,
использование RedrawWindow()
,
Те вызовут новый WM_PAINT
сообщение будет сгенерировано.
У вас нет никакой информации о окнах других программ, раскрывающих ваши окна. Только операционная система имеет эту информацию. Таким образом, вы не знаете все время, когда или где нужно перекрасить окно. WM_PAINT и BeginPaint предоставляют эту недостающую информацию.
Так как WM_PAINT
это не настоящее сообщение.
Думайте об этом, как будто каждое окно имеет структуру, хранящую «недопустимую область», то есть «эта часть окна на экране больше не актуальна и требует перекраски».
Эта недопустимая область изменяется самим оконным менеджером (размер окна изменяется, открывается и т. Д.) Или путем вызова InvalidateRect
, ValidateRect
, EndPaint
и тому подобное.
Теперь вот грубый макет того, как GetMessage
обрабатывает это:
... GetMessage(MSG* msg, ...)
{
while(true) {
if(ThereIsAnyMessageInTheMessageQueue()) {
*msg = GetFirstMessageOfTheMessageQueue();
return ...;
} else if(TheInvalidRegionIsNotEmpty()) {
*msg = CreateWMPaintMessage();
return ...;
} else {
WaitUntilSomethingHappend();
}
}
}
ТЛ; др: WM_PAINT
предназначен для получения, а не отправки.