CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Chowanie TBalloonHint

Chowanie TBalloonHint

dział ogólny

Chowanie TBalloonHint

Nowy postprzez MisticFrezer » wtorek, 7 września 2010, 10:44

Witam

Mam dziwny problem z TBaloonHint.
Chcę chować baloniki wcześniej niż jest ustalone w HideAfter (po poruszeniu myszką), za pomocą HideHint();

Funkcja tworząca baloniki
Kod: Zaznacz cały
void ShowBalloonComponentTip(TBalloonHint * ptr, TComponent * owner, String szMsg, String szTitle, int timeout)
{
if(ptr)delete ptr;
ptr = new TBalloonHint(owner);

POINT pt;
GetCursorPos(&pt);
ptr->Title = szTitle;
ptr->Description = szMsg;
ptr->Style = bhsBalloon;
ptr->HideAfter = timeout;

ptr->ShowHint(pt);
}


Bezruch myszy wykrywa Timer:

Kod: Zaznacz cały

void __fastcall TForm1::HintTimerTimer(TObject *Sender)
{
POINT pt;
GetCursorPos(&pt);

if(LastCurPos.x == pt.x && LastCurPos.y == pt.y)
{

  if(CursorOnComponent->Name == ListBox1->Name)
  {
   ShowBalloonComponentTip(hint_msg, CursorOnComponent, "info","xxx",1000);
  }
  else if(CursorOnComponent->Name == OfflineL->Name )
  {
   ShowBalloonComponentTip(hint_msg, CursorOnComponent, "inne info","xxx",1000);
  }
}
else if(hint_msg)hint_msg->HideHint();

LastCurPos = pt;
ShowMessage((int)hint_msg);

}

hint_msg to wskaźnik na TBalloonHint, należący do Forma1.
CursorOnComponent to TComponent * , nad którym ma sie pojawic hint. To akurat nieważne, ponieważ baloniki pojawiają się.
Problem jest w tym, że nie chcą sie chować - nie reagują na HideHint();

Zauważyłem, ze wskaźnik hint_msg jest zawsze 0. Dlaczego, skoro tworzę go przez new?
Avatar użytkownika
MisticFrezer
Bladawiec
Bladawiec
 
Posty: 23
Dołączył(a): wtorek, 23 lutego 2010, 23:57
Lokalizacja: Wrocław
Podziękował : 1
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP3, Windows 7 Pro
Kompilator: BCB6, RAD Studio 2010, VS 2010
Gadu Gadu: 0
    Windows XPOpera

Re: Chowanie TBalloonHint

Nowy postprzez polymorphism » wtorek, 7 września 2010, 10:56

Dlatego, że ptr jest lokalną zmienną:
KOD cpp:     UKRYJ  
void ShowBalloonComponentTip(TBalloonHint * ptr, ...)
{
     ptr = new TBalloonHint(owner);
     ...

Zrób tę funkcję metodą TForm1, czy czego tam, i będzie git 8-) (oczywiście nie przekazuj w parametrach metody składowych klasy, ponieważ efekt będzie ten sam, no i sensu nie będzie)

____
p.s. oczywiście możesz przekazać wskaźnik przez referencję lub wskaźnik, ale jeśli jest to funkcja na użytek tylko jednej klasy, lepiej będzie jak zrobisz to tak, jak napisałem wyżej.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Chowanie TBalloonHint

Nowy postprzez MisticFrezer » wtorek, 7 września 2010, 11:12

No tak, zaćmienie, coś sobie ubzdurałem że jak przekażę wskaźnik, to będę fajny. Zrobiłem tak:
Kod: Zaznacz cały
TBalloonHint * ShowBalloonComponentTip(TComponent * owner, String szMsg, String szTitle, int timeout)
{
TBalloonHint * ptr;
ptr = new TBalloonHint(owner);

POINT pt;
GetCursorPos(&pt);
ptr->Title = szTitle;
ptr->Description = szMsg;
ptr->Style = bhsBalloon;
ptr->HideAfter = timeout;

ptr->ShowHint(pt);
return ptr;
}

