2015-06-01 38 views
5

Hem TImage hem de TButton denetimi olan bir formum var. OnClick olayına yanıt verme hızının TImage için biraz yavaş olduğunu fark ettim (hızlı tıklama!), Böylece ölçtüm. 100+ tıklama (ve her denetim için geldiğince tutarlı oranı tutarak kadar hızlı geldiğince tıklayarak) ben ölçümlerini var: Ortalama ~ 105-116ms TImage: TButton Ortalama ~Delphi - TImage tıklama hızı, TButton ile karşılaştırıldığında yavaş yavaş

220-235ms Bunu benzer sonuçlarla birkaç kez tekrarladım. TImage işlemi neden TButton'un oranının yaklaşık yarısını tıklıyor? Windows ileti kuyruğunu WM_LBUTTON_DOWN adresinden OnClick olayına işlemek daha yavaş olabilir mi? Belki önceki tıklamaların N ms'sindeyse tıklamaları yutuyor mu?

Bu durumu etkileyen TImage özelliklerinde hiçbir şey görünmüyor.

Not: İlgili ise, burada Delphi 7 ve standart VCL denetimlerini kullanma.

DÜZENLEME:

// Define variables (in class definition) 
m_dwBtnClicks, m_dwImgClicks: DWORD; 
m_dwLastBtnClickTicks, m_dwLastImgClickTicks: DWORD; 
m_fTotalBtnClicksTicks, m_fTotalImgClicksTicks: Single; 

// Initialise variables (in form's OnCreate event) 
m_dwBtnClicks := 0; 
m_dwImgClicks := 0; 

m_dwLastBtnClickTicks := 0; 
m_dwLastImgClickTicks := 0; 

m_fTotalImgClicksTicks := 0.0; 
m_fTotalImgClicksTicks := 0.0; 

// OnClick events 
procedure TfrmQwerty.btnClick(Sender: TObject); 
var 
    dwTime: DWORD; 
begin 
    // TButton click! 
    Inc(m_dwBtnClicks); 
    dwTime := GetTickCount(); 
    if (m_dwLastBtnClickTicks > 0) then 
     m_fTotalBtnClicksTicks := (m_fTotalBtnClicksTicks + (dwTime - m_dwLastBtnClickTicks)); 

    m_dwLastBtnClickTicks := dwTime; 
end; 

procedure TfrmQwerty.imgClick(Sender: TObject); 
var 
    dwTime: DWORD; 
begin 
    // TImage click! 
    Inc(m_dwImgClicks); 
    dwTime := GetTickCount(); 
    if (m_dwLastImgClickTicks > 0) then 
     m_fTotalImgClicksTicks := (m_fTotalImgClicksTicks + (dwTime - m_dwLastImgClickTicks)); 

    m_dwLastImgClickTicks := dwTime; 
end; 

// Some TTimer::OnTimer event to update the results on-screen 
procedure TfrmQwerty.OnTextEntryTimer(Sender: TObject); 
var 
    fTime: Single; 
begin 
    // Stop the timer 
    TextEntryTimer.Enabled := False; 

    if (m_dwBtnClicks > 1) then 
     begin 
     fTime := m_fTotalBtnClicksTicks/m_dwBtnClicks; 
     lblButtonClicks.Caption := Format('BtnClicks = %d [Avg = %.3fms]', [ 
      m_dwBtnClicks, fTime]); 
     end; 

    if (m_dwImgClicks > 1) then 
     begin 
     fTime := m_fTotalImgClicksTicks/m_dwImgClicks; 
     lblImageClicks.Caption := Format('ImgClicks = %d [Avg = %.3fms]', [ 
      m_dwImgClicks, fTime]); 
     end; 

    // Restart the timer 
    TextEntryTimer.Enabled := True; 
end; 
+0

Zamanlama nedir? Lütfen aynı zamanlamayı yapmamızı sağlayan kısa bir demo programı gösteriniz. –

+2

'TButton' 'OnClick''i tetiklemek için [' BN_CLICKED'] (https://msdn.microsoft.com/en-us/library/windows/desktop/bb761825%28v=vs.85%29.aspx) sistem bildirimini kullanır TImage sadece fare aşağı/fare up olay çiftini izler iken olay, bu yüzden fark olabilir sürpriz olmamalı. – TLama

+0

@DavidHeffernan: Tamam, bazı şeylerin nasıl zamanlandığını göstermek için kod eklendi. Hiçbir şey fantezi değil. Büyük farkı fark ettiğimde, TButton'u QWERTY stili bir ekran klavyesinde bir TImage ile değiştiriyordum. – AlainD

cevap

4

