TScrollBox i OnMouseWheel.

dział ogólny

TScrollBox i OnMouseWheel.

Nowy postprzez Cyfrowy Baron » niedziela, 27 czerwca 2010, 21:39

W komponencie typu TScrollBox nie działa przewijanie kółkiem myszy, gdy cały ScrollBox jest zasłonięty. Można sterować nim ręcznie, poprzez zmianę pozycji (właściwość Position), ale to nie zawsze jest zadowalające. Czy znasz sposób na zmuszenie obiektu ScrollBox do reagowania na kółko myszki?
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: TScrollBox i OnMouseWheel.

Nowy postprzez Cyfrowy Baron » poniedziaÅ‚ek, 28 czerwca 2010, 11:08

No i po raz kolejny sam muszę rozwiązać swój problem. Rozwiązanie znalazłem.

Gdy jakiś komponent np. Panel zapełnia cały obszar obiektu SrcollBox i nie można go przewijać kółkiem myszy należy posłużyć się zdarzeniami OnMouseWheelDown i OnMouseWheelUp formularza na którym znajduje się ScrollBox, trzeba przy tym ustawić właściwość KeyPreview formularza na true. Natomiast w zdarzeniu OnMouseMove dla obiektu, który znajduje się na ScrollBox, w przykładzie dla Panel1 należy ustawić focus na ScrollBox:

Kod: Zaznacz cały

