开发者

C++ Win32, easiest way to show a window with a bitmap

开发者 https://www.devze.com 2022-12-20 11:02 出处:网络
It\'s only for \'debugging\' purposes, so I don\'t want to spend a lot of time with this, nor it is very important. The program exports the data as a png, jpg, svg, etc... -so it\'s not a big deal, th

It's only for 'debugging' purposes, so I don't want to spend a lot of time with this, nor it is very important. The program exports the data as a png, jpg, svg, etc... -so it's not a big deal, though it could be good to see the image while it is being generated. Also, the program is going to be used in a Linux server; but I'll limit this 'feature' to the Win version.

I also don't want to use a library, except if it is very, very lightwei开发者_开发技巧ght (I used CImg for a while, but I wasn't very happy with its speed, so I ended up writing the important functions myself and just using libjpeg and libpng directly).

I have the image in an ARGB format (32bpp), though converting the format won't be a problem at all. I would like to use Win32, creating a window from a function deep inside the code (no known hInstance, etc), and writing the bitmap. Fast and easy, hopefully.

But I don't know the win32api enough. I've seen that the only option to draw (GDI) is trough a HBITMAP object... Any code snippet or example I can rely on? Any consideration I might not overlook? Or maybe -considering my time constrains- should I just forget it?

Thanks!


The biggest piece of work here is actually registering the window class and writing a minimal window procedure. But if this is debug only code, you can actually skip that part. (I'll come back to that later).

If you have an HBITMAP, then you would use BitBlt or StretchBlt to draw it, but if you don't already have the image as an HBITMAP, then StretchDIBits is probably a better choice since you can use it if you only have a pointer to the bitmap data. You have to pass it a source and destination rectangle, a BITMAPINFOHEADER and a pointer to the raw bitmap data. Something like this

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);

So the next part is how do I get a HDC to draw in? Well for Debug code, I often draw directly to the screen. HDC hdc = GetDC(NULL) will get a DC that can draw to the screen, but there are security issues and it doesnt' work the same with Aero in Windows Vista, so the other way is to draw onto a window. If you have a window that you can just draw over, then HDC hdc = GetDC(hwnd) will work.

The advantage of doing it this way is that you don't have to create and show a window, so it's less disruptive of code flow, It's helpful for debugging a specific problem, but not the sort of thing you can leave turned on all of the time.

For a longer term solution, You could create a dialog box and put your bitmap drawing call in the WM_PAINT or WM_ERASEBKGND message handler for the dialog box. But I don't recommend that you show a dialog box from deep inside code that isn't supposed to be doing UI. Showing a window, especially a dialog window will interfere with normal message flow in your application. If you want to use a dialog box for this bitmap viewer, then you want that dialog window to be something that the User shows, and that you just draw onto if it's there.

If you don't have access to an HINSTANCE, it's still possible to show a dialog box, it's just more work. That's sort of a different question.


About all you need is a handle to a device context (HDC). To display your data on it:

  1. CreateDibSection to create a DIBSection.
  2. Copy your data to the memory block returned by CreateDibSection.
  3. create a DC compatible with the target DC.
  4. Select the DIBSection into your newly created DC.
  5. BitBlt (or StretchBlt) from your DC to the target DC.
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号