Transparent Window

This article is based on the idea of Jason Wylie, the author of the article Transparent
Dialog, but it uses a mask bitmap instead of getting the transparency information out of
the bitmap. This way many funny things can be done…

Transparent Window Picture

In some cases it’s nice to have a window that not always looks the same (I mean
rectangular). So I created this CWnd based window class which implements a transparent
window. The transparency information is supplied by a mask bitmap.

To include this transparent window type into your application copy the Transparent
Window class files to your project’s directory. Create an object of this class and call
the CreateTransparent() method for it. The parameters are a window caption, a RECT
structure an ID for the mask bitmap and annother one for the background bitmap.

So your InitInstance() function should look like this:

BOOL CDrawtestApp::InitInstance()
{
    CRect rect(0, 0, 320, 150);
    CTransparentWnd* pTWnd = new CTransparentWnd;
    m_pMainWnd = pTWnd;
    pFrame->CreateTransparent("Transparent Test", rect,
IDB_MASK, IDB_BACK);
    pFrame->ShowWindow(SW_SHOW);
    pFrame->UpdateWindow();
    return TRUE;
}

The mechanism this window is working with is to set a proper window-region. This window
region is setup by the function SetupRegion(). The process is to load the specified
monochrome mask bitmap and to check for each pixel if it is set or not. For each set pixel
add this pixel’s position to the window region. This is very slow, but only done once at
startup. Therefore this window is not resizeable.

The code for the SetupRegion() function:

void CTransparentWnd::SetupRegion(CDC *pDC, unsigned short
MaskID)
{
    CDC
             memDC;
    CBitmap         cBitmap;
    CBitmap*        pOldMemBmp = NULL;
    COLORREF        col;
    CRect           
cRect;
    int
             x, y;
    CRgn            
m_Rgn, rgnTemp;

    GetWindowRect(&cRect);

    cBitmap.LoadBitmap(MaskID);
    memDC.CreateCompatibleDC(pDC);
    pOldMemBmp = memDC.SelectObject(&cBitmap);

    m_Rgn.CreateRectRgn(0, 0, cRect.Width(), cRect.Height());
    for(x=0; x<=cRect.Width(); x++)
    {
        for(y=0; y<=cRect.Height(); y++)
        {
            col = memDC.GetPixel(x,
y);
            if(col == 0)
            {
               
rgnTemp.CreateRectRgn(x, y, x+1, y+1);
               
m_Rgn.CombineRgn(&m_Rgn, &rgnTemp, RGN_XOR);
               
rgnTemp.DeleteObject();    
            }
        }
    }
    if (pOldMemBmp) memDC.SelectObject(pOldMemBmp);
    SetWindowRgn((HRGN)m_Rgn, TRUE);
}

The next proble is to make this window moveable. There are two possibilities. You can
override the ONNcHittest() function and redirect all HTCLIENT results to HTCAPTION result,
or you only override the OnLButtonDown() function and send the correct hittest result to
the framework.

void CTransparentWnd::OnLButtonDown(UINT nFlags, CPoint
point)
{
    CWnd::OnLButtonDown(nFlags, point);
    PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x,point.y));
}

Now you can move the window by clicking anywere inside the window region.

Download demo project – 23 KB

Download source – 3 KB

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read