2014-10-28 42 views
3

我試圖實現類似於大多數媒體播放器的功能,通過在媒體持續時間軌道欄上移動鼠標,它將顯示一個小的彈出窗口,通知您當前鼠標當前位置。雖然在實現下面給出的代碼時我注意到了一個奇怪的行爲。軌道欄鼠標移動事件的奇怪行爲

procedure TForm1.TrackBar1MouseMove(Sender: TObject; Shift: TShiftState; X, 
    Y: Single); 
var 
    pers: Extended; 
begin 
    pers := (X/TrackBar1.Width); 
    PixelLabel.Text := FloatToStr(pers * TrackBar1.Max); 
end; 

如果我在賽道欄的中間點擊我會得到相當接近該點的實際軌跡欄的值,所以如果例如推力杆範圍從去,我點擊中間的某處我得到,但隨着我向左或向右移動,我開始分別獲得更小和更大的值。因此,如果我的鼠標接近開始例如我可能會得到而不是應該是該點的實際值。有人能指出我在這裏做錯了什麼嗎?

編輯

通過實際軌道條價值我的意思是,從得到的值:

procedure TForm1.TrackBar1Change(Sender: TObject); 
begin 
    ActualLabel.Text := 'Actual Val: '+FloatToStr(TrackBar1.Value); 

end; 

因此,我將移動鼠標讓在308位說(軌跡欄從0到609這裏),我會得到一個鱸魚值0.50574這告訴我,在位置308鼠標下的軌跡欄的值是10114,但通過單擊鼠標並啓動onChange函數我得到一個值10116.隨着我們去f,這個差異會增加從軌道杆中間到其中任一側。

編輯2

更清楚的例子是這樣。如下圖所示,我將鼠標移動到位置X = 572。如果以整個軌跡欄的百分比表示該位置將是572/609 = 0,9392。所以人們可能會認爲該位置的軌跡欄的值的百分比(如圖所示,最小值:0 - 最大值:200)將是相同的。換句話說,MValue/max = 0,9392。

enter image description here

但點擊軌跡欄在確切的位置,然後請求它的價值它不會返回我計算爲「MValue」,如下所示的圖像(鼠標是不可見的,但之後這個圖像是的確之後我點擊在相同的位置軌跡欄中,你可以看到ActualValue被更新)

enter image description here

+0

嘗試'TrackBar1.ClientWidth'而不是'Width',儘管我認爲這不會太大差異。這個想法是,實際的軌道比控制的寬度小几個像素。 – 2014-10-28 15:03:13

+0

ClientWidth不是跟蹤欄的屬性,如果你的意思是絕對寬度,我嘗試過,但它完全一樣。 – dearn44 2014-10-28 15:05:50

+0

我剛剛注意到你使用的是Firemonkey,但概念是相同的,實際的軌跡欄本身比控件的寬度小。您必須確定實際曲目的寬度,並且可能沒有直接屬性來告訴您這些信息。 – 2014-10-28 15:06:34

回答

3

問題1

您的計算值與控件使用的值不匹配。控制不符合本規則可以在FMX.StdCtrls發現:

function PosToValue(MinValue, MaxValue, ViewportSize, ThumbSize, TrackSize, 
    Pos: Single; IgnoreViewportSize: boolean): Single; 
var ValRel: Double; 
begin 
    Result := MinValue; 
    if (ViewportSize < 0) or IgnoreViewportSize then 
    ViewportSize := 0; 
    ValRel := TrackSize - ThumbSize; 
    if ValRel > 0 then 
    begin 
    ValRel := (Pos - ThumbSize/2)/ValRel; 
    if ValRel < 0 then 
     ValRel := 0; 
    if ValRel > 1 then 
     ValRel := 1; 
    Result := MinValue + ValRel * (MaxValue - MinValue - ViewportSize); 
    end; 
end; 

不同的是,這裏的代碼,使拇指大小的津貼。您的公式相當於調用此函數併爲ThumbSize傳遞0的值。

如果您想複製控件的行爲,那麼您還需要使用此算法。你需要受保護的黑客破解課程。

type 
    THackedTrackBar = class(TTrackBar); 

procedure TForm1.TrackBar1MouseMove(Sender: TObject; Shift: TShiftState; 
    X, Y: Single); 
var 
    tb: THackedTrackBar; 
begin 
    tb := THackedTrackBar(TrackBar1); 
    Label1.Text := FloatToStr(
    PosToValue(
     tb.Min, 
     tb.Max, 
     tb.ViewportSize, 
     tb.GetThumbSize(tb.FIgnoreViewportSize), 
     tb.Width, 
     X, 
     tb.FIgnoreViewportSize 
    ) 
); 
end; 

問題2

OnMouseMove當光標在軌道拇指不火。這似乎是FMX TTrackBar控制器的一個基本限制。底層框架顯然意識到光標位於拇指上方,因爲它以不同的顏色(即所謂的熱追蹤效果)來繪製它。然而,框架似乎這樣做不利於讓你知道鼠標正在移動。

軌跡欄上的拇指作爲單獨的對象實現。這是TThumb類型的對象。 TTrackBar控件通過受保護的屬性顯示對象。您可以使用受保護的hack來獲取拇指對象,然後設置其事件處理程序。沒有太多樂趣,但肯定是解決這個問題的一種方法。

+0

確實是,但是拇指放在旁邊,我真正的問題是,這些價值並不如預期。讓我用代碼來更新問題,展示如何獲得我稱之爲「實際」軌跡欄值的代碼。 – dearn44 2014-10-28 15:21:14

+0

這裏的數值就好了。對於最小值爲0,最大值爲100的我的跟蹤欄,您的代碼會生成0到100之間的值,但不會跟蹤拇指。我正在使用XE7,因爲我認爲你是。 – 2014-10-28 15:23:45

+0

是的,的確,它會產生從最小值到最大值的值,因爲由於某些原因,由於某些原因,這些值與跟蹤欄本身實際認爲是該位置下的正確值不同。檢查我的編輯對問題的更好理解。 – dearn44 2014-10-28 15:29:11

0

對於你最初的問題,你需要深入研究風格以找到圍繞軌道欄左右填充的確切數量。請注意,這取決於平臺,風格和Delphi版本。

你可能會考慮使用自己的風格,所以你知道一切都將是恆定的。

爲了解決David Heffernan提出的問題,您可以對TTrackBar(使其成爲客戶端對齊的軌跡欄的子項)進行透明控制,攔截鼠標事件,執行自己的處理並將它們傳遞到跟蹤欄。

+0

這不應該是問題,因爲如果您在移動鼠標時檢查X的值,則它將在位置開始時正確地報告0,並在位置爲0.x的軌道欄的末尾609報告。 – dearn44 2014-10-28 15:31:45

+0

當鼠標位於軌跡條的最左端(最低位置)時,你說Position.X = 0?如果是這樣,那麼你似乎直接矛盾你自己的問題。 – 2014-10-30 12:22:46

+0

如何?也許檢查接受的答案可能會讓你更好地瞭解我的意思。 – dearn44 2014-10-30 12:33:19