Advertisement

C\C++ - win32: how create regions by images?

Started by April 03, 2015 04:03 PM
9 comments, last by cambalinho 9 years, 9 months ago

heres how i create the Region:


HRGN  hRgn = CreateRectRgn(0,0,0, 0);

now see how i test the pixels on a variable:


DWORD p=0;
    for (WORD y=0; y<wBmpHeight; y++)
    {
        for (WORD x=0; x<wBmpWidth; x++)
        {
            BYTE jRed   = pPixels[p+2];
            BYTE jGreen = pPixels[p+1];
            BYTE jBlue  = pPixels[p+0];
            COLORREF pixelcolor=RGB(jRed,jGreen,jBlue);
            if (pixelcolor!=backcolor)
            {
                // add regions points, except the backcolor
                hTmpRgn = CreateRectRgn(x,y,x+1,y+1);
                CombineRgn(hRgn, hRgn, hTmpRgn, RGN_OR);
                DeleteObject(hTmpRgn);
            }

            // next pixel
            p+=3;
        }
    }

i see 2 problems:

1 - the backcolor is showed sad.png ;

2 - the control size is allways changed sad.png

so what i'm doing wrong?

Regions are not designed to work per-pixel to begin with.

Have you tried layered windows?

Niko Suni

Advertisement

Regions are not designed to work per-pixel to begin with.

Have you tried layered windows?

you are mistaken: http://comrade.ownz.com/docs/regions.html

several people did that ;)

i can't use the layered with child controls before windows 8

The fact that people sometimes use them that way does not negate the fact that this was not part of their design.

They were not designed for it. The API does not directly support it. Many people have discovered the pattern that you described above, a manual per-pixel creation of regions that consume a huge amount of resources to initially create.

They were not meant for that, they are a bad tool for per-pixel cutouts. They are slow to generate and slow to render... plus there are alternatives that are designed to properly handle transparency.

There are very few times that regions are the only way to accomplish cutouts inside Windows. If you happen to be in one of those very few uses then a region may be your tool of last resort.

But it should not be a go-to tool. Windows supports transparency and even alpha-blending for almost everything. Use per-pixel regions if no other alternatives, because unfortunately some things don't support it. For everything else, use the more modern APIs.

That was my point. I know you can use regions for this. I also know from experience that it's not necessarily a good idea.

Niko Suni

The fact that people sometimes use them that way does not negate the fact that this was not part of their design.

They were not designed for it. The API does not directly support it. Many people have discovered the pattern that you described above, a manual per-pixel creation of regions that consume a huge amount of resources to initially create.

They were not meant for that, they are a bad tool for per-pixel cutouts. They are slow to generate and slow to render... plus there are alternatives that are designed to properly handle transparency.

There are very few times that regions are the only way to accomplish cutouts inside Windows. If you happen to be in one of those very few uses then a region may be your tool of last resort.

But it should not be a go-to tool. Windows supports transparency and even alpha-blending for almost everything. Use per-pixel regions if no other alternatives, because unfortunately some things don't support it. For everything else, use the more modern APIs.

i don't use window 8. almost people. i belive, uses the windows 7.

the WS_EX_TRANSPARENT isn't compatible with WS_CLIPCHILDREN :(

Advertisement
This is a interesting read on WS_EX_TRANSPARENT. It might not do what you think it does:

http://blogs.msdn.com/b/oldnewthing/archive/2012/12/17/10378525.aspx

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

This is a interesting read on WS_EX_TRANSPARENT. It might not do what you think it does:

http://blogs.msdn.com/b/oldnewthing/archive/2012/12/17/10378525.aspx

true... the Microsoft can be more complicated than it's lol

heres the Region function working:


