如何绘制一个圆角窗体,并能移动和通过拖拽改变大小。
解决方案 »
- 如何在FR中动态显示图片?
- 请问,Fastreport有没有办法让pagefooter和masterdata连在一起?
- 请各位大侠帮小弟看看下面的算法代码,总是和预期的目标有所出入,请指正,谢谢!
- 怎么建立个对话框?
- 这几天我的可用分,怎么一直没增加?是不是因为这个?http://community.csdn.net/Expert/topic/3069/3069678.xml?temp=.4146692
- 莱鸟问题,如何用两个TADOquery建立主从表,需要运行效率最好
- 为什么会出错?
- 调用过程
- 用delphi如何开发向手机发短信的程序?
- sql server 2000
- cxgrid 单元格赋值 效率太慢问题。。
- 关于结构体数组的传递问题,急。。。。,DLL
begin
SetwindowRgn(Handle, CreateRoundRectRgn(0, 0, Width, Height, 25, 25), True);
end;
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;type
TForm1 = class(TForm)
Button1: TButton;
Image1: TImage;
procedure Button1Click(Sender: TObject);
procedure FormResize(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure SetTheRegion;
procedure WMEraseBkGnd(var Msg: TWMEraseBkGnd); message WM_ERASEBKGND;
procedure WMNCHitTest(var msg: TWMNCHitTest); message WM_NCHITTEST;
end;var
Form1: TForm1;implementationuses BmpRgn;{$R *.dfm}procedure TForm1.SetTheRegion;
var
HR: HRGN;
begin
Image1.Picture.Bitmap.Width := Self.Width;
Image1.Picture.Bitmap.Height := Self.Height;
BitBlt(Image1.Picture.Bitmap.Canvas.Handle, 0, 0, Width, Height, GetWindowDC(Handle), 0, 0, SRCCOPY); HR := BmpToRegion(Self, Image1.Picture.Bitmap);
SetWindowRgn(handle, HR, true);
Invalidate;
end;procedure TForm1.WMEraseBkGnd(var Msg: TWMEraseBkGnd);
var
Brush: TBrush;
begin
Brush := TBrush.Create;
Brush.Color := Color;
FillRect(Msg.DC, ClientRect, Brush.Handle);
Brush.Free;
with Image1.Picture.Bitmap do
BitBlt(Msg.DC, 0, 0, Width, Height, Canvas.Handle, 0, 0, SRCCOPY);
Msg.Result := 1;
end;procedure TForm1.WMNCHitTest(var msg: TWMNCHitTest);
var
i: integer;
p: TPoint;
AControl: TControl;
MouseOnControl: boolean;
begin
inherited;
if msg.result = HTCLIENT then
begin
p.x := msg.XPos;
p.y := msg.YPos;
p := ScreenToClient(p);
MouseOnControl := false;
for i := 0 to ControlCount - 1 do
begin
if not MouseOnControl
then
begin
AControl := Controls[i];
if ((AControl is TWinControl) or (AControl is TGraphicControl))
and (AControl.Visible)
then MouseOnControl := PtInRect(AControl.BoundsRect, p);
end
else
break;
end;
if (not MouseOnControl) then msg.Result := HTCAPTION;
end;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
Close;
end;procedure TForm1.FormResize(Sender: TObject);
begin
//SetTheRegion;
SetwindowRgn(Handle, CreateRoundRectRgn(0, 0, Width, Height, 25, 25), True);
end;end.
那是直接用背景图片画的,给你个例子:调用:
unit uDetail;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, StdCtrls,
Buttons, ExtCtrls, Grids, DBGrids, DB;type
TfmDetail = class(TForm)
ImageAll: TImage;
LabTitle2: TLabel;
LabTitle1: TLabel;
Image3: TImage;
btClose: TSpeedButton;
DBGrid1: TDBGrid;
DataSource1: TDataSource;
procedure FormCreate(Sender: TObject);
procedure btCloseClick(Sender: TObject);
private
{ Private declarations }
procedure SetTheRegion;
procedure WMEraseBkGnd(var Msg: TWMEraseBkGnd); message WM_ERASEBKGND;
procedure WMNCHitTest(var msg: TWMNCHitTest); message WM_NCHITTEST;
public
{ Public declarations }
end;{var
fmDetail: TfmDetail;}implementationuses BmpRgn;{$R *.dfm}procedure TfmDetail.SetTheRegion;
var HR: HRGN;
begin
HR := BmpToRegion(Self, ImageAll.Picture.Bitmap);
SetWindowRgn(Handle, HR, true);
Invalidate;
end;procedure TfmDetail.FormCreate(Sender: TObject);
var
sImage: String;
begin
sImage := ExtractFilePath(Application.ExeName) + 'sDetail.bmp';
if FileExists(sImage) then
begin
ImageAll.Picture.LoadFromFile(sImage);
SetTheRegion;
end;
end;procedure TfmDetail.WMEraseBkGnd(var Msg: TWMEraseBkGnd);
var Brush: TBrush;
begin
Brush := TBrush.Create;
Brush.Color := Color;
FillRect(Msg.DC, ClientRect, Brush.Handle);
Brush.Free;
with ImageAll.Picture.Bitmap do
BitBlt( Msg.DC, 0, 0, Width, Height, Canvas.Handle, 0, 0, SRCCOPY);
Msg.Result := 1;
end;procedure TfmDetail.WMNCHitTest(var msg: TWMNCHitTest);
var
i: integer;
p: TPoint;
AControl: TControl;
MouseOnControl: boolean;
begin
inherited;
if msg.result = HTCLIENT then begin
p.x := msg.XPos;
p.y := msg.YPos;
p := ScreenToClient(p);
MouseOnControl := false;
for i := 0 to ControlCount-1 do begin
if not MouseOnControl
then begin
AControl := Controls[i];
if ((AControl is TWinControl) or (AControl is TGraphicControl))
and (AControl.Visible)
then MouseOnControl := PtInRect( AControl.BoundsRect, p);
end
else
break;
end;
if (not MouseOnControl) then msg.Result := HTCAPTION;
end;
end;
unit BmpRgn;interfaceuses
Windows,SysUtils, Classes, Graphics, Dialogs, Forms;(***************************************************************************)
(* This is the only function you need to call *)
(***************************************************************************)
(**) function BmpToRegion( Form: TForm; Bmp: tbitmap): HRGN; (**)
(***************************************************************************)
TYPE
TBooleanArray = array of array of boolean;
TPointsArray = array of TPoint; TRGBTripleRow =array[0..30000]of trgbtriple;
PRGBTripleRow=^TRGBTripleRow;
VAR
Mask: TBooleanArray;
Points: TPointsArray; BmpWidth: integer;
BmpHeight: integer;
MaskWidth: integer;
MaskHeight: integer;
PointCount: integer;CONST
ErrSuccess = 0;
ErrNoStart = -1;
ErrUnclosed = -2;
implementation(***************************************************************************)
(**) (**)
(* A few utility procedures and functions for debugging purposes *)
(**) (**)
(***************************************************************************)procedure ShowXY(s: string; x,y: integer);
begin
ShowMessage( Format('%s %d,%d',[s,x,y]));
end;
procedure DumpMask( filename: string);
var f: TextFile; x,y: integer; c: char;
begin
AssignFile( f, filename);
Rewrite(f);
for y := 0 to MaskHeight-1 do begin
for x := 0 to MaskWidth-1 do begin
if mask[x,y] then c := 'X' else c := '.';
Write(f,c);
end;
Writeln(f);
end;
CloseFile( f);
end;
procedure DumpPoints( filename: string);
var f: TextFile; i: integer;
begin
AssignFile( f, filename);
Rewrite( f);
if PointCount > 0 then begin
for i := 0 to PointCount-1 do begin
with Points[i] do writeln( f, Format('%d -> %d,%d',[i,x,y]));
end;
end else begin
writeln(f, 'Points array is empty');
end;
CloseFile( f);
end;
procedure Init( w,h: integer);
begin
BmpWidth := w+2;
BmpHeight := h+2;
MaskWidth := BmpWidth*3;
MaskHeight := BmpHeight*3;
PointCount := 0;
SetLength( Mask, MaskWidth, MaskHeight);
SetLength( Points, BmpWidth * BmpHeight);
end;
procedure CleanupPointers;
begin
Mask := nil;
Points := nil;
end;procedure CreateMask(var Bmp: TBitmap);
var
x,y:integer;
r,g,b: byte;
p: prgbtriplerow;
TranspColor: TColor;
Temp: TBitmap; procedure SetMaskValues( value: boolean);
var i,j: integer;
begin
for j := 0 to 2 do begin
for i := 0 to 2 do begin
mask[x*3+i,y*3+j] := value;
end;
end;
end;begin
TranspColor := Bmp.Canvas.Pixels[0,0];
r := GetRValue( TranspColor);
g := GetGValue( TranspColor);
b := GetBValue( TranspColor); Temp := TBitmap.Create;
with Temp do begin
Width := BmpWidth;
Height := BmpHeight;
Canvas.Brush.Color := TranspColor;
Canvas.FillRect( Rect(0,0,BmpWidth,BmpHeight));
Canvas.Draw(1,1,Bmp);
end;
Temp.PixelFormat := pf24bit; for y := 0 to BmpHeight-1 do begin
p := Temp.Scanline[y];
for x := 0 to BmpWidth-1 do begin
with p[x] do begin
// set mask to false for transparent pixels
if (rgbtred = r) and (rgbtgreen = g) and (rgbtblue = b)
then SetMaskValues( false)
else SetMaskValues( true);
end;
end;
end; Temp.Free;
end;function ConvertMaskToPoints: integer;
var
x,y: integer;
startx, starty: integer;
nextx, nexty: integer;
prev1x, prev1y: integer;
prev2x, prev2y: integer;
function Available(px,py: integer): boolean;
begin
result := (not ((px = prev1x) and (py = prev1y))) and
(not ((px = prev2x) and (py = prev2y)));
end; function OnEdge(px,py: integer): boolean;
begin
result := (not mask[px+0,py-1]) or // north
(not mask[px+1,py-1]) or // northeast
(not mask[px+1,py+0]) or // east
(not mask[px+1,py+1]) or // southeast
(not mask[px+0,py+1]) or // south
(not mask[px-1,py+1]) or // southwest
(not mask[px-1,py+0]) or // west
(not mask[px-1,py-1]); // northwest
end; function SamePoint( p1,p2: TPoint): boolean;
begin
result := (p1.x = p2.x) and (p1.y = p2.y);
end;begin
PointCount := 0; // find a coordinate where tracing can begin
startx := -1;
starty := -1;
for y := 0 to MaskHeight-1 do begin
for x := 0 to MaskWidth-1 do begin
if (startx < 0) or (starty < 0) then begin
if Mask[x,y] then begin
startx := x;
starty := y;
end;
end;
end;
end; // if no starting point found, exit
if (startx < 0) or (starty < 0) then begin
result := ErrNoStart;
exit;
end; // points coordinates are in actual size, not inflated size
PointCount := 1;
Points[0] := Point( startx div 3, starty div 3); // at startx,starty begin tracing counter of mask
nextx := startx;
nexty := starty;
x := startx;
y := starty;
if mask[x+1,y] then begin
nextx := x+1;
nexty := y;
end else
if mask[x,y+1] then begin
nextx := x;
nexty := y+1;
end; prev2x := 0;
prev2y := 0;
prev1x := x;
prev1y := y;
x := nextx;
y := nexty; repeat // north
if mask[x,y-1] and available(x,y-1) and onedge(x,y-1) then begin
nextx := x;
nexty := y-1;
end else
// east
if mask[x+1,y] and available(x+1,y) and onedge(x+1,y) then begin
nextx := x+1;
nexty := y;
end else
// south
if mask[x,y+1] and available(x,y+1) and onedge(x,y+1) then begin
nextx := x;
nexty := y+1;
end else
// west
if mask[x-1,y] and available(x-1,y) and onedge(x-1,y) then begin
nextx := x-1;
nexty := y;
end; // if next not found, then unclosed path so exit
if (nextx = x) and (nexty = y) then begin
ShowXY('Unclosed at ',x,y);
result := ErrUnclosed;
exit;
end; // if we're not back at the start, add nextx, nexty to points
if (nextx <> startx) or (nexty <> starty) then begin
if not SamePoint( Point(nextx div 3, nexty div 3), Points[ PointCount-1]) then begin
inc( PointCount);
Points[PointCount-1] := Point( nextx div 3, nexty div 3);
end;
prev2x := prev1x;
prev2y := prev1y;
prev1x := x;
prev1y := y;
x := nextx;
y := nexty;
end; until (nextx = startx) and (nexty = starty);
setlength( Points, PointCount);
result := ErrSuccess;
end;// This routine shifts each point by a fixed amount, to compensate
// for forms with differing border styles.
procedure ShiftPoints( var points: tpointsarray; pointcount, xdelta, ydelta: integer);
var i: integer;
begin
for i := 0 to pointcount-1 do begin
points[i].x := points[i].x+xdelta;
points[i].y := points[i].y+ydelta;
end;
end;// This routine follows the sequence of points in the outline and
// using LineTo commands, creates a closed path that can then be
// converted to a region.
function PointsToRegion( dc: hDC; points: tpointsarray; pointcount: integer): HRGN;
var i: integer;
begin
MoveToEx( dc, Points[0].x, Points[0].y, nil);
BeginPath( dc);
for i := 1 to pointcount-1 do with points[i] do lineto( dc, x,y);
EndPath( dc);
result := PathToRegion( dc);
end;
//---------------------------------------------------------------------
// This is the All-In-One routine and should be the only one that
// you need to call in your program. It calls everything above and
// if all goes well, Voila! - a form with a custom skin created from
// a bitmap.
//
// Parameters:
// Form - your form (usually Self) in the form's OnCreate handler
// Bmp - the bitmap to use for the form's region.
//
// Returns:
// If successful, a handle to the new region is returned which
// can then be passed to SetWindowRgn. If not successful, the
// return value is null, which can also be passed to SetWindowRgn
// but only serves to draw the entire form.
//----------------------------------------------------------------------
function BmpToRegion( Form: TForm; Bmp: tbitmap): HRGN;
var
DeltaX, DeltaY, Success: integer;
rgn: HRGN;
MenuHandle: HMENU;
begin Init( Bmp.Width, Bmp.Height);
CreateMask( Bmp);
Success := ConvertMaskToPoints; if Success = errSuccess then begin DeltaX := -1;
DeltaY := -1;
case Form.BorderStyle of bsDialog:
begin
DeltaX := DeltaX+GetSystemMetrics( sm_cxFixedFrame);
DeltaY := DeltaY+GetSystemMetrics( sm_cyFixedFrame)
+GetSystemMetrics( sm_cyCaption);
end;
bsSingle:
begin
DeltaX := DeltaX+GetSystemMetrics( sm_cxFixedFrame);
DeltaY := DeltaY+GetSystemMetrics( sm_cyFixedFrame)
+GetSystemMetrics( sm_cyCaption);
end;
bsSizeable:
begin
DeltaX := DeltaX+GetSystemMetrics( sm_cxSizeFrame);
DeltaY := DeltaY+GetSystemMetrics( sm_cySizeFrame)
+GetSystemMetrics( sm_cyCaption);
end;
bsSizeToolWin:
begin
DeltaX := DeltaX+GetSystemMetrics( sm_cxSizeFrame);
DeltaY := DeltaY+GetSystemMetrics( sm_cySizeFrame)
+GetSystemMetrics( sm_cySMCaption);
end;
bsToolWindow:
begin
DeltaX := DeltaX+GetSystemMetrics( sm_cxFixedFrame);
DeltaY := DeltaY+GetSystemMetrics( sm_cyFixedFrame)
+GetSystemMetrics( sm_cySMCaption);
end;
end; MenuHandle := GetMenu( Form.Handle);
if MenuHandle <> 0
then DeltaY := DeltaY + GetSystemMetrics( sm_cyMenu); ShiftPoints( Points, PointCount, DeltaX, DeltaY);
rgn := PointsToRegion( Bmp.Canvas.Handle, Points, PointCount); end else begin
rgn := 0;
end; CleanupPointers;
result := rgn;
end;end.
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, pngimage;type
TfrmMain = class(TForm)
Image1: TImage;
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
procedure WMNCHITTEST(var msg: TWMNCHitTest); message WM_NCHITTEST; public
{ Public declarations }
end;var
frmMain: TfrmMain;implementation{$R *.dfm}const
arr: array[-2..21] of string = (
'HTERROR',
'HTTRANSPARENT',
'HTNOWHERE',
'HTCLIENT - 客户区',
'HTCAPTION - 标题',
'HTSYSMENU - 系统菜单',
'HTGROWBOX',
'HTMENU - 菜单',
'HTHSCROLL - 水平滚动条',
'HTVSCROLL - 垂直滚动条',
'HTMINBUTTON - 最小化按钮',
'HTMAXBUTTON - 最大化按钮',
'HTLEFT - 左边界',
'HTRIG - 右边界',
'HTTOP - 上边界',
'HTTOPLEFT - 左上角',
'HTTOPRIG - 右上角',
'HTBOTTOM - 下边界',
'HTBOTTOMLEFT - 左下角',
'HTBOTTOMRIG - 右下角',
'HTBORDER',
'HTOBJECT',
'HTCLOSE - 关闭按钮',
'HTHELP');procedure TfrmMain.WMNCHITTEST(var msg: TWMNCHitTest); //确定鼠标落的位置
var
ix, iy: Integer;
begin
inherited; ix := msg.XPos;
iy := msg.YPos; if (ix >= Left + Width - 2) and (iy >= Top + Height - 2) then
begin
Msg.Result := HTBOTTOMRIGHT; //右下角
end
else if (ix <= Left + 2) and (iy >= Top + Height - 2) then
begin
Msg.Result := HTBOTTOMLEFT; //左下角
end else if (ix <= Left + 2) and (iy <= Top + 2) then
begin
Msg.Result := HTTOPLEFT; //左上角
end
else if (ix >= Left + Width - 2) and (iy <= Top + 2) then
begin
Msg.Result := HTTOPRIGHT; //右上角
end
else if (ix >= Left) and (ix <= left + 2) and (iy >= Top + 2) then
begin
Msg.Result := HTLEFT; // 左边界
end
else if (ix >= Left + Width - 2) then
begin
Msg.Result := HTRIGHT; //右边界
end
else if (iy <= Top + 2) then
begin
Msg.Result := HTTOP; //上边界
end
else if (iy >= Top + Height - 2) then
begin
Msg.Result := HTBOTTOM; //底部
end
else if ((ix >= left)) and ((iy >= top + 2) and (iy <= top + 50)) then
begin
Msg.Result := HTCAPTION; //标题栏
end;
end;
procedure TfrmMain.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if (ssleft in Shift) then //鼠标左键
begin
ReleaseCapture; Perform(WM_syscommand, $F012, 0);end;
end;procedure TfrmMain.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if (ssleft in Shift) then //鼠标左键begin
ReleaseCapture; Perform(WM_syscommand, $F012, 0);end;
end;end.