Solved

The transparent Dialog

Posted on 2000-03-14
19
1,488 Views
Last Modified: 2013-11-20
when i make a transparent dialog doing all this:

BOOL CWhatisthisDlg::OnEraseBkgnd(CDC* pDC)
{
//over ride OnErase

//return CDialog::OnEraseBkgnd(pDC);

return TRUE;
}

BOOL CWhatisthisDlg::PreCreateWindow(CREATESTRUCT& cs)
{
cs.dwExStyle = WS_EX_TRANSPARENT;
cs.style = WS_BORDER | WS_CAPTION;
      
return CDialog::PreCreateWindow(cs);
}

void CWhatisthisDlg::OnMove(int x, int y)
{
CDialog::OnMove(x, y);
      
Invalidate();
UpdateWindow();
      
}

My problem is when i move the dialog if i move it a short distance it shows the dialog in it's previous position and not what's behind it. if you could create a quick program and edit the sections i posted above you would see what it is i'm trying to accomplish, i do not wish to create a region, i want the dialog to appear like it's glass when you click on it you are still clicking on the dialog, what i have now works fine but as you can see when you move it you can see where it was previously.

0
Comment
Question by:bradsoblesky
  • 10
  • 6
  • 2
  • +1
19 Comments
 
LVL 5

Expert Comment

by:vachooho
ID: 2618342
0
 
LVL 1

Accepted Solution

by:
hiap_ho earned 200 total points
ID: 2618421
I learn this trick a couple days ago from Wyn ( one of the experts in Experts Exchange )

1. Create a bitmap and add it to resource as IDB_BITMAP, the bitmap only need to contain WhiteColor, since the white color will become transparant. The size of the bitmap should be equal to you dialog box size.

Add the following function to your class or you can set it just as global function ( I get this function from www.codeguru.com ):

HRGN BitmapToRegion (HBITMAP hBmp, COLORREF cTransparentColor = 0xFFFFFF, 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 = min(0xff, lr + GetRValue(cTolerance));
                              BYTE hg = min(0xff, lg + GetGValue(cTolerance));
                              BYTE hb = 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
                              GlobalFree(hData);
                              SelectObject(hDC, holdBmp);
                              DeleteDC(hDC);
                        }

                        DeleteObject(SelectObject(hMemDC, holdBmp));
                  }

                  DeleteDC(hMemDC);
            }      
      }

      return hRgn;
}

OnInitDlg function add the following code :
      CBitmap cbmp;
      cbmp.LoadBitmap(IDB_BITMAP);
      HBITMAP Bmp;
      Bmp=(HBITMAP)cbmp;

      HRGN reg = BitmapToRegion(Bmp);
      this->SetWindowRgn(reg,TRUE);

OnPaint function add the following code
      CBitmap cbmp;
      cbmp.LoadBitmap(IDB_BITMAP);
      HBITMAP Bmp;
      Bmp=(HBITMAP)cbmp;
      
      BITMAP bm;
      GetObject(Bmp, sizeof(bm), &bm);
      CPaintDC dc(this);
      HDC memdc = CreateCompatibleDC(NULL);
      HBITMAP h = (HBITMAP)SelectObject(memdc, Bmp);
      BitBlt(dc,0,0,bm.bmWidth,bm.bmHeight,memdc,0,0,SRCCOPY);  
      SelectObject(memdc, h);

It works when I try it out, so just try it out and tell me how you are doing. =)
Have a nice day

Hiap Ho
0
 
LVL 1

Expert Comment

by:hiap_ho
ID: 2618437
http://www.codeguru.com/dialog/transparent_dialog.shtml
I have tried above code before and to my disappointment, some of the part is not transparant. And when you tried to reduced the size of the dialog box, well it leaves some messy drawing out of the dialog box =(
0
 
LVL 1

Expert Comment

by:hiap_ho
ID: 2618456
Ups forget to tell you something, do put some color at the spot where you want anything to appear. Let's say you title bar, or button or edit box ? or maybe some parts of the dialog box where you want it to appear ? It's a bit difficult to make the adjustment though, but it's really is transparant, and transparant at the place you want it to be =)

Have a nice day,

Hiap Ho
0
 

Author Comment

by:bradsoblesky
ID: 2618465
What happens when you click on the transparent area? If it selects what is in the background this is not what i want. I only want the dialog to appear transparent but really be like it has a glass window you can see through it but it's still there.
0
 
LVL 1

Expert Comment

by:hiap_ho
ID: 2618477
On more things the function is not very perfect yet. It'll leave some white patches some spaces to the low right of the transparant color if you use the dialog box with frame and title bar. If you use it with dialog box without title bar and without frame, it will work perfectly.

Regards,

Hiap Ho
0
 

Author Comment

by:bradsoblesky
ID: 2618485
200 points requires at least a correct answer i wish to repost and give more details so it can be answered.
0
 

Author Comment

by:bradsoblesky
ID: 2618486
This question has a deletion request Pending
0
 
LVL 1

Expert Comment

by:hiap_ho
ID: 2618492
This question no longer is pending deletion
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 1

Expert Comment

by:hiap_ho
ID: 2618493
To eliminate this problem just adjust posx and posy value in the OnPaint function

      BitBlt(dc,0,0,bm.bmWidth,bm.bmHeight,memdc,posx,posy,SRCCOPY);

Regards,

Hiap Ho

0
 
LVL 1

Expert Comment

by:hiap_ho
ID: 2618496
You don't need to delete the question, you can just edit it =) and all of us will be gladly help you
0
 
LVL 1

Expert Comment

by:hiap_ho
ID: 2618510
For this case, it will be a blank and won't appear as a glass window.
Here is an idea, but I'm not sure how to do it. Capture the screen into memory dc, then whenever you move, you'll call repaint that will repaint your dialog background.
0
 

Author Comment

by:bradsoblesky
ID: 2618515
Edited text of question.
0
 

Author Comment

by:bradsoblesky
ID: 2618517
I've done that, but it does the same thing unless i hide the dialog capture the screen then show it and paint to it which is not prefered.
0
 
LVL 1

Expert Comment

by:hiap_ho
ID: 2618597
For this case, it will be a blank and won't appear as a glass window.
Here is an idea, but I'm not sure how to do it. Capture the screen into memory dc, then whenever you move, you'll call repaint that will repaint your dialog background.
0
 
LVL 1

Expert Comment

by:hiap_ho
ID: 2618603
ups some error in my connection
repeated comments, sorry
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2619407
see MS KB article

INFO: Transparent Windows
ID: Q92526
 
Note that Win2000 directly supports transparent (and semi-transparent) windows (that is sorta-how it does the shadowing on the mouse pointer).

Win98 is _supposed_ to support some of the new Win2000 features in this area (eg. transition effect) but although you can make them compile and build, at run-time it just doesn't work.
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2619428
Also, is it important that you allow the dialog to be dragged?

If not then just force it to be stationary (fairly easy) and then there is no problem.

If you DO wnat to make it draggable, one possibility while movement is to hide, move, capture the background and show. in response to dragging the window.  The problem there is that you get some flicker and poor mouse tracking as you drag.

You can make this a bit better by drawing an outline frame when moving and using a timer so that the dialog does not get made visible again until the user has left it alone for a couple of hundred milli-seconds.
0
 

Author Comment

by:bradsoblesky
ID: 2622097
It's dissapointing to post my last 200 points to a question and not get an answer worth 50 but have to give the 200 to someone unfort.
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Different colored text in ComboBox without Subclassing 8 45
Powershell based monitoring system 2 127
post4 challenge 28 83
Line meaning 9 77
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

747 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

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now