i działa.
W każdym razie dziękuję. :)
Avatar użytkownika
MisticFrezer
Bladawiec
Bladawiec
 
Posty: 23
Dołączył(a): wtorek, 23 lutego 2010, 23:57
Lokalizacja: Wrocław
Podziękował : 1
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP3, Windows 7 Pro
Kompilator: BCB6, RAD Studio 2010, VS 2010
Gadu Gadu: 0
    Windows XPOpera

Re: Chowanie TBalloonHint

Nowy postprzez Cyfrowy Baron » wtorek, 7 września 2010, 11:37

Tworzysz obiekt wewnątrz funkcji:

KOD cpp:     UKRYJ  
TBalloonHint * ShowBalloonComponentTip(TComponent * owner, String szMsg, String szTitle, int timeout)
{
TBalloonHint * ptr = new TBalloonHint(owner);// tak też można


ale go nie usuwasz w tejże funkcji. Obiekt tworzony wewnątrz funkcji jest obiektem lokalnym, poza funkcją nie istnieje. Nie niszczysz obiektu, gdyż go zwracasz, niemniej jednak obiekt pozostaje.

Tak wogóle to jest to dla mnie niezrozumiałe. Tworzysz obiekt wewnątrz funkcji, definiujesz go. Balonik wyświetla komunikat, ale po co zwracasz ten obiekt.

Chyba czegoś tutaj nie rozumiem, gdyż kod wydaje się pozbawiony sensu, albo nierozważnie sam utrudniasz sobie zadanie.

Czy to kod jakiegoś komponentu, klasy czy co?
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: Chowanie TBalloonHint

Nowy postprzez Cyfrowy Baron » wtorek, 7 września 2010, 12:18

Gdy się temu bliżej przyjrzałem to wydaje mi się, że można to zrobić tak:

KOD cpp:     UKRYJ  
void ShowBalloonComponentTip(TBalloonHint * ptr, String szMsg, String szTitle, int timeout, POINT pt)
{
  ptr->Title = szTitle;
  ptr->Description = szMsg;
  ptr->Style = bhsBalloon;
  ptr->HideAfter = timeout;

  ptr->ShowHint(pt);
}
//-------------------------------------------------------------------------------------------
void __fastcall TForm1::HintTimerTimer(TObject *Sender)
{
  POINT pt;
  GetCursorPos(&pt);

  if(LastCurPos.x == pt.x && LastCurPos.y == pt.y)
  {
    if(CursorOnComponent->Name == ListBox1->Name)
    {
     ShowBalloonComponentTip(hint_msg,  "info", "xxx", 1000, pt);
    }
   else
     if(CursorOnComponent->Name == OfflineL->Name )
     {
       ShowBalloonComponentTip(hint_msg, "inne info","xxx",1000, pt);
     }
  }
  else
     if( hint_msg ) hint_msg->HideHint(); /* ten warunek jest niezrozumiału, co właściwie zwraca hint_msg skoro to obiekt, może powinno być: if( hint_msg->Visible) */

  LastCurPos = pt;
  ShowMessage((int)hint_msg); /* co ty właściwie tutaj wyświetlasz, skoro hint_msg to komponent ?! */
}
 




hint_msg to wskaźnik na TBalloonHint, należący do Forma1.


Co to właściwie znaczy, gdyż z Twojego kodu można wywnioskować, ze to komponent, na co wskazuje chociażby ten fragment kodu: hint_msg->HideHint();




Te dwa elementy:

KOD cpp:     UKRYJ  
if( hint_msg )
ShowMessage((int)hint_msg);


są niepoprawne.
Co do pierwszego ( if( hint_msg ) hint_msg->HideHint(); ) jeżeli hint_msg jest true to ukryj hint_msg. Nie widzę w tym sensu.
Drugi element ( ShowMessage((int)hint_msg); ) wyświetl komunikat o treści hint_msg skonwertowane do wartości typu integer. Po pierwsze funkcja ShowMessage oczekuje jako argumentu wartości typu String a nie int, więc nie można obiektu (jak sądzę) hint_msg konwertować na int, a jeżeli hint_msg jest komponentem, to konwertowanie obiektu na wartość liczbową jest pozbawione sensu.



TComponent *owner jest zbędne, gdyż i tak wyświetlasz komponent w pozycji określonej przez strukturę POINT a nie na konkretnym komponencie, tak że mimo iż przypisujesz balonikowi rodzica to i tak nie ma to znaczenia, gdyż wyświetlany jest w pozycji pt.
:shock: :o :twisted: :lol:
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: Chowanie TBalloonHint

Nowy postprzez Cyfrowy Baron » wtorek, 7 września 2010, 13:21

Tak mi ten Twój kod nie pasuje, że opracowałem własny. Przy czym zakładam, że hint_msg to komponent typu TBalloonHint należący do Form1.

plik nagłówkowy np. Unit1.h
KOD cpp:     UKRYJ  
#include <map>
/* reszta, której nie wymieniam */
private:    // User declarations
         std::map<String, int> myComp;


plik źródłowy np. Unit1.cpp
KOD cpp:     UKRYJ  
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
 myComp["ListBox1"] = 1;
 myComp["OfflineL"] = 2;
}
//---------------------------------------------------------------------------
void ShowBalloonComponentTip(TBalloonHint * ptr, String szMsg, String szTitle,
        int timeout, POINT pt)
{
  ptr->Title = szTitle;
  ptr->Description = szMsg;
  ptr->Style = bhsBalloon;
  ptr->HideAfter = timeout;

  ptr->ShowHint(pt);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
 POINT pt;
 GetCursorPos(&pt);

 TControl *comp = FindVCLWindow(pt); /* ta funkcja sprawdza na który komponent wskazuje kursor myszy */

 if(comp == NULL)
 {
  hint_msg->HideHint();
  return;
 }
 else
 {
  if(hint_msg->ShowingHint) return; /* blokuje wyświetlanie komunikatu, gdyż jest już wyświetlony, zapobiega to migotaniu */
  switch(myComp[comp->Name]) /* sprawdzanie w oparciu o mapę asocjacyjną, który komponent jest wybrany, to lepsze niż tworzenie listy warunków */
  {
   case 0: hint_msg->HideHint(); break;
   case 1: ShowBalloonComponentTip(hint_msg,  "info", "xxx", 1000, pt); break; // zgodnie z mapą - ListBox1
   case 2: ShowBalloonComponentTip(hint_msg,  "inne info", "xxx", 1000, pt); break; // zgodnie z mapą - OfflineL
   default: hint_msg->HideHint();
  }
 }
}




