CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - [BCB C++] TSpeedButton "wciśnięty"

[BCB C++] TSpeedButton "wciśnięty"

dział ogólny

[BCB C++] TSpeedButton "wciśnięty"

Nowy postprzez Darek_C++ » czwartek, 30 sierpnia 2012, 08:40

Witam ponownie,
czy idzie programowo ustawić przycisk typu TSpeedButton lub inny by wyglądał na "wciśnięty".
Chodzi mi o to by uzyskać taką funkcjonalność: User wciska przycisk który obok niego otwiera menu kontekstowe TPopupMenu sam jednocześnie zostaje w pozycji wciśnięty do czasu gdy user nie wybierze pozycji z menu lub je zamknie je klikając "obok".
----
Widze, że podobną funkcjonalność mógł bym uzyskać za pomocą TPanel tylko nie wiem czy jego wygląd idzie upodobnić do Buttona czyli "bardziej wypukły/wklęsłego" ustawić :)
----
Wcisniecie TSpeedButaona zadziała takim kodem:
KOD cpp:     UKRYJ  
void __fastcall TSprawdzaczPozycji::SpeedButton3Click(TObject *Sender)
{
        SpeedButton3->GroupIndex = 2;
        SpeedButton3->AllowAllUp = true;
        SpeedButton3->Down = true;
        PopupMenuWypiszWyniki->Popup(348,this->Height+30);
}

Wyciśniecie takim:
KOD cpp:     UKRYJ  
  SpeedButton3->GroupIndex = 2;
  SpeedButton3->AllowAllUp = true;
  SpeedButton3->Down = false;
  Application->ProcessMessages();

Jeśli user wybierze jakaś pozycję z menu to "wyciśniecie" jest proste, ale nie wiem jak wycisnąć jak nie wykona akcji i menu się zamknie, bo nie ma zdarzenie onCLose dla PopupMenu :( Czyli zostaje mi sprawdzanie położenia kursora i jak wyjdzie z danego zakresu położenia w jakim jest otwarte PopupMenu to wykonać akcje kod zamykający czy jest jakiś "wygodniejszy" sposób na to :)
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: [BCB C++] TSpeedButton "wciśnięty"

Nowy postprzez Cyfrowy Baron » czwartek, 30 sierpnia 2012, 10:58

Jeżeli dla SpeedButton ustawiasz wartość GroupIndex większą od 0, np. 2 to żadnemu innemu przyciskowi SpeedButton nie przypisuj tej wartości gdyż będą wtedy należały to tej samej grupy i będą się przełączały na zmianę. Jeżeli ustawiasz AllowUp na true, to nie musisz już sterować wartością Down, gdyż przycisk sam będzie nią sterował, dlatego kod powinien wyglądać tak:

KOD cpp:     UKRYJ  
void __fastcall TSprawdzaczPozycji::SpeedButton3Click(TObject *Sender)
{
        SpeedButton3->GroupIndex = 2;
        SpeedButton3->AllowAllUp = true;
        PopupMenuWypiszWyniki->Popup(348,this->Height+30);
}
Darek_C++ napisał(a):Jeśli user wybierze jakaś pozycję z menu to "wyciśniecie" jest proste, ale nie wiem jak wycisnąć jak nie wykona akcji i menu się zamknie,


Z tym jest problem bo to nie SpeedButton steruje PopupMenu. Trzeba by tutaj cyklicznie sprawdzać, czy PopupMenu już się zamknęło. Nie znalazłem komunikatu, który by był wysyłany prze PopupMenu gdy to się zamyka, a samo menu też nie zwraca żadnej wartości przy zamykaniu. Dlatego lepszym rozwiązaniem jest użycie komponentu TLMDSpeedButton, który działa tak samo jak klasyczny TSpeedButton, ale można pod niego podpiąć PopuMenu i nie trzeba nim sterować ręcznie.
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: [BCB C++] TSpeedButton "wciśnięty"

Nowy postprzez Darek_C++ » czwartek, 30 sierpnia 2012, 11:06

Niestety używany przeze mnie Turbo Explorer C++ nie pozwala na instalację komponentów ... chyba, że szło by go wstawić bez instalacji w aplikacje :)
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: [BCB C++] TSpeedButton "wciśnięty"

Nowy postprzez Cyfrowy Baron » czwartek, 30 sierpnia 2012, 11:10

Nie da się. Ale w tym przypadku większość rozwiązań, która zadziała np. w XE2 nie sprawdzi się w TEC++.

Po za tym, w żaden sposób nie udało mi się sprawdzić, czy PopupMenu już się zamknęło, więc chyba to rozwiązanie nie przejdzie, skoro PopupMenu nie informuje w żaden sposób o tym, że jest już zamknięte.
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: [BCB C++] TSpeedButton "wciśnięty"

