HBitMap to TBitMap? lazarus / 39-Graphics ---------------------------------------------------------------------- user5 · 2015-04-23 20:26 Can someone please show me a method that actually works to make a TBitMap from a HBitMap? I've looked all over and I'm going nuts. ---------------------------------------------------------------------- user5 · 2015-04-23 21:43 Now I think my problem isn't just how to make a bitmap from an hbitmap. Can anyone tell me why the function below fails and crashes with a SIGSEGV error on the line of code that follows the question marks? function CopyScreenToBitmap(newRect : TRect; pData : PByte;     pHeader : PBitmapInfo) : HBitmap;   var     // screen DC and memory DC     hScrDC, hMemDC : HDC;     // handles to deice-dependent bitmaps     hBmp, hOldBmp : HBitmap;      // coordinates of rectangle to grab     nX, nY, nX2, nY2,     // DIB width and height     nWidth, nHeight,     // screen resolution     xScrn, yScrn : Integer;   begin     // check for an empty rectangle     if IsRectEmpty(newRect) then     begin       Result := 0;       Exit;     end;     // create a DC for the screen and create     // a memory DC compatible to screen DC     hScrDC := CreateDC('DISPLAY', nil, nil, nil);     hMemDC := CreateCompatibleDC(hScrDC);     // get points of rectangle to grab     nX := newRect.Left;     nY := newRect.Top;     nX2:= newRect.Right;     nY2:= newRect.Bottom;     // get screen resolution     xScrn := GetDeviceCaps(hScrDC, HORZRES);     yScrn := GetDeviceCaps(hScrDC, VERTRES);     //make sure bitmap rectangle is visible     if (nX < 0) then       nX := 0;     if (nY < 0) then       nY := 0;     if (nX2 > xScrn) then       nX2 := xScrn;     if (nY2 > yScrn) then       nY2 := yScrn;     nWidth  := nX2 - nX;     nHeight := nY2 - nY;     // create a bitmap compatible with the screen DC     hBmp := CreateCompatibleBitmap(hScrDC, nWidth, nHeight);     // select new bitmap into memory DC     hOldBmp := SelectObject(hMemDC, hBmp);     // bitblt screen DC to memory DC     BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);     // select old bitmap back into memory DC and get handle to     // bitmap of the screen     hBmp := SelectObject(hMemDC, hOldBmp); //??? The next line causes the program to crash with a SIGSEGV error?????????     // Copy the bitmap data into the provided BYTE buffer     GetDIBits(hScrDC, hBmp, 0, nHeight, pData, pHeader^, DIB_RGB_COLORS);     // clean up     DeleteDC(hScrDC);     DeleteDC(hMemDC);     // return handle to the bitmap     Result := hBmp;   end; ---------------------------------------------------------------------- User137 · 2015-04-24 03:54 I don't see where the error is, but if this is related to the video- like screen capture of other thread there could be alot to optimize. You could only create and reserve all the DC's and bitmap variables outside of the function. Reuse the already allocated data locations, fill them with pixels and save to storage location. But if it's only for 1-time screenshot, then nevermind. ---------------------------------------------------------------------- user5 · 2015-04-24 14:21 Thanks for your response, User137. Yes, this is related to my other posts in that I've been looking at ways to speed up multiple screen captures, but I admit that I don't know much about HBitmaps and such but I've been trying to learn. taazz suggested that the use of CreatecompatibleDC might help so I started looking into all this but I don't know where to start. I've checked out some other screen capture methods but the one I have seems to be better than what I've found so far. The function I posted probably failed because I was trying to use it outside of the context of the unit that it is a part of, which I found at https://github.com/TheBlackSheep/DSPack- Lazarus/blob/master/DXSUtil.pas. I'm not sure how I will proceed from this point but I guess that I'll just do the best that I can. ---------------------------------------------------------------------- user5 · 2015-04-24 15:46 User137, you were kind enough to respond to my message post so I would like to ask you or anyone else about the code below which I found on this forum! This code snippet makes an HBitmap and places it on the clipboard. I know it works because I ran it and used MSPaint to fetch it from the clipboard. Now, my question is, how do I make a bitmap from this that I can save to disk? I'm really excited about this. var      MemDC: HDC;      MemBitmap, OldBitmap: HBITMAP;      W, H: Integer;    begin      W := Image5.Picture.Bitmap.Width;      H := Image5.Picture.Bitmap.Height;      MemDC := Windows.CreateCompatibleDC(Canvas.Handle);      MemBitmap := Windows.CreateCompatibleBitmap(Canvas.Handle, W, H);      OldBitmap := Windows.SelectObject(MemDC, MemBitmap);      Windows.BitBlt(MemDC, 0, 0, W, H, Image5.Picture.Bitmap.Canvas.Handle, 0, 0, SRCCOPY);      Windows.OpenClipboard(Handle);      Windows.EmptyClipboard;      Windows.SetClipboardData(CF_BITMAP, MemBitmap);      Windows.CloseClipboard;      Windows.SelectObject(MemDC, OldBitmap);      Windows.DeleteDC(MemDC);      Windows.DeleteObject(MemBitmap);    end; ---------------------------------------------------------------------- user5 · 2015-04-24 15:57 The code I posted puts a picture in a TImage onto the clipboard but I need, I think, to make an HBitmap from a screen capture and to do it fast and then to save it to a file. The code I'm currently using to make a screen capture is below. I don't understand much about HBitmaps but I am wondering if any of this would enable me to make faster screen captures. var   r: TRect; begin   c.Handle := GetWindowDC(GetDesktopWindow);   try     r := Rect(0, 0, tempwidth, tempheight);     Bild.Width := tempwidth;     Bild.Height := tempheight;     Bild.Canvas.CopyRect(r, c, r);   finally     ReleaseDC(0, c.Handle);   end; end; ---------------------------------------------------------------------- taazz · 2015-04-24 15:58 Quote from: user5 on April 24, 2015, 05:46:06 pmUser137, you were kind enough to respond to my message post so I would like to ask you or anyone else about the code below which I found on this forum! This code snippet makes an HBitmap and places it on the clipboard. I know it works because I ran it and used MSPaint to fetch it from the clipboard. Now, my question is, how do I make a bitmap from this that I can save to disk? I'm really excited about this. var      MemDC: HDC;      MemBitmap, OldBitmap: HBITMAP;      W, H: Integer;    begin      W := Image5.Picture.Bitmap.Width;      H := Image5.Picture.Bitmap.Height;      MemDC := Windows.CreateCompatibleDC(Canvas.Handle);      MemBitmap := Windows.CreateCompatibleBitmap(Canvas.Handle, W, H);      OldBitmap := Windows.SelectObject(MemDC, MemBitmap);      Windows.BitBlt(MemDC, 0, 0, W, H, Image5.Picture.Bitmap.Canvas.Handle, 0, 0, SRCCOPY); //     Windows.OpenClipboard(Handle); //     Windows.EmptyClipboard; //     Windows.SetClipboardData(CF_BITMAP, MemBitmap); //     Windows.CloseClipboard;       MemBitmap.Savetofile('MyBitmap........          Windows.SelectObject(MemDC, OldBitmap);      Windows.DeleteDC(MemDC);      Windows.DeleteObject(MemBitmap);    end; ---------------------------------------------------------------------- user5 · 2015-04-24 17:46 Wow! The test procedure below captures the canvas directly into an HBitmap (MemBitmap) and places it onto the Clipboard. One test run that I ran saved three hundred and sixty 528x386 screen captures onto the clipboard in less than a second of time! My God, I have never seen such speed and on an older computer too!!!! If I can find a way to change the HBitmap into a TBitmap then I will always be so thankful to taazz. Man, as far as I'm concerned, if he names it then he can have it. I've been searching the Web for hours and hours for the last day or so, studying and learning but I haven't found a reliable way to create a bitmap from MemBitmap. PLEASE! PLEASE! Somebody show me how to save an HBitmap into a TBitmap! Thank you all so much! procedure TForm5.Button26Click(Sender: TObject); var  MemDC: HDC;  MemBitmap, OldBitmap: HBITMAP;  W, H: Integer; begin  W := 528;  H := 386;  MemDC := Windows.CreateCompatibleDC(Canvas.Handle);  MemBitmap := Windows.CreateCompatibleBitmap(Canvas.Handle, W, H);  OldBitmap := Windows.SelectObject(MemDC, MemBitmap);  Windows.BitBlt(MemDC, 0, 0, W, H, Canvas.Handle, 0, 0, SRCCOPY);  Windows.OpenClipboard(Handle);  Windows.EmptyClipboard;  Windows.SetClipboardData(CF_BITMAP, MemBitmap);  Windows.CloseClipboard;  Windows.SelectObject(MemDC, OldBitmap);  Windows.DeleteDC(MemDC);  Windows.DeleteObject(MemBitmap); end; ---------------------------------------------------------------------- user5 · 2015-04-24 17:56 This is just a followup to my last post. I can save the clipboard contents into a bitmap and then save the bitmap onto disk using "MyBit map.LoadFromClipboardFormat(PredefinedClipboardFormat(pcfBitmap));" but I was wondering if there is a different way to do this. Jeeeezzz... I have so much to think about now. Thanks, taazz!!!!!!! If you run for U.S. president then I'll vote fer ya. ---------------------------------------------------------------------- user5 · 2015-04-25 03:33 In case anyone is interested, using the code described in my previous posts with a ramdisk and only putting the statement Windows.BitBlt(MemDC, 0, 0, W, H, Canvas.Handle, 0, 0, SRCCOPY); inside the capturing loop, it's possible to make an hour long, 15fps movie in less than 5 minutes! Oh, by the way, to convert an HBitmap directly into a Bitmap without using the clipboard, all you have to do is: mybitmap.Handle := MemBitmap (the HBitmap) and then save the bitmap mybitmap into a file (mybitmap.bmp). That's all there is to it. I found that answer on a spanish language web site. Thanks again taazz. It took a lot of effort, searching and studying but I finally found the answers I needed. I did all the work myself without any real help from anyone but you pointed me into the right direction. All praise to Lazarus.