Można to udoskonalić tworząc mapę komunikatów:

plik nagłówkowy np. Unit1.h
KOD cpp:     UKRYJ  
#include <map>
/* reszta, której nie wymieniam */
private:    // User declarations
         std::map<String, String> myComp;


plik źródłowy np. Unit1.cpp
KOD cpp:     UKRYJ  
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
 myComp["ListBox1"] = "komunikat 1";
 myComp["OfflineL"]  = "komunikat 2";
}
//---------------------------------------------------------------------------
void ShowBalloonComponentTip(TBalloonHint * ptr, String szMsg, String szTitle,
        int timeout, POINT pt)
{
  ptr->Title = szTitle;
  ptr->Description = szMsg;
  ptr->Style = bhsBalloon;
  ptr->HideAfter = timeout;

  ptr->ShowHint(pt);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
 POINT pt;
 GetCursorPos(&pt);

 TControl *comp = FindVCLWindow(pt);

 if(comp == NULL)
 {
  hint_msg->HideHint();
  return;
 }
 else
 {
  if(hint_msg->ShowingHint) return;

  if(myComp[comp->Name].IsEmpty()) hint_msg->HideHint();
  else
    ShowBalloonComponentTip(hint_msg,  myComp[comp->Name], "xxx", 1000, pt);
 }
}