//nice function for get the HBITMAP pixels with DIB's ;)
BYTE* Get24BitPixels(HBITMAP pBitmap, WORD *pwWidth, WORD *pwHeight)
{
  // a bitmap object just to get bitmap width and height
	BITMAP bmpBmp;

  // pointer to original bitmap info
	LPBITMAPINFO pbmiInfo;

  // bitmap info will hold the new 24bit bitmap info
  BITMAPINFO bmiInfo;

  // width and height of the bitmap
  WORD wBmpWidth, wBmpHeight;

  // ---------------------------------------------------------
  // get some info from the bitmap
  // ---------------------------------------------------------
	GetObject(pBitmap, sizeof(bmpBmp),&bmpBmp);
  pbmiInfo   = (LPBITMAPINFO)&bmpBmp;

  // get width and height
	wBmpWidth  = (WORD)pbmiInfo->bmiHeader.biWidth;
	wBmpWidth -= (wBmpWidth%4);                       // width is 4 byte boundary aligned.
	wBmpHeight = (WORD)pbmiInfo->bmiHeader.biHeight;

  // copy to caller width and height parms
  *pwWidth  = wBmpWidth;
  *pwHeight = wBmpHeight;
  // ---------------------------------------------------------

	// allocate width * height * 24bits pixels
  BYTE *pPixels = new BYTE[wBmpWidth*wBmpHeight*3];
	if (!pPixels) return NULL;

  // get user desktop device context to get pixels from
	HDC hDC = GetWindowDC(NULL);

  // fill desired structure
	bmiInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmiInfo.bmiHeader.biWidth = wBmpWidth;
	bmiInfo.bmiHeader.biHeight = -wBmpHeight;
	bmiInfo.bmiHeader.biPlanes = 1;
	bmiInfo.bmiHeader.biBitCount = 24;
	bmiInfo.bmiHeader.biCompression = BI_RGB;
	bmiInfo.bmiHeader.biSizeImage = wBmpWidth*wBmpHeight*3;
	bmiInfo.bmiHeader.biXPelsPerMeter = 0;
	bmiInfo.bmiHeader.biYPelsPerMeter = 0;
	bmiInfo.bmiHeader.biClrUsed = 0;
	bmiInfo.bmiHeader.biClrImportant = 0;

  // get pixels from the original bitmap converted to 24bits
  int iRes = GetDIBits(hDC,pBitmap,0,wBmpHeight,(LPVOID)pPixels,&bmiInfo,DIB_RGB_COLORS);

  // release the device context
	ReleaseDC(NULL,hDC);

  // if failed, cancel the operation.
	if (!iRes)
  {
    delete pPixels;
    return NULL;
  };

  // return the pixel array
	return pPixels;
}

HRGN RegionbyBitmap(HBITMAP pBitmap,COLORREF clrTransparent=-1 )
{
    BYTE jTranspR = GetRValue(clrTransparent), jTranspG=GetGValue(clrTransparent), jTranspB=GetBValue(clrTransparent);
  // bitmap width and height
  WORD wBmpWidth,wBmpHeight;

  // the final region and a temporary region
  HRGN hRgn, hTmpRgn;

  // 24bit pixels from the bitmap
  BYTE *pPixels = Get24BitPixels(pBitmap, &wBmpWidth, &wBmpHeight);
  if (!pPixels) return NULL;

  // create our working region
  hRgn = CreateRectRgn(0,0,wBmpWidth,wBmpHeight);
  if (!hRgn) { delete pPixels; return NULL; }

  // ---------------------------------------------------------
  // scan the bitmap
  // ---------------------------------------------------------
  DWORD p=0;
  for (WORD y=0; y<wBmpHeight; y++)
  {
    for (WORD x=0; x<wBmpWidth; x++)
    {
      BYTE jRed   = pPixels[p+2];
      BYTE jGreen = pPixels[p+1];
      BYTE jBlue  = pPixels[p+0];

      if ((jRed == jTranspR && jGreen == jTranspG && jBlue == jTranspB))
      {
        // remove transparent color from region
        hTmpRgn = CreateRectRgn(x,y,x+1,y+1);
        CombineRgn(hRgn, hRgn, hTmpRgn, RGN_XOR);
        DeleteObject(hTmpRgn);
      }

      // next pixel
      p+=3;
    }
  }

  // release pixels
  delete pPixels;

  // return the region
  return hRgn;
}

heres how use it:


if(inst->blnTransparent==true)
                {
                    TransparentBlt(test.hdc,0,0,imglabel.width(),imglabel.height(),imglabel,0,0, imglabel.width(),imglabel.height(), inst->clrBackColor);
                    inst->LabelRegion=RegionbyBitmap(imglabel, inst->clrBackColor);
                    SetWindowRgn(inst->hwnd,inst->LabelRegion,TRUE);

                }

now the child control is realy showed 'transparent'... what i mean is that the child control shape is the bitmap shape ;)

thanks to all

why i'm receiving negative reputation on #3 if i'm right?

only after windows 8(and windows 8 can use layed with child controls)

from: https://msdn.microsoft.com/en-us/library/windows/desktop/ff700543%28v=vs.85%29.aspx

we read:

WS_EX_LAYERED 0x00080000

The window is a layered window. This style cannot be used if the window has a class style of either CS_OWNDC or CS_CLASSDC.

Windows 8: The WS_EX_LAYERED style is supported for top-level windows and child windows. Previous Windows versions support WS_EX_LAYERED only for top-level windows.

The same member has voted down all your posts across multiple threads. Normally, I would tell you to ignore it, but looking at his reputation, he votes down more than he votes up. This goes against the purpose of the rating system.

He appears to be a troll. Consider messaging a moderator about this.

This topic is closed to new replies.

Advertisement