分享

delphi

 quasiceo 2013-10-23

I tried to do with SetWindowRgn, and I couldn't.

Can do that (the top 2 corners are rounded, the window has a shadow) like on this picture?

enter image description here

asked Feb 13 '12 at 9:27
maxfax
1,6451158

2  
Which version you are using , if XE2 VCL styles are there –  VibeeshanRC Feb 13 '12 at 10:18

 
What's your OS? –  menjaraz Feb 13 '12 at 11:22

 
Isn't this the default behaviour on Windows 7? –  Uwe Raabe Feb 13 '12 at 11:23
2  
@Uwe, no it isn't in case you have BorderStyle set to the bsNone or e.g. in case you have custom shaped form. –  TLama Feb 13 '12 at 11:25

 
XE2 VCL, Windows 7 –  maxfax Feb 14 '12 at 3:49

1 Answer

up vote 11 down vote accepted

Here is a code sample of how to set the window region with shadow:
(Notes: The Form BorderStyle assumed to be bsNone, not re-sizable)

type
TForm1 = class(TForm)
  procedure FormCreate(Sender: TObject);
private
  procedure CreateFlatRoundRgn;
protected
  procedure CreateParams(var Params: TCreateParams); override;
public
end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure ExcludeRectRgn(var Rgn: HRGN; LeftRect, TopRect, RightRect, BottomRect: Integer);
var
  RgnEx: HRGN;
begin
  RgnEx := CreateRectRgn(LeftRect, TopRect, RightRect, BottomRect);
  CombineRgn(Rgn, Rgn, RgnEx, RGN_OR);
  DeleteObject(RgnEx);
end;

procedure TForm1.CreateFlatRoundRgn;
const
  CORNER_SIZE = 6;
var
  Rgn: HRGN;
begin
  with BoundsRect do
  begin
    Rgn := CreateRoundRectRgn(0, 0, Right - Left + 1, Bottom - Top + 1, CORNER_SIZE, CORNER_SIZE);
    // exclude left-bottom corner
    ExcludeRectRgn(Rgn, 0, Bottom - Top - CORNER_SIZE div 2, CORNER_SIZE div 2, Bottom - Top + 1);
    // exclude right-bottom corner
    ExcludeRectRgn(Rgn, Right - Left - CORNER_SIZE div 2, Bottom - Top - CORNER_SIZE div 2, Right - Left , Bottom - Top);
  end;
  // the operating system owns the region, delete the Rgn only SetWindowRgn fails
  if SetWindowRgn(Handle, Rgn, True) = 0 then
    DeleteObject(Rgn);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  BorderStyle := bsNone;
  CreateFlatRoundRgn;
end;

procedure TForm1.CreateParams(var Params: TCreateParams);
const
  CS_DROPSHADOW = $00020000;
begin
  inherited CreateParams(Params);
  with Params do
  begin
    Style := WS_POPUP;
    WindowClass.Style := WindowClass.Style or CS_DROPSHADOW;
  end;
end;

Another way to draw a custom shadow would be to set Window WS_EX_LAYERED and use UpdateLayeredWindow

Here is a very good example of how it's done (sources are in C++ but very easy to understand)

For more complicated shapes you can use a PNG image on the form and Alpha Blend it.


EDIT:

Resizing a WS_POPUP Window is a world of pain... You have a few options:

NOTE that you need to re-create the Window region when you re-size it (e.g OnResize event).

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约