unit dav7RotationBtn; { rotation button component } interface uses Classes,Controls,Graphics,Messages; type Torientation = (orHorizontal,orVertical); TRotationChange = procedure(sender : TObject; position : byte) of object; TonButtonPaint = procedure(sender : TObject) of object; TDav7RotationBtn = class(TgraphicControl) private FMap : Tbitmap; Fmoving : boolean; FoldX : smallInt; FoldY : smallInt; Forientation : TOrientation; FonEnter : TNotifyEvent; FonLeave : TNotifyEvent; FonChange : TRotationChange; FonButtonPaint : TonButtonPaint; FBorderwidth : byte; FBordercolor1 : cardinal; FBordercolor2 : cardinal; FBGcolor : cardinal; FNotchColor : cardinal; FNotchWidth : byte; FNotchSpacing : byte; FPixelRatio : byte; Fpixelcount : smallInt; Fmaxpixelcount : smallInt; FPosition : byte; FMaximum : byte; FDCC : byte; procedure setOrientation(ortn : TOrientation); procedure setbordercolor1(col : cardinal); procedure setbordercolor2(col : cardinal); procedure setBGcolor(col : cardinal); procedure setborderwidth(bw : byte); procedure setNotchWidth(nw : byte); procedure setNotchSpacing(ns : byte); procedure setNotchColor(col : cardinal); procedure setPosition(pos : byte); procedure setmaximum(m : byte); procedure setpixelratio(pr : byte); procedure draw; protected procedure paint;override; procedure mousemove(Shift : Tshiftstate; x,y : integer); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure CMmouseEnter(var message : Tmessage); message CM_MOUSEENTER; procedure CMmouseLeave(var message : Tmessage); message CM_MOUSELEAVE; public constructor create(AOwner : TComponent); override; destructor destroy; override; property map : Tbitmap read Fmap; published property orientation : TOrientation read FOrientation write setOrientation; property OnEnter : TNotifyEvent read FOnEnter write FOnEnter; property OnLeave : TNotifyEvent read FonLeave write FOnLeave; property onChange : TRotationChange read FonChange write FonChange; property onButtonPaint : TonButtonPaint read FonButtonPaint write FonButtonPaint; property visible; property enabled; property bordercolor1 : cardinal read FBordercolor1 write setBordercolor1; property bordercolor2 : cardinal read FBordercolor2 write setbordercolor2; property BGcolor : cardinal read FBGcolor write setBGcolor; property borderwidth : byte read FBorderwidth write setBorderwidth; property notchwidth : byte read FNotchwidth write setNotchWidth; property notchSpacing : byte read FNotchSpacing write setNotchSpacing; property notchColor : cardinal read Fnotchcolor write setNotchColor; property position : byte read Fposition write setPosition; property maximum : byte read Fmaximum write setmaximum; property pixelratio : byte read FPixelRatio write setpixelratio; end; procedure Register; implementation procedure Register; begin RegisterComponents('system',[Tdav7RotationBtn]); end; constructor TDav7RotationBtn.create(Aowner : TComponent); begin inherited create(AOwner); width := 30; height := 120; Forientation := orVertical; Fborderwidth := 2; FBordercolor1 := $404040; FBordercolor2 := $808080; FbgColor := $c0c0c0; FNotchColor := $000000; FnotchWidth := 5; FNotchSpacing := 5; Fpixelratio := 10; Fmaximum := 10; Fmaxpixelcount := 105; end; destructor TDav7RotationBtn.destroy; begin map.free; inherited destroy; end; procedure TDav7RotationBtn.setOrientation(ortn : TOrientation); var h : integer; begin if ((ortn = orHorizontal) and (width < height)) or ((ortn = orVertical) and (width > height)) then begin h := height; height := width; width := h; end; FOrientation := ortn; draw; end; procedure Tdav7RotationBtn.CMmouseLeave(var message : Tmessage); begin if not (csDesigning in componentstate) and assigned(FOnLeave) then onLeave(self); end; procedure Tdav7RotationBtn.CMmouseEnter(var message : Tmessage); begin FDCC := 0; if not (csDesigning in componentstate) and assigned(FOnEnter) then onEnter(self); end; procedure TDav7RotationBtn.setbordercolor1(col : cardinal); begin Fbordercolor1 := col; draw; end; procedure TDav7RotationBtn.setbordercolor2(col : cardinal); begin Fbordercolor2 := col; draw; end; procedure TDav7RotationBtn.setBGcolor(col : cardinal); begin FBgcolor := col; draw; end; procedure TDav7RotationBtn.setborderwidth(bw : byte); begin if bw >= width shr 1 then bw := 0; FBorderwidth := bw; draw; end; procedure TDav7RotationBtn.setNotchWidth(nw : byte); begin FNotchWidth := nw; draw; end; procedure TDav7RotationBtn.setNotchSpacing(ns : byte); begin FNotchSpacing := ns; draw; end; procedure TDav7RotationBtn.setNotchColor(col : cardinal); begin FNotchColor := col; draw; end; procedure TDav7RotationBtn.setPosition(pos : byte); begin FPosition := pos; Fpixelcount := pos * pixelratio; draw; end; procedure TDav7RotationBtn.setmaximum(m : byte); begin Fmaximum := m; if m < Fposition then begin Fposition := m; FPixelcount := m * Fpixelratio; end; Fmaxpixelcount := Fpixelratio * (m+1) - 1; draw; end; procedure TDav7RotationBtn.setpixelratio(pr : byte); begin FPixelRatio := pr; Fpixelcount := Fposition * pr; Fmaxpixelcount := pr * (Fmaximum+1) - 1; draw; end; procedure TDav7RotationBtn.paint; begin draw; end; procedure TDav7RotationBtn.mousemove(Shift : Tshiftstate; x,y : integer); var dy,dx : smallInt; newPosition : byte; begin if Fmoving then begin dx := x - FoldX; dy := y - FoldY; FoldX := x; FoldY := y; case Forientation of orVertical : Fpixelcount := Fpixelcount - dy; orHorizontal : Fpixelcount := Fpixelcount + dx; end;//case if Fpixelcount < 0 then Fpixelcount := 0 else if Fpixelcount > Fmaxpixelcount then Fpixelcount := Fmaxpixelcount; newposition := Fpixelcount div Fpixelratio; if newposition <> Fposition then begin Fposition := newposition; if assigned(FonChange) then Fonchange(self,Fposition); end; draw; end; end; procedure TDav7RotationBtn.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin Fmoving:= true; FoldX := x; FoldY := y; end; procedure TDav7RotationBtn.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin Fmoving := false; end; procedure TDav7RotationBtn.draw; var i,radius,notchInterval,tape : smallInt; x1,y1,x2,y2,pixbase : smallInt; RI,rad2 : longInt; a,h : double; begin if assigned(Fmap) = false then begin Fmap := Tbitmap.create; Fmap.pixelformat := pf32bit; end; if Fmap.Width <> width then Fmap.Width := width; if Fmap.Height <> height then Fmap.Height := height; with Fmap do with canvas do begin brush.Color := FbgColor; brush.Style := bsSolid; fillrect(rect(0,0,width,height)); pen.Width := 1; for i := 0 to FBorderwidth-1 do begin pen.Color := FBordercolor1; moveto(width-i-1,i); lineto(i,i); lineto(i,height-1-i); pen.color := FBordercolor2; lineto(width-1-i,height-1-i); lineto(width-i-1,i); end; // notchInterval := FNotchSpacing + FNotchWidth; pen.Color := FNotchColor; x1 := FBorderwidth; y1 := FBorderwidth; x2 := width - FBorderwidth; y2 := height - FBorderwidth; if Forientation = orVertical then begin radius := height shr 1; rad2 := radius*radius; for i := y1 to y2 - 1 do begin if i = radius then a := 0.5*pi else begin RI := radius-i; h := sqrt(rad2 - sqr(RI)); a := arctan(h/RI); if RI < 0 then a := pi + a; end; tape := round(a*radius); if ((tape + Fpixelcount) mod notchInterval) < FnotchWidth then begin moveto(x1,i); lineto(x2,i); end; end; end; if Forientation = orHorizontal then begin radius := width shr 1; rad2 := radius*radius; pixbase := FMaxpixelcount - Fpixelcount; for i := x1 to x2-1 do begin if i = radius then a := 0.5*pi else begin RI := radius-i; h := sqrt(rad2 - sqr(RI)); a := arctan(h/RI); if RI < 0 then a := pi + a; end; tape := round(a*radius); if ((pixbase + tape) mod notchInterval) < FnotchWidth then begin moveto(i,y1); lineto(i,y2); end; end; end; end;//with if assigned(FonButtonPaint) then FonButtonPaint(self); self.Canvas.Draw(0,0,Fmap); end; end.