Transparent Splash screen (using BCB 5, for Win9x - Vista ... if possible)

I have implemented a splash screen and was wondering if it's possible
somehow to set one of the colours as transparent ?
So that only the "real" picture would be shown and the white colour frame
around the (non-rectangle) logo would be invisible ?

I understand that I need to define a region that will not be painted by the OS and that I have to provide that handle like so:

HRGN PolygonHandle =// code to be written

if (PolygonHandle)
    {
    int res = SetWindowRgn(
        Handle,             // handle to window whose window region is to be set
        PolygonHandle,      // handle to region
        true                // window redraw flag
        );
    }

I have experimented with simple ellipses (successfully), e.g CreateEllipticRgn()

But now I need to define the region that is my own logo
I'm open for all suggestions.  E.g. if I can make a POINT array during design time (somehow) I can use CreatePolygonRgn() for instance ?

I also tried BitmapToRegion() during design time.
This function simply lifted from this example project:
http://codeguru.earthweb.com/bitmap/bmp_to_rgn.shtml
But no joy as CreateDIBSection() returns NULL all the time and GetLastError() returns 87 ?

so ... I'm stuck ...
cybergonzoAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

cybergonzoAuthor Commented:
incentive
kode99Commented:
Check out this free component with source,  its actually written in C++ and not delphi

http://www.ciemmesoft.com/componenti/categorieing.asp?ID=2&PAG=1

It allows for a custom shaped form that is based off a bitmap using a transparent bitmap image.  Rather
neat and if you dont want use it directly the source would be a good example to work from.
cybergonzoAuthor Commented:
Thanks for the tip but oh boy ... do I have to sift through tons of third party code ?
I'd rather not use a third party component right now.
Become a Certified Penetration Testing Engineer

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

Jase-CoderCommented:
cybergonzoAuthor Commented:
I actually appear to have BitmapToRegion() working (see my original post), I passed the wrong handle.

I appreciate links to components but I'm not looking for third party components really, even with code they tend to be more complex and a lot of code sifting needs to be done (I'm rather auto didact when having to search through other people's code).
cybergonzoAuthor Commented:
> http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=596&lngWId=7

This appears to be in Delphi so definitly not something I can use, sorry.
cybergonzoAuthor Commented:
Ok, I suppose I have to award myself the points :)
I got the BitmapToRegion() function to work (see my initial Q) and it looks 'neat' ;-)
Thanks for the component suggestions but that was simply not what I needed.
kode99Commented:
You might find it worthwhile to check out the source on that component anyway.  Its pretty short,  the whole file is only around 300 lines or so.
Jase-CoderCommented:
The functions in delphi are very similar to delphi for instance, you used the BitmapToregion function which is in the delphi source. The Bitmap class is the same!

Also you can compile delphi code in BCB.
cybergonzoAuthor Commented:
I got it to work by using the function I suggested myself in my initial question.
The function: BitmapToRegion() which can be found here:
http://codeguru.earthweb.com/bitmap/bmp_to_rgn.shtml

The problem why I didn't get it to work first was that I was passing the wrong handle to the BitMapToRegion() function


HRGN PolygonHandle = BitmapToRegion (Image->Picture->Bitmap->Handle, 0x00D0D0CF, 0x00000000) ; // LIGHTER GREY

if (PolygonHandle)
    {
    int res = SetWindowRgn(
        Handle,                  // handle to window whose window region is to be set
        PolygonHandle,      // handle to region
        true                // window redraw flag
        );
    }



