Add Drawing Transparent Bitmaps


A portion of a graphic image that does not change the contents of the screen is termed "transparent."
The DrawIcon function can create an image that contains transparent portions.
It is also possible to obtain this functionality using the BitBlt function; however, there are some additional steps involved.
The first step is to obtain the contents of the area where the bitmap will be drawn and to store this background image in a memory display context (DC). Mask out the area of the background that corresponds to the nontransparent portion of the image bitmap and mask out all transparent pixels from the image bitmap. Use the XOR raster operation to merge the image bitmap into the background bitmap. Finally, use the BitBlt function to move the merged image to the destination DC.

  1. procedure DrawTransparentBitmap(DC: HDC; hBmp : HBITMAP ;
  2.           xStart: integer; yStart : integer; cTransparentColor : COLORREF);
  3. var
  4.       bm:                                                  BITMAP;
  5.       cColor:                                              COLORREF;
  6.       bmAndBack, bmAndObject, bmAndMem, bmSave:            HBITMAP;
  7.       bmBackOld, bmObjectOld, bmMemOld, bmSaveOld:         HBITMAP;
  8.       hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave:        HDC;
  9.       ptSize:                                              TPOINT;
  10.  
  11. begin
  12.    hdcTemp := CreateCompatibleDC(dc);
  13.    SelectObject(hdcTemp, hBmp);   >// Select the bitmap
  14.  
  15.    GetObject(hBmp, sizeof(BITMAP), @bm);
  16.    ptSize.x := bm.bmWidth;            >// Get width of bitmap
  17.    ptSize.y := bm.bmHeight;           >// Get height of bitmap
  18.    DPtoLP(hdcTemp, ptSize, 1);        >// Convert from device
  19.                                       // to logical points
  20.  
  21.    // Create some DCs to hold temporary data.
  22.    hdcBack   := CreateCompatibleDC(dc);
  23.    hdcObject := CreateCompatibleDC(dc);
  24.    hdcMem    := CreateCompatibleDC(dc);
  25.    hdcSave   := CreateCompatibleDC(dc);
  26.  
  27.    // Create a bitmap for each DC. DCs are required for a number of
  28.    // GDI functions.
  29.  
  30.    // Monochrome DC
  31.    bmAndBack   := CreateBitmap(ptSize.x, ptSize.y, 1, 1, nil);
  32.  
  33.    // Monochrome DC
  34.    bmAndObject := CreateBitmap(ptSize.x, ptSize.y, 1, 1, nil);
  35.  
  36.    bmAndMem    := CreateCompatibleBitmap(dc, ptSize.x, ptSize.y);
  37.    bmSave      := CreateCompatibleBitmap(dc, ptSize.x, ptSize.y);
  38.  
  39.    // Each DC must select a bitmap object to store pixel data.
  40.    bmBackOld   := SelectObject(hdcBack, bmAndBack);
  41.    bmObjectOld := SelectObject(hdcObject, bmAndObject);
  42.    bmMemOld    := SelectObject(hdcMem, bmAndMem);
  43.    bmSaveOld   := SelectObject(hdcSave, bmSave);
  44.  
  45.    // Set proper mapping mode.
  46.    SetMapMode(hdcTemp, GetMapMode(dc));
  47.  
  48.    // Save the bitmap sent here, because it will be overwritten.
  49.    BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
  50.  
  51.    // Set the background color of the source DC to the color.
  52.    // contained in the parts of the bitmap that should be transparent
  53.    cColor := SetBkColor(hdcTemp, cTransparentColor);
  54.  
  55.    // Create the object mask for the bitmap by performing a BitBlt
  56.    // from the source bitmap to a monochrome bitmap.
  57.    BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0,
  58.           SRCCOPY);
  59.  
  60.    // Set the background color of the source DC back to the original
  61.    // color.
  62.    SetBkColor(hdcTemp, cColor);
  63.  
  64.    // Create the inverse of the object mask.
  65.    BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0,
  66.           NOTSRCCOPY);
  67.  
  68.    // Copy the background of the main DC to the destination.
  69.    BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, dc, xStart, yStart,
  70.           SRCCOPY);
  71.  
  72.    // Mask out the places where the bitmap will be placed.
  73.    BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);
  74.  
  75.    // Mask out the transparent colored pixels on the bitmap.
  76.    BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
  77.  
  78.    // XOR the bitmap with the background on the destination DC.
  79.    BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
  80.  
  81.    // Copy the destination to the screen.
  82.    BitBlt(dc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0,
  83.           SRCCOPY);
  84.  
  85.    // Place the original bitmap back into the bitmap sent here.
  86.    BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);
  87.  
  88.    // Delete the memory bitmaps.
  89.    DeleteObject(SelectObject(hdcBack, bmBackOld));
  90.    DeleteObject(SelectObject(hdcObject, bmObjectOld));
  91.    DeleteObject(SelectObject(hdcMem, bmMemOld));
  92.    DeleteObject(SelectObject(hdcSave, bmSaveOld));
  93.  
  94.    // Delete the memory DCs.
  95.    DeleteDC(hdcMem);
  96.    DeleteDC(hdcBack);
  97.    DeleteDC(hdcObject);
  98.    DeleteDC(hdcSave);
  99.    DeleteDC(hdcTemp);
  100. end;
  101.  
  102. The following is an example of how the
  103. DrawTransparentBitmap function might be called:
  104.  
  105. procedure TForm1.Button1Click(Sender: TObject);
  106. begin
  107.   DrawTransparentBitmap(Form1.Canvas.Handle,
  108.  Image1.Picture.Bitmap.Handle, 10, 10, clWhite);
  109. end;
