С++ Win32, самый простой способ показать окно с растровым изображением

Это только для целей «отладки», поэтому я не хочу тратить на это много времени, да и это не очень важно. Программа экспортирует данные в формате png, jpg, svg и т. д., так что это не имеет большого значения, хотя было бы неплохо увидеть изображение во время его создания. Также программа будет использоваться на сервере Linux; но я ограничу эту «функцию» версией Win.

Я также не хочу использовать библиотеку, за исключением случаев, когда она очень и очень легкая (некоторое время я использовал CImg, но меня не очень устраивала его скорость, поэтому в итоге я сам написал важные функции и просто использовал libjpeg и libpng напрямую).

У меня есть изображение в формате ARGB (32bpp), хотя преобразование формата не будет проблемой. Я хотел бы использовать Win32, создавая окно из функции глубоко внутри кода (без известного hInstance и т. д.) и записывая растровое изображение. Надеюсь, быстро и легко.

Но я недостаточно знаю win32api. Я видел, что единственный вариант рисования (GDI) - это объект HBITMAP... На какой-нибудь фрагмент кода или пример, на который я могу положиться? Любое соображение, которое я мог бы не упускать из виду? Или, может быть, учитывая мои временные ограничения, я должен просто забыть об этом?

Спасибо!


person huff    schedule 16.02.2010    source источник


Ответы (2)


Самой большой частью работы здесь является регистрация оконного класса и написание минимальной оконной процедуры. Но если это код только для отладки, вы можете пропустить эту часть. (Я вернусь к этому позже).

Если у вас есть HBITMAP, вы должны использовать BitBlt или StretchBlt, чтобы нарисовать его, но если у вас еще нет образа в виде HBITMAP, то StretchDIBits, вероятно, является лучшим выбором, поскольку вы можете использовать его, если у вас есть только указатель на растровые данные. Вы должны передать ему прямоугольник источника и назначения, BITMAPINFOHEADER и указатель на необработанные данные растрового изображения. Что-то вроде этого

SIZE sBmp = { 100, 200 };
LPBITMAPINFOHEADER pbi;    // the bitmap header from the file, etc.
LPVOID             pvBits; // the raw bitmap bits

StretchDIBits (hdc, 0, 0, sBmp.cx, sBmp.cy, 
               0, 0, sBmp.cx, sBmp.cy,
               pvBits, pbi, 
               DIB_RGB_COLORS, 
               SRCCOPY);

Итак, следующая часть — как заставить HDC рисовать? Что касается кода отладки, я часто рисую прямо на экране. HDC hdc = GetDC(NULL) получит DC, который может рисовать на экране, но есть проблемы с безопасностью, и он не работает так же с Aero в Windows Vista, поэтому другой способ — рисовать на окне. Если у вас есть окно, которое вы можете просто нарисовать, то HDC hdc = GetDC(hwnd) будет работать.

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

Для более долгосрочного решения вы можете создать диалоговое окно и поместить вызов рисования растрового изображения в обработчик сообщений WM_PAINT или WM_ERASEBKGND для диалогового окна. Но я не рекомендую вам показывать диалоговое окно из глубокого внутреннего кода, который не должен выполнять пользовательский интерфейс. Отображение окна, особенно диалогового окна, будет мешать нормальному потоку сообщений в вашем приложении. Если вы хотите использовать диалоговое окно для этого средства просмотра растровых изображений, то вы хотите, чтобы это диалоговое окно было чем-то, что показывает пользователь, и на котором вы просто рисуете, если оно есть.

Если у вас нет доступа к HINSTANCE, все равно можно отобразить диалоговое окно, это просто дополнительная работа. Это как бы другой вопрос.

person John Knoeller    schedule 16.02.2010
comment
Спасибо за ответ. Ну, действительно, в Windows 7 aero он просто появляется и моментально исчезает, если я рисую на экран. Отключение uxsms заставляет его работать лучше, но я предполагаю, что предпочту нарисовать его вместо диалогового окна, поэтому мне нужен ответ на этот другой вопрос: D. - person huff; 16.02.2010
comment
@huff: это должен быть новый вопрос. что-то вроде того, как создать простое диалоговое окно без ресурса. - person John Knoeller; 16.02.2010
comment
Я сделаю это. Я догадываюсь, как выйти из положения с CreateIndirect, но все же было бы неплохо задать вопрос здесь. - person huff; 16.02.2010

Все, что вам нужно, — это дескриптор контекста устройства (HDC). Чтобы отобразить на нем ваши данные:

  1. CreateDibSection для создания DIBSection.
  2. Скопируйте свои данные в блок памяти, возвращенный CreateDibSection.
  3. создайте контроллер домена, совместимый с целевым контроллером домена.
  4. Выберите DIBSection в только что созданный DC.
  5. BitBlt (или StretchBlt) с вашего контроллера домена на целевой контроллер домена.
person Jerry Coffin    schedule 16.02.2010