| 1 | unit Xvcl.Controls;
|
|---|
| 2 |
|
|---|
| 3 | interface
|
|---|
| 4 |
|
|---|
| 5 | uses
|
|---|
| 6 | Xvcl.Generics, Xvcl.Classes, Xvcl.Graphics;
|
|---|
| 7 |
|
|---|
| 8 | type
|
|---|
| 9 | TControl = class;
|
|---|
| 10 | TWinControl = class;
|
|---|
| 11 |
|
|---|
| 12 | TMessage = class
|
|---|
| 13 | Number: Integer;
|
|---|
| 14 | Handled: Boolean;
|
|---|
| 15 | end;
|
|---|
| 16 |
|
|---|
| 17 | TMouseButton = (mbLeft, mbRight, mbMiddle);
|
|---|
| 18 | TMouseButtonSet = set of TMouseButton;
|
|---|
| 19 | TMessageMouse = class(TMessage)
|
|---|
| 20 | Position: TPoint;
|
|---|
| 21 | Buttons: TMouseButtonSet;
|
|---|
| 22 | end;
|
|---|
| 23 | TMessageMouseDown = class(TMessageMouse);
|
|---|
| 24 | TMessageMouseUp = class(TMessageMouse);
|
|---|
| 25 | TMessageMouseMove = class(TMessageMouse);
|
|---|
| 26 |
|
|---|
| 27 | TKeyState = (ksShift, ksAlt, ksOS);
|
|---|
| 28 | TKeyStateSet = set of TKeyState;
|
|---|
| 29 | TMessageKeyboard = class(TMessage)
|
|---|
| 30 | KeyCode: Integer;
|
|---|
| 31 | States: TKeyStateSet;
|
|---|
| 32 | end;
|
|---|
| 33 |
|
|---|
| 34 | TControlCanvas = class(TCanvas)
|
|---|
| 35 | protected
|
|---|
| 36 | function GetVideoDevice: TVideoDevice; override;
|
|---|
| 37 | public
|
|---|
| 38 | Control: TControl;
|
|---|
| 39 | function AdjustPos(Position: TPoint): TPoint; override;
|
|---|
| 40 | end;
|
|---|
| 41 |
|
|---|
| 42 | TControlMove = class
|
|---|
| 43 | Control: TControl;
|
|---|
| 44 | StartControlPos: TPoint;
|
|---|
| 45 | StartMousePos: TPoint;
|
|---|
| 46 | Active: Boolean;
|
|---|
| 47 | end;
|
|---|
| 48 |
|
|---|
| 49 | TControl = class(TComponent)
|
|---|
| 50 | private
|
|---|
| 51 | FCanvas: TControlCanvas;
|
|---|
| 52 | FParent: TWinControl;
|
|---|
| 53 | FVisible: Boolean;
|
|---|
| 54 | FBounds: TRectangle;
|
|---|
| 55 | FOnClick: TNotifyEvent;
|
|---|
| 56 | FColor: TColor;
|
|---|
| 57 | FOnMouseDown: TNotifyEvent;
|
|---|
| 58 | FOnMouseUp: TNotifyEvent;
|
|---|
| 59 | function GetCanvas: TCanvas;
|
|---|
| 60 | procedure SetParent(const Value: TWinControl); virtual;
|
|---|
| 61 | procedure SetColor(const Value: TColor);
|
|---|
| 62 | protected
|
|---|
| 63 | function GetVideoDevice: TVideoDevice; virtual;
|
|---|
| 64 | function HandleMessage(Message: TMessage): Boolean; virtual;
|
|---|
| 65 | public
|
|---|
| 66 | Move: TControlMove;
|
|---|
| 67 | function ClientToScreen(Position: TPoint): TPoint; virtual;
|
|---|
| 68 | function ScreenToClient(Position: TPoint): TPoint; virtual;
|
|---|
| 69 | procedure Paint; virtual;
|
|---|
| 70 | constructor Create; override;
|
|---|
| 71 | destructor Destroy; override;
|
|---|
| 72 | property Bounds: TRectangle read FBounds write FBounds;
|
|---|
| 73 | property Visible: Boolean read FVisible write FVisible;
|
|---|
| 74 | property Canvas: TCanvas read GetCanvas;
|
|---|
| 75 | property Parent: TWinControl read FParent write SetParent;
|
|---|
| 76 | property VideoDevice: TVideoDevice read GetVideoDevice;
|
|---|
| 77 | property Color: TColor read FColor write SetColor;
|
|---|
| 78 | property OnClick: TNotifyEvent read FOnClick write FOnClick;
|
|---|
| 79 | property OnMouseDown: TNotifyEvent read FOnMouseDown write FOnMouseDown;
|
|---|
| 80 | property OnMouseUp: TNotifyEvent read FOnMouseUp write FOnMouseUp;
|
|---|
| 81 | end;
|
|---|
| 82 |
|
|---|
| 83 | TWinControl = class(TControl)
|
|---|
| 84 | protected
|
|---|
| 85 | function HandleMessage(Message: TMessage): Boolean; override;
|
|---|
| 86 | public
|
|---|
| 87 | Controls: TList<TControl>;
|
|---|
| 88 | procedure Paint; override;
|
|---|
| 89 | constructor Create; override;
|
|---|
| 90 | destructor Destroy; override;
|
|---|
| 91 | end;
|
|---|
| 92 |
|
|---|
| 93 | TButton = class(TControl)
|
|---|
| 94 | private
|
|---|
| 95 | FCaption: string;
|
|---|
| 96 | procedure SetCaption(const Value: string);
|
|---|
| 97 | public
|
|---|
| 98 | procedure Paint; override;
|
|---|
| 99 | constructor Create; override;
|
|---|
| 100 | property Caption: string read FCaption write SetCaption;
|
|---|
| 101 | end;
|
|---|
| 102 |
|
|---|
| 103 | TLabel = class(TControl)
|
|---|
| 104 | private
|
|---|
| 105 | FCaption: string;
|
|---|
| 106 | procedure SetCaption(const Value: string);
|
|---|
| 107 | public
|
|---|
| 108 | procedure Paint; override;
|
|---|
| 109 | property Caption: string read FCaption write SetCaption;
|
|---|
| 110 | end;
|
|---|
| 111 |
|
|---|
| 112 |
|
|---|
| 113 | implementation
|
|---|
| 114 |
|
|---|
| 115 | { TControl }
|
|---|
| 116 |
|
|---|
| 117 | function TControl.ClientToScreen(Position: TPoint): TPoint;
|
|---|
| 118 | begin
|
|---|
| 119 | Result := Position.Add(Bounds.TopLeft);
|
|---|
| 120 | if Assigned(Parent) then Result := Parent.ClientToScreen(Result);
|
|---|
| 121 | end;
|
|---|
| 122 |
|
|---|
| 123 | constructor TControl.Create;
|
|---|
| 124 | begin
|
|---|
| 125 | inherited;
|
|---|
| 126 | Move := TControlMove.Create;
|
|---|
| 127 | FColor := clWhite;
|
|---|
| 128 | end;
|
|---|
| 129 |
|
|---|
| 130 | destructor TControl.Destroy;
|
|---|
| 131 | begin
|
|---|
| 132 | Move.Destroy;
|
|---|
| 133 | if Assigned(FCanvas) then FCanvas.Destroy;
|
|---|
| 134 | inherited;
|
|---|
| 135 | end;
|
|---|
| 136 |
|
|---|
| 137 | function TControl.GetCanvas: TCanvas;
|
|---|
| 138 | begin
|
|---|
| 139 | if not Assigned(FCanvas) then begin
|
|---|
| 140 | FCanvas := TControlCanvas.Create;
|
|---|
| 141 | FCanvas.Control := Self;
|
|---|
| 142 | end;
|
|---|
| 143 | Result := FCanvas;
|
|---|
| 144 | end;
|
|---|
| 145 |
|
|---|
| 146 | function TControl.GetVideoDevice: TVideoDevice;
|
|---|
| 147 | begin
|
|---|
| 148 | if Assigned(Parent) then Result := Parent.VideoDevice
|
|---|
| 149 | else Result := nil;
|
|---|
| 150 | end;
|
|---|
| 151 |
|
|---|
| 152 | function TControl.HandleMessage(Message: TMessage): Boolean;
|
|---|
| 153 | begin
|
|---|
| 154 | Result := False;
|
|---|
| 155 | if Message is TMessageMouseDown then begin
|
|---|
| 156 | if Assigned(FOnMouseDown) then FOnMouseDown(Self);
|
|---|
| 157 | Color := clGray;
|
|---|
| 158 | Paint;
|
|---|
| 159 | Result := True;
|
|---|
| 160 | end else
|
|---|
| 161 | if Message is TMessageMouseUp then begin
|
|---|
| 162 | if Assigned(FOnMouseUp) then FOnMouseUp(Self);
|
|---|
| 163 | Color := clSilver;
|
|---|
| 164 | Paint;
|
|---|
| 165 | if Assigned(FOnClick) then FOnClick(Self);
|
|---|
| 166 | Result := True;
|
|---|
| 167 | end;
|
|---|
| 168 | end;
|
|---|
| 169 |
|
|---|
| 170 | procedure TControl.Paint;
|
|---|
| 171 | begin
|
|---|
| 172 | with Canvas do begin
|
|---|
| 173 | Brush.Color := Color;
|
|---|
| 174 | FillRect(TRectangle.Create(0, 0, Bounds.Width, Bounds.Height));
|
|---|
| 175 | end;
|
|---|
| 176 | end;
|
|---|
| 177 |
|
|---|
| 178 | function TControl.ScreenToClient(Position: TPoint): TPoint;
|
|---|
| 179 | begin
|
|---|
| 180 | Result := Position.Substract(Bounds.TopLeft);
|
|---|
| 181 | if Assigned(Parent) then Result := Parent.ClientToScreen(Result);
|
|---|
| 182 | end;
|
|---|
| 183 |
|
|---|
| 184 | procedure TControl.SetColor(const Value: TColor);
|
|---|
| 185 | begin
|
|---|
| 186 | if FColor <> Value then begin
|
|---|
| 187 | FColor := Value;
|
|---|
| 188 | Paint;
|
|---|
| 189 | end;
|
|---|
| 190 | end;
|
|---|
| 191 |
|
|---|
| 192 | procedure TControl.SetParent(const Value: TWinControl);
|
|---|
| 193 | begin
|
|---|
| 194 | if FParent <> Value then begin
|
|---|
| 195 | if Assigned(FParent) then Parent.Controls.Remove(Self);
|
|---|
| 196 | FParent := Value;
|
|---|
| 197 | if Assigned(FParent) then Parent.Controls.Add(Self);
|
|---|
| 198 | end;
|
|---|
| 199 | end;
|
|---|
| 200 |
|
|---|
| 201 | { TButton }
|
|---|
| 202 |
|
|---|
| 203 | constructor TButton.Create;
|
|---|
| 204 | begin
|
|---|
| 205 | inherited;
|
|---|
| 206 | FColor := clSilver;
|
|---|
| 207 | end;
|
|---|
| 208 |
|
|---|
| 209 | procedure TButton.Paint;
|
|---|
| 210 | begin
|
|---|
| 211 | inherited;
|
|---|
| 212 | with Canvas do begin
|
|---|
| 213 | MoveTo(TPoint.Create(0, 0));
|
|---|
| 214 | LineTo(TPoint.Create(Bounds.Width - 1, 0));
|
|---|
| 215 | LineTo(TPoint.Create(Bounds.Width - 1, Bounds.Height - 1));
|
|---|
| 216 | LineTo(TPoint.Create(0, Bounds.Height - 1));
|
|---|
| 217 | LineTo(TPoint.Create(0, 0));
|
|---|
| 218 | TextOut(TPoint.Create((Bounds.Width - GetTextSize(Caption).X) div 2,
|
|---|
| 219 | (Bounds.Height - GetTextSize(Caption).Y) div 2), Caption);
|
|---|
| 220 | end;
|
|---|
| 221 | end;
|
|---|
| 222 |
|
|---|
| 223 | procedure TButton.SetCaption(const Value: string);
|
|---|
| 224 | begin
|
|---|
| 225 | if FCaption <> Value then begin
|
|---|
| 226 | FCaption := Value;
|
|---|
| 227 | Paint;
|
|---|
| 228 | end;
|
|---|
| 229 | end;
|
|---|
| 230 |
|
|---|
| 231 | { TControlCanvas }
|
|---|
| 232 |
|
|---|
| 233 | function TControlCanvas.AdjustPos(Position: TPoint): TPoint;
|
|---|
| 234 | begin
|
|---|
| 235 | if Assigned(Control) then
|
|---|
| 236 | Result := Control.ClientToScreen(Position)
|
|---|
| 237 | else Result := inherited;
|
|---|
| 238 | end;
|
|---|
| 239 |
|
|---|
| 240 | function TControlCanvas.GetVideoDevice: TVideoDevice;
|
|---|
| 241 | begin
|
|---|
| 242 | if Assigned(Control) then Result := Control.VideoDevice
|
|---|
| 243 | else Result := nil;
|
|---|
| 244 | end;
|
|---|
| 245 |
|
|---|
| 246 | { TWinControl }
|
|---|
| 247 |
|
|---|
| 248 | constructor TWinControl.Create;
|
|---|
| 249 | begin
|
|---|
| 250 | inherited;
|
|---|
| 251 | Controls := TList<TControl>.Create;
|
|---|
| 252 | end;
|
|---|
| 253 |
|
|---|
| 254 | destructor TWinControl.Destroy;
|
|---|
| 255 | begin
|
|---|
| 256 | Controls.Destroy;
|
|---|
| 257 | inherited;
|
|---|
| 258 | end;
|
|---|
| 259 |
|
|---|
| 260 | function TWinControl.HandleMessage(Message: TMessage): Boolean;
|
|---|
| 261 | var
|
|---|
| 262 | Control: TControl;
|
|---|
| 263 | begin
|
|---|
| 264 | Result := False;
|
|---|
| 265 | for Control in Controls do begin
|
|---|
| 266 | if Message is TMessageMouse then
|
|---|
| 267 | with TMessageMouse(Message) do begin
|
|---|
| 268 | if Control.Bounds.Contains(ScreenToClient(Position)) then begin
|
|---|
| 269 | if TWinControl(Control).HandleMessage(Message) then begin
|
|---|
| 270 | Result := True;
|
|---|
| 271 | Break;
|
|---|
| 272 | end;
|
|---|
| 273 | end;
|
|---|
| 274 | end;
|
|---|
| 275 | end;
|
|---|
| 276 | end;
|
|---|
| 277 |
|
|---|
| 278 | procedure TWinControl.Paint;
|
|---|
| 279 | var
|
|---|
| 280 | C: TControl;
|
|---|
| 281 | begin
|
|---|
| 282 | inherited;
|
|---|
| 283 | for C in Controls do C.Paint;
|
|---|
| 284 | end;
|
|---|
| 285 |
|
|---|
| 286 | { TLabel }
|
|---|
| 287 |
|
|---|
| 288 | procedure TLabel.Paint;
|
|---|
| 289 | begin
|
|---|
| 290 | inherited;
|
|---|
| 291 | with Canvas do begin
|
|---|
| 292 | TextOut(TPoint.Create((Bounds.Width - GetTextSize(Caption).X) div 2,
|
|---|
| 293 | (Bounds.Height - GetTextSize(Caption).Y) div 2), Caption);
|
|---|
| 294 | end;
|
|---|
| 295 | end;
|
|---|
| 296 |
|
|---|
| 297 | procedure TLabel.SetCaption(const Value: string);
|
|---|
| 298 | begin
|
|---|
| 299 | if FCaption <> Value then begin
|
|---|
| 300 | FCaption := Value;
|
|---|
| 301 | Paint;
|
|---|
| 302 | end;
|
|---|
| 303 | end;
|
|---|
| 304 |
|
|---|
| 305 | end.
|
|---|