Код рисования не работает должным образом в моем обработчике сообщений WM_COMMAND
У меня есть следующий код, который должен рисовать picture2.bmp
после того, как пользователь вызывает элемент ID_FILE_32771
,
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case ID_FILE_32771:
hdc = BeginPaint(hWnd, &ps);
LoadAndBlitBitmap2(__T("D://picture2.bmp"), hdc);
EndPaint(hWnd, &ps);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
LoadAndBlitBitmap(__T("D://picture.bmp"), hdc);
EndPaint(hWnd, &ps);
break;
Проблема в том, что ничего не красится. hdc
не правильно инициализирован. Что я делаю не так, и как мне это исправить?
3 ответа
BeginPaint
а также EndPaint
функции должны вызываться только при обработке WM_PAINT
сообщение. То, как вы это сделали, в обработке WM_COMMAND
, неправильно:
case ID_FILE_32771:
hdc = BeginPaint(hWnd, &ps); // WRONG, WRONG!
LoadAndBlitBitmap2(__T("D://picture2.bmp"), hdc);
EndPaint(hWnd, &ps); // ALSO WRONG!
break;
Весь код рисования должен быть внутри WM_PAINT
обработчик. Вы собираетесь получить WM_PAINT
сообщения всякий раз, когда ваше окно должно быть нарисовано, а иногда это вне вашего контроля. Так что должна быть логика в WM_PAINT
обработчик, который знает, что рисовать на основе текущего состояния приложения.
Другими словами, вам нужно установить флаг в ответ на клики по ID_FILE_32771
чтобы ваша программа знала, что она должна вызывать LoadAndBlitBitmap2
когда он перекрашивается, а не LoadAndBlitBitmap
(почему они не являются одной и той же функцией, которой вы просто передаете разные имена файлов?).
Вне WM_PAINT
обработчик, вы вызываете событие рисования, делая недействительным содержимое вашего окна. Самый простой и наиболее подходящий способ сделать это - вызвать InvalidateRect
функция Например:
case ID_FILE_32771:
// Set a flag indicating that picture2 should be painted
// (or some other equivalent mechanism)
paintPicture2 = true;
// Signal that the window should be repainted.
InvalidateRect(hWnd, NULL, TRUE);
break;
По телефону UpdateWindow
после InvalidateRect
Вы будете вынуждены немедленно перекрасить, но это редко необходимо. Кроме того, вы можете пропустить танец с двумя функциями и вызвать более мощный RedrawWindow
функционировать напрямую.
В любом случае, вы будете ссылаться на WM_PAINT
обработчик сообщений, и он запросит текущее состояние приложения и нарисует соответствующую картинку.
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// Paint the appropriate thing, depending on the app's current state
if (paintPicture2)
LoadAndBlitBitmap(__T("D://picture.bmp"), hdc);
else
LoadAndBlitBitmap(__T("D://picture.bmp"), hdc);
EndPaint(hWnd, &ps);
break;
BeginPaint используется только в WM_PAINT. Вы можете использовать GetDC, если вам нужен HDC вне WM_PAINT. Но лучшее решение обычно заключается в том, чтобы просто вызвать InvalidateRect вне WM_PAINT. Это приведет к появлению нового WM_PAINT в ближайшее время, и вы сделаете все рисование в WM_PAINT.
Из MSDN:
Приложение не должно звонить
BeginPaint
кроме как в ответ на сообщение WM_PAINT
То есть ваше исправление состоит в том, чтобы использовать API предполагаемым образом, что обычно делает представление недействительным через InvalidateRect
а затем рисует WM_PAINT
когда вас попросят