Aberration Napisano Styczeń 7, 2019 Autor Zgłoś Udostępnij Napisano Styczeń 7, 2019 Bardzo się zdziwiłem, gdy zobaczyłem, że do obsługi myszuży w kontrolce FlatBtn używasz timera. Nie jestem pewien, ale ilość timerów jest chyba ograniczona(?), a co będzie jeśli będziesz chciał mieć kilka FlatButtonów (a zazwyczaj tak jest)?. Według mnie lepiej było by obsługiwać WM_NCHITTEST i SetCapture(), ReleaseCapture(). Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Omega Napisano Styczeń 8, 2019 Zgłoś Udostępnij Napisano Styczeń 8, 2019 komunikat WM_NCHITTEST jest wywolywany tylko w momencie kiedy myszka jest nad oknem. Nawet SetCapture() nic nie da jak dosc szybko przesuniesz myszke poza okno glowne. I tak w tym momencie do okna juz nie zostanie przeslany komunikat i nie odblokujesz aktywnego okna (releasecapture). Byc moze sie myle, ale jezeli ty znasz rozwiazanie to napisz krotki kod jak ty to widzisz. Zaintrygowala mnie twoja wiadomosc i chcialem sprawdzic czy to dziala. Okazuje sie, ze jak szybko usuniemy myszke poza okno glowne, jednoczesnie zjezdzajac z naszego flat buttona, do okna nie jest przesylany zaden komunikat - mimo setcapture(). I jak wtedy odblokowac aktywne okno? Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Freak Napisano Styczeń 8, 2019 Zgłoś Udostępnij Napisano Styczeń 8, 2019 No właśnie, jak ktoś zna lepsze rozwiązanie to niech napisze, bo tworzenie timera jest trochę lamerskie ;) Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Aspect Napisano Styczeń 8, 2019 Zgłoś Udostępnij Napisano Styczeń 8, 2019 Spoon napisał: ...bo tworzenie timera jest trochę lamerskie ;) Hehe, dzięki za uznanie ;). Jasne, że można to zrobić na kilka sposobów. Sam miałem pewne opory przed timerem, ale ten pomysł jako pierwszy rozwiązał wszystkie moje problemy z wejścem/wyjściem myszy z obszaru kontrolki, więc go zostawiłem. Alternatywne rozwiązanie praktycznie podał wyżej już sam Marcin. W komunikacje WM_NCHITTEST (można też użyć WM_MOUSEMOVE): 1. Przechwytujemy ruchy myszki ( używamy SetCapture(); ). 2. Sprawdzamy, czy mysz znajduje się w obszarze kontrolki (ze względu na to, że użyliśmy SetCapture(); nie możemy być tego pewni). 3. Jeżeli tak, to ustawiamy odpowiednią zmienną (wMouseOver w przkładzie do FlatBtn) na true 4. Jeżeli nie (mysz zeszła znad obszaru kontrolki), to ustawiamy tę zmienną na false i zwalniamy przechwytywanie myszy ( ReleaseCapture(); ) Nie wiem jak to będzie z przechwytywaniem tego komunikaty przy szybkich ruchach myszy, ale uważam, że nie powinno być z tym problemów (w wolnej chwili sprawdzę). Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Omega Napisano Styczeń 8, 2019 Zgłoś Udostępnij Napisano Styczeń 8, 2019 To teraz wyobraz sobie, ze flat button lezy na krawedzi okna glownego. Unosisz myszke nad kontrolke, zmenna przyjmuje wartosc true (w kom. np. WM_MOUSEMOVE). Teraz rusz z kontrolki myszke szybciutko poza okno glowne. Jak zmienisz zmienna na true, jak do niej nie sa juz przesylane zadne komunikaty - mimo SetCapture(). Trzeba to sprawdzic, bo kazda sytuacja musi byc obsluzona. Ha, mozna zalozyc hooka na mysze. Ale jezeli oprocz tego, ze kursor znajdzie sie poza oknem to np. zostanie klikniety jakies inne okno, z poza naszego procesu. Wtedy hook juz tez nie bedzie funkcjonowal. Chyba, ze zalozysz globalnego hooka w dll'u o wspolnej pamieci dzielonej. Ale dla flatta takie rzeczy robic? Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Flinch Napisano Styczeń 9, 2019 Zgłoś Udostępnij Napisano Styczeń 9, 2019 Kożystając z okazji chciałbym dodać, że wydaje mi się dobrym zwyczajem było by dodanie do stylu klasy kontrolki CS_GLOBALCLASS. Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Omega Napisano Styczeń 9, 2019 Zgłoś Udostępnij Napisano Styczeń 9, 2019 No i rozwiazal sie jeden problem. Kiedys byl takie pytanie w sprawie tworzenia wlasnych klas, ale takich, zeby mogly byc wykorzystywane przez wszystkie aplikacje, tak jak np. klasa EDIT. Salwadore odpowiedzial wlasnie na ten problem. Ale czy globalne klasy maja cos wspolnego z badanem ruchu kursora poza forma? Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Aspect Napisano Styczeń 9, 2019 Zgłoś Udostępnij Napisano Styczeń 9, 2019 Sprawdziłem w praktyce algorytm, który napisałem powyżej (użyłem komunikatu WM_MOUSEMOVE). Nie zauważyłem błędnego działania kontrolki przy szybkim zdejmowaniu myszy z przycisku. Problem pojawia się natomiast w momencie kliknięcia przycisku "Kontakt", kiedy to otwiera się okno domyślnego klienta poczty i zasłania przycisk. Po ponownym wyświetleniu okna programu testowego przycisk cały czas jest wypukły (do ponownego naciśnięcia go). Marcinie, rozwiń proszę swój pomysł i napisz jak, według Ciebie, należało by go zrealizować. Salwadore, dzięki za cenną uwagę. Dodam tylko, że w przypadku użycia tego stylu, po skończeniu używania kontrolki należy jej klasę "odrejestrować" funkcją UnregisterClass();. Ps. Marcin napisał: ...ilość timerów jest chyba ograniczona... Rozumiem, że jest to ograniczenie dla całego systemu? Czy ktoś w związku z tym orientuje się ile maksymalnie timerów system może obsłużyć? (Wrzuciłem do aplikacji 30 przycisków i wszystko działało jak należy - dla większej ilości nie sprawdzałem.) Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Omega Napisano Styczeń 9, 2019 Zgłoś Udostępnij Napisano Styczeń 9, 2019 Ilosc timerow jest ograniczona, jak i jest ograniczona ilosc nowych klas okien. Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Flinch Napisano Styczeń 10, 2019 Zgłoś Udostępnij Napisano Styczeń 10, 2019 Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Aspect Napisano Styczeń 12, 2019 Zgłoś Udostępnij Napisano Styczeń 12, 2019 Wkleiłem Twoją funkcję obsługi (żywcem) do kodu kontrolki i... 1. Salwadore napisał: DeleteObject ((HGDIOBJ) hfFlateButton); Wywołując tę funkcję dla hfFlateButton kasujesz obiekt czcionki, z którego korzysta cały dialog box i wszystkie jego kontrolki-dzieci (w związku z tym przy kolejnym odmalowaniu okna czcionka zmiania się na standardową - tę dużą, pogrubioną). Ogólnie uważam, że nie powinno się kasować obiektów, których się nie stworzyło. 2. Przycisk rzeczywiście wraca do stanu pierwotnego po zasłonięciu go klientem poczty, ale niestety dopiero po najechaniu myszą na okno-rodzica FlatButtona. //edit 3. Ustaw przycisk tak aby jego krawędź stykała się z krawędzią okna, albo tak aby trochę za nią wychodził. Najedź na przycisk i zjedź z niego zjeżdżając jednocześnie z okna-rodzica. Przycisk pozostaje wypukły. Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Flinch Napisano Styczeń 12, 2019 Zgłoś Udostępnij Napisano Styczeń 12, 2019 Dzięki za słuszne uwagi, błedy poprawię. 1. Z przyzwyczajenia kasuje wszystkie niepotrzebne obiekty. 2. Postaram się znaleść rozwiązanie inne niż timer. 3. Błąd powstaje wtedy, gdy sprawdza się pozycje kursora w jednym prostokącie zamiast dwóch (rectParent & rectClient). +---------------------------------+ | | | | | +-------+------+ | | | | rectParent | rectClient | | | | | +-------+------+ | | | | +---------------------------------+ Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Omega Napisano Styczeń 12, 2019 Zgłoś Udostępnij Napisano Styczeń 12, 2019 I wlasnie o to caly czas chodzi, o kontrolke bedaca na krawedzi okna glownego. Szybki ruch myszki powoduje, ze okno juz nie obsluzy komunikatu (prawdopodobnie zadnego - nie jestem do konca pewien) jak kursor bedzie poza forma glownego okna. Ja nie widzialem innego wyjscia jak zastosowac zegar. Chyba, ze tworzy sie kontrolki globalne, jak salwadore podpowiedzial. W dll'ach mozna utworzyc hooka "maksymalnie" globalnego (w dllu musi byc zmienna wspoldzielaca miedzy wszystkie procesy - salwadore juz zadal to pytanie w jednym poscie), ktory by sprawdzal polozenie myszki. Wtedy to juz by byl luks. Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Flinch Napisano Styczeń 13, 2019 Zgłoś Udostępnij Napisano Styczeń 13, 2019 Poprawiłem, jak napisałem, żrby sprawdzało czy kursor jest na przycisku i w oknie rodzica, to błedu nie wykazuje: case WM_MOUSEMOVE: lData = GetWindowLong (hWnd, GWL_USERDATA); GetCursorPos (& ptCursor); GetWindowRect (hWnd, & rectClient); if (GetCapture () != hWnd) SetCapture (hWnd); RECT rectParent; GetWindowRect (GetParent (hWnd), & rectParent); if (PtInRect (& rectParent, ptCursor) && PtInRect (& rectClient, ptCursor)) { if (HIWORD (lData) == false) { GetClientRect (hWnd, & rectClient); InvalidateRect (hWnd, & rectClient, true); } SetWindowLong (hWnd, GWL_USERDATA, MAKELONG (LOWORD (lData), true)); } else { SetWindowLong (hWnd, GWL_USERDATA, MAKELONG (LOWORD (lData), false)); if (GetCapture () == hWnd) //&& LOWORD (lData) == false) ReleaseCapture (); GetClientRect (hWnd, & rectClient); InvalidateRect (hWnd, & rectClient, true); } break; Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Aspect Napisano Styczeń 13, 2019 Zgłoś Udostępnij Napisano Styczeń 13, 2019 No dobra, to teraz (dla przycisku stykającego się z krawędzią) najedź na przycisk, naciśnij klawisz myszy, zjedź trzymając, puść klawisz i najedź spowrotem. ;) Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Omega Napisano Styczeń 13, 2019 Zgłoś Udostępnij Napisano Styczeń 13, 2019 Pamietaj, ze trzeba przewidziec wszystkie nieprzewidywalne rzeczy Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Flinch Napisano Styczeń 13, 2019 Zgłoś Udostępnij Napisano Styczeń 13, 2019 Rozumiem, że trzeba wszystko przewidzieć, ale po co programista miałby umieszczaś przycisk poza oknem rodzica??? Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Aspect Napisano Styczeń 14, 2019 Zgłoś Udostępnij Napisano Styczeń 14, 2019 Nie musi umieszczć poza. Wystarczy jak przycisk będzie się stykał z krawędzią okna, albo jak przycisk będzie trochę dalej ale akurat będzie dużo obliczeń i komunikaty będą wysyłane rzadziej. Z resztą tak samo dzieje się jak przysłonisz przycisk innym oknem. Poza tym wykonaj sobie jeszcze taki eksperyment: Zrób sobie przycisk który nic nie otwiera (powiedzmy niech zmienia tekst okna). Najedź na niego, naciśnij klawisz myszy i puść bez poruszania myszką. Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Aberration Napisano Styczeń 29, 2019 Autor Zgłoś Udostępnij Napisano Styczeń 29, 2019 Marcin came back!!! Po pierwsze to sorry, że tak długo nie odpisywałem, ale nie mam stałego łącza, a ostatnio nawet przez phone mi co trochę rozłączało. Ale mam dla cierpliwych rozwiązanie. Po drugie to moje pierwsze wersja (ta z SetCapture) była zła. Dział ona poza obszarem okna tylko wtedy, gdy jakiś przycisk mysz jest pressed. A po za tym WM_NCMOUSEMOVE nie ma nic to rzeczy/ A po trzecie: TRACKMOUSEEVENT tme; case WM_MOUSEMOVE: if(firsttime){ firsttime = false; GetClientRect(okno,&rect); tme.cbSize = sizeof(tme); tme.dwFlags = TME_LEAVE; tme.dwHoverTime = 0; tme.hwndTrack = okno; TrackMouseEvent(&tme); InvalidateRect(okno,0,0); } return 0; case WM_MOUSELEAVE: firsttime = false; InvalidateRect(okno,0,0); return 0; Zmienna firsttime oznacza, czy najście na mysz jest po raz pierwszy. (Od niej zależy też wygląd buttona). Ważne jest także nowe dodane przezemnie rzeczy:WM_MOUSELEAVE i TrackMouseEvent(). TrackMouseEvent() jest odpowiedzialna za sprawdzanie (przy podanych parametrach) czy myszka opuściła obszar kontrolki i jeśli tak to wysyła do niej WM_MOUSELEAVE. Parametrem jest wskaźnik do struktury TRACKMOUSEEVENT: typedef struct tagTRACKMOUSEEVENT { DWORD cbSize; DWORD dwFlags; HWND hwndTrack; DWORD dwHoverTime; } TRACKMOUSEEVENT, *LPTRACKMOUSEEVENT; cbSize - chyba wiadomo; dwFlags: #define TME_HOVER 0x00000001 - czuwanie czy mysz nie wchodzi na obszar okna #define TME_LEAVE 0x00000002 - czuwanie czy mysz nie opuściła #define TME_QUERY 0x40000000 - nie pamiętam #define TME_CANCEL 0x80000000 - anulowanie czuwania hwndTrack - okno dwHoverTime - czas czuwania jeśli TME_HOVER jest ustawiony I po czwarte: Już pewnie wpisujecie kod i do dzieła (tak też zrobiłem jak odnalazłem tą funkcję), a VC na to, że: undefinded symbol: TrackMouseEvent() I wogóle nie zna anie TME_LEAVE, anie WM_MOUSELEAVE czy struktury TRACKMOUSEEVENT Znajdują się one w jakimś nagłówku stansardowym, ale jakieś dafinicje nie pozwalają im się kompilować??? Dlatego podałem w poście wszystkie ważne definicje i stałe #ifndef WM_MOUSELEAVE #define WM_MOUSELEAVE 0x02A3 #endif , które musicie dołączyć. Build......... No i errorów mniej, bo undefinded przechodzi w unreferenced TrackMouseEvent: znalezioną przez siebie definicję funkcji WINUSERAPI BOOL WINAPI TrackMouseEvent( LPTRACKMOUSEEVENT lpEventTrack); musiałem poprzedzić extern "C" i wszystko gra. Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Freak Napisano Styczeń 30, 2019 Zgłoś Udostępnij Napisano Styczeń 30, 2019 Dobra robota Marcin, wiedziałem że da się bez timera :) Ale z tymi deklaracjami to trochę przekombinowałeś w Devie wystarczy windows.h i kompilator wszystko widzi, a w Visualu nie sprawdzałem. Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Omega Napisano Styczeń 30, 2019 Zgłoś Udostępnij Napisano Styczeń 30, 2019 No rzeczywiscie chyba tak mozna rozwiazac. Odrazu powiem, ze sposob nie zadziala w windows 95. Moze i leciwy system, ale i nie ma obslugi tej funkcji w api. p.s. a czy przypadkiem ten czas nie przeznaczyles na rozwiazanie problemow. Wydaje mi sie, ze jak pisales pierwsza podpowiedz w tym poscie to miales inna roznice post. Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.