2005. március 20., vasárnap

How to clip the client area of a form using regions


Problem/Question/Abstract:

I'm trying to produce a form that has transparent areas in it (no border or title with odd shape edges/ holes). I've successfully done this; the problem I'm having is the refreshing of the transparent areas. I have an idea form the conceptual point of what to do, but was hoping some could let me know if this sounds like it would work, and any technical information on how to do it.

I want to pass the WM_PAINT message that my form gets on to the window(s) underneath my form, so that those windows refresh themselves. Then, only after the window(s) beneath my form finish refreshing, I want to refresh my form (act on the WM_PAINT message in a normal manner).

Answer:

While the method you are attempting to use could work, it's much easier to use SetWindowRgn().

This API function will associate an HRGN with your window. This region will be used to determine the area your window is allowed to paint in:


procedure CutOutClient(pForm: TForm);
var
  rgnCenter: HRGN;
  rcWindow: TRect;
  rcClient: TRect;
begin
  GetWindowRect(pForm.Handle, rcWindow);
  Windows.GetClientRect(pForm.Handle, rcClient);
  MapWindowPoints(pForm.Handle, HWND_DESKTOP, rcClient, 2);
  OffsetRect(rcClient, -rcWindow.Left, -rcWindow.Top);
  rgnCenter := CreateRectRgnIndirect(rcClient);
  try
    SetWindowRgn(pForm.Handle, rgnCenter, IsWindowVisible(pForm.Handle));
  finally
    DeleteObject(rgnCenter);
  end;
end;


This procedure should clip the client area from your form. To extend this, you simply need to create a different region. See the CreateEllipticRgn, CreatePolygonRgn, CreateRectRgn, and CombineRgn (as well as a few others).

Nincsenek megjegyzések:

Megjegyzés küldése