Advertisement
Guest User

Component

a guest
Jul 12th, 2020
232
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 44.99 KB | None | 0 0
  1. {
  2.   untPianoRoll v1.0.0 - a simple pianoroll editor
  3.   for Delphi 2010 - 10.4 by Ernst Reidinga
  4.   https://erdesigns.eu
  5.  
  6.   This unit is part of the ERDesigns Midi Components Pack.
  7.  
  8.   (c) Copyright 2020 Ernst Reidinga <ernst@erdesigns.eu>
  9.  
  10.   Bugfixes / Updates:
  11.   - Initial Release 1.0.0
  12.  
  13.   If you use this unit, please give credits to the original author;
  14.   Ernst Reidinga.
  15. }
  16.  
  17. unit untPianoRoll;
  18.  
  19. interface
  20.  
  21. uses
  22.   System.SysUtils, System.Classes, Winapi.Windows, Vcl.Controls, Vcl.Graphics,
  23.   Winapi.Messages, GDIPlus;
  24.  
  25. type
  26.   TPianoRollItem = class(TCollectionItem)
  27.   private
  28.     FRow      : Integer;
  29.     FCol      : Integer;
  30.     FOffset   : Single;
  31.     FLength   : Single;
  32.     FColor    : TColor;
  33.     FSelected : Boolean;
  34.     FCaption  : TCaption;
  35.  
  36.     procedure SetRow(const I: Integer);
  37.     procedure SetCol(const I: Integer);
  38.     procedure SetOffset(const S: Single);
  39.     procedure SetLength(const S: Single);
  40.     procedure SetColor(const C: TColor);
  41.     procedure SetSelected(const B: Boolean);
  42.     procedure SetCaption(const C: TCaption);
  43.   protected
  44.     function GetDisplayName: string; override;
  45.   public
  46.     constructor Create(AOWner: TCollection); override;
  47.  
  48.     procedure Assign(Source: TPersistent); override;
  49.   published
  50.     property Row: Integer read FRow write SetRow default 0;
  51.     property Col: Integer read FCol write SetCol default 0;
  52.     property OffSet: Single read FOffset write SetOffset;
  53.     property Length: Single read FLength write SetLength;
  54.     property Color: TColor read FColor write SetColor default clNone;
  55.     property Caption: TCaption read FCaption write SetCaption;
  56.     property Selected: Boolean read FSelected write SetSelected;
  57.   end;
  58.  
  59.   TPianoRollItems = class(TOwnedCollection)
  60.   private
  61.     FOnChange : TNotifyEvent;
  62.  
  63.     procedure ItemChanged(Sender: TObject);
  64.  
  65.     function GetItem(Index: Integer): TPianoRollItem;
  66.     procedure SetItem(Index: Integer; const Value: TPianoRollItem);
  67.   protected
  68.     procedure Update(Item: TCollectionItem); override;
  69.   public
  70.     constructor Create(AOwner: TPersistent);
  71.     function Add: TPianoRollItem;
  72.     procedure Assign(Source: TPersistent); override;
  73.  
  74.     property Items[Index: Integer]: TPianoRollItem read GetItem write SetItem;
  75.     property OnChange: TNotifyEvent read FOnChange write FOnChange;
  76.   end;
  77.  
  78.   TPianoRollNotes = class(TPersistent)
  79.   private
  80.     { Private declarations }
  81.     FColor           : TColor;
  82.     FToColor         : TColor;
  83.     FSelectedColor   : TColor;
  84.     FSelectedToColor : TColor;
  85.     FLineColor       : TColor;
  86.     FFont            : TFont;
  87.     FShowCaptions    : Boolean;
  88.  
  89.     FOnChange   : TNotifyEvent;
  90.  
  91.     procedure SetColor(const C: TColor);
  92.     procedure SetToColor(const C: TColor);
  93.     procedure SetSelectedColor(const C: TColor);
  94.     procedure SetSelectedToColor(const C: TColor);
  95.     procedure SetLineColor(const C: TColor);
  96.     procedure SetFont(const F: TFont);
  97.     procedure SetShowCaptions(const B: Boolean);
  98.   public
  99.     { Public declarations }
  100.     constructor Create; virtual;
  101.     destructor Destroy; override;
  102.   published
  103.     { Published declarations }
  104.     property Color: TColor read FColor write SetColor default $00C7F3C0;
  105.     property ToColor: TColor read FToColor write SetToColor default $00A6D09E;
  106.     property SelectedColor: TColor read FSelectedColor write SetSelectedColor default $009D9DFC;
  107.     property SelectedToColor: TColor read FSelectedToColor write SetSelectedToColor default $008281DD;
  108.     property LineColor: TColor read FLineColor write SetLineColor default $00433B3C;
  109.     property Font: TFont read FFont write SetFont;
  110.     property ShowCaptions: Boolean read FShowCaptions write SetShowCaptions default True;
  111.  
  112.     property OnChange: TNotifyEvent read FOnChange write FonChange;
  113.   end;
  114.  
  115.   TPianoRollPositionIndicator = class(TPersistent)
  116.   private
  117.     { Private declarations }
  118.     FHeight     : Integer;
  119.     FWidth      : Integer;
  120.     FColor      : TColor;
  121.     FLineColor  : TColor;
  122.  
  123.     FOnChange   : TNotifyEvent;
  124.  
  125.     procedure SetHeight(const I: Integer);
  126.     procedure SetWidth(const I: Integer);
  127.     procedure SetColor(const C: TColor);
  128.     procedure SetLineColor(const C: TColor);
  129.   public
  130.     { Public declarations }
  131.     constructor Create; virtual;
  132.   published
  133.     { Published declarations }
  134.     property Height: Integer read FHeight write SetHeight default 8;
  135.     property Width: Integer read FWidth write SetWidth default 12;
  136.     property Color: TColor read FColor write SetColor default $0067D7AE;
  137.     property LineColor: TColor read FLineColor write SetLineColor default $0067D7AE;
  138.  
  139.     property OnChange: TNotifyEvent read FOnChange write FonChange;
  140.   end;
  141.  
  142.   TPianoRollRuler = class(TPersistent)
  143.   private
  144.     { Private declarations }
  145.     FHeight     : Integer;
  146.     FColor      : TColor;
  147.     FToColor    : TColor;
  148.     FLineColor  : TColor;
  149.     FFont       : TFont;
  150.     FShowLines  : Boolean;
  151.     FShowNumbers: Boolean;
  152.  
  153.     FOnChange   : TNotifyEvent;
  154.  
  155.     procedure SetHeight(const I: Integer);
  156.     procedure SetColor(const C: TColor);
  157.     procedure SetToColor(const C: TColor);
  158.     procedure SetLineColor(const C: TColor);
  159.     procedure SetFont(const F: TFont);
  160.     procedure SetShowLines(const B: Boolean);
  161.     procedure SetShowNumbers(const B: Boolean);
  162.   public
  163.     { Public declarations }
  164.     constructor Create; virtual;
  165.     destructor Destroy; override;
  166.   published
  167.     { Published declarations }
  168.     property Height: Integer read FHeight write SetHeight default 32;
  169.     property Color: TColor read FColor write SetColor default $00322A1D;
  170.     property ToColor: TColor read FToColor write SetToColor default $00453C2F;
  171.     property LineColor: TColor read FLineColor write SetLineColor default $00676456;
  172.     property Font: TFont read FFont write SetFont;
  173.     property ShowLines: Boolean read FShowLines write SetShowLines default False;
  174.     property ShowNumbers: Boolean read FShowNumbers write SetShowNumbers default True;
  175.  
  176.     property OnChange: TNotifyEvent read FOnChange write FonChange;
  177.   end;
  178.  
  179.   TPianoRollGrid = class(TPersistent)
  180.   private
  181.     { Private declarations }
  182.     FColor1     : TColor;
  183.     FColor2     : TColor;
  184.     FLineColor1 : TColor;
  185.     FLineColor2 : TColor;
  186.  
  187.     FOnChange   : TNotifyEvent;
  188.  
  189.     procedure SetColor1(const C: TColor);
  190.     procedure SetColor2(const C: TColor);
  191.     procedure SetLineColor1(const C: TColor);
  192.     procedure SetLineColor2(const C: TColor);
  193.   public
  194.     { Public declarations }
  195.     constructor Create; virtual;
  196.   published
  197.     { Published declarations }
  198.     property Color1: TColor read FColor1 write SetColor1 default $004E4335;
  199.     property Color2: TColor read FColor2 write SetColor2 default $00483E2D;
  200.     property LineColor1: TColor read FLineColor1 write SetLineColor1 default $00231908;
  201.     property LineColor2: TColor read FLineColor2 write SetLineColor2 default $0043382A;
  202.  
  203.     property OnChange: TNotifyEvent read FOnChange write FonChange;
  204.   end;
  205.  
  206.   TPianoRollLoopBar = class(TPersistent)
  207.   private
  208.     { Private declarations }
  209.     FStart     : Single;
  210.     FStop      : Single;
  211.     FColor     : TColor;
  212.     FLineColor : TColor;
  213.  
  214.     FOnChange   : TNotifyEvent;
  215.  
  216.     procedure SetStart(const S: Single);
  217.     procedure SetStop(const S: Single);
  218.     procedure SetColor(const C: TColor);
  219.     procedure SetLineColor(const C: TColor);
  220.   public
  221.     { Public declarations }
  222.     constructor Create; virtual;
  223.   published
  224.     { Published declarations }
  225.     property Start: Single read FStart write SetStart;
  226.     property Stop: Single read FStop write SetStop;
  227.     property Color: TColor read FColor write SetColor default $004A47CF;
  228.     property LineColor: TColor read FLineColor write SetLineColor default $004A47CF;
  229.  
  230.     property OnChange: TNotifyEvent read FOnChange write FonChange;
  231.   end;
  232.  
  233.   TPianoRollSelection = class(TPersistent)
  234.   private
  235.     { Private declarations }
  236.     FColor     : TColor;
  237.     FLineColor : TColor;
  238.  
  239.     FOnChange   : TNotifyEvent;
  240.  
  241.     procedure SetColor(const C: TColor);
  242.     procedure SetLineColor(const C: TColor);
  243.   public
  244.     { Public declarations }
  245.     constructor Create; virtual;
  246.   published
  247.     { Published declarations }
  248.     property Color: TColor read FColor write SetColor default $004A47CF;
  249.     property LineColor: TColor read FLineColor write SetLineColor default $004A47CF;
  250.  
  251.     property OnChange: TNotifyEvent read FOnChange write FonChange;
  252.   end;
  253.  
  254.  
  255.   TPianoRoll = class(TCustomControl)
  256.   private
  257.     { Private declarations }
  258.  
  259.     { Buffer - Avoid flickering }
  260.     FBuffer           : TBitmap;
  261.     FRulerBuffer      : TBitmap;
  262.     FUpdateRect       : TRect;
  263.  
  264.     { Redraw part }
  265.     FRedrawRuler: Boolean;
  266.  
  267.     { Scroll Positions and Max }
  268.     FScrollPosX : Integer;
  269.     FScrollPosY : Integer;
  270.     FScrollMaxX : Integer;
  271.     FScrollMaxY : Integer;
  272.     FOldScrollX : Integer;
  273.     FOldScrollY : Integer;
  274.  
  275.     { Selection }
  276.     FIsSelecting : Boolean;
  277.     FSelectFrom  : TPoint;
  278.     FSelectTo    : TPoint;
  279.  
  280.     { Settings }
  281.     FPositionIndicator  : TPianoRollPositionIndicator;
  282.     FRuler              : TPianoRollRuler;
  283.     FGrid               : TPianoRollGrid;
  284.     FLoopBar            : TPianoRollLoopBar;
  285.     FSelection          : TPianoRollSelection;
  286.     FItems              : TPianoRollItems;
  287.     FNotes              : TPianoRollNotes;
  288.  
  289.     { Zoom factor }
  290.     FZoomHorizontal : Integer;
  291.     FZoomVertical   : Integer;
  292.  
  293.     { Player position }
  294.     FPlayerPosition : Single;
  295.  
  296.     { Rows and Columns }
  297.     FMaxRows : Integer;
  298.     FMaxCols : Integer;
  299.  
  300.     procedure WMPaint(var Msg: TWMPaint); message WM_PAINT;
  301.     procedure WMEraseBkGnd(var Msg: TWMEraseBkGnd); message WM_ERASEBKGND;
  302.  
  303.     procedure SetScrollPosX(const I: Integer);
  304.     procedure SetScrollPosY(const I: Integer);
  305.  
  306.     procedure SetItems(I: TPianoRollItems);
  307.  
  308.     procedure SetZoomHorizontal(const Z: Integer);
  309.     procedure SetZoomVertical(const Z: Integer);
  310.  
  311.     procedure SetPlayerPosition(const S: Single);
  312.     procedure SetMaxRows(const I: Integer);
  313.     procedure SetMaxCols(const I: Integer);
  314.   protected
  315.     { Protected declarations }
  316.     procedure SettingsChanged(Sender: TObject);
  317.  
  318.     procedure Paint; override;
  319.     procedure Resize; override;
  320.     procedure CreateParams(var Params: TCreateParams); override;
  321.     procedure WndProc(var Message: TMessage); override;
  322.     function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; override;
  323.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  324.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  325.     procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
  326.   public
  327.     { Public declarations }
  328.     constructor Create(AOwner: TComponent); override;
  329.     destructor Destroy; override;
  330.  
  331.     property UpdateRect: TRect read FUpdateRect write FUpdateRect;
  332.  
  333.     property RedrawRuler: Boolean read FRedrawRuler write FRedrawRuler;
  334.   published
  335.     { Published declarations }
  336.     property PositionIndicator: TPianoRollPositionIndicator read FPositionIndicator;
  337.     property Ruler: TPianoRollRuler read FRuler;
  338.     property Grid: TPianoRollGrid read FGrid;
  339.     property LoopBar: TPianoRollLoopBar read FLoopBar;
  340.     property Selection: TPianoRollSelection read FSelection;
  341.     property Items: TPianoRollItems read FItems write SetItems;
  342.     property Notes: TPianoRollNotes read FNotes;
  343.  
  344.     property ZoomHorizontal: Integer read FZoomHorizontal write SetZoomHorizontal default 100;
  345.     property ZoomVertical: Integer read FZoomVertical write SetZoomVertical default 100;
  346.  
  347.     property MaxRows: Integer read FMaxRows write SetMaxRows default 64;
  348.     property MaxCols: Integer read FMaxCols write SetMaxCols default 32;
  349.  
  350.     property PlayerPosition: Single read FPlayerPosition write SetPlayerPosition;
  351.   end;
  352.  
  353. procedure Register;
  354.  
  355. implementation
  356.  
  357. uses Math;
  358.  
  359. { Zoom defaults }
  360. const
  361.   { Block width @ 100% zoom = 56px (div 4 = 14px per small block) }
  362.   BlockWidth100 = 56;
  363.   { Block height @ 100% zoom = 14px }
  364.   BlockHeight100 = 14;
  365.  
  366. (******************************************************************************)
  367. (*
  368. (*  Piano Roll Collection Item (TPianoRollItem)
  369. (*
  370. (******************************************************************************)
  371.  
  372. constructor TPianoRollItem.Create(AOWner: TCollection);
  373. begin
  374.   inherited Create(AOwner);
  375.   FColor   := clNone;
  376.   FLength  := 1;
  377.   FRow     := 1;
  378.   FCol     := 1;
  379.   FCaption := '';
  380. end;
  381.  
  382. procedure TPianoRollItem.SetRow(const I: Integer);
  383. begin
  384.   if (I <> Row) then
  385.   begin
  386.     if (I > 0) then
  387.       FRow := I
  388.     else
  389.       FRow := 1;
  390.     Changed(False);
  391.   end;
  392. end;
  393.  
  394. procedure TPianoRollItem.SetCol(const I: Integer);
  395. begin
  396.   if I <> Col then
  397.   begin
  398.     if (I > 0) then
  399.       FCol := I
  400.     else
  401.       FCol := 1;
  402.     Changed(False);
  403.   end;
  404. end;
  405.  
  406. procedure TPianoRollItem.SetOffset(const S: Single);
  407. begin
  408.   if S <> OffSet then
  409.   begin
  410.     FOffSet := S;
  411.     Changed(False);
  412.   end;
  413. end;
  414.  
  415. procedure TPianoRollItem.SetLength(const S: Single);
  416. begin
  417.   if S <> Length then
  418.   begin
  419.     FLength := S;
  420.     Changed(False);
  421.   end;
  422. end;
  423.  
  424. procedure TPianoRollItem.SetColor(const C: TColor);
  425. begin
  426.   if C <> Color then
  427.   begin
  428.     FColor := C;
  429.     Changed(False);
  430.   end;
  431. end;
  432.  
  433. procedure TPianoRollItem.SetSelected(const B: Boolean);
  434. begin
  435.   if B <> Selected then
  436.   begin
  437.     FSelected := B;
  438.     Changed(False);
  439.   end;
  440. end;
  441.  
  442. procedure TPianoRollItem.SetCaption(const C: TCaption);
  443. begin
  444.   if C <> Caption then
  445.   begin
  446.     FCaption := C;
  447.     Changed(False);
  448.   end;
  449. end;
  450.  
  451. function TPianoRollItem.GetDisplayName : string;
  452. begin
  453.   { Maybe change this to the corresponding notes ? }
  454.   if (Caption <> '') then
  455.     Result := Caption
  456.   else
  457.     Result := Format('Row %d - Col %d', [Row, Col]);
  458. end;
  459.  
  460. procedure TPianoRollItem.Assign(Source: TPersistent);
  461. begin
  462.   inherited;
  463.   if Source is TPianoRollItem then
  464.   begin
  465.     Row    := TPianoRollItem(Source).Row;
  466.     Col    := TPianoRollItem(Source).Col;
  467.     OffSet := TPianoRollItem(Source).OffSet;
  468.     Length := TPianoRollItem(Source).Length;
  469.     Color  := TPianoRollItem(Source).Color;
  470.     Changed(False);
  471.   end else Inherited;
  472. end;
  473.  
  474. (******************************************************************************)
  475. (*
  476. (*  Piano Roll Item Collection (TPianoRollItems)
  477. (*
  478. (******************************************************************************)
  479. constructor TPianoRollItems.Create(AOwner: TPersistent);
  480. begin
  481.   inherited Create(AOwner, TPianoRollItem);
  482. end;
  483.  
  484. procedure TPianoRollItems.ItemChanged(Sender: TObject);
  485. begin
  486.   if Assigned(FOnChange) then FOnChange(Self);
  487. end;
  488.  
  489. procedure TPianoRollItems.SetItem(Index: Integer; const Value: TPianoRollItem);
  490. begin
  491.   inherited SetItem(Index, Value);
  492.   ItemChanged(Self);
  493. end;
  494.  
  495. procedure TPianoRollItems.Update(Item: TCollectionItem);
  496. begin
  497.   inherited Update(Item);
  498.   if Assigned(FOnChange) then FOnChange(Self);
  499. end;
  500.  
  501. function TPianoRollItems.GetItem(Index: Integer) : TPianoRollItem;
  502. begin
  503.   Result := inherited GetItem(Index) as TPianoRollItem;
  504. end;
  505.  
  506. function TPianoRollItems.Add : TPianoRollItem;
  507. begin
  508.   Result := TPianoRollItem(inherited Add);
  509. end;
  510.  
  511. procedure TPianoRollItems.Assign(Source: TPersistent);
  512. var
  513.   LI   : TPianoRollItems;
  514.   Loop : Integer;
  515. begin
  516.   if (Source is TPianoRollItems)  then
  517.   begin
  518.     LI := TPianoRollItems(Source);
  519.     Clear;
  520.     for Loop := 0 to LI.Count - 1 do
  521.         Add.Assign(LI.Items[Loop]);
  522.   end else inherited;
  523. end;
  524.  
  525. (******************************************************************************)
  526. (*
  527. (*  Piano Roll Notes (TPianoRollNotes)
  528. (*
  529. (******************************************************************************)
  530. constructor TPianoRollNotes.Create;
  531. begin
  532.   inherited Create;
  533.   FFont            := TFont.Create;
  534.   FFont.OnChange   := FOnChange;
  535.   FFont.Name       := 'Segoe UI';
  536.   FFont.Color      := $00433B3C;
  537.   FFont.Size       := 8;
  538.   FColor           := $00C7F3C0;
  539.   FToColor         := $00A6D09E;
  540.   FSelectedColor   := $009D9DFC;
  541.   FSelectedToColor := $008281DD;
  542.   FLineColor       := $00433B3C;
  543.   FShowCaptions    := True;
  544. end;
  545.  
  546. destructor TPianoRollNotes.Destroy;
  547. begin
  548.   FFont.Free;
  549.   inherited Destroy;
  550. end;
  551.  
  552. procedure TPianoRollNotes.SetColor(const C: TColor);
  553. begin
  554.   if C <> Color then
  555.   begin
  556.     FColor := C;
  557.     if Assigned(FOnChange) then FOnChange(Self);
  558.   end;
  559. end;
  560.  
  561. procedure TPianoRollNotes.SetToColor(const C: TColor);
  562. begin
  563.   if C <> ToColor then
  564.   begin
  565.     FToColor := C;
  566.     if Assigned(FOnChange) then FOnChange(Self);
  567.   end;
  568. end;
  569.  
  570. procedure TPianoRollNotes.SetSelectedColor(const C: TColor);
  571. begin
  572.   if C <> SelectedColor then
  573.   begin
  574.     FSelectedColor := C;
  575.     if Assigned(FOnChange) then FOnChange(Self);
  576.   end;
  577. end;
  578.  
  579. procedure TPianoRollNotes.SetSelectedToColor(const C: TColor);
  580. begin
  581.   if C <> SelectedToColor then
  582.   begin
  583.     FSelectedToColor := C;
  584.     if Assigned(FOnChange) then FOnChange(Self);
  585.   end;
  586. end;
  587.  
  588. procedure TPianoRollNotes.SetLineColor(const C: TColor);
  589. begin
  590.   if C <> LineColor then
  591.   begin
  592.     FLineColor := C;
  593.     if Assigned(FOnChange) then FOnChange(Self);
  594.   end;
  595. end;
  596.  
  597. procedure TPianoRollNotes.SetFont(const F: TFont);
  598. begin
  599.   FFont.Assign(F);
  600.   if Assigned(FOnChange) then FOnChange(Self);
  601. end;
  602.  
  603. procedure TPianoRollNotes.SetShowCaptions(const B: Boolean);
  604. begin
  605.   if B <> ShowCaptions then
  606.   begin
  607.     FShowCaptions := B;
  608.     if Assigned(FOnChange) then FOnChange(Self);
  609.   end;
  610. end;
  611.  
  612. (******************************************************************************)
  613. (*
  614. (*  Piano Roll Position Indicator (TPianoRollPositionIndicator)
  615. (*
  616. (******************************************************************************)
  617.  
  618. constructor TPianoRollPositionIndicator.Create;
  619. begin
  620.   inherited Create;
  621.   FHeight    := 8;
  622.   FWidth     := 12;
  623.   FColor     := $0067D7AE;
  624.   FLineColor := $0067D7AE;
  625. end;
  626.  
  627. procedure TPianoRollPositionIndicator.SetHeight(const I: Integer);
  628. begin
  629.   if I <> FHeight then
  630.   begin
  631.     FHeight := I;
  632.     if Assigned(FOnChange) then FOnChange(Self);
  633.   end;
  634. end;
  635.  
  636. procedure TPianoRollPositionIndicator.SetWidth(const I: Integer);
  637. begin
  638.   if I <> FWidth then
  639.   begin
  640.     FWidth := I;
  641.     if Assigned(FOnChange) then FOnChange(Self);
  642.   end;
  643. end;
  644.  
  645. procedure TPianoRollPositionIndicator.SetColor(const C: TColor);
  646. begin
  647.   if C <> FColor then
  648.   begin
  649.     FColor := C;
  650.     if Assigned(FOnChange) then FOnChange(Self);
  651.   end;
  652. end;
  653.  
  654. procedure TPianoRollPositionIndicator.SetLineColor(const C: TColor);
  655. begin
  656.   if C <> FLineColor then
  657.   begin
  658.     FLineColor := C;
  659.     if Assigned(FOnChange) then FOnChange(Self);
  660.   end;
  661. end;
  662.  
  663. (******************************************************************************)
  664. (*
  665. (*  Piano Roll Ruler (TPianoRollRuler)
  666. (*
  667. (******************************************************************************)
  668.  
  669. constructor TPianoRollRuler.Create;
  670. begin
  671.   inherited Create;
  672.   FFont          := TFont.Create;
  673.   FFont.OnChange := FOnChange;
  674.   FFont.Color    := $00676456;
  675.   FFont.Name     := 'Segoe UI';
  676.   FHeight        := 32;
  677.   FColor         := $00322A1D;
  678.   FToColor       := $00453C2F;
  679.   FLineColor     := $00676456;
  680.   FShowLines     := False;
  681.   FShowNumbers   := True;
  682. end;
  683.  
  684. destructor TPianoRollRuler.Destroy;
  685. begin
  686.   FFont.Free;
  687.   inherited Destroy;
  688. end;
  689.  
  690. procedure TPianoRollRuler.SetHeight(const I: Integer);
  691. begin
  692.   if I <> FHeight then
  693.   begin
  694.     FHeight := I;
  695.     if Assigned(FOnChange) then FOnChange(Self);
  696.   end;
  697. end;
  698.  
  699. procedure TPianoRollRuler.SetColor(const C: TColor);
  700. begin
  701.   if C <> FColor then
  702.   begin
  703.     FColor := C;
  704.     if Assigned(FOnChange) then FOnChange(Self);
  705.   end;
  706. end;
  707.  
  708. procedure TPianoRollRuler.SetToColor(const C: TColor);
  709. begin
  710.   if C <> FToColor then
  711.   begin
  712.     FToColor := C;
  713.     if Assigned(FOnChange) then FOnChange(Self);
  714.   end;
  715. end;
  716.  
  717. procedure TPianoRollRuler.SetLineColor(const C: TColor);
  718. begin
  719.   if C <> FLineColor then
  720.   begin
  721.     FLineColor := C;
  722.     if Assigned(FOnChange) then FOnChange(Self);
  723.   end;
  724. end;
  725.  
  726. procedure TPianoRollRuler.SetFont(const F: TFont);
  727. begin
  728.   if F <> FFont then
  729.   begin
  730.     FFont.Assign(F);
  731.     if Assigned(FOnChange) then FOnChange(Self);
  732.   end;
  733. end;
  734.  
  735. procedure TPianoRollRuler.SetShowLines(const B: Boolean);
  736. begin
  737.   if B <> FShowLines then
  738.   begin
  739.     FShowLines := B;
  740.     if Assigned(FOnChange) then FOnChange(Self);
  741.   end;
  742. end;
  743.  
  744. procedure TPianoRollRuler.SetShowNumbers(const B: Boolean);
  745. begin
  746.   if B <> FShowNumbers then
  747.   begin
  748.     FShowNumbers := B;
  749.     if Assigned(FOnChange) then FOnChange(Self);
  750.   end;
  751. end;
  752.  
  753. (******************************************************************************)
  754. (*
  755. (*  Piano Roll Grid (TPianoRollGrid)
  756. (*
  757. (******************************************************************************)
  758.  
  759. constructor TPianoRollGrid.Create;
  760. begin
  761.   inherited Create;
  762.   FColor1     := $004E4335;
  763.   FColor2     := $00483E2D;
  764.   FLineColor1 := $00231908;
  765.   FLineColor2 := $0043382A;
  766. end;
  767.  
  768. procedure TPianoRollGrid.SetColor1(const C: TColor);
  769. begin
  770.   if C <> FColor1 then
  771.   begin
  772.     FColor1 := C;
  773.     if Assigned(FOnChange) then FOnChange(Self);
  774.   end;
  775. end;
  776.  
  777. procedure TPianoRollGrid.SetColor2(const C: TColor);
  778. begin
  779.   if C <> FColor2 then
  780.   begin
  781.     FColor2 := C;
  782.     if Assigned(FOnChange) then FOnChange(Self);
  783.   end;
  784. end;
  785.  
  786. procedure TPianoRollGrid.SetLineColor1(const C: TColor);
  787. begin
  788.   if C <> FLineColor1 then
  789.   begin
  790.     FLineColor1 := C;
  791.     if Assigned(FOnChange) then FOnChange(Self);
  792.   end;
  793. end;
  794.  
  795. procedure TPianoRollGrid.SetLineColor2(const C: TColor);
  796. begin
  797.   if C <> FLineColor2 then
  798.   begin
  799.     FLineColor2 := C;
  800.     if Assigned(FOnChange) then FOnChange(Self);
  801.   end;
  802. end;
  803.  
  804. (******************************************************************************)
  805. (*
  806. (*  Piano Roll Loop Bar (TPianoRollLoopBar)
  807. (*
  808. (******************************************************************************)
  809.  
  810. constructor TPianoRollLoopBar.Create;
  811. begin
  812.   inherited Create;
  813.   FStart     := 0;
  814.   FStop      := 0;
  815.   FColor     := $004A47CF;
  816.   FLineColor := $004A47CF;
  817. end;
  818.  
  819. procedure TPianoRollLoopBar.SetStart(const S: Single);
  820. begin
  821.   if S <> FStart then
  822.   begin
  823.     if FStop < S then
  824.       FStart := FStop
  825.     else
  826.       FStart := S;
  827.     if Assigned(FOnChange) then FOnChange(Self);
  828.   end;
  829. end;
  830.  
  831. procedure TPianoRollLoopBar.SetStop(const S: Single);
  832. begin
  833.   if S <> FStop then
  834.   begin
  835.     if S < FStart then
  836.       FStop := FStart
  837.     else
  838.       FStop := S;
  839.     if Assigned(FOnChange) then FOnChange(Self);
  840.   end;
  841. end;
  842.  
  843. procedure TPianoRollLoopBar.SetColor(const C: TColor);
  844. begin
  845.   if C <> FColor then
  846.   begin
  847.     FColor := C;
  848.     if Assigned(FOnChange) then FOnChange(Self);
  849.   end;
  850. end;
  851.  
  852. procedure TPianoRollLoopBar.SetLineColor(const C: TColor);
  853. begin
  854.   if C <> FLineColor then
  855.   begin
  856.     FLineColor := C;
  857.     if Assigned(FOnChange) then FOnChange(Self);
  858.   end;
  859. end;
  860.  
  861. (******************************************************************************)
  862. (*
  863. (*  Piano Roll Selection (TPianoRollSelection)
  864. (*
  865. (******************************************************************************)
  866.  
  867. constructor TPianoRollSelection.Create;
  868. begin
  869.   inherited Create;
  870.   FColor     := $004A47CF;
  871.   FLineColor := $004A47CF;
  872. end;
  873.  
  874. procedure TPianoRollSelection.SetColor(const C: TColor);
  875. begin
  876.   if C <> FColor then
  877.   begin
  878.     FColor := C;
  879.     if Assigned(FOnChange) then FOnChange(Self);
  880.   end;
  881. end;
  882.  
  883. procedure TPianoRollSelection.SetLineColor(const C: TColor);
  884. begin
  885.   if C <> FLineColor then
  886.   begin
  887.     FLineColor := C;
  888.     if Assigned(FOnChange) then FOnChange(Self);
  889.   end;
  890. end;
  891.  
  892. (******************************************************************************)
  893. (*
  894. (*  Piano Roll (TPianoRoll)
  895. (*
  896. (******************************************************************************)
  897.  
  898. constructor TPianoRoll.Create(AOwner: TComponent);
  899. begin
  900.   inherited Create(AOwner);
  901.  
  902.   { If the ControlStyle property includes csOpaque, the control paints itself
  903.     directly. We dont want the control to accept controls - but this might
  904.     change in the future so we leave it here commented out. offcourse we
  905.     like to get click, double click and mouse events. }
  906.   ControlStyle := ControlStyle + [csOpaque{, csAcceptsControls},
  907.     csCaptureMouse, csClickEvents, csDoubleClicks];
  908.  
  909.   { Create persistent classes }
  910.   FPositionIndicator := TPianoRollPositionIndicator.Create;
  911.   FPositionIndicator.OnChange := SettingsChanged;
  912.   FRuler := TPianoRollRuler.Create;
  913.   FRuler.OnChange := SettingsChanged;
  914.   FGrid := TPianoRollGrid.Create;
  915.   FGrid.OnChange := SettingsChanged;
  916.   FLoopBar := TPianoRollLoopBar.Create;
  917.   FLoopBar.OnChange := SettingsChanged;
  918.   FSelection := TPianoRollSelection.Create;
  919.   FSelection.OnChange := SettingsChanged;
  920.   FItems := TPianoRollItems.Create(Self);
  921.   FItems.OnChange := SettingsChanged;
  922.   FNotes := TPianoRollNotes.Create;
  923.   FNotes.OnChange := SettingsChanged;
  924.    
  925.   { Create Buffers }
  926.   FBuffer := TBitmap.Create;
  927.   FBuffer.PixelFormat := pf32bit;
  928.   FRulerBuffer := TBitmap.Create;
  929.   FRulerBuffer.PixelFormat := pf32bit;
  930.  
  931.   { Zoomfactor }
  932.   FZoomHorizontal := 100;
  933.   FZoomVertical   := 100;
  934.  
  935.   { Max Rows, Cols }
  936.   MaxRows := 64;
  937.   MaxCols := 32;
  938.  
  939.   { Initial Repaint }
  940.   RedrawRuler             := True;
  941. end;
  942.  
  943. destructor TPianoRoll.Destroy;
  944. begin
  945.   { Free Buffers }
  946.   FBuffer.Free;
  947.   FRulerBuffer.Free;
  948.  
  949.   { Free Persistent classes }
  950.   FPositionIndicator.Free;
  951.   FRuler.Free;
  952.   FGrid.Free;
  953.   FSelection.Free;
  954.   FItems.Free;
  955.   FNotes.Free;
  956.   inherited Destroy;
  957. end;
  958.  
  959. procedure TPianoRoll.WMPaint(var Msg: TWMPaint);
  960. begin
  961.   GetUpdateRect(Handle, FUpdateRect, False);
  962.   inherited;
  963. end;
  964.  
  965. procedure TPianoRoll.SetZoomHorizontal(const Z: Integer);
  966. begin
  967.   if Z <> FZoomHorizontal then
  968.   begin
  969.     if (Z < 50) then
  970.       FZoomHorizontal := 50
  971.     else
  972.     begin
  973.       FZoomHorizontal := Z;
  974.       RedrawRuler := True;
  975.       Invalidate;
  976.     end;
  977.   end;
  978. end;
  979.  
  980. procedure TPianoRoll.SetZoomVertical(const Z: Integer);
  981. begin
  982.   if Z <> FZoomVertical then
  983.   begin
  984.     if (Z < 50) then
  985.        FZoomVertical := 50
  986.     else
  987.     begin
  988.       FZoomVertical := Z;
  989.       Invalidate;
  990.     end;
  991.   end;
  992. end;
  993.  
  994. procedure TPianoRoll.SetPlayerPosition(const S: Single);
  995. begin
  996.   if (S >= 0) then
  997.   begin
  998.     FPlayerPosition := S;
  999.     Invalidate;
  1000.   end;
  1001. end;
  1002.  
  1003. procedure TPianoRoll.SetMaxRows(const I: Integer);
  1004. begin
  1005.   if (I <> MaxRows) then
  1006.   begin
  1007.     RedrawRuler := True;
  1008.     FMaxRows := I;
  1009.     Invalidate;
  1010.   end;
  1011. end;
  1012.  
  1013. procedure TPianoRoll.SetMaxCols(const I: Integer);
  1014. begin
  1015.   if (I <> MaxCols) then
  1016.   begin
  1017.     RedrawRuler  := True;
  1018.     FMaxCols := I;
  1019.     Invalidate;
  1020.   end;
  1021. end;
  1022.  
  1023.  
  1024. procedure TPianoRoll.SettingsChanged(Sender: TObject);
  1025. begin
  1026.   { Settings changed - repaint }
  1027.   RedrawRuler := True;
  1028.   Invalidate;
  1029. end;
  1030.  
  1031. procedure TPianoRoll.WMEraseBkGnd(var Msg: TWMEraseBkgnd);
  1032. begin
  1033.   { Draw Buffer to the Control }
  1034.   BitBlt(Msg.DC, 0, 0, ClientWidth, ClientHeight, FBuffer.Canvas.Handle, 0, 0, SRCCOPY);
  1035.   Msg.Result := -1;
  1036. end;
  1037.  
  1038. procedure TPianoRoll.SetScrollPosX(const I: Integer);
  1039. begin
  1040.   FScrollPosX := I;
  1041.   FScrollPosX := EnsureRange(FScrollPosX, 0, FScrollMaxX);
  1042.   FRedrawRuler := True;
  1043.   if FOldScrollX <> FScrollPosX then Invalidate;
  1044.   FOldScrollX := FScrollPosX;
  1045. end;
  1046.  
  1047. procedure TPianoRoll.SetScrollPosY(const I: Integer);
  1048. begin
  1049.   FScrollPosY := I;
  1050.   FScrollPosY := EnsureRange(FScrollPosY, 0, FScrollMaxY);
  1051.   FRedrawRuler := True;
  1052.   if FOldScrollY <> FScrollPosY then Invalidate;
  1053.   FOldScrollY := FScrollPosY;
  1054. end;
  1055.  
  1056. procedure TPianoRoll.SetItems(I: TPianoRollItems);
  1057. begin
  1058.   FItems.Assign(I);
  1059.   Invalidate;
  1060. end;
  1061.  
  1062. procedure TPianoRoll.Paint;
  1063. var
  1064.   HBlockSize  : Single;
  1065.   VBlockSize  : Integer;
  1066.   VisibleRows : Integer;
  1067.   VisibleCols : Integer;
  1068.   SubColWidth : Integer;
  1069.  
  1070.   procedure RepaintRuler;
  1071.   var
  1072.     FClientRect    : TGPRect;
  1073.     FGraphics      : IGPGraphics;
  1074.     FSolidBrush    : IGPSolidBrush;
  1075.     FFontBrush     : IGPSolidBrush;
  1076.     FGradientBrush : IGPLinearGradientBrush;
  1077.     FPen           : IGPPen;
  1078.     FFont          : TGPFont;
  1079.     FFontRect      : TGPRectF;
  1080.   var
  1081.     I, C, X, T : Integer;
  1082.   begin
  1083.     RedrawRuler := False;
  1084.     FRulerBuffer.SetSize(ClientWidth, Ruler.Height);
  1085.     FGraphics := TGPGraphics.Create(FRulerBuffer.Canvas.Handle);
  1086.     FGraphics.SmoothingMode     := SmoothingModeAntiAlias;
  1087.     FGraphics.InterpolationMode := InterpolationModeHighQualityBicubic;
  1088.     { Draw Ruler background }
  1089.     FClientRect := TGPRect.Create(0, 0, FRulerBuffer.Width, FRulerBuffer.Height);
  1090.     if Ruler.ToColor <> clNone then
  1091.     begin
  1092.       FGradientBrush := TGPLinearGradientBrush.Create(FClientRect,
  1093.         TGPColor.CreateFromColorRef(Ruler.Color),
  1094.         TGPColor.CreateFromColorRef(Ruler.ToColor), 90);
  1095.       FGraphics.FillRectangle(FGradientBrush, FClientRect);
  1096.     end else
  1097.     begin
  1098.       FSolidBrush := TGPSolidBrush.Create(TGPColor.CreateFromColorRef(Ruler.Color));
  1099.       FGraphics.FillRectangle(FSolidBrush, FClientRect);
  1100.     end;
  1101.     { Draw ruler outline }
  1102.     FClientRect.Width  := FClientRect.Width - 1;
  1103.     FClientRect.Height := FClientRect.Height -1;
  1104.     FPen := TGPPen.Create(TGPColor.CreateFromColorRef(Ruler.LineColor));
  1105.     FPen.Alignment := PenAlignmentInset;
  1106.     FGraphics.DrawRectangle(FPen, FClientRect);
  1107.     { Draw ruler lines }
  1108.     if Ruler.ShowLines then
  1109.     begin
  1110.       T := Ceil(Ruler.Height / 2);
  1111.       for I := 0 to Ceil(ClientWidth / HBlockSize) do
  1112.       FGraphics.DrawLine(FPen, I * HBlockSize, T, I * HBlockSize, FClientRect.Bottom);
  1113.     end;
  1114.     { Draw ruler numbers }
  1115.     if Ruler.ShowNumbers then
  1116.     begin
  1117.       FFontBrush := TGPSolidBrush.Create(TGPColor.CreateFromColorRef(Ruler.Font.Color));
  1118.       FFont      := TGPFont.Create(Ruler.Font.Name, Ruler.Font.Size, [{FontStyleBold}]);
  1119.       FFontRect  := FGraphics.MeasureString('123456789', FFont, TGPPointF.Create(0, 0));
  1120.       T := Ceil(FClientRect.Height - (FFontRect.Height +2));
  1121.       C := 0;
  1122.       for I := 0 to Ceil(ClientWidth / (SubColWidth * 4)) do if (I mod 4) = 0 then
  1123.       begin
  1124.         Inc(C);
  1125.         FGraphics.DrawString(IntToStr(C), FFont, TGPPointF.Create((I * (SubColWidth * 4)) +2, T), FFontBrush);
  1126.       end;
  1127.     end;
  1128.   end;
  1129.  
  1130.   procedure RepaintPositionIndicator;
  1131.   var
  1132.     FGraphics      : IGPGraphics;
  1133.     FSolidBrush    : IGPSolidBrush;
  1134.     FPen           : IGPPen;
  1135.     FLineFade      : TGPColor;
  1136.     FLineFadePen   : IGPPen;
  1137.   var
  1138.     I, P : Integer;
  1139.   begin
  1140.     FGraphics := TGPGraphics.Create(FBuffer.Canvas.Handle);
  1141.     FGraphics.SmoothingMode     := SmoothingModeAntiAlias;
  1142.     FGraphics.InterpolationMode := InterpolationModeHighQualityBicubic;
  1143.     FSolidBrush := TGPSolidBrush.Create(TGPColor.CreateFromColorRef(PositionIndicator.Color));
  1144.     P := Round((PlayerPosition -1) * ((SubColWidth * 4) * 4));
  1145.     if (PlayerPosition > 0) then
  1146.     begin
  1147.       FPen := TGPPen.Create(TGPColor.CreateFromColorRef(PositionIndicator.LineColor));
  1148.       FPen.Alignment := PenAlignmentInset;
  1149.       FGraphics.DrawLine(FPen, P, Ruler.Height, P, ClientHeight);
  1150.       FLineFade := TGPColor.CreateFromColorRef(PositionIndicator.LineColor);
  1151.       for I := 1 to 6 do
  1152.       begin
  1153.         FLineFade.Alpha := 30 - (I *3);
  1154.         FLineFadePen := TGPPen.Create(FLineFade, I);
  1155.         FlineFadePen.LineJoin := LineJoinRound;
  1156.         FGraphics.DrawLine(FLineFadePen, (P +1) - I, Ruler.Height, (P +1) - I, ClientHeight -1);
  1157.       end;
  1158.     end;
  1159.     FGraphics.FillPolygon(FSolidBrush, [
  1160.       TGPPoint.Create(P, 1 + PositionIndicator.Height),
  1161.       TGPPoint.Create(P + Round(PositionIndicator.Width / 2), 1),
  1162.       TGPPoint.Create(P - Round(PositionIndicator.Width / 2), 1)
  1163.     ]);
  1164.   end;
  1165.  
  1166.   procedure RepaintLoopBar;
  1167.   var
  1168.     FGraphics      : IGPGraphics;
  1169.     FBrushColor    : TGPColor;
  1170.     FSolidBrush    : IGPSolidBrush;
  1171.     FPen           : IGPPen;
  1172.     FLineFadePen   : IGPPen;
  1173.     FLoopRect      : TGPRect;
  1174.   var
  1175.     S, E : Integer;
  1176.   begin
  1177.     FGraphics := TGPGraphics.Create(FBuffer.Canvas.Handle);
  1178.     FGraphics.SmoothingMode     := SmoothingModeAntiAlias;
  1179.     FGraphics.InterpolationMode := InterpolationModeHighQualityBicubic;
  1180.     FBrushColor := TGPColor.CreateFromColorRef(LoopBar.Color);
  1181.     FBrushColor.Alpha := 125;
  1182.     FSolidBrush := TGPSolidBrush.Create(FBrushColor);
  1183.     FPen := TGPPen.Create(TGPColor.CreateFromColorRef(LoopBar.LineColor));
  1184.     FPen.Alignment := PenAlignmentInset;
  1185.     S := Round((LoopBar.Start -1) * (HBlockSize * 4));
  1186.     E := Round((LoopBar.Stop -1) * (HBlockSize * 4));
  1187.     FLoopRect := TGPRect.Create(S, 1, E - S, Ruler.Height -3);
  1188.     FGraphics.FillRectangle(FSolidBrush, FLoopRect);
  1189.     FGraphics.DrawRectangle(FPen, FLoopRect);
  1190.   end;
  1191.  
  1192.   procedure DrawGrid;
  1193.   var
  1194.     FClientRect  : TGPRect;
  1195.     FRowRect     : TGPRect;
  1196.     FGraphics    : IGPGraphics;
  1197.     FSolidBrush1 : IGPSolidBrush;
  1198.     FSolidBrush2 : IGPSolidBrush;
  1199.     FPen1        : IGPPen;
  1200.     FPen2        : IGPPen;
  1201.     FPen3        : IGPPen;
  1202.   var
  1203.     X, Y, XI, YI : Integer;
  1204.   begin
  1205.     FGraphics := TGPGraphics.Create(FBuffer.Canvas.Handle);
  1206.     FGraphics.SmoothingMode     := SmoothingModeAntiAlias;
  1207.     FGraphics.InterpolationMode := InterpolationModeHighQualityBicubic;
  1208.     FClientRect := TGPRect.Create(0, 0, ClientWidth, ClientHeight);
  1209.     { Create brushes and pens }
  1210.     FSolidBrush1 := TGPSolidBrush.Create(TGPColor.CreateFromColorRef(Grid.Color1));
  1211.     FSolidBrush2 := TGPSolidBrush.Create(TGPColor.CreateFromColorRef(Grid.Color2));
  1212.     FPen1        := TGPPen.Create(TGPColor.CreateFromColorRef(Grid.LineColor1));
  1213.     FPen2        := TGPPen.Create(TGPColor.CreateFromColorRef(Grid.LineColor2));
  1214.     FPen3        := TGPPen.Create(TGPColor.CreateFromColorRef(Grid.LineColor1), 2);
  1215.     { Draw Horizontal Rows }
  1216.     for YI := 0 to Ceil(FClientRect.Height / VBlockSize) do
  1217.     begin
  1218.       FRowRect := TGPRect.Create(0, Ruler.Height + (YI * VBlockSize), FClientRect.Width, VBlockSize);
  1219.       if Odd(YI) then
  1220.         FGraphics.FillRectangle(FSolidBrush2, FRowRect)
  1221.       else
  1222.         FGraphics.FillRectangle(FSolidBrush1, FRowRect);
  1223.     end;
  1224.  
  1225.     { Draw Grid Horizontal }
  1226.     for YI := 0 to Ceil(FClientRect.Height / VBlockSize) do
  1227.     begin
  1228.       if (YI mod 4) = 0 then
  1229.         FGraphics.DrawLine(FPen1, 0, Ruler.Height + (YI * VBlockSize), ClientWidth, Ruler.Height + (YI * VBlockSize))
  1230.       else
  1231.         FGraphics.DrawLine(FPen2, 0, Ruler.Height + (YI * VBlockSize), ClientWidth, Ruler.Height + (YI * VBlockSize));
  1232.     end;
  1233.  
  1234.     { Draw Grid Vertical }
  1235.     for XI := 0 to Ceil(FClientRect.Width / SubColWidth) do
  1236.     begin
  1237.       if (XI mod 16) = 0 then
  1238.         FGraphics.DrawLine(FPen3, (XI * SubColWidth), Ruler.Height, (XI * SubColWidth), ClientHeight)
  1239.       else
  1240.       if (XI mod 4) = 0 then
  1241.         FGraphics.DrawLine(FPen1, (XI * SubColWidth), Ruler.Height, (XI * SubColWidth), ClientHeight)
  1242.       else
  1243.         FGraphics.DrawLine(FPen2, (XI * SubColWidth), Ruler.Height, (XI * SubColWidth), ClientHeight);
  1244.     end;
  1245.   end;
  1246.  
  1247.   procedure DrawItems;
  1248.   var
  1249.     FGraphics  : IGPGraphics;
  1250.     FPen       : IGPPen;
  1251.     FFontBrush : IGPSolidBrush;
  1252.     FFont      : TGPFont;
  1253.  
  1254.     procedure DrawNote(const Brush: IGPBrush; const Caption: string; const Rect: TGPRectF);
  1255.     begin
  1256.       FGraphics.FillRectangle(Brush, Rect);
  1257.       FGraphics.DrawRectangle(FPen, Rect);
  1258.       //if (Caption <> '') then
  1259.       //FGraphics.DrawString('Caption', FFont, Rect, TGPStringFormat.GenericDefault, FFontBrush);
  1260.     end;
  1261.  
  1262.   var
  1263.     FSolidBrush1    : IGPSolidBrush;
  1264.     FSolidBrush2    : IGPSolidBrush;
  1265.     FSolidBrush3    : IGPSolidBrush;
  1266.     FGradientBrush1 : IGPLinearGradientBrush;
  1267.     FGradientBrush2 : IGPLinearGradientBrush;
  1268.     FNoteRect       : TGPRectF;
  1269.   var
  1270.     I : Integer;
  1271.     B : Integer;
  1272.   begin
  1273.     FGraphics := TGPGraphics.Create(FBuffer.Canvas.Handle);
  1274.     FGraphics.SmoothingMode     := SmoothingModeAntiAlias;
  1275.     FGraphics.InterpolationMode := InterpolationModeHighQualityBicubic;
  1276.     { Grid is subdivided in 4 parts - 4X4 }
  1277.     B := (SubColWidth * 4) * 4;
  1278.     { Create solid brushes and pen }
  1279.     FSolidBrush1 := TGPSolidBrush.Create(TGPColor.CreateFromColorRef(Notes.Color));
  1280.     FSolidBrush2 := TGPSolidBrush.Create(TGPColor.CreateFromColorRef(Notes.SelectedColor));
  1281.     FPen         := TGPPen.Create(TGPColor.CreateFromColorRef(Notes.LineColor));
  1282.     { Create gradient brushes }
  1283.     FNoteRect := TGPRectF.Create(0, Ruler.Height, ClientWidth, VBlockSize);
  1284.     FGradientBrush1 := TGPLinearGradientBrush.Create(FNoteRect,
  1285.       TGPColor.CreateFromColorRef(Notes.Color),
  1286.       TGPColor.CreateFromColorRef(Notes.ToColor), 90);
  1287.     FGradientBrush2 := TGPLinearGradientBrush.Create(FNoteRect,
  1288.       TGPColor.CreateFromColorRef(Notes.SelectedColor),
  1289.       TGPColor.CreateFromColorRef(Notes.SelectedToColor), 90);
  1290.     { Create font }
  1291.     FFontBrush := TGPSolidBrush.Create(TGPColor.CreateFromColorRef(Notes.Font.Color));
  1292.     FFont      := TGPFont.Create(Notes.Font.Name, Notes.Font.Size, [{FontStyleBold}]);
  1293.     { Draw Notes }
  1294.     for I := 0 to Items.Count -1 do
  1295.     begin
  1296.       { Check if the note is in the visible area - edit this according to scroll pos }
  1297.       if (Items.Items[I].Row <= VisibleRows) and (Items.Items[I].Col <= VisibleCols) then
  1298.       begin
  1299.         FNoteRect := TGPRectF.Create(
  1300.           ((Items.Items[I].Col -1) * B) + (Items.Items[I].OffSet * B),
  1301.            Ruler.Height + ((Items.Items[I].Row -1) * VBlockSize),
  1302.            Items.Items[I].Length * B,
  1303.            VBlockSize
  1304.           );
  1305.         { Check if the note is selected }
  1306.         if Items.Items[I].Selected then
  1307.         begin
  1308.           if (Notes.SelectedToColor = clNone) then
  1309.             DrawNote(FSolidBrush2, Items.Items[I].Caption, FNoteRect)
  1310.           else
  1311.             DrawNote(FGradientBrush2, Items.Items[I].Caption, FNoteRect);
  1312.         end else
  1313.         { Custom color? }
  1314.         if (Items.Items[I].Color <> clNone) then
  1315.         begin
  1316.           FSolidBrush3 := TGPSolidBrush.Create(TGPColor.CreateFromColorRef(Items.Items[I].Color));
  1317.           DrawNote(FSolidBrush3, Items.Items[I].Caption, FNoteRect);
  1318.         end else
  1319.         { Draw normal }
  1320.         begin
  1321.           if (Notes.ToColor = clNone) then
  1322.             DrawNote(FSolidBrush1, Items.Items[I].Caption, FNoteRect)
  1323.           else
  1324.             DrawNote(FGradientBrush1, Items.Items[I].Caption, FNoteRect);
  1325.         end;
  1326.       end;
  1327.     end;
  1328.   end;
  1329.  
  1330.   procedure DrawSelectionFrame;
  1331.   var
  1332.     FGraphics   : IGPGraphics;
  1333.     FSolidBrush : IGPSolidBrush;
  1334.     FPen        : IGPPen;
  1335.     FBrushColor : TGPColor;
  1336.     FSelectRect : TGPRect;
  1337.   begin
  1338.     FGraphics := TGPGraphics.Create(FBuffer.Canvas.Handle);
  1339.     FGraphics.SmoothingMode     := SmoothingModeAntiAlias;
  1340.     FGraphics.InterpolationMode := InterpolationModeHighQualityBicubic;
  1341.     FBrushColor := TGPColor.CreateFromColorRef(Selection.Color);
  1342.     FBrushColor.Alpha := 100;
  1343.     FSolidBrush := TGPSolidBrush.Create(FBrushColor);
  1344.     FPen        := TGPPen.Create(TGPColor.CreateFromColorRef(Selection.LineColor));
  1345.     FSelectRect := TGPRect.Create(FSelectFrom.X, FSelectFrom.Y, FSelectTo.X - FSelectFrom.X, FSelectTo.Y - FSelectFrom.Y);
  1346.     FGraphics.FillRectangle(FSolidBrush, FSelectRect);
  1347.     FGraphics.DrawRectangle(FPen, FSelectRect);
  1348.   end;
  1349.  
  1350. var
  1351.   X, Y, W, H : Integer;
  1352.   SI         : TScrollInfo;
  1353. begin
  1354.   if not Assigned(FBuffer) then Exit;
  1355.  
  1356.   { Horizontal block size - calculate it here so we can use it for drawing the
  1357.     rulerbar, but also for drawing the grid and the tones }
  1358.   HBlockSize := (ZoomHorizontal * (BlockWidth100 / 100));
  1359.   { Vertical block size - height of the bars }
  1360.   VBlockSize := Round(ZoomVertical * (BlockHeight100 / 100));
  1361.   { Calculate width (4x4 grid) }
  1362.   SubColWidth  := Ceil(HBlockSize / 4);
  1363.  
  1364.   { Set Max Scrollbar }
  1365.   if (HBlockSize * MaxCols) > ClientWidth then
  1366.     FScrollMaxX := Round(HBlockSize * MaxCols)
  1367.   else
  1368.     FScrollMaxX := ClientWidth;
  1369.   if (VBlockSize * MaxRows) > (ClientHeight - Ruler.Height) then
  1370.     FScrollMaxY := (VBlockSize * MaxRows) + Ruler.Height
  1371.   else
  1372.     FScrollMaxY := ClientHeight;
  1373.  
  1374.   { Calculate visible rows and columns }
  1375.   VisibleRows := Ceil(ClientHeight / VBlockSize);
  1376.   VisibleCols := Ceil(ClientWidth / HBlockSize);
  1377.  
  1378.   { Set Buffer size }
  1379.   FBuffer.SetSize(ClientWidth, ClientHeight);
  1380.  
  1381.   { Ruler }
  1382.   if RedrawRuler then RepaintRuler;
  1383.  
  1384.   { Draw everything to the buffer }
  1385.   DrawGrid;
  1386.   BitBlt(FBuffer.Canvas.Handle, ClientRect.Left, ClientRect.Top, ClientWidth, Ruler.Height,
  1387.     FRulerBuffer.Canvas.Handle, 0,  0, SRCCOPY);
  1388.   RepaintLoopBar;
  1389.   RepaintPositionIndicator;
  1390.   DrawItems;
  1391.  
  1392.   { Do we want a selectionframe? }
  1393.   if FIsSelecting then DrawSelectionFrame;
  1394.  
  1395.   { Now draw the Buffer to the components surface }
  1396.   X := UpdateRect.Left;
  1397.   Y := UpdateRect.Top;
  1398.   W := UpdateRect.Right - UpdateRect.Left;
  1399.   H := UpdateRect.Bottom - UpdateRect.Top;
  1400.   if (W <> 0) and (H <> 0) then
  1401.     { Only update part - invalidated }
  1402.     BitBlt(Canvas.Handle, X, Y, W, H, FBuffer.Canvas.Handle, X,  Y, SRCCOPY)
  1403.   else
  1404.     { Repaint the whole buffer to the surface }
  1405.     BitBlt(Canvas.Handle, 0, 0, ClientWidth, ClientHeight, FBuffer.Canvas.Handle, X,  Y, SRCCOPY);
  1406.  
  1407.   { Vertical Scrollbar }
  1408.   SI.cbSize := Sizeof(SI);
  1409.   SI.fMask  := SIF_ALL;
  1410.   SI.nMin   := 0;
  1411.   SI.nMax   := FScrollMaxY;
  1412.   SI.nPage  := 100;
  1413.   SI.nPos   := FScrollPosY;
  1414.   SI.nTrackPos := SI.nPos;
  1415.   SetScrollInfo(Handle, SB_VERT, SI, True);
  1416.  
  1417.   { Horizontal Scrollbar }
  1418.   SI.cbSize := Sizeof(SI);
  1419.   SI.fMask  := SIF_ALL;
  1420.   SI.nMin   := 0;
  1421.   SI.nMax   := FScrollMaxX;
  1422.   SI.nPage  := 100;
  1423.   SI.nPos   := FScrollPosX;
  1424.   SI.nTrackPos := SI.nPos;
  1425.   SetScrollInfo(Handle, SB_HORZ, SI, True);
  1426. end;
  1427.  
  1428. procedure TPianoRoll.Resize;
  1429. begin
  1430.   RedrawRuler := True;
  1431. end;
  1432.  
  1433. procedure TPianoRoll.CreateParams(var Params: TCreateParams);
  1434. begin
  1435.   inherited CreateParams(Params);
  1436.   with Params do
  1437.     Style := Style or WS_HSCROLL or WS_VSCROLL and not (CS_HREDRAW or CS_VREDRAW);
  1438. end;
  1439.  
  1440. procedure TPianoRoll.WndProc(var Message: TMessage);
  1441. var
  1442.   SI : TScrollInfo;
  1443. begin
  1444.   inherited;
  1445.   case Message.Msg of
  1446.     // Capture Keystrokes
  1447.     WM_GETDLGCODE:
  1448.       Message.Result := Message.Result or DLGC_WANTARROWS or DLGC_WANTALLKEYS;
  1449.  
  1450.     // Horizontal Scrollbar
  1451.     WM_HSCROLL:
  1452.       begin
  1453.         case Message.WParamLo of
  1454.           SB_LEFT      : SetScrollPosX(0);
  1455.           SB_RIGHT     : SetScrollPosX(FScrollMaxX);
  1456.           SB_LINELEFT  : SetScrollPosX(FScrollPosX - 10);
  1457.           SB_LINERIGHT : SetScrollPosX(FScrollPosX + 10);
  1458.           SB_PAGELEFT  : SetScrollPosX(FScrollPosX - ClientWidth);
  1459.           SB_PAGERIGHT : SetScrollPosY(FScrollPosX + ClientWidth);
  1460.           SB_THUMBTRACK:
  1461.             begin
  1462.               ZeroMemory(@SI, SizeOf(SI));
  1463.               SI.cbSize := Sizeof(SI);
  1464.               SI.fMask := SIF_TRACKPOS;
  1465.               if GetScrollInfo(Handle, SB_HORZ, SI) then
  1466.                 SetScrollPosX(SI.nTrackPos);
  1467.             end;
  1468.         end;
  1469.         Message.Result := 0;
  1470.       end;
  1471.  
  1472.     // Vertical Scrollbar
  1473.     WM_VSCROLL:
  1474.       begin
  1475.         case Message.WParamLo of
  1476.           SB_TOP      : SetScrollPosY(0);
  1477.           SB_BOTTOM   : SetScrollPosY(FScrollMaxY);
  1478.           SB_LINEUP   : SetScrollPosY(FScrollPosY - 10);
  1479.           SB_LINEDOWN : SetScrollPosY(FScrollPosY + 10);
  1480.           SB_PAGEUP   : SetScrollPosY(FScrollPosY - ClientHeight);
  1481.           SB_PAGEDOWN : SetScrollPosY(FScrollPosY + ClientHeight);
  1482.           SB_THUMBTRACK:
  1483.             begin
  1484.               ZeroMemory(@SI, SizeOf(SI));
  1485.               SI.cbSize := Sizeof(SI);
  1486.               SI.fMask := SIF_TRACKPOS;
  1487.               if GetScrollInfo(Handle, SB_VERT, SI) then
  1488.                 SetScrollPosY(SI.nTrackPos);
  1489.             end;
  1490.         end;
  1491.         Message.Result := 0;
  1492.       end;
  1493.  
  1494.   end;
  1495. end;
  1496.  
  1497. function TPianoRoll.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
  1498.   MousePos: TPoint): Boolean;
  1499. begin
  1500.   if (ssCtrl in Shift) then ZoomHorizontal := ZoomHorizontal + (WheelDelta div 10)
  1501.   else
  1502.   begin
  1503.     if (ssShift in Shift) then
  1504.       SetScrollPosX(FScrollPosX - (WheelDelta div 10))
  1505.     else
  1506.       SetScrollPosY(FScrollPosY - (WheelDelta div 10));
  1507.   end;
  1508.   Result := True;
  1509. end;
  1510.  
  1511. procedure TPianoRoll.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1512. begin
  1513.   if Button = mbLeft then
  1514.   begin
  1515.     { Check if we are selecting a note }
  1516.  
  1517.     { If no note is selected then we want to show a selection frame }
  1518.     FSelectFrom  := Point(X, Y);
  1519.     FSelectTo    := Point(X, Y);
  1520.     FIsSelecting := True;
  1521.   end;
  1522.   inherited;
  1523. end;
  1524.  
  1525. procedure TPianoRoll.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1526. begin
  1527.   if FIsSelecting then
  1528.   begin
  1529.     FIsSelecting := False;
  1530.     Invalidate;
  1531.   end;
  1532.   inherited;
  1533. end;
  1534.  
  1535. procedure TPianoRoll.MouseMove(Shift: TShiftState; X: Integer; Y: Integer);
  1536. begin
  1537.   if FIsSelecting then
  1538.   begin
  1539.     FSelectTo := Point(X, Y);
  1540.     Invalidate;
  1541.   end;
  1542.   inherited;
  1543. end;
  1544.  
  1545. (******************************************************************************)
  1546. (*
  1547. (*  Register Piano Roll Componens (TPianoRoll)
  1548. (*
  1549. (*  note: Move this part to a serpate register unit!
  1550. (*
  1551. (******************************************************************************)
  1552.  
  1553. procedure Register;
  1554. begin
  1555.   RegisterComponents('ERDesigns MIDI', [TPianoRoll]);
  1556. end;
  1557.  
  1558. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement