Dlaczego po obróceniu kółka myszy, kontrolka dostaje komunikat CM_MOUSELEAVE?

0

Kontrolki działały prawidłowo w Lazarusie 1.6.4, a po aktualizacji do wersji 1.8, wszystkie zgłupiały. Otrzymują komunikat CM_MOUSELEAVE po obróceniu rolką myszy w dowolnym kierunku.

Mowa o sytuacji, kiedy różne własne kontrolki znajdują się na własnym panelu. Jeśli umieszczę np. przycisk bezpośrednio na formularzu to ta kontrolka zachowuje się poprawnie. Niestety ale do czasu, kiedy również bezpośrednio na formie położę np. standardowy TButton – wtedy też zaczyna wariować z tym komunikatem.

Podejrzewam, że powodem takiego problemu jest klasa tego mojego panelu, jednak przyczyny nie jestem w stanie namierzyć. Próbowałem już wszystkiego.


W celu reprodukcji błędu stworzyłem malutki pakiet z dwoma typami kontrolek – z panelem i przyciskiem. To co najistotniejsze przeniosłem ze swojego dużego projektu do tego pakietu. Do tego dorobiłem prostą apkę okienkową, aby móc testować te kontrolki. Kontrolki te też zawierają owy błąd, więc kod tych kontrolek nie pasuje do nowego LCL.

Pakiet zawiera moduły:

  • StupidRegister.pp – moduł z procedurą rejestracji kontrolek,
  • StupidCommon.pp – zawiera pseudobazowe klasy dla komponentów,
  • StupidPanel.pp – zawiera kontrolkę TStupidPanel,
  • StupidButton.pp – zawiera kontrolkę TStupidButton.

Każdy z tych modułów ma kilkadziesiąt linii kodu – tylko to co trzeba. W podkatalogu controls znajduje się plik StupidControls.lpk. Zakładka dla tych komponentów to Stupid Controls.

Problem obrazuje to nagranie – stupid controls.webm

Kursor znajduje się nad przyciskiem, obracam rolkę myszy i przycisk zostaje dezaktywowany, tak jakbym zabrał kursor w cholerę. Jeśli ktoś wie co jest przyczyną to proszę o wskazówki. W międzyczasie powalczę z tym i jeśli uda się rozwiązać problem to dam znać.

0

Nie wiem dziwne u mnie nie ma takiego problemu albo masz problem ze środowiskiem (np. przez jakieś resztki po poprzedniej wersji ) albo z systemem u mnie Win 10. W załączniku skompilowany exe to sobie możesz sprawdzić czy w nim masz problem (jeżeli nie to środowisko), możesz przesłać też swój to ja sprawdzę jak z nim u siebie.

EDIT @furious programming wymieniłem załącznik na 32 bit

0

Mam 32-bitowy system, a apka z załącznika jest 64-bitowa. :P

Pod wieczór przysiądę do tego i sprawdzę. Obstawiam, że mój problem związany jest z kompatybilnością LCL z WinXP, bo na tym systemie pracuję nad programem. Zależy mi na tym, aby moja aplikacja śmigała na wszystkich okienkach, od WinXP do Win10.

0

@kAzek: jest gorzej niż myślałem. Pod Win7 źle działają oba nasze exeki – sprawdziłem przed chwilą.

0

No nic, do tej pory nie znalazłem przyczyny generowania nadmiarowego komunikatu, a w wątku na forum Lazarusa nadal nie pojawił się ktoś, kto mógłby zidentyfikować problem. Na odpowiedź (tam) będę czekał i jeśli dowiem się o co chodzi to dam i tutaj znać.

Skoro nie da się zablokować wysyłania tego komunikatu, to zawsze można go zignorować. Komunikat dotrze do kontrolki i tak, więc należy sprawdzić, czy kursor nadal znajduje się nad tą kontrolką i jeśli tak – nie wykonywać logiki handlera komunikatu CM_MOUSELEAVE.

Czyli jeśli kod metody wyglądał tak:

procedure TStupidButton.CMMouseLeave(var AMessage: TLMessage);
begin
  FHover := False;
  inherited Invalidate();
end;

to teraz powinien wyglądać tak:

procedure TStupidButton.CMMouseLeave(var AMessage: TLMessage);
var
  LControl: TControl;
  LPoint: TPoint;
begin
  Windows.GetCursorPos(LPoint);
  LControl := FindLCLControl(LPoint);

  if Assigned(LControl) and (LControl <> Self) then
  begin
    FHover := False;
    inherited Invalidate();
  end;
end;

i wszystko będzie działało prawidłowo – u mnie działa. Tyle że to nie jest rozwiązanie problemu, a jego obejście. ;)


Edit: Zapomniałem o jednej rzeczy… Póki co sytuacja wygląda tak, że:

  • najeżdżamy kursorem – wysłany zostaje komunikat CM_MOUSEENTER,
  • obracamy rolką myszy – wysłany zostaje nadmiarowy komunikat CM_MOUSELEAVE,
  • przesuwamy ciut kursor – wysłany zostaje nadmiarowy komunikat CM_MOUSEENTER,
  • obracamy rolką myszy – znów nadmiarowy komunikat CM_MOUSELEAVE,
  • przesuwamy ciut kursor – znów nadmiarowy komunikat CM_MOUSEENTER,
  • zabieramy kursor znad kontrolki – wysłany zostaje komunikat CM_MOUSELEAVE.

Jak widać, nadmiarowe są dwa komunikaty:

  • CM_MOUSELEAVE – bezpośrednio po obróceniu rolki myszy, a następnie:
  • CM_MOUSEENTER – po przesunięciu kursora, nadal w obrębie komponentu.

Tak więc trzeba dodać łatki do dwóch metod – CMMouseEnter i CMMouseLeave… :/

1 użytkowników online, w tym zalogowanych: 0, gości: 1