0

Question is rather simple but I couldn't find nice & clean solution to my problem on the Internet. What I got are some drawings on my window. Now, I can save those using BitBlt function from window device context to image device context, and also from there to bitmap handle:

HDC bitmapDC = CreateCompatibleDC(dc);
HBITMAP bitmap = CreateCompatibleBitmap(bitmapDC, 200, 200);
SelectObject(bitmapDC,bitmap);
BitBlt(bitmapDC, 0, 0, 200, 200, dc, 200, 200, SRCCOPY);

But from there I'm lost. I had a look at GDI+ Bitmap class which got save function, and I found how to implement code for retrieving CLSID of picture encoding. However I don't know if I use loading to that class correctly. There's overloaded constructor for HBITMAP, but it's also asking for some palette, which I set to NULL:

Bitmap image(bitmap,NULL);

I tried to save png file but it resulted in black quare without those drawings I was expecting. If you'd like, full code for my painting procedure:

void GetCLSID(const WCHAR* format, CLSID* pClsid){
    UINT  num = 0;          // number of image encoders
    UINT  size = 0;         // size of the image encoder array in bytes

    ImageCodecInfo* pImageCodecInfo = NULL;

    GetImageEncodersSize(&num, &size);

    pImageCodecInfo = (ImageCodecInfo*)(malloc(size));

    GetImageEncoders(num, size, pImageCodecInfo);

    for(UINT j = 0; j < num; ++j)
    {
      if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
      {
         *pClsid = pImageCodecInfo[j].Clsid;
         free(pImageCodecInfo);
      }    
    }
}

void OnPaint(HDC dc){
    RECT rect; rect.bottom = 0; rect.top = 20; rect.left = 0; rect.right = 100;
    HBRUSH blueBrush = CreateSolidBrush(RGB(0,0,200));
    FillRect(dc, &rect, blueBrush);

    Graphics graphics(dc);
    Pen      pen(Color(255, 0, 0, 255));
    graphics.DrawLine(&pen, 0, 0, 200, 100);

    SolidBrush greenBrush(Color(0,200,0));
    Rect ellipseRect(20,20,20,20);
    graphics.FillEllipse(&greenBrush, ellipseRect);

    SolidBrush redBrush(Color(200,0,0));
    Rect boxRectangle(0,40,20,100);
    graphics.FillRectangle(&redBrush, boxRectangle);

    pen.SetColor(Color(200,0,200));
    pen.SetWidth(20);
    graphics.DrawBezier(&pen, 100, 20, 130, 40, 200, 10, 230, 20);

    HDC bitmapDC = CreateCompatibleDC(dc);
    HBITMAP bitmap = CreateCompatibleBitmap(bitmapDC, 200, 200);
    SelectObject(bitmapDC,bitmap);
    BitBlt(bitmapDC, 0, 0, 500, 500, dc, 500, 500, SRCCOPY);

    Bitmap image(bitmap,NULL);
    CLSID clsID;
    GetCLSID(L"image/png", &clsID);
    image.Save(L"pic.png", &clsID);

}

I couldn't even imagine that simple saving will be such problem, so I'll be glad for any help, thanks!

Raven
  • 4,783
  • 8
  • 44
  • 75
  • The [Wikipedia page](http://en.wikipedia.org/wiki/BMP_file_format) has an excellent reference. GDI+ seems a little over the top. Couldn't you use MFC or ATL? – David Heffernan May 24 '11 at 21:25
  • Well there's possibility I'd need it for my exam (that's why I'm trying to get as short solution as possible without much dependecies). The idea is just to save some drawings that has been made and I find this the best way. But back to topic, we can use just freeware ofcourse, so I'm running on VS2010 Express = No ATL / MFC, just plain win32.. I'm not even sure if there's GDI+, going to find out tomorrow. – Raven May 24 '11 at 21:35

1 Answers1

2

I gave code here which does pretty much what you want: How to save the client area of a child Window to a Bitmap file?

It is very verbose in C. It's a lot better in C++ because of CImage

Community
  • 1
  • 1
Mike Kwan
  • 24,123
  • 12
  • 63
  • 96
  • Well I was trying to avoid that implementation of saveBMP... function. It looks like using gdi+ save I wouldn't have to play with those binaries and headers for bitmaps, but I couldn't get it working. Well if there won't be any other way, do you also have code for that function? I saw some scraps on other forums and I can say that without knowing exactly what to do I could screw it up... – Raven May 24 '11 at 21:27
  • Use the first snippet of code.. That doesn't require a SaveBMP function. Save() handles all that for you. – Mike Kwan May 24 '11 at 21:36
  • Ah that one, I skipped it immediatly, I should mention it but as I said in coment to my question, I can't be using ATL (or MFC). Well I already knew that win32 is pain in the ass, but had no alternatives. Schoolmates are doing all of this in delphi but I find pascal deprecated and won't learn it just to have some fancy easy graphic interference. It's shareware anyway but school have bought it :/ And I'm just one of few who work with c++... – Raven May 24 '11 at 21:45
  • @Raven. In Delphi the solution is as follows. `Bitmap.Handle := hBmp; Bitmap.SaveToFile(FileName);` I don't know why you would prefer to work with the raw Win32 API to that. You can't have your cake and eat it. – David Heffernan May 24 '11 at 21:53
  • @David It's quite simple. Apart from that deplhi is based on pascal, it's commerical the same way MFC or ATL is.. And those 2 frameworks got also easy ways to do that saving as can be seen in Mikes link. But I don't really look forward to learning something I can throw away as soon as I leave high school because I'll never use it. If there weren't those exams I wouldn't even care about it.. And teacher says it's ok that I use whatever I like as long, as I can produce similliar results. Well and I can do almost everything they can, but there are some problems like this... – Raven May 24 '11 at 22:13
  • It's just me, and maybe I miss many functions just because I didn't look close enough, but I find c++/c most suitable for me. Now I'm trying to learn Python and if I'll be learning next lnaguage candidates are Java or C#. For each mentioned I can find a good reason why to know it... but not the same with pascal.. – Raven May 24 '11 at 22:57
  • You can use CImage in Win32, simply #include and #include . Also #include , it wants CString apparently. – Pierre Apr 18 '16 at 13:03