unit unit2;
{$mode objfpc}{$H+}
interface
uses
Windows, Messages, Types, GraphType,
Classes , SysUtils , Forms , Controls , Graphics ,
Dialogs , StdCtrls , ExtCtrls , Buttons;
type
TResizeMode = (rmNone, rmTop, rmLeft, rmRight, rmBottom, rmTopLeft, rmTopRight, rmBottomLeft, rmBottomRight);
TFormState = (fsNormal, fsMaximized, fsMinimized);
type
{ TForm1 }
TForm1 = class(TForm)
btnExit: TBitBtn;
btnMax: TBitBtn;
btnMin: TBitBtn;
Button1: TButton;
imgIcon: TImage;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
lblCaption: TLabel;
pnlClientArea: TPanel;
pnlCaption: TPanel;
pnlBottom: TPanel;
pnlTop: TPanel;
pnlLeft: TPanel;
pnlRight: TPanel;
procedure FormCreate(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X , Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X , Y: Integer
);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X , Y: Integer);
procedure pnlCaptionMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X , Y: Integer);
strict private
FResizeMode: TResizeMode;
FResizeRect: TRect;
FResizing: Boolean;
FDesktopBitmap: HBITMAP;
private
procedure DrawRectangleOnDesktop(const ALeft, ATop, AWidth, AHeight: Integer);
procedure CaptureDesktop;
procedure ClearRectangleFromDesktop;
protected
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
FResizeMode := rmNone;
FResizing := False;
FResizeRect := Rect(0, 0, 0, 0);
imgIcon.Picture.Icon.Assign(Application.Icon);
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X , Y: Integer);
begin
CaptureDesktop;
if (Button = mbLeft) and (FResizeMode <> rmNone) then
FResizing := True;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X , Y: Integer);
begin
if FResizing then
begin
ClearRectangleFromDesktop;
FResizeRect := Rect(0, 0, 0, 0);
FResizing := False;
end;
//todo: resize window to the new dimensions by taking care of positions
end;
procedure TForm1.CaptureDesktop;
var
DesktopDC, MemDC: HDC;
begin
DesktopDC := GetDC(GetDesktopWindow);
MemDC := CreateCompatibleDC(DesktopDC);
FDesktopBitmap := CreateCompatibleBitmap(DesktopDC, Screen.Width, Screen.Height);
SelectObject(MemDC, FDesktopBitmap);
BitBlt(MemDC, 0, 0, Screen.Width, Screen.Height, DesktopDC, 0, 0, SRCCOPY);
ReleaseDC(GetDesktopWindow, DesktopDC);
DeleteDC(MemDC);
end;
procedure TForm1.ClearRectangleFromDesktop;
var
DesktopDC, MemDC: HDC;
begin
DesktopDC := GetDC(GetDesktopWindow);
MemDC := CreateCompatibleDC(DesktopDC);
SelectObject(MemDC, FDesktopBitmap);
BitBlt(DesktopDC, 0, 0, Screen.Width, Screen.Height, MemDC, 0, 0, SRCCOPY);
ReleaseDC(GetDesktopWindow, DesktopDC);
DeleteDC(MemDC);
end;
procedure TForm1.DrawRectangleOnDesktop(const ALeft, ATop, AWidth, AHeight: Integer);
var
DesktopDC: HDC;
begin
DesktopDC := GetDC(GetDesktopWindow);
try
with TCanvas.Create do
begin
Handle := DesktopDC;
Pen.Color := clRed;
Pen.Width := 2;
Brush.Color := clNone;
Brush.Style := bsClear;
Rectangle(ALeft, ATop, AWidth, AHeight);
Free;
end;
finally
ReleaseDC(GetDesktopWindow, DesktopDC);
end;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X ,
Y: Integer);
var
ctrl: TControl;
pt1, pt2: TPoint;
begin
pt1 := ScreenToClient(Mouse.CursorPos);
ctrl := ControlAtPos(pt1, [capfRecursive, capfAllowWinControls]);
if ((not FResizing) and Assigned(ctrl)) then
begin
Label2.Caption := ctrl.Name;
if ctrl.Name = 'pnlTop' then
begin
if ((pt1.Y >= 0) and (pt1.Y <= pnlTop.Height)) then
FResizeMode := rmTop;
if ((pt1.X >= 0) and (pt1.X <= pnlTop.Height)) then
FResizeMode := rmTopLeft;
if ((pt1.X >= pnlTop.Width - pnlTop.Height) and (pt1.X <= pnlTop.Width)) then
FResizeMode := rmTopRight;
end;
if ctrl.Name = 'pnlBottom' then
begin
if ((pt1.Y >= (Self.Height - pnlBottom.Height)) and (pt1.Y <= Self.Height)) then
FResizeMode := rmBottom;
if ((pt1.X >= 0) and (pt1.X <= pnlBottom.Height)) then
FResizeMode := rmBottomLeft;
if ((pt1.X >= pnlBottom.Width - pnlBottom.Height) and (pt1.X <= pnlBottom.Width)) then
FResizeMode := rmBottomRight;
end;
if ctrl.Name = 'pnlLeft' then
begin
if ((pt1.X >= 0) and (pt1.X <= pnlLeft.Width)) then
FResizeMode := rmLeft;
if ((pt1.Y >= 0) and (pt1.Y <= pnlLeft.Width)) then
FResizeMode := rmTopLeft;
if ((pt1.Y >= (Self.Height - pnlLeft.Width - 5)) and (pt1.X <= pnlLeft.Width)) then
FResizeMode := rmBottomLeft;
end;
if ctrl.Name = 'pnlRight' then
begin
if ((pt1.X >= (Self.Width - pnlRight.Width)) and (pt1.X <= Self.Width)) then
FResizeMode := rmRight;
if ((pt1.Y >= 0) and (pt1.Y <= pnlLeft.Width)) then
FResizeMode := rmTopRight;
if ((pt1.Y >= (Self.Height - pnlRight.Width - 5)) and (pt1.X <= Self.Width)) then
FResizeMode := rmBottomRight;
end;
Label1.Caption := Format('x: %d, y: %d', [pt1.x, pt1.y]);
case FResizeMode of
rmNone : begin pnlTop.Cursor := crDefault; pnlLeft.Cursor := crDefault; pnlRight.Cursor := crDefault; pnlBottom.Cursor := crDefault; end;
rmTop, rmBottom : begin pnlTop.Cursor := crSizeNS; pnlBottom.Cursor := crSizeNS; end;
rmLeft, rmRight : begin pnlLeft.Cursor := crSizeWE; pnlRight.Cursor := crSizeWE; end;
rmTopLeft, rmBottomRight: begin pnlTop.Cursor := crSizeNWSE; pnlLeft.Cursor := crSizeNWSE; pnlRight.Cursor := crSizeNWSE; pnlBottom.Cursor := crSizeNWSE; end;
rmTopRight, rmBottomLeft: begin pnlTop.Cursor := crSizeNESW; pnlLeft.Cursor := crSizeNESW; pnlRight.Cursor := crSizeNESW; pnlBottom.Cursor := crSizeNESW; end;
end;
end;
if (FResizing and (FResizeMode <> rmNone)) then
begin
FResizeRect := Self.ClientRect;
case FResizeMode of
rmTop : ; //- begin Self.Top := pt.Y; Self.Height := ABS(pt.Y); end;
rmBottom : FResizeRect.Height := pt1.Y; //+ Self.Height := pt.Y;
rmLeft : ; //- Self.Width := ABS(pt.X);
rmRight : FResizeRect.Width := pt1.X; //+ Self.Width := pt.X;
rmTopLeft : ;
rmBottomRight : begin Self.Height := pt1.Y; Self.Width := pt1.X; end;
rmTopRight : ; //- begin Self.Height := pt.Y; Self.Width := pt.X; end;
rmBottomLeft : ;
end;
pt2 := ClientToScreen(pt1);
ClearRectangleFromDesktop;
// my calculations are not matching :-(
DrawRectangleOnDesktop(pt2.X, pt2.Y, FResizeRect.Width, FResizeRect.Height);
end;
end;
procedure TForm1.pnlCaptionMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X , Y: Integer);
begin
ReleaseCapture;
SendMessage(Self.Handle, WM_SYSCOMMAND, SC_MOVE or HTCAPTION, 0);
end;
end.