void __fastcall TMainForm
::FormMouseWheelDown(TObject *Sender, TShiftState Shift,
          TPoint &MousePos, bool &Handled)
{
 if(GetFocus() == ScrollBox1->Handle || GetFocus() == Panel1->Handle)
 {
  ScrollBox1->Perform(WM_VSCROLL10);
 }
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormMouseWheelUp(TObject *Sender, TShiftState Shift,
          TPoint &MousePos, bool &Handled)
{
 if(GetFocus() == ScrollBox1->Handle || GetFocus() == Panel1->Handle)
 {
   ScrollBox1->Perform(WM_VSCROLL00);
 }
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Panel1MouseMove(TObject *Sender, TShiftState Shift,
          int X, int Y)
{
 if(GetFocus() != ScrollBox1->Handle)
  ScrollBox1->SetFocus();
}
 
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: TScrollBox i OnMouseWheel.

Nowy postprzez Koziol » Å›roda, 30 czerwca 2010, 08:01

Hm a nie lepszym rozwiązaniem było by zastosować Application->OnMessage?
Kod: Zaznacz cały
void __fastcall TForm1::FormCreate(TObject *Sender)
{
     Application->OnMessage = AppMessage;
}

void __fastcall TForm1::AppMessage(tagMSG &Msg, bool &Handled)
{
     Handled = true;
     switch(Msg.message)
     {
          case WM_VSCROLL:
               ScrollBox1->Perform(WM_VSCROLL, Msg.wParam, Msg.lParam);
          break;
          default:
               Handled = false;
          break;
     }
}


Nie uwzględniłem co prawda focusa ale dodanie go nie jest problemem.
Avatar użytkownika
Koziol
Intelektryk
Intelektryk
 
Posty: 144
Dołączył(a): niedziela, 13 lipca 2008, 17:36
PodziÄ™kowaÅ‚ : 8
OtrzymaÅ‚ podziÄ™kowaÅ„: 2
System operacyjny: Windows XP Pro SP2
Kompilator: C++ Builder
    Windows XPFirefox

Re: TScrollBox i OnMouseWheel.

Nowy postprzez Cyfrowy Baron » Å›roda, 30 czerwca 2010, 11:31

A sprawdzałeś ten kod?! Bo ja już tak kombinowałem, problem w tym, że komunikat WM_VSCROLL nie ma nic wspólnego ze zdarzeniem MouseWheel, dlatego to nie działa. Próbowałem przechwytywać komunikat WM_MOUSEWHELL, ale to też nie działa.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: TScrollBox i OnMouseWheel.

Nowy postprzez Koziol » Å›roda, 30 czerwca 2010, 12:20

Kółko myszy



Niektóre myszy są wyposażone w kółko (rolkę) które umożliwia w większości programów np. wygodne przesuwanie pasków przewijania.

Po obróceniu rolką zostaje wysłany do procedury okna specjalny komunikat WM_MOUSEWHEEL. W młodszym słowie lParam zawarta jest współrzędna x kursora natomiast w starszym współrzędna y. Parametr wParam zawiera w młodszym słowie stan przycisków myszy i klawiszy ALT, SHIFT, CTRL. Starsze słowo zawiera natomiast dystans o jaki zostało przesunięte kółko, jest on wielokrotnością wartości WHEEL_DELTA która wynosi 120. Jeśli wartość jest dodatnia znaczy to że kółko jest przesuwane do przodu, natomiast wartość ujemna oznacza przesuwanie w tył. To jest moja własna sugestia: Microsoft zdefiniował WHEEL_DELTA, by udostępnić na przyszłość sobie czy innym producentom myszek możliwość zmiany, ponieważ przewidział że będą produkowane lepsze myszki (z większą czułością kółka). Aby móc używać kółka trzeba na początku programu zdefiniować tą linijkę:



#define _WIN32_WINNT 0x0500



Kod: Zaznacz cały
//---------------------------------------------------------------------------
#define _WIN32_WINNT 0x0500
#include <vcl.h>
#include <windows.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
     Application->OnMessage = AppMessage;
}

void __fastcall TForm1::AppMessage(tagMSG &Msg, bool &Handled)
{
     Handled = 0;
     if(Msg.message==WM_MOUSEWHEEL)

  {
               ScrollBox1->Perform(WM_VSCROLL, 1, 0);
               Handled = 1;

  }

}


W ten sposob działa ale nie wiem jak rozgryźć przesuwanie w dół i w góre. Znaczy co wysłać do ScrollBox1->Perform. (
Kod: Zaznacz cały
ScrollBox1->Perform(WM_VSCROLL, 0, 0)
// przesuwa również w dół


:!: Należy pamiętac o tej linijce bez niej nie działa #define _WIN32_WINNT 0x0500

Za ten post autor Koziol otrzymał podziękowanie od:
Cyfrowy Baron
Avatar użytkownika
Koziol
Intelektryk
Intelektryk
 
Posty: 144
Dołączył(a): niedziela, 13 lipca 2008, 17:36
PodziÄ™kowaÅ‚ : 8
OtrzymaÅ‚ podziÄ™kowaÅ„: 2
System operacyjny: Windows XP Pro SP2
Kompilator: C++ Builder
    Windows XPFirefox

Re: TScrollBox i OnMouseWheel.

Nowy postprzez Cyfrowy Baron » Å›roda, 30 czerwca 2010, 12:55

Ten wpis: #define _WIN32_WINNT 0x0500 wywołuje błąd w bibliotece windows.hpp, ale kod działa i bez tego, tylko trzeba wysłać komunikat Perform(WM_VSCROLL, 1, 0) -> przewija na dół lub Perform(WM_VSCROLL, 0, 0) -> przewija do góry. Zmiana stanu zmiennej Handled jest zbędna.

Kod: Zaznacz cały

void __fastcall TForm1
::AppMessage(tagMSG &Msg, bool &Handled)
{
 if(Msg.message == WM_MOUSEWHEEL)
 {
  int zDelta = GET_WHEEL_DELTA_WPARAM(Msg.wParam);
  if(zDelta < 0) ScrollBox1->Perform(WM_VSCROLL, 1, 0);
  else ScrollBox1->Perform(WM_VSCROLL, 0, 0);
 }
}
 


Teraz ma to już ręce i nogi, ale do pełni szczęścia brakuje mi tego:

Kod: Zaznacz cały

void __fastcall TForm1
::Panel1MouseMove(TObject *Sender, TShiftState Shift, int X,
          int Y)
{
 if(GetFocus() != ScrollBox1->Handle)
  ScrollBox1->SetFocus();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ApplicationEvents1Message(tagMSG &Msg, bool &Handled) // komponent TApplicationEvents zdarzenie OnMessage
{
 if(Msg.message == WM_MOUSEWHEEL)
 {
  int zDelta = GET_WHEEL_DELTA_WPARAM(Msg.wParam);
  if(zDelta < 0) SendMessage(GetFocus(), WM_VSCROLL, 1, 0);
  else SendMessage(GetFocus(), WM_VSCROLL, 0, 0);
 }
}
 
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: TScrollBox i OnMouseWheel.

Nowy postprzez Koziol » Å›roda, 30 czerwca 2010, 13:06

Cyfrowy Baron napisał(a):Ten wpis: #define _WIN32_WINNT 0x0500 wywołuje błąd w bibliotece windows.hpp, ale kod działa i bez tego, tylko trzeba wysłać komunikat


Widocznie w nowszej wersji nie jest już potrzebne. W BCB6 nie chodzi :)

Cyfrowy Baron napisał(a):Zmiana stanu zmiennej Handled jest zbędna.


Tutaj również starsza wersja się "wysypuje" jeżeli nie zmieni się stanu ;)


No ale najważniejsze jest to, że działa :)
Avatar użytkownika
Koziol
Intelektryk
Intelektryk
 
Posty: 144
Dołączył(a): niedziela, 13 lipca 2008, 17:36
PodziÄ™kowaÅ‚ : 8
OtrzymaÅ‚ podziÄ™kowaÅ„: 2
System operacyjny: Windows XP Pro SP2
Kompilator: C++ Builder
    Windows XPFirefox


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przeglÄ…da forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 4 gości