?
Solved

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

Posted on 2006-04-26
13
Medium Priority
?
1,220 Views
Last Modified: 2013-11-17
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 ...
0
Comment
Question by:cybergonzo
  • 6
  • 2
  • 2
  • +1
11 Comments
 

Author Comment

by:cybergonzo
ID: 16544633
incentive
0
 
LVL 25

Expert Comment

by:kode99
ID: 16546952
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.
0
 

Author Comment

by:cybergonzo
ID: 16547050
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.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 11

Expert Comment

by:Jase-Coder
ID: 16547270
0
 

Author Comment

by:cybergonzo
ID: 16547304
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).
0
 

Author Comment

by:cybergonzo
ID: 16547332
> 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.
0
 

Author Comment

by:cybergonzo
ID: 16547802
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.
0
 
LVL 25

Expert Comment

by:kode99
ID: 16548294
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.
0
 
LVL 11

Expert Comment

by:Jase-Coder
ID: 16553001
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.
0
 

Author Comment

by:cybergonzo
ID: 16733849
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;
}
//---------------------------------------------------------------------------
0
 

Accepted Solution

by:
CetusMOD earned 0 total points
ID: 16814615
PAQed with points refunded (400)

CetusMOD
Community Support Moderator
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In our object-oriented world the class is a minimal unit, a brick for constructing our applications. It is an abstraction and we know well how to use it. In well-designed software we are not usually interested in knowing how objects look in memory. …
Update (December 2011): Since this article was published, the things have changed for good for Android native developers. The Sequoyah Project (http://www.eclipse.org/sequoyah/) automates most of the tasks discussed in this article. You can even fin…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.
Suggested Courses

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question