Creating Shaped Windows Using Regions with Win32 | CodeGuru

Creating Shaped Windows Using Regions with Win32

Environment: VC6, Windows 9x/NT/2000/XP This article shows how to create a shaped window using a bitmap image file and using the mouse to drag it. The basic scheme is to scan a bitmap image data, skip over the transparent pixels, and create the region when a non-transparent pixel is found. For subsequent non-transparent pixels, the […]

Written By
CodeGuru Staff
CodeGuru Staff
Jun 3, 2003
2 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

Environment: VC6, Windows 9x/NT/2000/XP

This article shows how to create a shaped window using a bitmap image file and using the mouse to drag it.

The basic scheme is to scan a bitmap image data, skip over the transparent pixels, and create the region when a non-transparent pixel is found. For subsequent non-transparent pixels, the region is combined with the previous one. The transparent pixel is a particular color value of the pixel that is not used to create the window.

Getting Started

The first requirement is to create a bitmap image using image editors such as MSPaint, Photoshop, and so forth. This bitmap must have, apart from other colors used, one color that is to be interpreted as a transparent color by the application program. For example, white means a pixel RGB value of RGB(255,255,255). So, the program will skip all the bitmap data corresponding to this color for processing.

Understanding the Application

We start by creating a modeless dialog box:

HWND hwndDlg = CreateDialog(hInstance,
                            MAKEINTRESOURCE(IDD_DIALOG1),
                            ghWnd, (DLGPROC)DialogProc);

The next step is creating the region window. This includes loading the bitmap image file into memory and obtaining information about the bitmap image (such as the width and height of the image.)

HANDLE hBitmap = (HBITMAP)LoadImage(GetModuleHandle(NULL),
                                    imageFile, IMAGE_BITMAP, 0, 0,
                                    LR_LOADFROMFILE);

To create the region, the bitmap data is scanned and all the RGB color values corresponding to the transparent color are skipped from processing. For all the other color values, their corresponding logical coordinates are used to create the region.

//create an empty region
hRgn = CreateRectRgn(0,0,0,0);
//Create a region from a bitmap with transparency colour of white
//change the pixel values for a different transparency color
//ex - RGB(0,0,0) will mean a transparency color of black.. so the
//areas of the bitmap not used to create the window will be black
COLORREF crTransparent = RGB(255, 255, 255);

int iX = 0;
int iRet = 0;
for (int iY = 0; iY < bmpInfo.bmHeight; iY++)
{
  do
  {
    //skip over transparent pixels at start of lines.
    while (iX < bmpInfo.bmWidth && GetPixel(hdcMem, iX, iY)
              == crTransparent) iX++;
    //remember this pixel
    int iLeftX = iX;
    //now find first non-transparent pixel
    while (iX < bmpInfo.bmWidth && GetPixel(hdcMem, iX, iY) !
              = crTransparent) ++iX;
    //create a temp region on this info
    HRGN hRgnTemp = CreateRectRgn(iLeftX, iY, iX, iY+1);
    //combine into main region
    iRet = CombineRgn(hRgn, hRgn, hRgnTemp, RGN_OR);
    if(iRet == ERROR)
    {
      return;
    }
    //delete the temp region for next pass
    DeleteObject(hRgnTemp);
  }while(iX < bmpInfo.bmWidth);
  iX = 0;
}
Advertisement

After the region is created, the window region is set by calling SetWindowRgn,

iRet = SetWindowRgn(hwndDlg, hRgn, TRUE);

and its position is set by calling SetWindowPos:

iRet = SetWindowPos(hwndDlg, HWND_TOPMOST, iX, iY, bmpInfo.bmWidth,
                    bmpInfo.bmHeight, NULL);

Finally, render the bitmap image into the region by calling the function BitBlt.

BitBlt(hdcDest, 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, hdcMem,
                0, 0, SRCCOPY);

Dragging the Window

The window is dragged by handling messages in the dialog procedure:

case WM_LBUTTONDOWN:
  mouseState = 1;
  return TRUE;
case WM_MOUSEMOVE:
  if(mouseState)
  {
    GetCursorPos(&CursPt);
    PostMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION,
                MAKELPARAM( CursPt.x, CursPt.y));
    mouseState = 0;
  }
  return TRUE;

Downloads


Download demo project – 11 Kb


Download source – 6 Kb

CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.