VCL kaynak burada senin arkadaşın: İşte şeyler zaman aşımına nasıl gösteren bazı örnek kodudur. Belirtildiği gibi, bu, bunları oluşturmak için yeterince hızlı tıkladığında Windows tarafından gönderilen çift tıklama mesajlarından kaynaklanır. Sol fare tuşu artar -

procedure TControl.WMLButtonDown(var Message: TWMLButtonDown); 
begin 
    SendCancelMode(Self); 
    inherited; 
    if csCaptureMouse in ControlStyle then 
    MouseCapture := True; 
    if csClickEvents in ControlStyle then // !! Note here 
    Include(FControlState, csClicked); // Storing that we've been clicked 
    DoMouseDown(Message, mbLeft, []); 
end; 

Adım 2: Sol fare düğmesi aşağı gider - 1

Adım:

de çift tıklama tetiklemek için yeterince hızlı tıklayarak ne olur bakalım.

procedure TControl.WMLButtonUp(var Message: TWMLButtonUp); 
begin 
    inherited; 
    if csCaptureMouse in ControlStyle then MouseCapture := False; 
    if csClicked in ControlState then  // !! Note here 
    begin         // Firing CLICK event primed 
    Exclude(FControlState, csClicked); // from the method above 
    if ClientRect.Contains(SmallPointToPoint(Message.Pos)) then 
     Click; 
    end; 
    DoMouseUp(Message, mbLeft); 
end; 

Adım 3 - Sol fare düğmesine tekrar iner.

Bu sefer, çift tıklama! Bunun tamamen farklı bir mesajla uğraştığını unutmayın - işletim sisteminden çift tıklatma mesajı, aşağı fare mesajı değil. Buradaki işleyici hala MouseDown olayını tetikler, ancak , denetimin, fare düğmesi geri geldiğinde tıklama olayını tetiklemesine neden olmaz.

procedure TControl.WMLButtonDblClk(var Message: TWMLButtonDblClk); 
begin 
    SendCancelMode(Self); 
    inherited; 
    if csCaptureMouse in ControlStyle then MouseCapture := True; 
    if csClickEvents in ControlStyle then DblClick; 
    DoMouseDown(Message, mbLeft, [ssDouble]); 
end; 

bir Düğme o düğme tıklandığında her zaman oluşturulur özel BN_CLICKED mesajı alır özel TWinControl olduğundan

bakılmaksızın bir çift tıklama ya da çok görülebilir olsun. Basit bir kontrol olmak, basit bir iş yapar ve bu nedenle hızlı bir şekilde tıklandığında (çift tıklama oranından daha hızlı) bir düğmeden iki kat daha fazla tıklama etkinliği görürsünüz.

procedure TCustomButton.CNCommand(var Message: TWMCommand); 
begin 
    if Message.NotifyCode = BN_CLICKED then Click; 
end; 

bir TButton onun ControlStyle yılındacsClickEvents seçenek olmadan oluşturulan bu özel mesajlar alabilirsiniz beri aynı zamanda bir TControl için kullanılan Yukarıdaki adımlarda elleçleme olmasına rağmen bu yüzden de, dikkat edebilirsiniz TImage (ve diğer) denetimleri geçerli değildir (yani: WMLButtonDown işleyicisindeki Click için başlatma).Eğer keşfettim gibi

, OnMouseDown veya OnMouseUp olaylar ne olursa olsun onlar tıklama veya çift tıklama olarak ele alınmalıdır olsun, senin TImage kontrolünde tüm bu olayları yakalamak için izin verecektir. TControl.WndProc yılında,

Image1.ControlStyle := Image1.ControlStyle - [csDoubleClicks]; 

Burada: Eğer TImage işleme çift tıklama umurumda değil eğer


Alternatif olarak siz kontrol stilini ayarlayabilirsiniz

if not (csDoubleClicks in ControlStyle) then 
    case Message.Msg of 
    WM_LBUTTONDBLCLK, WM_RBUTTONDBLCLK, WM_MBUTTONDBLCLK: 
     Dec(Message.Msg, WM_LBUTTONDBLCLK - WM_LBUTTONDOWN); 
    end; 

You çift ​​tıklama olayları basit fare aşağı olaylara dönüştürülür görebilirsiniz.

+0

Tıklama Tıklanma, fare aşağıdan ziyade fare yukarıdayken gerçekleşir. –

+0

@DavidHeffernan Aksini söylemediğimi sanmıyorum. Fareyi kesinlikle aşan çift tıklamayı kastetmedikçe. –

+0

Dediniz ki: “OnMouseDown” olayı keşfettiğiniz gibi, tıklanma veya çift tıklama olarak kabul edilip edilmediğine bakılmaksızın tüm fare aşağı olayları yakalamanıza izin verecektir. * –