MMOscope.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:93k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Fax.: +49 (0)351-8037944              =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.html             =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 12.04.98 - 23:06:25 $                                        =}
  24. {========================================================================}
  25. Unit MMOscope;
  26. {$I COMPILER.INC}
  27. interface
  28. uses
  29. {$IFDEF WIN32}
  30.     Windows,
  31. {$ELSE}
  32.     WinTypes,
  33.     WinProcs,
  34. {$ENDIF}
  35.     SysUtils,
  36.     Messages,
  37.     Classes,
  38.     Graphics,
  39.     Controls,
  40.     Forms,
  41.     Dialogs,
  42.     ExtCtrls,
  43.     Menus,
  44.     MMUtils,
  45.     MMString,
  46.     MMObj,
  47.     MMSystem,
  48.     MMRegs,
  49.     MMPCMSup,
  50.     MMWaveIO,
  51.     MMDIBCv;
  52. const
  53.     {$IFDEF CBUILDER3} {$EXTERNALSYM SCALEHEIGHT} {$ENDIF}
  54.     SCALEHEIGHT     = 40;
  55.     {$IFDEF CBUILDER3} {$EXTERNALSYM SCALEWIDTH} {$ENDIF}
  56.     SCALEWIDTH      = 32;
  57.     {$IFDEF CBUILDER3} {$EXTERNALSYM SCALEFONT} {$ENDIF}
  58.     SCALEFONT       = 'ARIAL';
  59.     SCALEFONTSIZE   : integer = 10;
  60.     INFOCOLOR       : TCOLOR = clWhite;
  61.     EFFECTLIMIT     : integer = 3;
  62.     {$IFDEF CBUILDER3} {$EXTERNALSYM MAX_FFTLEN} {$ENDIF}
  63.     MAX_FFTLEN      = 4096; { Define the maximum FFT buffer length. }
  64. type
  65.     EMMOscopeError   = class(Exception);
  66.     TMMOscopeKind    = (okDots,okConLines,okVertLines,okMirLines,okSpikes);
  67.     TMMOscopeEffect  = (efNone,efPeak,efSplit);
  68.     TMMOscopeDrawLine= procedure(Sender: TObject; DIB: TMMDIBCanvas; Rect: TRect; Data: PSmallArray)of object;
  69.     TMMOscopeSelect  = procedure(Sender: TObject; Min, Max: Longint) of object;
  70.     {-- TMMOscope --------------------------------------------------------}
  71.     TMMOscope = class(TMMDIBGraphicControl)
  72.     private
  73.       FEnabled       : Boolean;        { Enable or disable Scope         }
  74.       FForeColor     : TColor;         { foreground color                }
  75.       FInactColor    : TColor;         { color for unmarked regions      }
  76.       FOffColor      : TColor;         { foreColor if disabled           }
  77.       FEffectColor   : TColor;         { color for the effects           }
  78.       FScaleTextColor: TColor;         { the text color for the scale    }
  79.       FScaleLineColor: TColor;         { the line color for the scale    }
  80.       FGridColor     : TColor;         { the grid color                  }
  81.       FScaleBackColor: TColor;         { background color for scale      }
  82.       FSelectColor   : TColor;         { color for selected range        }
  83.       FSelectDotColor: TColor;         { border color for selected range }
  84.       FLocatorColor  : TColor;         { locator color                   }
  85.       FEffect        : TMMOscopeEffect;{ differrent color effects        }
  86.       FSampleRate    : Longint;        { A/D sampling rate               }
  87.       FBits          : TMMBits;        { bit8 or bit16                   }
  88.       FChannel       : TMMChannel;     { chBoth, chLeft or chRigth       }
  89.       FMode          : TMMMode;        { mMono, mStereo                  }
  90.       FBytes         : Longint;        { calculated data bytes per scope }
  91.       FKind          : TMMOscopeKind;  { scope drawing modes             }
  92.       FSteps         : Integer;        { plot every 'steps' samples      }
  93.       FZoom          : Integer;        { the actual zoom factor          }
  94.       FGain          : Integer;        { the linear gain for the pcm data}
  95.       FData          : PSmallArray;    { sample data buffer              }
  96.       FWidth         : integer;        { calculated width without border }
  97.       FHeight        : integer;        { calculated height without border}
  98.       FMiddle        : integer;        { calculated middleline           }
  99.       FClientRect    : TRect;          { calculated beveled Rect         }
  100.       FOldShowHint   : Boolean;        { saved ShowHint propertie        }
  101.       FShowInfo      : Boolean;        { show the amp/time info or not   }
  102.       FShowInfoHint  : Boolean;        { mouse is down, show the info    }
  103.       FDrawMidLine   : Boolean;        { draw a midline with inactive clr}
  104.       FDrawAmpScale  : Boolean;        { draw the amp scale or not       }
  105.       FDrawTimeScale : Boolean;        { draw the time scale or not      }
  106.       FDrawGrid      : Boolean;        { draw the grid or not            }
  107.       FMarkBegin     : integer;        { start pos for marked region     }
  108.       FMarkEnd       : integer;        { end pos for marked region       }
  109.       FSelectStart   : Longint;        { start pos for selected region   }
  110.       FSelectEnd     : Longint;        { end pos for selected region     }
  111.       FLocator       : Longint;        { current locator position        }
  112.       FFTLen         : integer;        { Number of points for FFT (dummy)}
  113.       Fx1            : integer;        { horiz. pos. counter for display }
  114.       Fx2            : integer;        { horiz. pos. counter for bar     }
  115.       FNumScaleSteps : integer;        { pre-calc. number of scale steps }
  116.       FBarWidth      : integer;        { width for the moving bar        }
  117.       FBarColor      : TColor;         { the color for the moving bar    }
  118.       FBarTickColor  : TColor;         { the color for the ticks on bar  }
  119.       FNeedReset     : Boolean;        { the oscope needs a reset        }
  120.       FAccelerate    : Boolean;        { accelerate the display refresh  }
  121.       FScroll        : Boolean;        { scroll the display or not       }
  122.       FRange         : Longint;
  123.       FCenter        : Longint;
  124.       FEffectTop     : integer;
  125.       FEffectBottom  : integer;
  126.       FLowPass       : Boolean;
  127.       FDrawing       : Boolean;
  128.       FLocked        : Boolean;
  129.       FUseSelection  : Boolean;
  130.       
  131.       { Events }
  132.       FOnGainOverflow: TNotifyEvent;
  133.       FOnPcmOverflow : TNotifyEvent;
  134.       FOnPostPaint   : TNotifyEvent;
  135.       FOnDrawLine    : TMMOscopeDrawLine;
  136.       FOnSelecting   : TMMOscopeSelect;
  137.       FOnSelectEnd   : TMMOscopeSelect;
  138.       procedure CreateDataBuffers(Length: Cardinal);
  139.       procedure FreeDataBuffers;
  140.       procedure SetBytesPerScope;
  141.       procedure InitializeData;
  142.       procedure CalcScaleSteps;
  143.       procedure DrawAmplitudeScale;
  144.       procedure DrawTimeScales;
  145.       procedure DrawGrids;
  146.       procedure DrawBar;
  147.       procedure DrawInfo(Pos: TPoint);
  148.       procedure DrawInactive;
  149.       procedure DrawAsDots;
  150.       procedure DrawAsSpikes;
  151.       procedure DrawAsConLines;
  152.       procedure DrawAsVertLines;
  153.       procedure DrawAsMirLines;
  154.       procedure DrawSelection(aCanvas: TMMDIBCanvas; sStart, sEnd: Longint;
  155.                               sColor: TColor; Solid: Boolean);
  156.       procedure DrawLocator(aCanvas: TMMDIBCanvas; aPos: Longint; aColor: TColor);
  157.       procedure DrawOscope(ClearBackGround: Boolean);
  158.       procedure AdjustSize(var W, H: Integer);
  159.       procedure AdjustBounds;
  160.       procedure SetEnabled(Value: Boolean);
  161.       procedure SetColors(Index: Integer; aValue: TColor);
  162.       procedure SetPCMWaveFormat(wf: TPCMWaveFormat);
  163.       function  GetPCMWaveFormat: TPCMWaveFormat;
  164.       procedure SetBits(aValue: TMMBits);
  165.       procedure SetChannel(aValue: TMMChannel);
  166.       procedure SetMode(aValue: TMMMode);
  167.       procedure SetSampleRate(aValue: Longint);
  168.       procedure SetSteps(aValue: Integer);
  169.       procedure SetZoom(aValue: Integer);
  170.       procedure SetGain(aValue: Integer);
  171.       function  GetGain: integer;
  172.       procedure SetEffect(aValue: TMMOscopeEffect);
  173.       procedure SetEffectLimits;
  174.       procedure SetKind(aValue: TMMOscopeKind);
  175.       procedure SetDrawMidLine(aValue: Boolean);
  176.       procedure SetDrawAmpScale(aValue: Boolean);
  177.       procedure SetDrawTimeScale(aValue: Boolean);
  178.       procedure SetDrawGrid(aValue: Boolean);
  179.       procedure SetBarWidth(aValue: integer);
  180.       procedure SetFFTLen(aLength: integer);
  181.       procedure SetAccelerate(aValue: Boolean);
  182.       procedure SetScroll(aValue: Boolean);
  183.       function  GetScaleBackColor: TColor;
  184.       procedure SetLocator(aValue: Longint);
  185.     protected
  186.       procedure ChangeDesigning(aValue: Boolean); override;
  187.       procedure Paint; override;
  188.       procedure GainOverflow; dynamic;
  189.       procedure PcmOverflow; dynamic;
  190.       procedure SetBounds(aLeft, aTop, aWidth, aHeight: integer); override;
  191.       procedure Changed; override;
  192.       procedure Selecting(Min, Max: Longint); dynamic;
  193.       procedure SelectEnd(Min, Max: Longint); dynamic;
  194.       procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  195.       procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  196.       procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  197.     public
  198.       constructor Create(AOwner: TComponent); override;
  199.       destructor  Destroy; override;
  200.       procedure   RefreshPCMData(PCMData: Pointer);
  201.       procedure   SetData(lpData: PSmallArray);
  202.       procedure   ResetData;
  203.       function    GetAmplitude(Pos: TPoint): Float;
  204.       function    GetTime(Pos: TPoint): Float;
  205.       property    BytesPerScope: Longint read FBytes;
  206.       property    PCMWaveFormat: TPCMWaveFormat read GetPCMWaveFormat write SetPCMWaveFormat;
  207.       procedure   Marked(mkBegin, mkEnd: integer; Redraw: Boolean);
  208.       procedure   Select(sStart, sEnd: Longint; Redraw: Boolean);
  209.       property    SelectionStart: Longint read FSelectStart;
  210.       property    SelectionEnd: Longint read FSelectEnd;
  211.       property    Locator: Longint read Flocator write SetLocator default -1;
  212.       function    IsLocator(X: integer): Boolean;
  213.       function    IsSelectStart(X: integer): Boolean;
  214.       function    IsSelectEnd(X: integer): Boolean;
  215.       function    IsInSelection(X: integer): Boolean;
  216.     published
  217.       { Events }
  218.       property OnClick;
  219.       property OnDblClick;
  220.       property OnMouseDown;
  221.       property OnMouseMove;
  222.       property OnMouseUp;
  223.       property OnDragDrop;
  224.       property OnDragOver;
  225.       property OnEndDrag;
  226.       property OnStartDrag;
  227.       property OnGainOverflow: TNotifyEvent read FOnGainOverflow write FOnGainOverflow;
  228.       property OnPcmOverflow: TNotifyEvent read FOnPcmOverflow write FOnPcmOverflow;
  229.       property OnDrawLine: TMMOscopeDrawLine read FOnDrawLine write FOnDrawLine;
  230.       property OnPostPaint: TNotifyEvent read FOnPostPaint write FOnPostPaint;
  231.       property OnSelecting: TMMOscopeSelect read FOnSelecting write FOnSelecting;
  232.       property OnSelectEnd: TMMOscopeSelect read FOnSelectEnd write FOnSelectEnd;
  233.       property Align;
  234.       property Bevel;
  235.       property PopupMenu;
  236.       property BackGroundDIB;
  237.       property UseBackGroundDIB;
  238.       property PaletteRealize;
  239.       property PaletteMapped;
  240.       property Color default clBlack;
  241.       property Cursor default crCross;
  242.       property ParentShowHint;
  243.       property ParentColor default False;
  244.       property Visible;
  245.       property ShowHint;
  246.       property ShowInfo: Boolean read FShowInfo write FShowInfo default True;
  247.       property Enabled: Boolean read FEnabled write SetEnabled default True;
  248.       property Height default 90;
  249.       property Width default 194;
  250.       property Accelerate: Boolean read FAccelerate write SetAccelerate default True;
  251.       property Scroll: Boolean read FScroll write SetScroll default False;
  252.       property DrawMidLine: Boolean read FDrawMidLine write SetDrawMidLine default False;
  253.       property Kind: TMMOscopeKind read FKind write SetKind default okDots;
  254.       property ForegroundColor: TColor index 0 read FForeColor write SetColors default clAqua;
  255.       property InactiveColor: TColor index 1 read FInactColor write SetColors default clTeal;
  256.       property EffectColor: TColor index 2 read FEffectColor write SetColors default clRed;
  257.       property DisabledColor: TColor index 3 read FOffColor write SetColors default clGray;
  258.       Property ScaleTextColor: TColor index 4 read FScaleTextColor write SetColors default clBlack;
  259.       Property ScaleLineColor: TColor index 5 read FScaleLineColor write SetColors default clBlack;
  260.       Property GridColor: TColor index 6 read FGridColor write SetColors default clGray;
  261.       property BarColor: TColor index 7 read FBarColor write SetColors default clGray;
  262.       property BarTickColor: TColor index 8 read FBarTickColor write SetColors default clWhite;
  263.       {$IFDEF BUILD_ACTIVEX}
  264.       property ScaleBackColor: TColor index 9 read FScaleBackColor write SetColors default clBtnFace;
  265.       {$ENDIF}
  266.       property SelectionColor: TColor index 10 read FSelectColor write SetColors default clRed;
  267.       property SelectionDotColor: TColor index 11 read FSelectDotColor write SetColors default clRed;
  268.       property LocatorColor: TColor index 12 read FLocatorColor write SetColors default clYellow;
  269.       property BarWidth: integer read FBarWidth write SetBarWidth default 5;
  270.       property BitLength: TMMBits read FBits write SetBits default b8bit;
  271.       property Channel: TMMChannel read FChannel write SetChannel default chBoth;
  272.       property SampleRate: Longint read FSampleRate write SetSampleRate default 11025;
  273.       property Mode: TMMMode read FMode write SetMode default mMono;
  274.       property Steps: Integer read FSteps write SetSteps default 1;
  275.       property Zoom: Integer read FZoom write SetZoom default 1;
  276.       property Gain: Integer read GetGain write SetGain default 0;
  277.       property Effect: TMMOscopeEffect read FEffect write SetEffect default efNone;
  278.       property DrawAmpScale: Boolean read FDrawAmpScale write SetDrawAmpScale default False;
  279.       property DrawTimeScale: Boolean read FDrawTimeScale write SetDrawTimeScale default False;
  280.       property DrawGrid: Boolean read FDrawGrid write SetDrawGrid default False;
  281.       property FFTLength: integer read FFTLen write SetFFTLen default 128;
  282.       property LowPass: Boolean read FLowPass write FLowPass default False;
  283.       property Locked: Boolean read FLocked write FLocked default False;
  284.       property UseSelection: Boolean read FUseSelection write FUseSelection default False;
  285.     end;
  286. implementation
  287. const
  288.    CreateCount : Longint = 0;
  289.    ControlList : TList   = nil;
  290.    SaveDC      : HDC     = 0;
  291.    SaveBitmap  : HBitmap = 0;
  292.    SaveWidth   : integer = 0;
  293.    SaveHeight  : integer = 0;
  294.    SaveInfoPos : TPoint  = (X:0;Y:0);
  295.    OldBitmap   : HBitmap = 0;
  296.    OldDrawPos  : TPoint  = (X:0;Y:0);
  297. {------------------------------------------------------------------------}
  298. procedure AddOscope(Oscope: TMMOscope);
  299. begin
  300.    inc(CreateCount);
  301.    if (CreateCount = 1) then
  302.    begin
  303.       ControlList := TList.Create;
  304.    end;
  305.    if ControlList.IndexOf(Oscope) = -1 then
  306.       ControlList.Add(Oscope);
  307. end;
  308. {------------------------------------------------------------------------}
  309. procedure RemoveOscope(Oscope: TMMOscope);
  310. begin
  311.    ControlList.Remove(Oscope);
  312.    ControlList.Pack;
  313.    dec(CreateCount);
  314.    if (CreateCount = 0) then
  315.    begin
  316.       ControlList.Free;
  317.       ControlList := nil;
  318.    end;
  319. end;
  320. {------------------------------------------------------------------------}
  321. procedure ResetOscope(Oscope: TMMOscope);
  322. var
  323.    i: integer;
  324. begin
  325.    if (ControlList <> nil) and (ControlList.Count > 0) then
  326.    begin
  327.       if Oscope.FScroll then
  328.       for i := 0 to ControlList.Count-1 do
  329.           if (ControlList.Items[i] <> Oscope) then
  330.              TMMOscope(ControlList.Items[i]).FNeedReset := True;
  331.    end;
  332. end;
  333. {-- TMMOscope ------------------------------------------------------------}
  334. constructor TMMOscope.Create(AOwner: TComponent);
  335. begin
  336.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  337.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  338.    inherited Create(AOwner);
  339.    FData := Nil;
  340.    FRange := $FFFF;
  341.    FCenter := $7FFF;
  342.    FMarkBegin := 0;
  343.    FMarkEnd := Width;
  344.    FSelectStart := -1;
  345.    FSelectEnd := -1;
  346.    FLocator := -1;
  347.    FEnabled := True;
  348.    Color := clBlack;
  349.    FForeColor := clAqua;
  350.    FInactColor := clTeal;
  351.    FOffColor  := clGray;
  352.    FEffectColor := clRed;
  353.    FScaleTextColor := clBlack;
  354.    FScaleLineColor:= clBlack;
  355.    FGridColor := clGray;
  356.    FScaleBackColor:= clBtnFace;
  357.    FSelectColor := clRed;
  358.    FSelectDotColor := clRed;
  359.    FLocatorColor := clYellow;
  360.    FBits := b8Bit;
  361.    FChannel   := chBoth;
  362.    FMode := mMono;
  363.    FSampleRate := 11025;
  364.    FSteps := 1;
  365.    FZoom := 1;
  366.    FGain := 8;                                    { no Gain = 8 div 8 = 1 }
  367.    FEffect := efNone;
  368.    FKind := okDots;
  369.    FDrawMidLine := False;
  370.    FDrawAmpScale := False;
  371.    FDrawTimeScale := False;
  372.    FDrawGrid := False;
  373.    FBarWidth := 5;
  374.    FBarColor := clGray;
  375.    FBarTickColor := clWhite;
  376.    Fx1 := -FBarWidth;
  377.    Fx2 := 0;
  378.    FNeedReset := False;
  379.    FAccelerate := True;
  380.    FShowInfoHint := False;
  381.    FShowInfo := True;
  382.    FScroll := False;
  383.    FFTLen := 8;
  384.    FLowPass := False;
  385.    FDrawing := False;
  386.    FLocked := False;
  387.    FUseSelection := False;
  388.    Height := 90;
  389.    Width := 194;
  390.    Cursor := crCross;
  391.    FFTLength := 128;
  392.    if not (csDesigning in ComponentState) then
  393.    begin
  394.       { update the oscope list }
  395.       AddOscope(Self);
  396.    end;
  397. end;
  398. {-- TMMOscope ------------------------------------------------------------}
  399. Destructor TMMOscope.Destroy;
  400. begin
  401.    if not (csDesigning in ComponentState) then
  402.    begin
  403.       { update the oscope list }
  404.       RemoveOscope(Self);
  405.    end;
  406.    FreeDataBuffers;
  407.    inherited Destroy;
  408. end;
  409. {-- TMMOscope ------------------------------------------------------------}
  410. procedure TMMOscope.ChangeDesigning(aValue: Boolean);
  411. begin
  412.    inherited ChangeDesigning(aValue);
  413.    if not (csDesigning in ComponentState) then
  414.    begin
  415.       { update the oscope list }
  416.       AddOscope(Self);
  417.       InitializeData;
  418.    end;
  419. end;
  420. {-- TMMOscope ------------------------------------------------------------}
  421. procedure TMMOscope.CreateDataBuffers(Length: Cardinal);
  422. begin
  423.    if (Length > 0) then
  424.    begin
  425.       { allocate memory for sample buffer and lock }
  426.       GlobalReAllocMem(Pointer(FData), (Length+4*10) * sizeOf(SmallInt));
  427.    end;
  428. end;
  429. {-- TMMOscope ------------------------------------------------------------}
  430. procedure TMMOscope.FreeDataBuffers;
  431. begin
  432.    GlobalFreeMem(Pointer(FData));
  433. end;
  434. {-- TMMOscope ------------------------------------------------------------}
  435. procedure TMMOscope.GainOverflow;
  436. begin
  437.    if Assigned(FOnGainOverflow) then FOnGainOverflow(Self);
  438. end;
  439. {-- TMMOscope ------------------------------------------------------------}
  440. procedure TMMOscope.PcmOverflow;
  441. begin
  442.    if Assigned(FOnPcmOverflow) then FOnPcmOverflow(Self);
  443. end;
  444. {-- TMMOscope ------------------------------------------------------------}
  445. procedure TMMOscope.InitializeData;
  446. Var
  447.    i: integer;
  448.    scale: real;
  449. begin
  450.    scale := 1.0;
  451.    if (csDesigning in ComponentState) then
  452.    for i := 0 to FWidth-1 do                           { create sine data }
  453.    begin
  454.       FData^[i] := Round(sin(i*2*PI/((FWidth-1)/8))*scale*$77FF);
  455.       scale := scale - (1.0/FWidth);
  456.    end
  457.    else                                                { create zero data }
  458.    for i := 0 to FWidth-1 do FData^[i] := 0;
  459.    FMarkBegin   := 0;                     { reset the marker positions }
  460.    FMarkEnd     := FWidth;
  461.    FSelectStart := -1;
  462.    FSelectEnd   := -1;
  463.    FLocator     := -1;
  464. end;
  465. {-- TMMOscope ------------------------------------------------------------}
  466. procedure TMMOscope.ResetData;
  467. var
  468.    P: TPoint;
  469. begin
  470.    if FShowInfoHint then
  471.    begin
  472.       GetCursorPos(P);
  473.       P := ScreenToClient(P);
  474.       Perform(WM_LBUTTONUP, 0, Longint(PointToSmallPoint(P)));
  475.    end;
  476.    { TODO: f黵 Scroll display }
  477.    InitializeData;
  478.    Refresh;
  479. end;
  480. {-- TMMOscope ------------------------------------------------------------}
  481. procedure TMMOscope.SetEnabled(Value: Boolean);
  482. begin
  483.    if (Value <> FEnabled) then
  484.    begin
  485.       FEnabled := Value;
  486.       {inherited Enabled := Value;}
  487.       Invalidate;
  488.    end;
  489. end;
  490. {-- TMMOscope ------------------------------------------------------------}
  491. procedure TMMOscope.SetBarWidth(aValue: integer);
  492. begin
  493.    if (aValue <> FBarWidth) then
  494.    begin
  495.       FBarWidth := Max(aValue,1);
  496.       Invalidate;
  497.    end;
  498. end;
  499. {-- TMMOscope ------------------------------------------------------------}
  500. procedure TMMOscope.SetFFTLen(aLength: integer);
  501. var
  502.    i: integer;
  503. begin
  504.    { FFTLen is here only a dummy to sync. the scrolling with other controls }
  505.    aLength := MinMax(aLength,1,MAX_FFTLEN);
  506.    { Convert FFTLen to a power of 2 }
  507.    i := 0;
  508.    while aLength > 1 do
  509.    begin
  510.       aLength := aLength shr 1;
  511.       inc(i);
  512.    end;
  513.    if (i > 0) then aLength := aLength shl i;
  514.    if (aLength <> FFTLen) then
  515.    begin
  516.       FFTLen := aLength;
  517.       if FScroll then
  518.       begin
  519.          SetBytesPerScope;
  520.          Invalidate;
  521.       end;
  522.    end;
  523. end;
  524. {-- TMMOscope ------------------------------------------------------------}
  525. procedure TMMOscope.SetKind(aValue: TMMOscopeKind);
  526. begin
  527.    if (aValue <> FKind) then
  528.    begin
  529.       FKind := aValue;
  530.       if (FKind = okSpikes) then
  531.       begin
  532.          FRange := $7FFF;
  533.          FCenter := 0;
  534.       end
  535.       else
  536.       begin
  537.          FRange := $FFFF;
  538.          FCenter := $7FFF;
  539.       end;
  540.      Invalidate;
  541.    end;
  542.    {$IFDEF WIN32}
  543.    {$IFDEF TRIAL}
  544.    {$DEFINE _HACK1}
  545.    {$I MMHACK.INC}
  546.    {$ENDIF}
  547.    {$ENDIF}
  548. end;
  549. {-- TMMOscope ------------------------------------------------------------}
  550. procedure TMMOscope.SetEffectLimits;
  551. begin
  552.    case FEffect of
  553.        efPeak : begin
  554.                    FEffectTop := FHeight div EFFECTLIMIT;
  555.                    FEffectBottom := FHeight - FEffectTop;
  556.                 end;
  557.        efSplit: begin
  558.                    FEffectTop := 0;
  559.                    FEffectBottom := FMiddle;
  560.                 end;
  561.    end;
  562. end;
  563. {-- TMMOscope ------------------------------------------------------------}
  564. procedure TMMOscope.SetEffect(aValue: TMMOscopeEffect);
  565. begin
  566.    FEffect := aValue;
  567.    SetEffectLimits;
  568.    Invalidate;
  569.    {$IFDEF WIN32}
  570.    {$IFDEF TRIAL}
  571.    {$DEFINE _HACK2}
  572.    {$I MMHACK.INC}
  573.    {$ENDIF}
  574.    {$ENDIF}
  575. end;
  576. {-- TMMOscope ------------------------------------------------------------}
  577. procedure TMMOscope.AdjustSize(var W, H: Integer);
  578. begin
  579.    W := Max(W,2*BevelExtend+2);
  580.    H := Max(H,2*BevelExtend+2) ;{and $FFFE;}
  581.    if FDrawAmpScale then
  582.       W := Max(W,2*SCALEWIDTH+2*BevelExtend+2);
  583.    if FDrawTimeScale then
  584.       H := Max(H,SCALEHEIGHT+2*BevelExtend+2); {and $FFFE};
  585. end;
  586. {-- TMMOscope ------------------------------------------------------------}
  587. procedure TMMOscope.AdjustBounds;
  588. var
  589.   W, H: Integer;
  590. begin
  591.    W := Width;
  592.    H := Height;
  593.    AdjustSize(W, H);
  594.    if (W <> Width) or (H <> Height) then SetBounds(Left, Top, W, H)
  595.    else Changed;
  596. end;
  597. {-- TMMOscope ------------------------------------------------------------}
  598. procedure TMMOscope.SetBounds(aLeft, aTop, aWidth, aHeight: integer);
  599. var
  600.   W, H: Integer;
  601. begin
  602.    W := aWidth;
  603.    H := aHeight;
  604.    AdjustSize (W, H);
  605.    inherited SetBounds(aLeft, aTop, W, H);
  606.    Changed;
  607. end;
  608. {-- TMMOscope ------------------------------------------------------------}
  609. procedure TMMOscope.Changed;
  610. begin
  611.    FClientRect := Rect(0,0,Width,Height);
  612.    { make place for amp the scale }
  613.    if FDrawAmpScale then
  614.       InflateRect(FClientRect, -SCALEWIDTH,0);
  615.    { make place for amp the scale }
  616.    if FDrawTimeScale then
  617.       dec(FClientRect.Bottom, SCALEHEIGHT);
  618.    { and now for the bevel }
  619.    InflateRect(FClientRect, -Bevel.BevelExtend, -Bevel.BevelExtend);
  620.    FWidth  := Max(FClientRect.Right - FClientRect.Left,4);
  621.    FHeight := Max(FClientRect.Bottom - FClientRect.Top,4);
  622.    FMiddle := FHeight div 2;
  623.                                             { adjust the data buffer size }
  624.    CreateDataBuffers(FWidth);
  625.    InitializeData;                                 { init the data buffer }
  626.    DIBCanvas.SetBounds(0,0,FWidth,FHeight);
  627.    SetEffectLimits;
  628.    SetBytesPerScope;                       { calc the new bytes per Scope }
  629.    FMarkBegin   := 0;                      { reset the marker positions }
  630.    FMarkEnd     := FWidth;
  631.    FSelectStart := -1;
  632.    FSelectEnd   := -1;
  633.    FLocator     := -1;
  634.    CalcScaleSteps;
  635.    inherited Changed;
  636. end;
  637. {-- TMMOscope ------------------------------------------------------------}
  638. Procedure TMMOscope.SetBytesPerScope;
  639. begin
  640.    FBytes := (Ord(FBits)+1) * (Ord(FMode)+1);
  641.    if FScroll then FBytes := FBytes  * FFTLen
  642.    else
  643.    begin
  644.       FBytes := FBytes * FWidth;
  645.       if (FZoom > 0) then FBytes := FBytes * FZoom
  646.       else if (FZoom < 0) then FBytes := ((FBytes div (abs(FZoom)+1)+5)div 4)*4;
  647.    end;
  648. end;
  649. {-- TMMOscope ------------------------------------------------------------}
  650. Procedure TMMOscope.SetPCMWaveFormat(wf: TPCMWaveFormat);
  651. var
  652.    pwfx: PWaveFormatEx;
  653. begin
  654.    pwfx := @wf;
  655.    if not pcmIsValidFormat(pwfx) then
  656.       raise EMMOscopeError.Create(LoadResStr(IDS_INVALIDFORMAT));
  657.    SampleRate := pwfx^.nSamplesPerSec;
  658.    BitLength := TMMBits(pwfx^.wBitsPerSample div 8 - 1);
  659.    Mode := TMMMode(pwfx^.nChannels-1);
  660. end;
  661. {-- TMMOscope ------------------------------------------------------------}
  662. function TMMOscope.GetPCMWaveFormat: TPCMWaveFormat;
  663. var
  664.    wfx: TWaveFormatEx;
  665. begin
  666.    pcmBuildWaveHeader(@wfx, (Ord(FBits)+1)*8, Ord(FMode)+1, SampleRate);
  667.    Result := PPCMWaveFormat(@wfx)^;
  668. end;
  669. {-- TMMOscope ------------------------------------------------------------}
  670. Procedure TMMOscope.SetBits(aValue: TMMBits);
  671. begin
  672.    if (aValue <> FBits) then
  673.    begin
  674.       FBits := aValue;
  675.       SetBytesPerScope;
  676.       Invalidate;
  677.    end;
  678. end;
  679. {-- TMMOscope ------------------------------------------------------------}
  680. Procedure TMMOscope.SetChannel(aValue: TMMChannel);
  681. begin
  682.    if (aValue <> FChannel) then
  683.    begin
  684.       FChannel := aValue;
  685.       SetBytesPerScope;
  686.       Invalidate;
  687.    end;
  688. end;
  689. {-- TMMOscope ------------------------------------------------------------}
  690. Procedure TMMOscope.SetMode(aValue: TMMMode);
  691. begin
  692.    if (aValue <> FMode) then
  693.    begin
  694.       FMode := aValue;
  695.       SetBytesPerScope;
  696.       Invalidate;
  697.    end;
  698.    {$IFDEF WIN32}
  699.    {$IFDEF TRIAL}
  700.    {$DEFINE _HACK3}
  701.    {$I MMHACK.INC}
  702.    {$ENDIF}
  703.    {$ENDIF}
  704. end;
  705. {-- TMMOscope ------------------------------------------------------------}
  706. procedure TMMOscope.SetSampleRate(aValue: Longint);
  707. begin
  708.    if (aValue <> FSampleRate) then
  709.    begin
  710.       FSampleRate := MinMax(aValue, 8000, 88200);
  711.       { Re-initialize the display }
  712.       Invalidate;
  713.    end;
  714. end;
  715. {-- TMMOscope ------------------------------------------------------------}
  716. Procedure TMMOscope.SetGain(aValue: Integer);
  717. begin
  718.    if (aValue <> FGain-8) and (aValue >= -8) and (aValue <= 32) then
  719.    begin
  720.       FGain := aValue + 8;
  721.       Invalidate;
  722.    end;
  723. end;
  724. {-- TMMOscope ------------------------------------------------------------}
  725. Function TMMOscope.GetGain: Integer;
  726. begin
  727.    Result := FGain - 8;
  728. end;
  729. {-- TMMOscope ------------------------------------------------------------}
  730. Procedure TMMOscope.SetSteps(aValue: Integer);
  731. begin
  732.    aValue := MinMax(1, aValue, 9);
  733.    if (aValue <> FSteps) then
  734.    begin
  735.       FSteps := aValue;
  736.       Invalidate;
  737.    end;
  738. end;
  739. {-- TMMOscope ------------------------------------------------------------}
  740. Procedure TMMOscope.SetZoom(aValue: Integer);
  741. begin
  742.    if (aValue <> FZoom) and (aValue <> 0) then
  743.    begin
  744.       FZoom := MinMax(aValue,-9,9);
  745.       SetBytesPerScope;
  746.       Invalidate;
  747.    end;
  748. end;
  749. {-- TMMOscope ------------------------------------------------------------}
  750. procedure TMMOscope.SetDrawAmpScale(aValue: Boolean);
  751. begin
  752.    if (aValue <> FDrawAmpScale) then
  753.    begin
  754.       FDrawAmpScale := aValue;
  755.       AdjustBounds;
  756.       Invalidate;
  757.    end;
  758. end;
  759. {-- TMMOscope ------------------------------------------------------------}
  760. procedure TMMOscope.SetDrawTimeScale(aValue: Boolean);
  761. begin
  762.    if (aValue <> FDrawTimeScale) then
  763.    begin
  764.       FDrawTimeScale := aValue;
  765.       AdjustBounds;
  766.       Invalidate;
  767.    end;
  768. end;
  769. {-- TMMOscope ------------------------------------------------------------}
  770. procedure TMMOscope.SetDrawGrid(aValue: Boolean);
  771. begin
  772.    if (aValue <> FDrawGrid) then
  773.    begin
  774.       FDrawGrid := aValue;
  775.       Invalidate;
  776.    end;
  777. end;
  778. {-- TMMOscope ------------------------------------------------------------}
  779. procedure TMMOscope.SetAccelerate(aValue: Boolean);
  780. begin
  781.    if (aValue <> FAccelerate) then
  782.    begin
  783.       FAccelerate := aValue;
  784.       if not FAccelerate and FScroll then Invalidate;
  785.    end;
  786. end;
  787. {-- TMMOscope ------------------------------------------------------------}
  788. Procedure TMMOscope.SetScroll(aValue: Boolean);
  789. begin
  790.    if (aValue <> FScroll) then
  791.    begin
  792.       FScroll := aValue;
  793.       Changed;
  794.    end;
  795. end;
  796. {-- TMMOscope ------------------------------------------------------------}
  797. Procedure TMMOscope.SetColors(Index: Integer; aValue: TColor);
  798. begin
  799.    case Index of
  800.         0: if FForeColor = aValue then exit else FForeColor := aValue;
  801.         1: if FInactColor = aValue then exit else FInactColor := aValue;
  802.         2: if FEffectColor = aValue then exit else FEffectColor := aValue;
  803.         3: if FOffColor = aValue then exit else FOffColor := aValue;
  804.         4: if FScaleTextColor = aValue then exit else FScaleTextColor := aValue;
  805.         5: if FScaleLineColor = aValue then exit else FScaleLineColor := aValue;
  806.         6: if FGridColor = aValue then exit else FGridColor := aValue;
  807.         7: if FBarColor = aValue then exit else FBarColor := aValue;
  808.         8: if FBarTickColor = aValue then exit else FBarTickColor := aValue;
  809.         9: if FScaleBackColor = aValue then exit else FScaleBackColor := aValue;
  810.        10: if FSelectColor = aValue then exit else FSelectColor := aValue;
  811.        11: if FSelectDotColor = aValue then exit else FSelectDotColor := aValue;
  812.        12: if FLocatorColor = aValue then exit else FLocatorColor := aValue;
  813.    end;
  814.    Invalidate;
  815. end;
  816. {-- TMMOscope ------------------------------------------------------------}
  817. procedure TMMOscope.Marked(mkBegin, mkEnd: Integer; Redraw: Boolean);
  818. begin
  819.    if (mkBegin <> FMarkBegin) then
  820.    begin
  821.       if (mkBegin < 0) then mkBegin := -1;
  822.       if (mkBegin > FWidth) then mkBegin := FWidth;
  823.       FMarkBegin := mkBegin;
  824.    end;
  825.    if (mkEnd <> FMarkEnd) then
  826.    begin
  827.       if (mkEnd < 0) then mkEnd := -1;
  828.       if (mkEnd > FWidth) then mkEnd := FWidth;
  829.       FMarkEnd := mkEnd;
  830.    end;
  831.    if Redraw then Refresh;
  832. end;
  833. {-- TMMOscope -----------------------------------------------------------------}
  834. procedure TMMOscope.Select(sStart, sEnd: Longint; Redraw: Boolean);
  835. var
  836.    oldStart,oldEnd: Longint;
  837. begin
  838.    oldStart:= FSelectStart;
  839.    oldEnd := FSElectEnd;
  840.    if (sStart <> FSelectStart) then
  841.    begin
  842.       if (sStart < 0) then sStart := -1;
  843.       if (sStart > FWidth) then sStart := FWidth;
  844.       FSelectStart := sStart;
  845.    end;
  846.    if (sEnd <> FSelectEnd) then
  847.    begin
  848.       if (sEnd < 0) then sEnd := -1;
  849.       if (sEnd > FWidth) then sEnd := FWidth;
  850.       FSelectEnd := sEnd;
  851.    end;
  852.    if (FSelectStart > FSelectEnd) then
  853.    begin
  854.       SwapLong(FSelectStart,FSelectEnd);
  855.    end;
  856.    if (FSelectEnd - FSelectStart <= 0) then
  857.    begin
  858.       FSelectStart := -1;
  859.       FSelectEnd := -1;
  860.    end;
  861.    if Redraw and ((oldStart <> FSelectStart) or (oldEnd <> FSelectEnd)) then
  862.       Refresh;
  863. end;
  864. {-- TMMOscope -----------------------------------------------------------------}
  865. procedure TMMOscope.SetLocator(aValue: Longint);
  866. var
  867.    oldLoc: Longint;
  868. begin
  869.    oldLoc := FLocator;
  870.    if (aValue <> FLocator) then
  871.    begin
  872.       if (aValue < 0) then aValue := -1;
  873.       if (aValue > FWidth) then aValue := FWidth;
  874.       FLocator := aValue;
  875.    end;
  876.    if (oldLoc <> FLocator) then
  877.       Refresh;
  878. end;
  879. {-- TMMOscope ------------------------------------------------------------}
  880. procedure TMMOscope.SetDrawMidLine(aValue: Boolean);
  881. begin
  882.    if (aValue <> FDrawMidLine) then
  883.    begin
  884.       FDrawMidLine := aValue;
  885.       Invalidate;
  886.    end;
  887. end;
  888. {-- TMMOscope ------------------------------------------------------------}
  889. Procedure TMMOscope.RefreshPCMData(PCMData: Pointer);
  890. Var
  891.    i,j: integer;
  892.    ReIndex: integer;
  893.    rZoom: integer;
  894.    wf: TPCMWaveFormat;
  895.    MinL,MaxL,MinR,MaxR: SmallInt;
  896. begin
  897.    if FEnabled and Visible and not FShowInfoHint then
  898.    begin
  899.       if FScroll then
  900.       begin
  901.          i := 0;
  902.          wf := GetPCMWaveFormat;
  903.          pcmFindMinMax(@wf, PCMData, FBytes,
  904.                        MinL,MaxL,MinR,MaxR);
  905.          if (FBits = b8bit) then
  906.          begin
  907.             if (FMode = mMono) or (FChannel = chLeft) then
  908.             begin
  909.                FData^[i] := (MinL-128) shl 8;
  910.                FData^[i+1] := (MaxL-128) shl 8;
  911.             end
  912.             else if (FChannel = chRight) then
  913.             begin
  914.                FData^[i] := (MinR-128) shl 8;
  915.                FData^[i+1] := (MaxR-128) shl 8;
  916.             end
  917.             else
  918.             begin
  919.                FData^[i] := ((MinL + MinR) div 2 - 128) shl 8;
  920.                FData^[i+1] := ((MaxL + MaxR) div 2 - 128) shl 8;
  921.             end;
  922.          end
  923.          else
  924.          begin
  925.             if (FMode = mMono) or (FChannel = chLeft) then
  926.             begin
  927.                FData^[i] := MinL;
  928.                FData^[i+1] := MaxL;
  929.             end
  930.             else if (FChannel = chRight) then
  931.             begin
  932.                FData^[i] := MinR;
  933.                FData^[i+1] := MaxR;
  934.             end
  935.             else
  936.             begin
  937.                FData^[i] := (Longint(MinL)+MinR) div 2;
  938.                FData^[i+1] := (Longint(MaxL)+MaxR) div 2;
  939.             end;
  940.          end;
  941.       end
  942.       else
  943.       begin
  944.          ReIndex := Ord(FChannel)-1;
  945.          j := 0;
  946.          rZoom := abs(FZoom);
  947.          if FZoom > 0 then
  948.          begin
  949.             { copy the sample Data from PCMData to FData }
  950.             if (FBits = b8bit) then
  951.             begin
  952.                if (FMode = mMono) then
  953.                for i := 0 to FWidth-1 do
  954.                begin
  955.                   FData^[i] := (PByteArray(PCMData)^[j]-128) shl 8;
  956.                   inc(j,rZoom);
  957.                end
  958.                else if (FChannel = chBoth) then
  959.                for i := 0 to FWidth-1 do
  960.                begin
  961.                   FData^[i] := ((Word(PByteArray(PCMData)^[j+j])+PByteArray(PCMData)^[j+j+1])div 2 -128) shl 8;
  962.                   inc(j,rZoom);
  963.                end
  964.                else
  965.                for i := 0 to FWidth-1 do
  966.                begin
  967.                   FData^[i] := (PByteArray(PCMData)^[j+j+ReIndex]-128) shl 8;
  968.                   inc(j,rZoom);
  969.                end;
  970.             end
  971.             else
  972.             begin
  973.                if (FMode = mMono) then
  974.                for i := 0 to FWidth-1 do
  975.                begin
  976.                   FData^[i] := PSmallArray(PCMData)^[j];
  977.                   inc(j,rZoom);
  978.                end
  979.                else if (FChannel = chBoth) then
  980.                for i := 0 to FWidth-1 do
  981.                begin
  982.                   FData^[i] := (Long(PSmallArray(PCMData)^[j+j])+PSmallArray(PCMData)^[j+j+1])div 2;
  983.                   inc(j,rZoom);
  984.                end
  985.                else
  986.                for i := 0 to FWidth-1 do
  987.                begin
  988.                   FData^[i] := PSmallArray(PCMData)^[j+j+ReIndex];
  989.                   inc(j,rZoom);
  990.                end;
  991.             end;
  992.          end
  993.          else
  994.          begin
  995.             inc(rZoom);
  996.             { copy the sample Data from PCMData to FData }
  997.             if (FBits = b8bit) then
  998.             begin
  999.                if (FMode = mMono) then
  1000.                for i := 0 to FWidth-1 do
  1001.                begin
  1002.                   FData^[i] := (PByteArray(PCMData)^[j]-128) shl 8;
  1003.                   if ((i+1) mod rZoom = 0) then inc(j);
  1004.                end
  1005.                else if (FChannel = chBoth) then
  1006.                for i := 0 to FWidth-1 do
  1007.                begin
  1008.                   FData^[i] := ((Word(PByteArray(PCMData)^[j+j])+PByteArray(PCMData)^[j+j+1])div 2 -128) shl 8;
  1009.                   if ((i+1) mod rZoom = 0) then inc(j);
  1010.                end
  1011.                else
  1012.                for i := 0 to FWidth-1 do
  1013.                begin
  1014.                   FData^[i] := (PByteArray(PCMData)^[j+j+ReIndex]-128) shl 8;
  1015.                   if ((i+1) mod rZoom = 0) then inc(j);
  1016.                end;
  1017.             end
  1018.             else
  1019.             begin
  1020.                if (FMode = mMono) then
  1021.                for i := 0 to FWidth-1 do
  1022.                begin
  1023.                   FData^[i] := PSmallArray(PCMData)^[j];
  1024.                   if ((i+1) mod rZoom = 0) then inc(j);
  1025.                end
  1026.                else if (FChannel = chBoth) then
  1027.                for i := 0 to FWidth-1 do
  1028.                begin
  1029.                   FData^[i] := (Long(PSmallArray(PCMData)^[j+j])+PSmallArray(PCMData)^[j+j+1])div 2;
  1030.                   if ((i+1) mod rZoom = 0) then inc(j);
  1031.                end
  1032.                else
  1033.                for i := 0 to FWidth-1 do
  1034.                begin
  1035.                   FData^[i] := PSmallArray(PCMData)^[j+j+ReIndex];
  1036.                   if ((i+1) mod rZoom = 0) then inc(j);
  1037.                end;
  1038.             end;
  1039.          end;
  1040.       end;
  1041.       SetData(FData);
  1042.    end;
  1043. end;
  1044. {-- TMMOscope ------------------------------------------------------------}
  1045. Procedure TMMOscope.SetData(lpData: PSmallArray);
  1046. var
  1047.    i,Last,Value: integer;
  1048. begin
  1049.    if (lpData <> FData) then
  1050.       GlobalMoveMem(lpData^,FData^,FWidth*sizeOf(Smallint));
  1051.    if FLowPass then
  1052.    begin
  1053.       Last := 0;
  1054.       for i := 0 to FWidth-1 do
  1055.       begin
  1056.          Value     := FData^[i];
  1057.          FData^[i] := (Last+Longint(Value)*3) div 4; { Soft LowPass }
  1058.          Last      := Value;
  1059.       end;
  1060.    end;
  1061.    FastDraw(DrawOscope,False);
  1062. end;
  1063. {-- TMMOscope ------------------------------------------------------------}
  1064. Procedure TMMOscope.DrawAsDots;
  1065. Var
  1066.    i: integer;
  1067.    Y1: integer;
  1068.    aColor: Long;
  1069.    rForeClr: Long;
  1070.    rInactClr: Long;
  1071.    rEffectClr: Long;
  1072.    Value: Longint;
  1073. begin
  1074.    with DIBCanvas do
  1075.    begin
  1076.       rForeClr := DIB_ColorToIndex(FForeColor);
  1077.       rInactClr := DIB_ColorToIndex(FInactColor);
  1078.       if FScroll then
  1079.       begin
  1080.          DIB_SetTColor(Color);
  1081.          DIB_VLine(Fx1,0,FHeight);
  1082.          DIB_SetColor(rForeClr);
  1083.          if (FEffect = efNone) then
  1084.          begin
  1085.             for i := 0 to 1 do
  1086.             begin              { display points by plotting samples in FData.}
  1087.                Value := FData^[i];
  1088.                if Value >= 32767 then PcmOverflow;
  1089.                Y1 := Long(Value * FGain div 8 + FCenter)* FHeight div FRange;
  1090.                if (Y1 > FHeight) then GainOverflow;
  1091.                DIB_SetPixel(Fx1, FHeight-Y1-1, rForeClr);
  1092.             end;
  1093.          end
  1094.          else
  1095.          begin
  1096.             rEffectClr := DIB_ColorToIndex(FEffectColor);
  1097.             for i := 0 to 1 do
  1098.             begin
  1099.                Value := FData^[i];
  1100.                if (Value >= 32767) then PcmOverflow;
  1101.                Y1 := Long(Value * FGain div 8 + FCenter)* FHeight div FRange;
  1102.                if (Y1 > FHeight) then GainOverflow;
  1103.                if (Y1 < FEffectTop) or (Y1 > FEffectBottom) then
  1104.                   DIB_SetPixel(Fx1, FHeight-Y1-1, rEffectClr)
  1105.                else
  1106.                 DIB_SetPixel(Fx1, FHeight-Y1-1, rForeClr);
  1107.             end;
  1108.          end;
  1109.       end
  1110.       else
  1111.       begin
  1112.          if (FEffect = efNone) then
  1113.          begin
  1114.             aColor := rInactClr;
  1115.             i := 0;
  1116.             while i < FWidth do
  1117.             begin              { display points by plotting samples in FData.}
  1118.                Value := FData^[i];
  1119.                if Value >= 32767 then PcmOverflow;
  1120.                Y1 := Long(Value * FGain div 8 + FCenter)* FHeight div FRange;
  1121.                if (Y1 > FHeight) then GainOverflow;
  1122.                if i > FMarkEnd then aColor := rInactClr
  1123.                else if i >= FMarkBegin then aColor := rForeClr;
  1124.                DIB_SetPixel(i, FHeight-Y1-1, aColor);
  1125.                inc(i,FSteps);
  1126.             end;
  1127.          end
  1128.          else
  1129.          begin
  1130.             rEffectClr := DIB_ColorToIndex(FEffectColor);
  1131.             aColor := rInactClr;
  1132.             i := 0;
  1133.             while i < FWidth do
  1134.             begin              { display points by plotting samples in FData.}
  1135.                Value := FData^[i];
  1136.                if Value >= 32767 then PcmOverflow;
  1137.                Y1 := Long(Value * FGain div 8 + FCenter)* FHeight div FRange;
  1138.                if (Y1 > FHeight) then GainOverflow;
  1139.                if i > FMarkEnd then aColor := rInactClr
  1140.                else if i >= FMarkBegin then aColor := rForeClr;
  1141.                if (aColor = rForeClr) and ((Y1 < FEffectTop) or (Y1 > FEffectBottom)) then
  1142.                   DIB_SetPixel(i, FHeight-Y1-1, rEffectClr)
  1143.                else
  1144.                   DIB_SetPixel(i, FHeight-Y1-1, aColor);
  1145.                inc(i,FSteps);
  1146.             end;
  1147.          end;
  1148.       end;
  1149.    end;
  1150. end;
  1151. {-- TMMOscope ------------------------------------------------------------}
  1152. Procedure TMMOscope.DrawAsConLines;
  1153. Var
  1154.    i: integer;
  1155.    Y1: integer;
  1156.    aColor: Long;
  1157.    rForeClr: Long;
  1158.    rInactClr: Long;
  1159.    rEffectClr: Long;
  1160.    Value: Longint;
  1161. begin
  1162.    with DIBCanvas do
  1163.    begin
  1164.       rForeClr := DIB_ColorToIndex(FForeColor);
  1165.       rInactClr := DIB_ColorToIndex(FInactColor);
  1166.       rEffectClr := DIB_ColorToIndex(FEffectColor);
  1167.       if FScroll then
  1168.       begin
  1169.          DIB_SetTColor(Color);
  1170.          DIB_VLine(Fx1,0,FHeight);
  1171.          DIB_SetColor(rForeClr);
  1172.          DIB_MoveTo(OldDrawPos.X,OldDrawPos.Y);
  1173.          if (FEffect = efNone) then
  1174.          begin
  1175.             for i := 0 to 1 do
  1176.             begin
  1177.                Value := FData^[i];
  1178.                if Value >= 32767 then PcmOverflow;
  1179.                Y1 := Long(Value * FGain div 8 + FCenter)* FHeight div FRange;
  1180.                if (Y1 > FHeight) then GainOverflow;
  1181.                DIB_LineTo(Fx1, FHeight-Y1-1);
  1182.             end;
  1183.          end
  1184.          else
  1185.          begin
  1186.             for i := 0 to 1 do
  1187.             begin
  1188.                Value := FData^[i];
  1189.                if Value >= 32767 then PcmOverflow;
  1190.                Y1 := Long(Value * FGain div 8 + FCenter)* FHeight div FRange;
  1191.                if (Y1 > FHeight) then GainOverflow;
  1192.                if (Y1 < FEffectTop) or (Y1 > FEffectBottom) then
  1193.                begin
  1194.                   DIB_SetColor(rEffectClr);
  1195.                   DIB_LineTo(Fx1, FHeight-Y1-1);
  1196.                end
  1197.                else
  1198.                begin
  1199.                   DIB_SetColor(rForeClr);
  1200.                   DIB_LineTo(Fx1, FHeight-Y1-1);
  1201.                end;
  1202.             end;
  1203.          end;
  1204.          OldDrawPos := Point(Fx1, FHeight-Y1-1);
  1205.       end
  1206.       else
  1207.       begin
  1208.          DIB_SetColor(rInactClr);
  1209.          if (FEffect = efNone) then
  1210.          begin
  1211.             i := FSteps;
  1212.             Y1 := Long(FData^[0] * Long(FGain) div 8 + FCenter)* FHeight div FRange;
  1213.             DIB_MoveTo(0,FHeight-Y1-1);
  1214.             while i < FWidth do
  1215.             begin           { display lines by plotting samples in FData.}
  1216.                Value := FData^[i];
  1217.                if Value >= 32767 then PcmOverflow;
  1218.                Y1 := Long(Value * FGain div 8 + FCenter)* FHeight div FRange;
  1219.                if (Y1 > FHeight) then GainOverflow;
  1220.                if i > FMarkEnd then DIB_SetColor(rInactClr)
  1221.                else if i > FMarkBegin then DIB_SetColor(rForeClr);
  1222.                DIB_LineTo(i, FHeight-Y1-1);
  1223.                inc(i, FSteps);
  1224.             end;
  1225.             DIB_LineTo(i, FHeight-Y1-1);
  1226.          end
  1227.          else
  1228.          begin
  1229.             aColor := rInactClr;
  1230.             i := FSteps;
  1231.             Y1 := Long(FData^[0] * Long(FGain) div 8 + FCenter)* FHeight div FRange;
  1232.             DIB_MoveTo(0, FHeight-Y1-1);
  1233.             while i < FWidth do
  1234.             begin           { display lines by plotting samples in FData.}
  1235.                Value := FData^[i];
  1236.                if Value >= 32767 then PcmOverflow;
  1237.                Y1 := Long(Value * FGain div 8 + FCenter)* FHeight div FRange;
  1238.                if (Y1 > FHeight) then GainOverflow;
  1239.                if i > FMarkEnd then aColor := rInactClr
  1240.                else if i > FMarkBegin then aColor := rForeClr;
  1241.                if (aColor = rForeClr) and ((Y1 < FEffectTop) or (Y1 > FEffectBottom)) then
  1242.                begin
  1243.                   DIB_SetColor(rEffectClr);
  1244.                   DIB_LineTo(i, FHeight-Y1-1);
  1245.                end
  1246.                else
  1247.                begin
  1248.                   DIB_SetColor(aColor);
  1249.                   DIB_LineTo(i, FHeight-Y1-1);
  1250.                end;
  1251.                inc(i, FSteps);
  1252.             end;
  1253.             DIB_LineTo(i, FHeight-Y1-1);
  1254.          end;
  1255.       end;
  1256.    end;
  1257. end;
  1258. {-- TMMOscope ------------------------------------------------------------}
  1259. Procedure TMMOscope.DrawAsVertLines;
  1260. Var
  1261.    i: integer;
  1262.    Y1: integer;
  1263.    aColor: Long;
  1264.    rForeClr: Long;
  1265.    rInactClr: Long;
  1266.    rEffectClr: Long;
  1267.    Value: Longint;
  1268. begin
  1269.    with DIBCanvas do
  1270.    begin
  1271.       rForeClr := DIB_ColorToIndex(FForeColor);
  1272.       rInactClr := DIB_ColorToIndex(FInactColor);
  1273.       rEffectClr := DIB_ColorToIndex(FEffectColor);
  1274.       i := 0;
  1275.       if FScroll then
  1276.       begin
  1277.          DIB_SetTColor(Color);
  1278.          DIB_VLine(Fx1,0,FHeight);
  1279.          DIB_SetColor(rForeClr);
  1280.          if (FEffect = efNone) then
  1281.          begin
  1282.             Value := FData^[i];
  1283.             if abs(FData^[i+1]) > abs(Value) then Value := FData^[i+1];
  1284.             if Value >= 32767 then PcmOverflow;
  1285.             Y1 := FHeight-(Long(Value * FGain div 8 + FCenter)* FHeight div FRange)-1;
  1286.             if (Y1 < -1) then GainOverflow;
  1287.             DIB_VLine(Fx1, FMiddle, Y1);
  1288.          end
  1289.          else if (FEffect = efPeak) then
  1290.          begin
  1291.             Value := FData^[i];
  1292.             if abs(FData^[i+1]) > abs(Value) then Value := FData^[i+1];
  1293.             if Value >= 32767 then PcmOverflow;
  1294.             Y1 := FHeight-(Long(Value * FGain div 8 + FCenter)* FHeight div FRange)-1;
  1295.             if (Y1 < -1) then GainOverflow;
  1296.             DIB_VLine(Fx1, FMiddle, Y1);
  1297.             if (Y1 < FEffectTop) then
  1298.             begin
  1299.                DIB_SetColor(rEffectClr);
  1300.                DIB_VLine(Fx1, Y1, Y1+5);
  1301.             end
  1302.             else if (Y1 > FEffectBottom) then
  1303.             begin
  1304.                DIB_SetColor(rEffectClr);
  1305.                DIB_VLine(Fx1, Y1, Y1-5);
  1306.             end;
  1307.          end
  1308.          else if (FEffect = efSplit) then
  1309.          begin
  1310.             for i := 0 to 1 do
  1311.             begin               { display lines by plotting samples in FData.}
  1312.                Value := FData^[i];
  1313.                if Value >= 32767 then PcmOverflow;
  1314.                Y1 := FHeight-(Long(Value * FGain div 8 + FCenter)* FHeight div FRange)-1;
  1315.                if (Y1 < -1) then GainOverflow;
  1316.                if (Y1 < FEffectBottom) then
  1317.                   DIB_SetColor(rEffectClr)
  1318.                else
  1319.                   DIB_SetColor(rForeClr);
  1320.                DIB_VLine(Fx1, FMiddle, Y1);
  1321.             end;
  1322.          end;
  1323.       end
  1324.       else
  1325.       begin
  1326.          DIB_SetColor(rInactClr);
  1327.          if (FEffect = efNone) then
  1328.          begin
  1329.             DIB_HLine(0, FMarkBegin, FMiddle);
  1330.             DIB_HLine(0, FMarkBegin, FMiddle-1);
  1331.             DIB_SetColor(rForeClr);
  1332.             DIB_HLine(FMarkBegin, FMarkEnd+1, FMiddle);
  1333.             DIB_HLine(FMarkBegin, FMarkEnd+1, FMiddle-1);
  1334.             DIB_SetColor(rInactClr);
  1335.             DIB_HLine(FMarkEnd+1, FWidth, FMiddle);
  1336.             DIB_HLine(FMarkEnd+1, FWidth, FMiddle-1);
  1337.             while i < FWidth do
  1338.             begin               { display lines by plntting samples in FData.}
  1339.                Value := FData^[i];
  1340.                if Value >= 32767 then PcmOverflow;
  1341.                Y1 := FHeight-(Long(Value * FGain div 8 + FCenter)* FHeight div FRange)-1;
  1342.                if (Y1 < -1) then GainOverflow;
  1343.                if i > FMarkEnd then DIB_SetColor(rInactClr)
  1344.                else if i >= FMarkBegin then DIB_SetColor(rForeClr);
  1345.                DIB_VLine(i, FMiddle, Y1);
  1346.                inc(i,FSteps);
  1347.             end;
  1348.          end
  1349.          else if (FEffect = efPeak) then
  1350.          begin
  1351.             DIB_HLine(0, FMarkBegin, FMiddle);
  1352.             DIB_HLine(0, FMarkBegin, FMiddle-1);
  1353.             DIB_SetColor(rForeClr);
  1354.             DIB_HLine(FMarkBegin, FMarkEnd+1, FMiddle);
  1355.             DIB_HLine(FMarkBegin, FMarkEnd+1, FMiddle-1);
  1356.             DIB_SetColor(rInactClr);
  1357.             DIB_HLine(FMarkEnd+1, FWidth, FMiddle);
  1358.             DIB_HLine(FMarkEnd+1, FWidth, FMiddle-1);
  1359.             aColor := rInactClr;
  1360.             while i < FWidth do
  1361.             begin               { display lines by plotting samples in FData.}
  1362.                Value := FData^[i];
  1363.                if Value >= 32767 then PcmOverflow;
  1364.                Y1 := FHeight-(Long(Value * FGain div 8 + FCenter)* FHeight div FRange)-1;
  1365.                if (Y1 < -1) then GainOverflow;
  1366.                if i > FMarkEnd then aColor := rInactClr
  1367.                else if i >= FMarkBegin then aColor := rForeClr;
  1368.                DIB_SetColor(aColor);
  1369.                DIB_VLine(i, FMiddle, Y1);
  1370.                if (aColor = rForeClr) then
  1371.                begin
  1372.                   if (Y1 < FEffectTop) then
  1373.                   begin
  1374.                      DIB_SetColor(rEffectClr);
  1375.                      DIB_VLine(i, Y1, Y1+5);
  1376.                   end
  1377.                   else if (Y1 > FEffectBottom) then
  1378.                   begin
  1379.                      DIB_SetColor(rEffectClr);
  1380.                      DIB_VLine(i, Y1, Y1-5);
  1381.                   end;
  1382.                end;
  1383.                inc(i,FSteps);
  1384.             end;
  1385.          end
  1386.          else if (FEffect = efSplit) then
  1387.          begin
  1388.             DIB_HLine(0, FMarkBegin, FMiddle);
  1389.             DIB_HLine(0, FMarkBegin, FMiddle-1);
  1390.             DIB_SetColor(rForeClr);
  1391.             DIB_HLine(FMarkBegin, FMarkEnd+1, FMiddle);
  1392.             DIB_SetColor(rEffectClr);
  1393.             DIB_HLine(FMarkBegin, FMarkEnd+1, FMiddle-1);
  1394.             DIB_SetColor(rInactClr);
  1395.             DIB_HLine(FMarkEnd+1, FWidth, FMiddle);
  1396.             DIB_HLine(FMarkEnd+1, FWidth, FMiddle-1);
  1397.             aColor := rInactClr;
  1398.             while i < FWidth do
  1399.             begin               { display lines by plotting samples in FData.}
  1400.                Value := FData^[i];
  1401.                if Value >= 32767 then PcmOverflow;
  1402.                Y1 := FHeight-(Long(Value * FGain div 8 + FCenter)* FHeight div FRange)-1;
  1403.                if (Y1 < -1) then GainOverflow;
  1404.                if i > FMarkEnd then aColor := rInactClr
  1405.                else if i >= FMarkBegin then aColor := rForeClr;
  1406.                if (aColor = rForeClr) and (Y1 < FEffectBottom) then
  1407.                   DIB_SetColor(rEffectClr)
  1408.                else
  1409.                   DIB_SetColor(aColor);
  1410.                DIB_VLine(i, FMiddle, Y1);
  1411.                inc(i,FSteps);
  1412.             end;
  1413.          end;
  1414.       end;
  1415.    end;
  1416. end;
  1417. {-- TMMOscope ------------------------------------------------------------}
  1418. Procedure TMMOscope.DrawAsMirLines;
  1419. Var
  1420.    i: integer;
  1421.    Y1,Y2: integer;
  1422.    aColor: Long;
  1423.    rForeClr: Long;
  1424.    rInactClr: Long;
  1425.    rEffectClr: Long;
  1426.    Value: Longint;
  1427. begin
  1428.    with DIBCanvas do
  1429.    begin
  1430.       rForeClr := DIB_ColorToIndex(FForeColor);
  1431.       rInactClr := DIB_ColorToIndex(FInactColor);
  1432.       rEffectClr := DIB_ColorToIndex(FEffectColor);
  1433.       i := 0;
  1434.       if FScroll then
  1435.       begin
  1436.          DIB_SetTColor(Color);
  1437.          DIB_VLine(Fx1,0,FHeight);
  1438.          DIB_SetColor(rForeClr);
  1439.          if (FEffect = efNone) then
  1440.          begin
  1441.             Value := FData^[i];
  1442.             if abs(FData^[i+1]) > abs(Value) then Value := FData^[i+1];
  1443.             if Value >= 32767 then PcmOverflow;
  1444.             Y1 := Long(Value * FGain div 8 + FCenter)* FHeight div FRange;
  1445.             if (Y1 > FHeight) then GainOverflow;
  1446.             DIB_VLine(Fx1, FHeight-Y1-1, Y1);
  1447.          end
  1448.          else if (FEffect = efPeak) then
  1449.          begin
  1450.             Value := FData^[i];
  1451.             if abs(FData^[i+1]) > abs(Value) then Value := FData^[i+1];
  1452.             if Value >= 32767 then PcmOverflow;
  1453.             Y1 := Long(Value * FGain div 8 + FCenter)* FHeight div FRange;
  1454.             if (Y1 > FHeight) then GainOverflow;
  1455.             Y2 := FHeight-Y1-1;
  1456.             DIB_VLine(Fx1, Y2, Y1);
  1457.             if (Y1 < FEffectTop) then
  1458.             begin
  1459.                DIB_SetColor(rEffectClr);
  1460.                DIB_VLine(Fx1,Y1,Y1+5);
  1461.                DIB_VLine(Fx1,Y2,Y2-5);
  1462.             end
  1463.             else if (Y1 > FEffectBottom) then
  1464.             begin
  1465.                DIB_SetColor(rEffectClr);
  1466.                DIB_VLine(Fx1,Y1,Y1-5);
  1467.                DIB_VLine(Fx1,Y2,Y2+5);
  1468.             end;
  1469.          end
  1470.          else if (FEffect = efSplit) then
  1471.          begin
  1472.             Value := FData^[i];
  1473.             if abs(FData^[i+1]) > abs(Value) then Value := FData^[i+1];
  1474.             if Value >= 32767 then PcmOverflow;
  1475.             Y1 := Long(Value * FGain div 8 + FCenter)* FHeight div FRange;
  1476.             if (Y1 > FHeight) then GainOverflow;
  1477.             if (Y1 < FEffectBottom) then
  1478.             begin
  1479.                DIB_SetColor(rEffectClr);
  1480.                DIB_VLine(Fx1, FMiddle, Y1);
  1481.                DIB_SetColor(rForeClr);
  1482.                DIB_VLine(Fx1, FMiddle, FHeight-Y1-1);
  1483.             end
  1484.             else
  1485.             begin
  1486.                DIB_SetColor(rForeClr);
  1487.                DIB_VLine(Fx1, FMiddle, Y1);
  1488.                DIB_SetColor(rEffectClr);
  1489.                DIB_VLine(Fx1, FMiddle, FHeight-Y1-1);
  1490.             end;
  1491.          end;
  1492.       end
  1493.       else
  1494.       begin
  1495.          DIB_SetColor(rInactClr);
  1496.          if (FEffect = efNone) then
  1497.          begin
  1498.             DIB_HLine(0, FMarkBegin, FMiddle);
  1499.             DIB_HLine(0, FMarkBegin, FMiddle-1);
  1500.             DIB_SetColor(rForeClr);
  1501.             DIB_HLine(FMarkBegin, FMarkEnd+1, FMiddle);
  1502.             DIB_HLine(FMarkBegin, FMarkEnd+1, FMiddle-1);
  1503.             DIB_SetColor(rInactClr);
  1504.             DIB_HLine(FMarkEnd+1, FWidth, FMiddle);
  1505.             DIB_HLine(FMarkEnd+1, FWidth, FMiddle-1);
  1506.             while i < FWidth do
  1507.             begin               { display lines by plotting samples in FData.}
  1508.                Value := FData^[i];
  1509.                if Value >= 32767 then PcmOverflow;
  1510.                Y1 := Long(Value * FGain div 8 + FCenter)* FHeight div FRange;
  1511.                if (Y1 > FHeight) then GainOverflow;
  1512.                if i > FMarkEnd then DIB_SetColor(rInactClr)
  1513.                else if i >= FMarkBegin then DIB_SetColor(rForeClr);
  1514.                DIB_VLine(i, FHeight-Y1-1, Y1);
  1515.                inc(i,FSteps);
  1516.             end;
  1517.          end
  1518.          else if (FEffect = efPeak) then
  1519.          begin
  1520.             DIB_HLine(0, FMarkBegin, FMiddle);
  1521.             DIB_HLine(0, FMarkBegin, FMiddle-1);
  1522.             DIB_SetColor(rForeClr);
  1523.             DIB_HLine(FMarkBegin, FMarkEnd+1, FMiddle);
  1524.             DIB_HLine(FMarkBegin, FMarkEnd+1, FMiddle-1);
  1525.             DIB_SetColor(rInactClr);
  1526.             DIB_HLine(FMarkEnd+1, FWidth, FMiddle);
  1527.             DIB_HLine(FMarkEnd+1, FWidth, FMiddle-1);
  1528.             aColor := rInactClr;
  1529.             while i < FWidth do
  1530.             begin               { display lines by plotting samples in FData.}
  1531.                Value := FData^[i];
  1532.                if Value >= 32767 then PcmOverflow;
  1533.                Y1 := Long(Value * FGain div 8 + FCenter)* FHeight div FRange;
  1534.                if (Y1 > FHeight) then GainOverflow;
  1535.                if i > FMarkEnd then aColor := rInactClr
  1536.                else if i >= FMarkBegin then aColor := rForeClr;
  1537.                Y2 := FHeight-Y1-1;
  1538.                DIB_SetColor(aColor);
  1539.                DIB_VLine(i, Y2, Y1);
  1540.                if (aColor = rForeClr) then
  1541.                begin
  1542.                   if (Y1 < FEffectTop) then
  1543.                   begin
  1544.                      DIB_SetColor(rEffectClr);
  1545.                      DIB_VLine(i,Y1,Y1+5);
  1546.                      DIB_VLine(i,Y2,Y2-5);
  1547.                   end
  1548.                   else if (Y1 > FEffectBottom) then
  1549.                   begin
  1550.                      DIB_SetColor(rEffectClr);
  1551.                      DIB_VLine(i,Y1,Y1-5);
  1552.                      DIB_VLine(i,Y2,Y2+5);
  1553.                   end;
  1554.                end;
  1555.                inc(i,FSteps);
  1556.             end;
  1557.          end
  1558.          else if (FEffect = efSplit) then
  1559.          begin
  1560.             DIB_HLine(0, FMarkBegin, FMiddle);
  1561.             DIB_HLine(0, FMarkBegin, FMiddle-1);
  1562.             DIB_SetColor(rForeClr);
  1563.             DIB_HLine(FMarkBegin, FMarkEnd+1, FMiddle);
  1564.             DIB_SetColor(rEffectClr);
  1565.             DIB_HLine(FMarkBegin, FMarkEnd+1, FMiddle-1);
  1566.             DIB_SetColor(rInactClr);
  1567.             DIB_HLine(FMarkEnd+1, FWidth, FMiddle);
  1568.             DIB_HLine(FMarkEnd+1, FWidth, FMiddle-1);
  1569.             aColor := rInactClr;
  1570.             while i < FWidth do
  1571.             begin               { display lines by plotting samples in FData.}
  1572.                Value := FData^[i];
  1573.                if Value >= 32767 then PcmOverflow;
  1574.                Y1 := Long(Value * FGain div 8 + FCenter)* FHeight div FRange;
  1575.                if (Y1 > FHeight) then GainOverflow;
  1576.                if i > FMarkEnd then aColor := rInactClr
  1577.                else if i >= FMarkBegin then aColor := rForeClr;
  1578.                if (aColor = rForeClr) then
  1579.                begin
  1580.                   if (Y1 < FEffectBottom) then
  1581.                   begin
  1582.                      DIB_SetColor(rEffectClr);
  1583.                      DIB_VLine(i, FMiddle, Y1);
  1584.                      DIB_SetColor(aColor);
  1585.                      DIB_VLine(i, FMiddle, FHeight-Y1-1);
  1586.                   end
  1587.                   else
  1588.                   begin
  1589.                      DIB_SetColor(aColor);
  1590.                      DIB_VLine(i, FMiddle, Y1);
  1591.                      DIB_SetColor(rEffectClr);
  1592.                      DIB_VLine(i, FMiddle, FHeight-Y1-1);
  1593.                   end;
  1594.                end
  1595.                else
  1596.                begin
  1597.                   DIB_SetColor(aColor);
  1598.                   DIB_VLine(i, FMiddle, Y1);
  1599.                   DIB_VLine(i, FMiddle, FHeight-Y1-1);
  1600.                end;
  1601.                inc(i,FSteps);
  1602.             end;
  1603.          end;
  1604.       end;
  1605.    end;
  1606. end;
  1607. {-- TMMOscope ------------------------------------------------------------}
  1608. Procedure TMMOscope.DrawAsSpikes;
  1609. Var
  1610.    i,Y1: integer;
  1611.    aColor: Long;
  1612.    rForeClr: Long;
  1613.    rInactClr: Long;
  1614.    rEffectClr: Long;
  1615.    Value: Longint;
  1616. begin
  1617.    with DIBCanvas do
  1618.    begin
  1619.       rForeClr := DIB_ColorToIndex(FForeColor);
  1620.       rInactClr := DIB_ColorToIndex(FInactColor);
  1621.       rEffectClr := DIB_ColorToIndex(FEffectColor);
  1622.       i := 0;
  1623.       if FScroll then
  1624.       begin
  1625.          DIB_SetTColor(Color);
  1626.          DIB_VLine(Fx1,0,FHeight);
  1627.          DIB_SetColor(rForeClr);
  1628.          if (FEffect = efNone) then
  1629.          begin
  1630.             Value := abs(FData^[i]);
  1631.             if abs(FData^[i+1]) > Value then Value := abs(FData^[i+1]);
  1632.             if Value >= 32767 then PcmOverflow;
  1633.             Y1 := FHeight-(Long(Word(Value)* Long(FGain) div 8 + FCenter)* FHeight div FRange)-1;
  1634.             if (Y1 < -1) then GainOverflow;
  1635.             DIB_VLine(Fx1, FHeight, Y1);
  1636.          end
  1637.          else if(FEffect = efPeak) then
  1638.          begin
  1639.             Value := abs(FData^[i]);
  1640.             if abs(FData^[i+1]) > Value then Value := abs(FData^[i+1]);
  1641.             if Value >= 32767 then PcmOverflow;
  1642.             Y1 := FHeight-(Long(Word(Value)* Long(FGain) div 8 + FCenter)* FHeight div FRange)-1;
  1643.             if (Y1 < -1) then GainOverflow;
  1644.             DIB_VLine(Fx1, FHeight, Y1);
  1645.             if (Y1 < FEffectTop shl 1) then
  1646.             begin
  1647.                DIB_SetColor(rEffectClr);
  1648.                DIB_VLine(Fx1, Y1, Y1+5);
  1649.             end;
  1650.          end
  1651.          else
  1652.          begin
  1653.             for i := 0 to 1 do
  1654.             begin               { display lines by plotting samples in FData.}
  1655.                Value := FData^[i];
  1656.                if Value >= 32767 then PcmOverflow;
  1657.                Y1 := Long(Word(ABS(Value))* Long(FGain) div 8 + FCenter)* FHeight div FRange;
  1658.                if (Y1 > FHeight) then GainOverflow;
  1659.                if (Y1 > FEffectBottom) then
  1660.                begin
  1661.                   DIB_SetColor(rEffectClr);
  1662.                   DIB_VLine(Fx1, FMiddle, FHeight-Y1-1);
  1663.                   DIB_SetColor(rForeClr);
  1664.                   DIB_VLine(Fx1, FHeight, FMiddle);
  1665.                end
  1666.                else DIB_VLine(Fx1, FHeight, FHeight-Y1-1);
  1667.             end;
  1668.          end;
  1669.       end
  1670.       else
  1671.       begin
  1672.          DIB_SetColor(rInactClr);
  1673.          if (FEffect = efNone) then
  1674.          begin
  1675.             while i < FWidth do
  1676.             begin               { display lines by plotting samples in FData.}
  1677.                Value := FData^[i];
  1678.                if Value >= 32767 then PcmOverflow;
  1679.                Y1 := FHeight-(Long(Word(ABS(Value))* Long(FGain) div 8 + FCenter)* FHeight div FRange)-1;
  1680.                if (Y1 < -1) then GainOverflow;
  1681.                if i > FMarkEnd then DIB_SetColor(rInactClr)
  1682.                else if i >= FMarkBegin then DIB_SetColor(rForeClr);
  1683.                DIB_VLine(i, FHeight, Y1);
  1684.                inc(i,FSteps);
  1685.             end;
  1686.          end
  1687.          else if(FEffect = efPeak) then
  1688.          begin
  1689.             aColor := rInactClr;
  1690.             while i < FWidth do
  1691.             begin               { display lines by plotting samples in FData.}
  1692.                Value := FData^[i];
  1693.                if Value >= 32767 then PcmOverflow;
  1694.                Y1 := FHeight-(Long(Word(ABS(Value))* Long(FGain) div 8 + FCenter)* FHeight div FRange)-1;
  1695.                if (Y1 < -1) then GainOverflow;
  1696.                if i > FMarkEnd then aColor := rInactClr
  1697.                else if i >= FMarkBegin then aColor := rForeClr;
  1698.                DIB_SetColor(aColor);
  1699.                DIB_VLine(i, FHeight, Y1);
  1700.                if (aColor = rForeClr) and (Y1 < FEffectTop shl 1) then
  1701.                begin
  1702.                   DIB_SetColor(rEffectClr);
  1703.                   DIB_VLine(i, Y1, Y1+5);
  1704.                end;
  1705.                inc(i,FSteps);
  1706.             end;
  1707.          end
  1708.          else
  1709.          begin
  1710.             aColor := rInactClr;
  1711.             while i < FWidth do
  1712.             begin               { display lines by plotting samples in FData.}
  1713.                Value := FData^[i];
  1714.                if Value >= 32767 then PcmOverflow;
  1715.                Y1 := Long(Word(ABS(Value))* Long(FGain) div 8 + FCenter)* FHeight div FRange;
  1716.                if (Y1 > FHeight) then GainOverflow;
  1717.                if i > FMarkEnd then aColor := rInactClr
  1718.                else if i >= FMarkBegin then aColor := rForeClr;
  1719.                if (aColor = rForeClr) and (Y1 > FEffectBottom) then
  1720.                begin
  1721.                   DIB_SetColor(rEffectClr);
  1722.                   DIB_VLine(i, FMiddle, FHeight-Y1-1);
  1723.                   DIB_SetColor(rForeClr);
  1724.                   DIB_VLine(i, FHeight, FMiddle);
  1725.                end
  1726.                else
  1727.                begin
  1728.                   DIB_SetColor(aColor);
  1729.                   DIB_VLine(i, FHeight, FHeight-Y1-1);
  1730.                end;
  1731.                inc(i,FSteps);
  1732.             end;
  1733.          end;
  1734.       end;
  1735.    end;
  1736. end;
  1737. {-- TMMOscope ------------------------------------------------------------}
  1738. function TMMOscope.GetAmplitude(Pos: TPoint): Float;
  1739. begin
  1740.    Result := 0;
  1741.    if PtInRect(FClientRect,Pos) then
  1742.    begin
  1743.       dec(Pos.Y,FClientRect.Top);
  1744.       if (FKind = okSpikes) then
  1745.           Result := (FHeight-Pos.Y-1)*(10/(FHeight-1))*0.1
  1746.       else
  1747.       begin
  1748.           Result := (FHeight/2-Pos.Y);
  1749.           if Result < 0 then Result := Result -1;
  1750.           Result := Result*(10/FHeight)*0.2;
  1751.       end;
  1752.    end;
  1753. end;
  1754. {-- TMMOscope ------------------------------------------------------------}
  1755. function TMMOscope.GetTime(Pos: TPoint): Float;
  1756. var
  1757.    wf: TPCMWaveFormat;
  1758. begin
  1759.    Result := 0;
  1760.    if PtInRect(FClientRect,Pos) then
  1761.    begin
  1762.       dec(Pos.X,FClientRect.Left-1);
  1763.       wf := PCMWaveFormat;
  1764.       Result := Pos.X * wioBytesToTime(@wf,FBytes)/FWidth;
  1765.    end;
  1766. end;
  1767. {-- TMMOscope ------------------------------------------------------------}
  1768. procedure TMMOscope.CalcScaleSteps;
  1769. begin
  1770.    { calc the number of steps required }
  1771.    FNumScaleSteps := 10;
  1772.    while (FHeight div FNumScaleSteps < SCALEFONTSIZE) do
  1773.    begin
  1774.       dec(FNumScaleSteps, 2);
  1775.       if FNumScaleSteps <= 2 then break;
  1776.    end;
  1777. end;
  1778. {-- TMMOscope ------------------------------------------------------------}
  1779. function TMMOscope.GetScaleBackColor: TColor;
  1780. begin
  1781.    {$IFNDEF BUILD_ACTIVEX}
  1782.    Result := TForm(Parent).Color;
  1783.    {$ELSE}
  1784.    Result := FScaleBackColor;
  1785.    {$ENDIF}
  1786. end;
  1787. {-- TMMOscope ------------------------------------------------------------}
  1788. procedure TMMOscope.DrawAmplitudeScale;
  1789. var
  1790.    aBitmap: TBitmap;
  1791.    i, X, Y,H: integer;
  1792.    Text,Text1: String;
  1793.    Scale: Float;
  1794.    YScale: integer;
  1795. begin
  1796.    { Put up the amplitude scale }
  1797.    if FDrawAmpScale then
  1798.    begin
  1799.       YScale := 1;
  1800.       aBitmap := TBitmap.Create;
  1801.       try
  1802.          if FDrawTimeScale then
  1803.             H := Height-SCALEHEIGHT
  1804.          else
  1805.             H := Height;
  1806.          aBitmap.Width := SCALEWIDTH;
  1807.          aBitmap.Height := H;
  1808.          aBitmap.Canvas.Font.Color := FScaleTextColor;
  1809.          aBitmap.Canvas.Pen.Color := FScaleLineColor;
  1810.          aBitmap.Canvas.Brush.Color := GetScaleBackColor;
  1811.          with aBitmap.Canvas do
  1812.          begin
  1813.             { calc the number of steps required }
  1814.             Scale := (YScale*32768.0)/FHeight;
  1815.             { draw the left side }
  1816.             FillRect(Rect(0,0,aBitmap.Width,aBitmap.Height));
  1817.             X := SCALEWIDTH-1;
  1818.             MoveTo(X, H-BevelExtend-1);
  1819.             for i := 0 to FNumScaleSteps do
  1820.             begin
  1821.                Y := H-BevelExtend-Trunc(i*YScale*32768.0/FNumScaleSteps/Scale)-1;
  1822.                LineTo(X, Y);
  1823.                LineTo(X-3, Y);
  1824.                MoveTo(X, Y);
  1825.                if (FKind = okSpikes) then
  1826.                begin
  1827.                   Text := Format('%4.2f',[i*(10/FNumScaleSteps)*0.1]);
  1828.                   Y := H-BevelExtend-Trunc(i*YScale*32768.0/FNumScaleSteps/Scale)-1;
  1829.           TextOutAligned(aBitmap.Canvas, X-5, Y, Text,SCALEFONT,SCALEFONTSIZE,1);{ right text }
  1830.                end;
  1831.             end;
  1832.             if (FKind <> okSpikes) then
  1833.             begin
  1834.                for i := 0 to FNumScaleSteps div 2 do
  1835.                begin
  1836.                   Text := Format('%4.2f',[i*(10/FNumScaleSteps*2)*0.1]);
  1837.                   Text1 := Text;
  1838.                   if (i > 0) then
  1839.                   begin
  1840.                      Text := '+'+Text;
  1841.                      Text1 := '-'+Text1;
  1842.                   end;
  1843.                   Y := H-BevelExtend-FMiddle-Trunc(i*YScale*32768.0/FNumScaleSteps/Scale)-1;
  1844.           TextOutAligned(aBitmap.Canvas, X-5, Y, Text,SCALEFONT,SCALEFONTSIZE,1);{ right text }
  1845.                   Y := BevelExtend+FMiddle+Trunc(i*YScale*32768.0/FNumScaleSteps/Scale)+1;
  1846.           TextOutAligned(aBitmap.Canvas, X-5, Y, Text1,SCALEFONT,SCALEFONTSIZE,1);{ right text }
  1847.                end;
  1848.             end;
  1849.             Canvas.Draw(-3, 0, aBitmap);
  1850.             { draw the right side }
  1851.             FillRect(Rect(0,0,aBitmap.Width,aBitmap.Height));
  1852.             X := 0;
  1853.             MoveTo(X, H-BevelExtend-1);
  1854.             for i := 0 to FNumScaleSteps do
  1855.             begin
  1856.                Y := H-BevelExtend-Trunc(i*YScale*32768.0/FNumScaleSteps/Scale)-1;
  1857.                LineTo(X, Y);
  1858.                LineTo(X+3, Y);
  1859.                MoveTo(X, Y);
  1860.                if (FKind = okSpikes) then
  1861.                begin
  1862.                   Text := Format('%4.2f',[i*(10/FNumScaleSteps)*0.1]);
  1863.                   Y := H-BevelExtend-Trunc(i*YScale*32768.0/FNumScaleSteps/Scale)-1;
  1864.           TextOutAligned(aBitmap.Canvas, X+29, Y, Text, SCALEFONT,SCALEFONTSIZE,1);{ right text }
  1865.                end;
  1866.             end;
  1867.             if (FKind <> okSpikes) then
  1868.             begin
  1869.                for i := 0 to FNumScaleSteps div 2 do
  1870.                begin
  1871.                   Text := Format('%4.2f',[i*(10/FNumScaleSteps*2)*0.1]);
  1872.                   Text1 := Text;
  1873.                   if (i > 0) then
  1874.                   begin
  1875.                      Text := '+'+Text;
  1876.                      Text1 := '-'+Text1;
  1877.                   end;
  1878.                   Y := H-BevelExtend-FMiddle-Trunc(i*YScale*32768.0/FNumScaleSteps/Scale)-1;
  1879.           TextOutAligned(aBitmap.Canvas, X+29, Y, Text, SCALEFONT,SCALEFONTSIZE,1);{ right text }
  1880.           Y := BevelExtend+FMiddle+Trunc(i*YScale*32768.0/FNumScaleSteps/Scale)+1;
  1881.           TextOutAligned(aBitmap.Canvas, X+29, Y, Text1, SCALEFONT,SCALEFONTSIZE,1);{ right text }
  1882.                end;
  1883.             end;
  1884.             Canvas.Draw((Width - SCALEWIDTH)+3, 0, aBitmap);
  1885.          end;
  1886.       finally
  1887.          aBitmap.Free;
  1888.       end;
  1889.    end;
  1890. end;
  1891. {-- TMMOscope ------------------------------------------------------------}
  1892. procedure TMMOscope.DrawTimeScales;
  1893. var
  1894.    aBitmap: TBitmap;
  1895.    i, X: integer;
  1896.    Text: String;
  1897.    Time: Longint;
  1898.    Step: Float;
  1899.    NumSteps: integer;
  1900.    wf: TPCMWaveFormat;
  1901. begin
  1902.    if FDrawTimeScale then
  1903.    begin
  1904.       aBitmap := TBitmap.Create;
  1905.       try
  1906.          aBitmap.Width := FWidth + 2*BevelExtend;
  1907.          aBitmap.Height := SCALEHEIGHT;
  1908.          aBitmap.Canvas.Font.Color := FScaleTextColor;
  1909.          aBitmap.Canvas.Pen.Color := FScaleLineColor;
  1910.          aBitmap.Canvas.Brush.Color := GetScaleBackColor;
  1911.          with aBitmap.Canvas do
  1912.          begin
  1913.             FillRect(Rect(0,0,aBitmap.Width,aBitmap.Height));
  1914.             { calc the number of steps required }
  1915.             NumSteps := 32;
  1916.             while (FWidth div NumSteps < SCALEFONTSIZE) do
  1917.             begin
  1918.                NumSteps := NumSteps div 2;
  1919.                if NumSteps = 1 then break;
  1920.             end;
  1921.             { Put up the time scale. }
  1922.             wf := PCMWaveFormat;
  1923.             Time := wioBytesToTime(@wf,FBytes);
  1924.             Step := Time/NumSteps;
  1925.             MoveTo(BevelExtend,0);
  1926.             for i := 0 to NumSteps do
  1927.             begin
  1928.                X := i * (FWidth-1) div NumSteps + BevelExtend;
  1929.                LineTo(X, 0);
  1930.                LineTo(X, 3);
  1931.                MoveTo(X, 0);
  1932.                Text := Format('%4.1f',[i*Step]);
  1933.                TextOutAligned(aBitmap.Canvas,X,6,Text,SCALEFONT,SCALEFONTSIZE,2);{ vertical text }
  1934.             end;
  1935.          end;
  1936.          Canvas.Draw(FClientRect.Left-BevelExtend,
  1937.                      FClientRect.Bottom+BevelExtend+3, aBitmap);
  1938.       finally
  1939.          aBitmap.Free;
  1940.       end;
  1941.    end;
  1942. end;
  1943. {-- TMMOscope ------------------------------------------------------------}
  1944. procedure TMMOscope.DrawGrids;
  1945. var
  1946.    i,X,Y,NumSteps: integer;
  1947.    YScale: integer;
  1948.    Scale: Float;
  1949. begin
  1950.    if FDrawGrid then
  1951.    with DIBCanvas do
  1952.    begin
  1953.       DIB_SetTColor(FGridColor);
  1954.       { the horizontal lines }
  1955.       YScale := 1;
  1956.       { calc the scale steps required }
  1957.       Scale := (YScale*32768.0)/FHeight;
  1958.       for i := 0 to FNumScaleSteps do
  1959.       begin
  1960.          Y := FHeight-Trunc(i*YScale*32760.0/FNumScaleSteps/Scale)-1;
  1961.          DIB_HLineDoted(0, FWidth, Y, 1);
  1962.       end;
  1963.       { the vertical lines }
  1964.       { calc the number of steps required }
  1965.       NumSteps := 32;
  1966.       while (FWidth div NumSteps < SCALEFONTSIZE) do
  1967.       begin
  1968.          NumSteps := NumSteps div 2;
  1969.          if NumSteps = 1 then break;
  1970.       end;
  1971.       for i := 0 to NumSteps do
  1972.       begin
  1973.          X := i * (FWidth-1) div NumSteps;
  1974.          DIB_VLineDoted(X, 0, FHeight, 1);
  1975.       end;
  1976.    end;
  1977. end;
  1978. {-- TMMOscope ------------------------------------------------------------}
  1979. procedure TMMOscope.DrawBar;
  1980. var
  1981.    i,Y: integer;
  1982.    aRect: TRect;
  1983. begin
  1984.    if FAccelerate then
  1985.    with Canvas do
  1986.    begin
  1987.       Pen.Mode := pmCopy;
  1988.       Pen.Color := FBarColor;
  1989.       Pen.Width := 1;
  1990.       aRect := Rect(FClientRect.Left+Fx2,FClientRect.Top,
  1991.                     FClientRect.Left+Fx2,FClientRect.Bottom);
  1992.       MoveTo(aRect.Left, aRect.Top);
  1993.       LineTo(aRect.Left, aRect.Bottom);
  1994.       for i := 0 to FNumScaleSteps do
  1995.       begin
  1996.          Y := (BevelExtend+FHeight)-Trunc(i * (FHeight-1)/FNumScaleSteps)-1;
  1997.          SetPixel(Handle,aRect.Left, Y, FBarTickColor);
  1998.       end;
  1999.    end
  2000.    else
  2001.    with DIBCanvas do
  2002.    begin
  2003.       Pen.Mode := pmCopy;
  2004.       Brush.Color := FBarColor;
  2005.       if Fx2 > Fx1 then
  2006.       begin
  2007.          aRect := Rect(Fx1+1,0,Fx2+1,FHeight);
  2008.          FillRect(aRect);
  2009.       end
  2010.       else
  2011.       begin
  2012.          aRect := Rect(0,0,Fx2+1,FHeight);
  2013.          FillRect(aRect);
  2014.       end;
  2015.       Pen.Color := FBarTickColor;
  2016.       for i := 0 to FNumScaleSteps do
  2017.       begin
  2018.          Y := FHeight - Trunc(i * (FHeight-1)/FNumScaleSteps)-1;
  2019.          MoveTo(aRect.Left,Y);
  2020.          LineTo(aRect.Right,Y);
  2021.       end;
  2022.    end;
  2023. end;
  2024. {$IFDEF WIN32}
  2025. {-- TMMOscope ------------------------------------------------------------}
  2026. procedure TMMOscope.DrawInfo(Pos: TPoint);
  2027. var
  2028.    Text: String;
  2029.    aRect: TRect;
  2030.    Buf: array[0..255] of char;
  2031.    DC: HDC;
  2032.    WindowHandle: HWND;
  2033. begin
  2034.    if FShowInfoHint then
  2035.    with DIBCanvas do
  2036.    begin
  2037.       if PtInRect(FClientRect,Pos) then
  2038.       begin
  2039.          Text := Format('%4.1f ms',[GetTime(Pos)])+
  2040.                  Format(' %4.2f V',[GetAmplitude(Pos)]);
  2041.          Font.Name := 'MS Sans Serif';
  2042.          Font.Size := 8;
  2043.          Font.Style := [];
  2044.          {$IFDEF WIN32}
  2045.          Font.Color := clInfoText;
  2046.          {$ELSE}
  2047.          Font.Color := clBlack;
  2048.          {$ENDIF}
  2049.          aRect.Left := Pos.X-BevelExtend;
  2050.          if FDrawAmpScale then dec(aRect.Left, SCALEWIDTH);
  2051.          aRect.Top := Pos.Y-BevelExtend+15;
  2052.          aRect.Right := aRect.Left + TextWidth(Text)+4;
  2053.          aRect.Bottom := aRect.Top + TextHeight(Text)+2;
  2054.          if (aRect.Bottom > FHeight) then OffsetRect(aRect,0,-40);
  2055.          if (aRect.Right > FWidth) then OffsetRect(aRect,FWidth-aRect.Right,0);
  2056.          if (aRect.Top < 0) then
  2057.          begin
  2058.             aRect.Top := 0;
  2059.             aRect.Bottom := TextHeight(Text)+2;
  2060.          end;
  2061.          if (SaveDC = 0) then
  2062.          begin
  2063.             { create memory DC for save bitmap }
  2064.             SaveDC := CreateCompatibleDC(DIBCanvas.Handle);
  2065.             { create bitmap to store background }
  2066.             SaveWidth := 10*TextWidth('W')+4;
  2067.             SaveHeight := TextHeight('W')+2;
  2068.             SaveBitmap := CreateCompatibleBitmap(DIBCanvas.Handle,SaveWidth,SaveHeight);
  2069.             OldBitmap := SelectObject(SaveDC, SaveBitmap);
  2070.          end
  2071.          else
  2072.             { restore background }
  2073.             BitBlt(DIBCanvas.Handle,SaveInfoPos.X,
  2074.                    SaveInfoPos.Y,SaveWidth,SaveHeight,
  2075.                    SaveDC,0,0,SRCCOPY);
  2076.          { save background }
  2077.          BitBlt(SaveDC,0,0,SaveWidth,SaveHeight,
  2078.                 DIBCanvas.Handle,aRect.Left,aRect.Top,SRCCOPY);
  2079.          SaveInfoPos := aRect.TopLeft;
  2080.          Brush.Color := INFOCOLOR;
  2081.          Brush.Style := bsSolid;
  2082.          Pen.Color := clBlack;
  2083.          Rectangle(aRect.Left,aRect.Top,aRect.Right,aRect.Bottom);
  2084.          Brush.Style := bsClear;
  2085.          DrawText(Handle, StrPCopy(Buf, Text), -1, aRect,
  2086.                   DT_SINGLELINE  or DT_VCENTER or DT_CENTER or DT_NOPREFIX);
  2087.          Brush.Style := bsSolid;
  2088.       end
  2089.       else if (SaveBitmap <> 0) then
  2090.       begin
  2091.          { restore background }
  2092.          BitBlt(DIBCanvas.Handle,SaveInfoPos.X,
  2093.                 SaveInfoPos.Y,SaveWidth,SaveHeight,
  2094.                 SaveDC,0,0,SRCCOPY);
  2095.       end;
  2096.       DIB_InitDrawing;                                  { copy to screen }
  2097.       DC := GetDeviceContext(WindowHandle);
  2098.       DIBCanvas.DIB_BitBlt(DC, FClientRect,0,0);
  2099.       ReleaseDC(WindowHandle, DC);
  2100.       DIB_DoneDrawing;
  2101.    end;
  2102. end;
  2103. {$ELSE}
  2104. {-- TMMOscope ------------------------------------------------------------}
  2105. procedure TMMOscope.DrawInfo(Pos: TPoint);
  2106. var
  2107.    Text: String;
  2108.    aRect: TRect;
  2109.    Buf: array[0..255] of char;
  2110.    Border: integer;
  2111. begin
  2112.    if FShowInfoHint then
  2113.    with Canvas do
  2114.    begin
  2115.       if PtInRect(FClientRect,Pos) then
  2116.       begin
  2117.          Text := Format('%4.1f ms',[GetTime(Pos)])+
  2118.                  Format(' %4.2f V',[GetAmplitude(Pos)]);
  2119.          Font.Name := 'MS Sans Serif';
  2120.          Font.Size := 8;
  2121.          Font.Style := [];
  2122.          {$IFDEF WIN32}
  2123.          Font.Color := clInfoText;
  2124.          {$ELSE}
  2125.          Font.Color := clBlack;
  2126.          {$ENDIF}
  2127.          aRect.Left := Pos.X;
  2128.          aRect.Top := Pos.Y+15;
  2129.          aRect.Right := aRect.Left + TextWidth(Text)+4;
  2130.          aRect.Bottom := aRect.Top + TextHeight(Text)+2;
  2131.          Border := BevelExtend;
  2132.          if FDrawAmpScale then inc(Border,SCALEHEIGHT);
  2133.          if (aRect.Bottom > Height-Border) then OffsetRect(aRect,0,-40);
  2134.          Border := BevelExtend;
  2135.          if FDrawAmpScale then inc(Border,SCALEWIDTH);
  2136.          if (aRect.Right > Width-Border) then OffsetRect(aRect,Width-Border-aRect.Right,0);
  2137.          if (aRect.Top < 0) then
  2138.          begin
  2139.             aRect.Top := 0;
  2140.             aRect.Bottom := TextHeight(Text)+2;
  2141.          end;
  2142.          if (SaveDC = 0) then
  2143.          begin
  2144.             { create memory DC for save bitmap }
  2145.             SaveDC := CreateCompatibleDC(Canvas.Handle);
  2146.             { create bitmap to store background }
  2147.             SaveWidth := 10*TextWidth('W')+4;
  2148.             SaveHeight := TextHeight('W')+2;
  2149.             SaveBitmap := CreateCompatibleBitmap(Canvas.Handle,SaveWidth,SaveHeight);
  2150.             OldBitmap := SelectObject(SaveDC, SaveBitmap);
  2151.          end
  2152.          else
  2153.             { restore background }
  2154.             BitBlt(Canvas.Handle,SaveInfoPos.X,
  2155.                    SaveInfoPos.Y,SaveWidth,SaveHeight,
  2156.                    SaveDC,0,0,SRCCOPY);
  2157.          { save background }
  2158.          BitBlt(SaveDC,0,0,SaveWidth,SaveHeight,
  2159.                 Canvas.Handle,aRect.Left,aRect.Top,SRCCOPY);
  2160.          SaveInfoPos := aRect.TopLeft;
  2161.          Brush.Color := INFOCOLOR;
  2162.          Brush.Style := bsSolid;
  2163.          Pen.Color := clBlack;
  2164.          Rectangle(aRect.Left,aRect.Top,aRect.Right,aRect.Bottom);
  2165.          Brush.Style := bsClear;
  2166.          DrawText(Handle, StrPCopy(Buf, Text), -1, aRect,
  2167.                   DT_SINGLELINE  or DT_VCENTER or DT_CENTER or DT_NOPREFIX);
  2168.          Brush.Style := bsSolid;
  2169.       end
  2170.       else if (SaveBitmap <> 0) then
  2171.       begin
  2172.          { restore background }
  2173.          BitBlt(Canvas.Handle,SaveInfoPos.X,
  2174.                    SaveInfoPos.Y,SaveWidth,SaveHeight,
  2175.                    SaveDC,0,0,SRCCOPY);
  2176.       end;
  2177.    end;
  2178. end;
  2179. {$ENDIF}
  2180. {-- TMMOscope ------------------------------------------------------------}
  2181. procedure TMMOscope.DrawSelection(aCanvas: TMMDIBCanvas; sStart, sEnd: Longint;
  2182.                                   sColor: TColor; Solid: Boolean);
  2183. begin
  2184.    if (sStart >= 0) and (sEnd >= 0) then
  2185.    begin
  2186.       with aCanvas do
  2187.       begin
  2188.          DIB_SetTColor(sColor);
  2189.          if Solid then
  2190.          begin
  2191.             DIB_FillRect(Rect(sStart,0,sEnd+1,Height));
  2192.          end
  2193.          else
  2194.          begin
  2195.             DIB_HLineDashed(sStart,sEnd+1,0);
  2196.             DIB_HLineDashed(sStart,sEnd+1,Height-1);
  2197.             DIB_VLineDashed(sStart,0,Height-1);
  2198.             DIB_VLineDashed(sEnd,0,Height-1);
  2199.          end;
  2200.       end;
  2201.    end;
  2202. end;
  2203. {-- TMMOscope ------------------------------------------------------------}
  2204. procedure TMMOscope.DrawLocator(aCanvas: TMMDIBCanvas; aPos: Longint; aColor: TColor);
  2205. begin
  2206.    with aCanvas do
  2207.    begin
  2208.       DIB_SetTColor(aColor);
  2209.       DIB_MoveTo(aPos,0);
  2210.       DIB_LineTo(aPos,FHeight);
  2211.    end;
  2212. end;
  2213. {-- TMMOscope ------------------------------------------------------------}
  2214. procedure TMMOscope.DrawInactive;
  2215. begin
  2216.    with DIBCanvas do
  2217.    begin
  2218.       DIB_SetTColor(FOffColor);
  2219.       DIB_HLine(5, FWidth-5, FMiddle);         { only Draw a horiz. line }
  2220.    end;
  2221. end;
  2222. {-- TMMOscope ------------------------------------------------------------}
  2223. procedure TMMOscope.DrawOscope(ClearBackGround: Boolean);
  2224. var
  2225.    aRect: TRect;
  2226. begin
  2227.    DIBCanvas.DIB_InitDrawing;
  2228.    if assigned(FOnDrawLine) then
  2229.    begin
  2230.       FOnDrawLine(Self,DIBCanvas,Rect(0,0,FWidth,FHeight),FData);
  2231.       DIBCanvas.DIB_BitBlt(Canvas.Handle, FClientRect,0,0);
  2232.    end
  2233.    else
  2234.    begin
  2235.       if not FScroll or (ClearBackGround or FNeedReset) then
  2236.       begin
  2237.          DrawBackGround;                    { Clear background or draw DIB }
  2238.          Fx1 := -FBarWidth;
  2239.          Fx2 := 0;
  2240.          OldDrawPos := Point(0,FMiddle);
  2241.          if not FNeedReset and FScroll then ResetOscope(Self);
  2242.       end;
  2243.       if not FEnabled then DrawInactive
  2244.       else
  2245.       begin
  2246.          if not FScroll then
  2247.          begin
  2248.             { draw solid Selection }
  2249.             DrawSelection(DIBCanvas,FSelectStart,FSelectEnd,FSelectColor,True);
  2250.             if FDrawMidLine then
  2251.             begin
  2252.                DIBCanvas.DIB_SetTColor(FOffColor);
  2253.                DIBCanvas.DIB_HLineDashed(0,FWidth,FMiddle);
  2254.             end;
  2255.             DrawGrids;                                       { draw the grid }
  2256.          end;
  2257.          case FKind of                            { draw the scope to bitmap }
  2258.            okDots      : DrawAsDots;
  2259.            okConLines  : DrawAsConLines;
  2260.            okVertLines : DrawAsVertLines;
  2261.            okMirLines  : DrawAsMirLines;
  2262.            okSpikes    : DrawAsSpikes;
  2263.          end;
  2264.       end;
  2265.       if FScroll then
  2266.       begin
  2267.          if ClearBackGround or FNeedReset or not FAccelerate then
  2268.          begin
  2269.             if (Fx2 < FWidth) then DrawBar;
  2270.             DIBCanvas.DIB_BitBlt(Canvas.Handle, FClientRect,0,0);
  2271.             FNeedReset := False;
  2272.          end
  2273.          else
  2274.          begin
  2275.             aRect := FClientRect;
  2276.             aRect.Left := FClientRect.Left + Fx1;
  2277.             aRect.Right := 1;
  2278.             DIBCanvas.DIB_BitBlt(Canvas.Handle,aRect,Fx1,0);
  2279.          end;
  2280.          { move the bar }
  2281.          if (Fx2 < FWidth) then
  2282.          begin
  2283.             if Accelerate then DrawBar;
  2284.             inc(Fx1);
  2285.             inc(Fx2);
  2286.          end
  2287.          else
  2288.          begin
  2289.             if Accelerate then
  2290.             begin
  2291.                {$IFNDEF BUILD_ACTIVEX}
  2292.                aRect:= BoundsRect;
  2293.                {$ELSE}
  2294.                aRect:= ClientRect;
  2295.                {$ENDIf}
  2296.                InflateRect(aRect, -BevelExtend, -BevelExtend);
  2297.                if FDrawAmpScale then
  2298.                   InflateRect(aRect, -SCALEWIDTH, 0);
  2299.                if FDrawTimeScale then
  2300.                   dec(aRect.Bottom, SCALEHEIGHT);
  2301.                dec(aRect.Right,FBarWidth-1);
  2302.                {$IFNDEF BUILD_ACTIVEX}
  2303.                ScrollWindowEx(Parent.Handle,-1,0,@aRect,@aRect,0,nil,0);
  2304.                {$ELSE}
  2305.                ScrollWindowEx(Handle,-1,0,@aRect,@aRect,0,nil,0);
  2306.                {$ENDIF}
  2307.             end
  2308.             else DIBCanvas.DIB_CopyDIBBits(biSurface,0,0,FWidth-1,FHeight,1,0);
  2309.          end;
  2310.       end
  2311.       else                                                 { copy to screen }
  2312.       begin
  2313.          { draw doted Selection }
  2314.          DrawSelection(DIBCanvas,FSelectStart,FSelectEnd,FSelectDotColor,False);
  2315.          { draw the locator }
  2316.          DrawLocator(DIBCanvas,FLocator,FLocatorColor);
  2317.          DIBCanvas.DIB_BitBlt(Canvas.Handle, FClientRect,0,0);
  2318.       end;
  2319.    end;
  2320.    DIBCanvas.DIB_DoneDrawing;
  2321.    if assigned(FOnPostPaint) then FOnPostPaint(Self);
  2322. end;
  2323. {-- TMMOscope ------------------------------------------------------------}
  2324. Procedure TMMOscope.Paint;
  2325. var
  2326.    H: integer;
  2327.    aRect: TRect;
  2328. begin
  2329.    with Canvas do
  2330.    begin
  2331.       if FDrawAmpScale or FDrawTimeScale then
  2332.       begin
  2333.          { clear the space between the scales only, to eliminate flicker }
  2334.          Brush.Color := GetScaleBackColor;
  2335.          Brush.Style := bsSolid;
  2336.          if FDrawAmpScale then
  2337.          begin
  2338.             H := Height;
  2339.             if FDrawTimeScale then H := Height-SCALEHEIGHT;
  2340.             aRect := Rect(SCALEWIDTH-3,0,SCALEWIDTH,H);
  2341.             FillRect(aRect);
  2342.             aRect:= Rect(Width-SCALEWIDTH,0,Width-SCALEWIDTH+3,H);
  2343.             FillRect(aRect);
  2344.          end;
  2345.          if FDrawTimeScale then
  2346.          begin
  2347.             aRect:= Rect(0,Height-SCALEHEIGHT,Width,Height-SCALEHEIGHT+3);
  2348.             FillRect(aRect);
  2349.             if FDrawAmpScale then
  2350.             begin
  2351.                aRect:= Rect(0,Height-SCALEHEIGHT,SCALEWIDTH,Height);
  2352.                FillRect(aRect);
  2353.                aRect:= Rect(WIDTH-SCALEWIDTH,Height-SCALEHEIGHT,Width,Height);
  2354.                FillRect(aRect);
  2355.             end;
  2356.          end;
  2357.          if FDrawAmpScale and FDrawTimeScale then
  2358.          begin
  2359.             { write text }
  2360.             Canvas.Font.Color := FScaleTextColor;
  2361.             TextOutAligned(Canvas, SCALEWIDTH-16, Height-SCALEHEIGHT+6,
  2362.                            'V', SCALEFONT,SCALEFONTSIZE, 1);
  2363.             TextOutAligned(Canvas, Width-SCALEWIDTH+18, Height-SCALEHEIGHT+6,
  2364.                            'V', SCALEFONT,SCALEFONTSIZE,0);
  2365.             TextOutAligned(Canvas, Width-SCALEWIDTH+2, Height-SCALEHEIGHT+20,
  2366.                            'mS', SCALEFONT,SCALEFONTSIZE,0);
  2367.          end;
  2368.          { make place for the scale }
  2369.          aRect := GetClientRect;
  2370.          if FDrawAmpScale then
  2371.             InflateRect(aRect,-SCALEWIDTH,0);
  2372.          if FDrawTimeScale then
  2373.             dec(aRect.Bottom, SCALEHEIGHT);
  2374.       end
  2375.       else aRect := GetClientRect;
  2376.       { draw the Bevel and fill the real area }
  2377.       aRect := Bevel.PaintBevel(Canvas, aRect, True);
  2378.    end;
  2379.    { now draw the scales and the oscope }
  2380.    DrawAmplitudeScale;
  2381.    DrawTimeScales;
  2382.    if (csDesigning in ComponentState) {$IFDEF WIN32}or (csPaintCopy in ControlState){$ENDIF} then
  2383.       DrawOscope(True)
  2384.    else
  2385.       FastDraw(DrawOscope,True);
  2386.    {$IFDEF BUILD_ACTIVEX}
  2387.    if Selected then
  2388.    begin
  2389.       Canvas.Brush.Style := bsClear;
  2390.       Canvas.Pen.Color   := clRed;
  2391.       Canvas.Rectangle(0,0,Width,Height);
  2392.       Canvas.Brush.Style := bsSolid;
  2393.    end;
  2394.    {$ENDIF}
  2395. end;
  2396. {-- TMMOscope ------------------------------------------------------------}
  2397. procedure TMMOscope.Selecting(Min, Max: Longint);
  2398. begin
  2399.    Select(Min,Max,True);
  2400.    if assigned(FOnSelecting) then FOnSelecting(Self,Min,Max);
  2401. end;
  2402. {-- TMMOscope ------------------------------------------------------------}
  2403. procedure TMMOscope.SelectEnd(Min, Max: Longint);
  2404. begin
  2405.    Select(Min,Max,False);
  2406.    if assigned(FOnSelectEnd)then FOnSelectEnd(Self,Min,Max);
  2407. end;
  2408. {-- TMMOscope ------------------------------------------------------------}
  2409. function TMMOscope.IsLocator(X: integer): Boolean;
  2410. begin
  2411.    Result := (FLocator >= 0) and
  2412.              (X >= (FLocator+BevelExtend)-3) and
  2413.              (X <= (FLocator+BevelExtend)+3) and
  2414.              (X >= 0) and (X <= Width);
  2415. end;
  2416. {-- TMMOscope ------------------------------------------------------------}
  2417. function TMMOscope.IsSelectStart(X: integer): Boolean;
  2418. begin
  2419.    Result := (FSelectStart >= 0) and
  2420.              (X >= (FSelectStart+BevelExtend)-3) and
  2421.              (X <= (FSelectStart+BevelExtend)+2) and
  2422.              (X >= 0) and (X <= Width);
  2423. end;
  2424. {-- TMMOscope ------------------------------------------------------------}
  2425. function TMMOscope.IsSelectEnd(X: integer): Boolean;
  2426. begin
  2427.    Result := (FSelectEnd >= 0) and
  2428.              (X >= (FSelectEnd+BevelExtend)-2) and
  2429.              (X <= (FSelectEnd+BevelExtend)+3) and
  2430.              (X >= 0) and (X <= Width);
  2431. end;
  2432. {-- TMMOscope ------------------------------------------------------------}
  2433. function TMMOscope.IsInSelection(X: integer): Boolean;
  2434. begin
  2435.    Result := (FSelectStart >= 0) and (FSelectEnd >= 0) and
  2436.              (X >= (FSelectStart+BevelExtend)) and
  2437.              (X <= (FSelectEnd+BevelExtend)) and
  2438.              (X >= 0) and (X <= Width);
  2439. end;
  2440. var
  2441.    StartOrigin,Origin,
  2442.    MinShift,
  2443.    MaxShift: Longint;
  2444.    Moving  : Boolean;
  2445. {-- TMMOscope ------------------------------------------------------------}
  2446. procedure TMMOscope.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  2447. var
  2448.    aRect: TRect;
  2449. begin
  2450.    if not (csDesigning in ComponentState) and Enabled then
  2451.    begin
  2452.       if (Button = mbLeft) and FShowInfo then
  2453.       begin
  2454.          aRect.TopLeft := ClientToScreen(FClientRect.TopLeft);
  2455.          aRect.BottomRight := ClientToScreen(FClientRect.BottomRight);
  2456.          ClipCursor(@aRect);
  2457.          FShowInfoHint := True;
  2458.          { maybe there is a hint, hide it }
  2459.          if ShowHint then
  2460.          begin
  2461.             FOldShowHint := ShowHint;
  2462.             ShowHint := False;
  2463.             Application.CancelHint;
  2464.             Update;
  2465.          end
  2466.          else FOldShowHint := False;
  2467.          {$IFDEF WIN32}
  2468.          { we must save the screen in our bitmap }
  2469.          DIBCanvas.CopyRect(Rect(0,0,FWidth,FHeight),Canvas,FClientRect);
  2470.          {$ENDIF}
  2471.          DrawInfo(Point(X,Y));
  2472.       end
  2473.       else if (Button = mbRight) and FUseSelection and not FLocked and not FDrawing then
  2474.       begin
  2475.          aRect := BeveledRect;
  2476.          if PtInRect(aRect,Point(X,Y)) then
  2477.          begin
  2478.             FDrawing := True;
  2479.             Moving := False;
  2480.             MouseCapture := True;
  2481.             if IsSelectStart(X) then
  2482.             begin
  2483.                Origin := FSelectEnd;
  2484.             end
  2485.             else if IsSelectEnd(X) then
  2486.             begin
  2487.                Origin := FSelectStart;
  2488.             end
  2489.             else if IsInSelection(X) then
  2490.             begin
  2491.                Windows.SetCursor(Screen.Cursors[crsHand4]);
  2492.                Moving := True;
  2493.                Origin := X-BevelExtend;
  2494.                MinShift := -(FSelectStart);
  2495.                MaxShift := (FWidth-1)-FSelectEnd;
  2496.             end
  2497.             else
  2498.             begin
  2499.                Windows.SetCursor(Screen.Cursors[crSizeWE]);
  2500.                Origin := X-BevelExtend;
  2501.                { clear old selection }
  2502.                Selecting(-1,-1);
  2503.                Selecting(Origin,Origin+1);
  2504.             end;
  2505.             StartOrigin := Origin;
  2506.          end;
  2507.       end;
  2508.    end;
  2509.    inherited MouseDown(Button, Shift, X, Y);
  2510. end;
  2511. {-- TMMOscope ------------------------------------------------------------}
  2512. procedure TMMOscope.MouseMove(Shift: TShiftState; X, Y: Integer);
  2513. var
  2514.    NewPos,Diff: Longint;
  2515. begin
  2516.    if FShowInfo and FShowInfoHint then
  2517.    begin
  2518.       inherited MouseMove(Shift, X, Y);
  2519.       DrawInfo(Point(X,Y));
  2520.    end
  2521.    else if FUseSelection and not FLocked and FDrawing then
  2522.    begin
  2523.       X := Limit(X,BevelExtend,(Width-BevelExtend)-1);
  2524.       if Moving then
  2525.       begin
  2526.          Diff := Limit((X-BevelExtend)-Origin,MinShift,MaxShift);
  2527.          Selecting(FSelectStart+Diff,FSelectEnd+Diff);
  2528.          Origin := Origin + Diff;
  2529.          MinShift := MinShift - Diff;
  2530.          MaxShift := MaxShift - Diff;
  2531.       end
  2532.       else
  2533.       begin
  2534.          NewPos := Limit(X-BevelExtend,0,Width-2*BevelExtend);
  2535.          Selecting(Origin,NewPos);
  2536.       end;
  2537.       inherited MouseMove(Shift, X, Y);
  2538.    end
  2539.    else if FUseSelection and not FLocked then
  2540.    begin
  2541.       inherited MouseMove(Shift, X, Y);
  2542.       if IsSelectStart(X) or IsSelectEnd(X) then
  2543.          Cursor := crSizeWE
  2544.       else if IsInSelection(X) then
  2545.          Cursor := crsHand3
  2546.       else if (Cursor=crSizeWE)or(Cursor=crsHand3)or(Cursor=crsZoom1) then
  2547.          Cursor := crDefault;
  2548.    end
  2549.    else
  2550.    begin
  2551.       inherited MouseMove(Shift, X, Y);
  2552.       if (Cursor <> crCross) and (Cursor <> crHourGlass) then
  2553.           Cursor := crDefault;
  2554.    end;
  2555. end;
  2556. {-- TMMOscope ------------------------------------------------------------}
  2557. procedure TMMOscope.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  2558. begin
  2559.    if (Button = mbLeft) and FShowInfoHint then
  2560.    begin
  2561.       { restore background }
  2562.       if FEnabled then DrawInfo(Point(-1,-1));
  2563.       if (SaveDC <> 0) then
  2564.       begin
  2565.          SelectObject(SaveDC, OldBitmap);
  2566.          DeleteObject(SaveBitmap);
  2567.          SaveBitmap := 0;
  2568.          DeleteDC(SaveDC);
  2569.          SaveDC := 0;
  2570.       end;
  2571.       FShowInfoHint := False;
  2572.       ClipCursor(nil);
  2573.       ShowHint := FOldShowHint;
  2574.    end
  2575.    else if (Button = mbRight) and FDrawing then
  2576.    begin
  2577.       FDrawing := False;
  2578.       MouseCapture := False;
  2579.       if (FSelectEnd = FSelectStart+1) or (FSelectEnd = FSelectStart-1) then
  2580.       begin
  2581.          Selecting(-1,-1);
  2582.       end;
  2583.       SelectEnd(FSelectStart,FSelectEnd);
  2584.    end;
  2585.    inherited MouseUp(Button, Shift, X, Y);
  2586. end;
  2587. end.