Jak widać funkcja ShowBalloonComponentTip występuje tylko raz w zdarzeniu OnTimer, ale za każdym wywołaniem otrzymuje inny komunikat z mapy uzależniony od tego na jaki komponent wskazuje kursor.
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: Chowanie TBalloonHint

Nowy postprzez polymorphism » wtorek, 7 września 2010, 15:42

Cyfrowy Baron napisał(a):
KOD cpp:     UKRYJ  
 if( hint_msg ) hint_msg->HideHint(); /* ten warunek jest niezrozumiału, co właściwie zwraca hint_msg skoro to obiekt, może powinno być: if( hint_msg->Visible) */

Nie, hint_msg jest wskaźnikiem na obiekt klasy TBalloonHint, zatem warunek jest jak najbardziej poprawny.

Cyfrowy Baron napisał(a):
KOD cpp:     UKRYJ  
ShowMessage((int)hint_msg); /* co ty właściwie tutaj wyświetlasz, skoro hint_msg to komponent ?! */

j/w. Chce wyświetlić wartość wskaźnika, stąd rzutowanie na int, ponieważ ten typ może być niejawnie przekonwertowany na AnsiString.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Chowanie TBalloonHint

Nowy postprzez Cyfrowy Baron » wtorek, 7 września 2010, 16:11

A czy nie prościej jest tak jak to pokazałem?! Nie bardzo rozumiem po co ten wskaźnik na obiekt?

W tym moim kodzie zmieniłbym jeszcze zdarzenie OnTimer na zdarzenie OnIdle wykorzystujące bezczynność aplikacji. Dzięki temu komunikat nie przeszkadzałby i pojawiałby się tylko w sytuacji, gdy użytkownik nic nie robi w programie.
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: Chowanie TBalloonHint

Nowy postprzez MisticFrezer » wtorek, 7 września 2010, 16:30

ShowMessage z adresem służyło w celach diagnostycznych. Dałem w Timer, poniewaz chcę, aby baloniki pojawiały sie po 3 sekundach.
Jednakże pomysł z FindVCLWindow(pt); jest bardzo dobry, wykorzystam go czym prędzej.

Cyfrowy Baron napisał(a):
hint_msg to wskaźnik na TBalloonHint, należący do Forma1.


Co to właściwie znaczy, gdyż z Twojego kodu można wywnioskować, ze to komponent, na co wskazuje chociażby ten fragment kodu: hint_msg->HideHint();

Nie rozumiem. Coś źle? To zwyczajny wskaźnik TBalloonHint * hint_msg; będący składnikiem klasy TForm1, ale umieszczony tam przeze mnie, a nie przez Designera. Tworzony / inicjalizowany jest dopiero w kodzie.

Cyfrowy Baron napisał(a):TComponent *owner jest zbędne, gdyż i tak wyświetlasz komponent w pozycji określonej przez strukturę POINT a nie na konkretnym komponencie, tak że mimo iż przypisujesz balonikowi rodzica to i tak nie ma to znaczenia, gdyż wyświetlany jest w pozycji pt.

Dobra uwaga.
Avatar użytkownika
MisticFrezer
Bladawiec
Bladawiec
 
Posty: 23
Dołączył(a): wtorek, 23 lutego 2010, 23:57
Lokalizacja: Wrocław
Podziękował : 1
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP3, Windows 7 Pro
Kompilator: BCB6, RAD Studio 2010, VS 2010
Gadu Gadu: 0
    Windows XPOpera

Re: Chowanie TBalloonHint

Nowy postprzez Cyfrowy Baron » wtorek, 7 września 2010, 16:31

Nie rozumiem. Coś źle? To zwyczajny wskaźnik TBalloonHint * hint_msg; będący składnikiem klasy TForm1, ale umieszczony tam przeze mnie, a nie przez Designera. Tworzony / inicjalizowany jest dopiero w kodzie.


Do czego jest Tobie ten wskaźnik właściwie potrzebny. Gdy przeanalizujesz mój kod zobaczysz, że wskaźnik bardziej przeszkadza niż pomaga.
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 4 gości