//---------------------------------------------------------------------------
// http://codeguru.earthweb.com/bitmap/bmp_to_rgn.shtml
//---------------------------------------------------------------------------
//
//      BitmapToRegion :      Create a region from the "non-transparent" pixels of a bitmap
//      Author :                  Jean-Edouard Lachand-Robert (http://www.geocities.com/Paris/LeftBank/1160/resume.htm), June 1998.
//
//      hBmp :                        Source bitmap
//      cTransparentColor :      Color base for the "transparent" pixels (default is black)
//      cTolerance :            Color tolerance for the "transparent" pixels.
//
//      A pixel is assumed to be transparent if the value of each of its 3 components (blue, green and red) is
//      greater or equal to the corresponding value in cTransparentColor and is lower or equal to the
//      corresponding value in cTransparentColor + cTolerance.
//
//---------------------------------------------------------------------------
HRGN TSplashScreen::BitmapToRegion (HBITMAP hBmp, COLORREF cTransparentColor = 0, COLORREF cTolerance = 0x101010)
{
      HRGN hRgn = NULL;

      if (hBmp)
      {
            // Create a memory DC inside which we will scan the bitmap content
            HDC hMemDC = CreateCompatibleDC(NULL);
            if (hMemDC)
            {
                  // Get bitmap size
                  BITMAP bm;
                  GetObject(hBmp, sizeof(bm), &bm);

                  // Create a 32 bits depth bitmap and select it into the memory DC
                  BITMAPINFOHEADER RGB32BITSBITMAPINFO = {
                              sizeof(BITMAPINFOHEADER),      // biSize
                              bm.bmWidth,                              // biWidth;
                              bm.bmHeight,                        // biHeight;
                              1,                                          // biPlanes;
                              32,                                          // biBitCount
                              BI_RGB,                                    // biCompression;
                              0,                                          // biSizeImage;
                              0,                                          // biXPelsPerMeter;
                              0,                                          // biYPelsPerMeter;
                              0,                                          // biClrUsed;
                              0                                          // biClrImportant;
                  };
                  VOID * pbits32;
                  HBITMAP hbm32 = CreateDIBSection(hMemDC, (BITMAPINFO *)&RGB32BITSBITMAPINFO, DIB_RGB_COLORS, &pbits32, NULL, 0);
                  if (hbm32)
                  {
                        HBITMAP holdBmp = (HBITMAP)SelectObject(hMemDC, hbm32);

                        // Create a DC just to copy the bitmap into the memory DC
                        HDC hDC = CreateCompatibleDC(hMemDC);
                        if (hDC)
                        {
                              // Get how many bytes per row we have for the bitmap bits (rounded up to 32 bits)
                              BITMAP bm32;
                              GetObject(hbm32, sizeof(bm32), &bm32);
                              while (bm32.bmWidthBytes % 4)
                                    bm32.bmWidthBytes++;

                              // Copy the bitmap into the memory DC
                              HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, hBmp);
                              BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY);

                              // For better performances, we will use the ExtCreateRegion() function to create the
                              // region. This function take a RGNDATA structure on entry. We will add rectangles by
                              // amount of ALLOC_UNIT number in this structure.
                              #define ALLOC_UNIT      100
                              DWORD maxRects = ALLOC_UNIT;
                              HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));
                              RGNDATA *pData = (RGNDATA *)GlobalLock(hData);
                              pData->rdh.dwSize = sizeof(RGNDATAHEADER);
                              pData->rdh.iType = RDH_RECTANGLES;
                              pData->rdh.nCount = pData->rdh.nRgnSize = 0;
                              SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);

                              // Keep on hand highest and lowest values for the "transparent" pixels
                              BYTE lr = GetRValue(cTransparentColor);
                              BYTE lg = GetGValue(cTransparentColor);
                              BYTE lb = GetBValue(cTransparentColor);
                              BYTE hr = (BYTE)min(0xff, lr + GetRValue(cTolerance));
                              BYTE hg = (BYTE)min(0xff, lg + GetGValue(cTolerance));
                              BYTE hb = (BYTE)min(0xff, lb + GetBValue(cTolerance));

                              // Scan each bitmap row from bottom to top (the bitmap is inverted vertically)
                              BYTE *p32 = (BYTE *)bm32.bmBits + (bm32.bmHeight - 1) * bm32.bmWidthBytes;
                              for (int y = 0; y < bm.bmHeight; y++)
                              {
                                    // Scan each bitmap pixel from left to right
                                    for (int x = 0; x < bm.bmWidth; x++)
                                    {
                                          // Search for a continuous range of "non transparent pixels"
                                          int x0 = x;
                                          LONG *p = (LONG *)p32 + x;
                                          while (x < bm.bmWidth)
                                          {
                                                BYTE b = GetRValue(*p);
                                                if (b >= lr && b <= hr)
                                                {
                                                      b = GetGValue(*p);
                                                      if (b >= lg && b <= hg)
                                                      {
                                                            b = GetBValue(*p);
                                                            if (b >= lb && b <= hb)
                                                                  // This pixel is "transparent"
                                                                  break;
                                                      }
                                                }
                                                p++;
                                                x++;
                                          }

                                          if (x > x0)
                                          {
                                                // Add the pixels (x0, y) to (x, y+1) as a new rectangle in the region
                                                if (pData->rdh.nCount >= maxRects)
                                                {
                                                      GlobalUnlock(hData);
                                                      maxRects += ALLOC_UNIT;
                                                      hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE);
                                                      pData = (RGNDATA *)GlobalLock(hData);
                                                }
                                                RECT *pr = (RECT *)&pData->Buffer;
                                                SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);
                                                if (x0 < pData->rdh.rcBound.left)
                                                      pData->rdh.rcBound.left = x0;
                                                if (y < pData->rdh.rcBound.top)
                                                      pData->rdh.rcBound.top = y;
                                                if (x > pData->rdh.rcBound.right)
                                                      pData->rdh.rcBound.right = x;
                                                if (y+1 > pData->rdh.rcBound.bottom)
                                                      pData->rdh.rcBound.bottom = y+1;
                                                pData->rdh.nCount++;

                                                // On Windows98, ExtCreateRegion() may fail if the number of rectangles is too
                                                // large (ie: > 4000). Therefore, we have to create the region by multiple steps.
                                                if (pData->rdh.nCount == 2000)
                                                {
                                                      HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
                                                      if (hRgn)
                                                      {
                                                            CombineRgn(hRgn, hRgn, h, RGN_OR);
                                                            DeleteObject(h);
                                                      }
                                                      else
                                                            hRgn = h;
                                                      pData->rdh.nCount = 0;
                                                      SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
                                                }
                                          }
                                    }

                                    // Go to next row (remember, the bitmap is inverted vertically)
                                    p32 -= bm32.bmWidthBytes;
                              }

                              // Create or extend the region with the remaining rectangles
                              HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
                              if (hRgn)
                              {
                                    CombineRgn(hRgn, hRgn, h, RGN_OR);
                                    DeleteObject(h);
                              }
                              else
                                    hRgn = h;

                              // Clean up
                              SelectObject(hDC, holdBmp);
                              DeleteDC(hDC);
                        }

                        DeleteObject(SelectObject(hMemDC, holdBmp));
                  }

                  DeleteDC(hMemDC);
            }
      }

      return hRgn;
}
//---------------------------------------------------------------------------
CetusMODCommented:
PAQed with points refunded (400)

CetusMOD
Community Support Moderator

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Editors IDEs

From novice to tech pro — start learning today.