Related Discussions
  • DOT ON SCREEN (2001-01-02 21:42:55)
    Delphi does not support a Pixel function with a HDC, you have to use the Windows-API-function COLORREF SetPixel( HDC hdc, // handle...
  • URGENT DLL PB (2001-01-16 01:08:13)
    Hmmm ... I'm not competent in returning bitmaps from DLLs but perhaps you have to specify some memory handling routines ? Regards /Filip
  • HOW TO SEND A BITMAP (TBITMAP) WITH THE TSERVERSOCKET/TCLIENTSOCKET? (2001-01-17 01:12:25)
    Hi thx for your help, but it won't work with me too, i can't find out what i am doing wrong, i put a source code here, maybe someone can tell me...
  • TRUE TRANSPARENCY IN CUSTOM CONTROLS? (2001-01-19 20:31:01)
    I don't really know, but I think you have to override the Paint-Procedure of the Component. In the class definition: protected procedure...
  • DRAWING A LINE ON MOUSE MOVE THEN ERASING IT AND DRAWING IT ANEW PRT 2 (2001-01-20 06:03:51)
    I successfully draw/erase lines on mousemove events by setting Pen.Mode := pmNotXOR;
  • DELPHI COMPONENT (2001-01-21 09:55:08)
    Hey! All i can suggest you is a piece of code (really confusing one) but I think that will do the job. Well... here it is... a long one but...
  • THAT HARD? (2001-01-22 22:54:21)
    ok thanks its working now.. the way I was loading the bmp was wrong.. 16x16 is ok btw
  • TRANSPARENT STRINGGRID (2002-01-17 06:35:13)
    try cooldev's TCoolStringGrid TCoolStringGrid is an Advanced string grid component. Wallpapers, transparency, flat borders, caption. Each...
  • HOW CAN I DRAW FIGURES DIRECTLY ON THE SCREEN (2001-01-24 20:49:21)
    To draw directly onto the screen, you should use CreateDC('DISPLAY', nil, nil, nil); instead of GetWindowDC(GetDesktopWindow()); Oregon Ghost
  • DETECTING SHADES OF COLOURS (GRAYSCALE) (2001-01-30 22:54:41)
    I'm Russian but I live in Belgium, so i'm not teh best in English too :) The way you calculate the greyscale color is the wrong one. red >...
Latest News
Submit News Form Past News
Latest Forum Entries