Nowy postprzez Cyfrowy Baron » czwartek, 30 sierpnia 2012, 11:31

Udało mi się zrobić coś takiego, co poniekąd działa:

KOD cpp:     UKRYJ  
BOOL downup = false; /* zmienna sterująca */

/* ZDARZENI ONCLICK DLA SPEEDBUTTON1 */
void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
 int left = this->Left + SpeedButton1->Left + SpeedButton1->Width;
 int top = this->Top + SpeedButton1->Top;

 PopupMenu1->Popup(left, top);
 downup = true;
}
//---------------------------------------------------------------------------

/* FUNKCJA PRZECHWYTUJĄCA KOMUNIKATY */
void __fastcall TForm1::ApplicationEvents1Message(tagMSG &Msg, bool &Handled)
{

 if( Msg.message == WM_LBUTTONUP || Msg.message == WM_RBUTTONUP && downup )
 {
  SpeedButton1->Down = false;
  downup = false;
 }
}
//---------------------------------------------------------------------------

/* POLECENIA POPUPMENU */
void __fastcall TForm1::Zapisz1Click(TObject *Sender)
{
 /* jakieś polecenie */

 SpeedButton1->Down = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Kopiuj1Click(TObject *Sender)
{
 /* jakieś polecenie */

 SpeedButton1->Down = false;
}


Do przechwytywania komunikatu posłużyłem się komponentem ApplicationEvent, ale możesz sobie stworzyć własną funkcję. Niestety to działa tylko w obrębie aplikacji, jeżeli użytkownik kliknie poza oknem aplikacji to przycisk nie powróci do pierwotnego stanu. By tak się stało należałoby przechwytywać globalnie komunikaty, czyli trzeba by montować hak, a to się staje już zbyt skomplikowane jak na taką prostą operację.

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
Darek_C++
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: [BCB C++] TSpeedButton "wciśnięty"

Nowy postprzez Darek_C++ » czwartek, 30 sierpnia 2012, 11:49

Ale PopupMenu pojawia się zupełnie w innym miejscu nie kolo przycisku :)
I nie powoduje, że przycisk zosatje wciśnięty po otwarciu popupa cały kod:
KOD cpp:     UKRYJ  
BOOL downup = false;
void __fastcall TSprawdzaczPozycji::SpeedButton3Click(TObject *Sender)
{
        int left = this->Left + SpeedButton3->Left + SpeedButton3->Width;
        int top = this->Top + SpeedButton3->Top;
        PopupMenuWypiszWyniki->Popup(left, top);
        downup = true;
}
/////
void __fastcall TSprawdzaczPozycji::ApplicationEvents1Message(tagMSG &Msg,
  bool &Handled)
{
 if( Msg.message == WM_LBUTTONUP || Msg.message == WM_RBUTTONUP && downup )
 {
  SpeedButton3->Down = false;
  downup = false;
 }
}

 
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: [BCB C++] TSpeedButton "wciśnięty"

Nowy postprzez Cyfrowy Baron » czwartek, 30 sierpnia 2012, 13:07

Darek_C++ napisał(a):I nie powoduje, że przycisk zostaje wciśnięty po otwarciu popupa cały kod:


U mnie działa poprawnie. Ja mam AllowUp i GropIndex ustawione w Object Inspector dlatego nie umieszczałem tego w kodzie.

Darek_C++ napisał(a):Ale PopupMenu pojawia się zupełnie w innym miejscu nie kolo przycisku


U mnie pojawia się przy przycisku przecież zmienne left i top przechowują pozycję przycisku względem ekranu. Nie wiem czemu u ciebie to nie działa, być może TEC++ jest coś inaczej. Co się tyczy zmiennej top to powinno się jeszcze dodać grubość belki tytułowej okna by pozycja względem górnej krawędzi ekranu była prawidłowa, np:

KOD cpp:     UKRYJ  
int top = this->Top + SpeedButton3->Top + GetSystemMetrics(SM_CXSIZE);


Nie wiem jak to jest w TEC++, ale w C++Builder pozycję PopupMenu podaje się względem górnego lewego rogu ekranu, a nie względem formularza.
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: [BCB C++] TSpeedButton "wciśnięty"

Nowy postprzez Darek_C++ » czwartek, 30 sierpnia 2012, 14:06

Po małej mienie czyli dodaniu tego co nie dałem
SpeedButton3->GroupIndex = 2;
SpeedButton3->AllowAllUp = true;
jest idealnie :)
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: [BCB C++] TSpeedButton "wciśnięty"

Nowy postprzez Cyfrowy Baron » czwartek, 30 sierpnia 2012, 14:20

