Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate an area of a Windows region (HRGN) in pixels?

What is the fastest way of getting the area of any arbitrary Windows region?

I know I can enumerate all points of bounding rectangle and call the PtInRegion() function but it seems not very fast. Maybe you know some faster way?

like image 431
Andrew Avatar asked Dec 26 '22 21:12

Andrew


1 Answers

When you call GetRegionData, you'll get a list of non-overlapping rectangles that make up the region. Add up their areas, something like this:

function GetRegionArea(rgn: HRgn): Cardinal;
var
  x: DWord;
  Data: PRgnData;
  Header: PRgnDataHeader;
  Rects: PRect;
  Width, Height: Integer;
  i: Integer;
begin
  x := GetRegionData(rgn, 0, nil);
  Win32Check(x <> 0);
  GetMem(Data, x);
  try
    x := GetRegionData(rgn, x, Data);
    Win32Check(x <> 0);
    Header := PRgnDataHeader(Data);
    Assert(Header.iType = rdh_Rectangles);

    Assert(Header.dwSize = SizeOf(Header^));
    Rects := PRect(Cardinal(Header) + Header.dwSize);
    // equivalent: Rects := PRect(@Data.Buffer);

    Result := 0;
    for i := 0 to Pred(Header.nCount) do begin
      Width := Rects.Right - Rects.Left;
      Height := Rects.Bottom - Rects.Top;
      Inc(Result, Width * Height);
      Inc(Rects);
    end;
  finally
    FreeMem(Data);
  end;
end;
like image 90
Rob Kennedy Avatar answered Mar 04 '23 14:03

Rob Kennedy