Darek_C++ napisał(a):jest idealnie


A co jeśli użytkownik kliknie w buttona a potem przesunie wskaźnik poza krawędź okna programu i kliknie poza tym oknem. Przycisk nie wróci do stanu pierwotnego mimo, że PopuMenu się zamknie!
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: [BCB C++] TSpeedButton "wciśnięty"

Nowy postprzez Darek_C++ » czwartek, 30 sierpnia 2012, 14:56

CB "na bezrybiu i rak ryba", wiec taka funkcjonalność mnie satysfakcjonuje, bo IMHO jest lepsza niż sam button otwierający Menu dodatkowe menu.
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: [BCB C++] TSpeedButton "wciśnięty"

Nowy postprzez Cyfrowy Baron » czwartek, 30 sierpnia 2012, 16:34

Proponuję więc jeszcze dołączyć te zdarzenia:

KOD cpp:     UKRYJ  
void __fastcall TForm1::FormMouseActivate(TObject *Sender, TMouseButton Button,
                  TShiftState Shift, int X, int Y, int HitTest, TMouseActivate &MouseActivate)

{
  SpeedButton1->Down = false;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift, int X,
          int Y)
{
 if( downup ) SpeedButton1->Down = false;
}


OnFormMouseActivate jest aktywowane w chwili aktywacji okna, czyli jeśli użytkownik kliknie poza oknem programu to okno się zdezaktywuje, a gdy je przywoła na pierwszy plan to się aktywuje i zmieni stan buttona.

Dodatkowo proponuję dodać obsługę zdarzenia OnFormMouseMove, które jest aktywowane gdy użytkownik przesuwa kursorem myszy w obszarze okna nie tylko gdy okno jest aktywne. Co ciekawe gdy przywołasz w obszarze okna PopupMenu to dopóki menu będzie wyświetlane okno nie będzie reagowało na zdarzenie OnFormMouseMove, więc nie spowoduje to zmiany stanu przycisku gdy PopuMenu jest aktywne. Przy takim rozwiązaniu można sobie darować zmienną downup oraz przechwytywanie komunikatów. Nie trzeba również w poleceniach PopupMenu zmieniać stanu przycisku. A żeby było jeszcze lepiej utwórz w komponencie ApplicationEvents obsługę zdarzenia OnDeactivate i masz to czego dokładnie potrzebujesz. Ważne jest też by PopupMenu było wywoływane tylko wtedy gdy użytkownik wciśnie przycisk do dołu (Down == true) w przeciwnym razie nastąpi desynchronizacja PopupMenu z przyciskiem jeżeli użytkownik kliknie w przycisk ponownie przy aktywnym menu. Teraz można pozbyć się zdarzenia OnFormMouseActivate bo jest już zbędne, gdyż przycisk wraca do pierwotnego stanu przy dezaktywacji okna, czyli po kliknięciu poza obszarem okna.
To jeszcze nie koniec. Wszak użytkownik może wybierać pozycje menu za pomocą strzałek klawiatury i akceptowań klawiszem ENTER lub anulować klawiszem Esc. Menu też się zamknie jeżeli zostanie naciśnięty któryś z przycisków Alt, więc je też trzeba obsłużyć. Trzeba więc jeszcze przechwycić komunikat o wciśnięciu tych klawiszy. Można to zrobić tak jak wcześniej w zdarzeniu OnMessage komponentu ApplicationEvents.

Kompletny kod:
KOD cpp:     UKRYJ  
/* ZDARZENI ONCLICK DLA SPEEDBUTTON1 */
void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
 int left = this->Left + SpeedButton1->Left + SpeedButton1->Width;
 int top = this->Top + SpeedButton1->Top;

 if( SpeedButton1->Down ) PopupMenu1->Popup(left, top);
}
//---------------------------------------------------------------------------

/* ZDARZENIE OnFormMouseMove */
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift, int X,
          int Y)
{
 if( SpeedButton1->Down ) SpeedButton1->Down = false;
}
//---------------------------------------------------------------------------

/* PRZECHYTYWANIE KOMUNIKATÓW */
void __fastcall TForm1::ApplicationEvents1Deactivate(TObject *Sender)
{
 if( SpeedButton1->Down ) SpeedButton1->Down = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ApplicationEvents1Message(tagMSG &Msg, bool &Handled)
{
  if( GetAsyncKeyState(VK_LMENU) || Msg.message == WM_KEYUP &&
         (Msg.wParam == VK_RETURN  || Msg.wParam == VK_ESCAPE
          || Msg.wParam == VK_MENU ) )
  {
        SpeedButton1->Down = false;
  }
}


U mnie działa dokładnie tak jak powinno.

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
Darek_C++
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


  • 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 16 gości

cron