MFC, opóźnienie animacji

0

Witam wszystkich.

Najpierw kilka podstawowych danych:
*język programu C++
*środowisko Visual Studio 2008
*aplikacja MFC, DialogBased

A teraz sprecyzowanie problemu:
Chcę (muszę) napisać program symulacyjny, którego jednym z elementów ma być wizualizacja obsługi procesów. W tym celu użyłem progress bar'ów, zupełnie to zresztą nieistotne. Chodzi mi o spowolnienie samej wizualizacji. Pierwszą moją myślą było użycie funkcji sleeep, jednak nie spełnia ona pokładanych w niej nadziei - słupki bowiem faktycznie elegancko wolniej opadają, jednak po zapuszczeniu symulacji okno programu przestaje reagować na cokolwiek, nie mogę go przesuwać, wciskać żadnych przycisków, jednym słowem brak jakiejkolwiek interakcji. Całość wraca do siebie, gdy obsługa procesów (wizualizacja) się zakończy, czyli razem z końcem wywołań funkcji sleep.
To co chciałbym osiągnąć chyba już jest jasne - aktywne i interaktywne okienko programu przy spowolnieniu działania algorytmu wizualizacji.

Bardzo, bardzo byłbym wdzięczny za wszelkie wskazówki i pomysły.
Pozdrawiam

0

zachowanie Twojego programu powinno Cie w pierwszej chwili nauczyc, ze nie powinno sie wykonywac dlugotrwalych operacji w eventhandlerach okna ani kontrolek (onclickach, onpaintach..).

jesli chcesz zachowywac responsywnosc GUI, wszystkie operacje czasozerne musisz miec albo rozbite na krotkie etapy pomiedzy ktorymi sterowanie wroci do petli komunikatow, albo w trakcie czasozernego przetwarzania tęże petle musisz recznie 'wywolac' co pewien czas, albo -- cale ciezkie przetwarzanie musi byc w osobnym watku, sterowanym 'sygnalami' przesylanymi -jakos- nieblokujaco z okna

0

Zacząłem szukać głębiej i temat wątków powraca do mnie nieuchronnie. Próbowałem coś takiego stworzyć, ale wewnątrz mojej funkcji wątku niewidoczne są obiekty i funkcję zadeklarowane gdzie indziej. Ba, obawiam się, że ma to właśnie związek z samą ideą wątku, ale może zupełnie źle kombinuję, bo to moje pierwsze zetknięcie się z wątkami właśnie.
Jeśli moje pytania są naiwne, proszę wybaczcie. Moja sytuacja wygląda następująco - mam na główne okno programu wrzucone te nieszczęsne paski postępu (progress bar), czy istnieje możliwość obsługi stanu tych obiektów wewnątrz nowego wątku? Czy musiałbym tworzyć te obiekty dynamicznie, w momencie wywołania wątku?

Bardzo pomocny byłby też jakiś przykład kodu, jak to wszystko się realizuje, bo w sieci znalazłem milion strzępów, każdy niepodobny do innego.

0

teoretycznie wystarczyloby zebys przekazal jakos (zmienna, parametry watku, etc) zestaw wskaznikow na owe progressbary i juz moglbys sobie z watku na nich operowac.

jednak, dotykanie kontrolek GUI z watku innego niz ten ktory je stworzyl jest dosc niebezpieczne. w momencie gdy watek-nr-2 uruchomilby jakas metode, to moglby trafic na pechowy moment ze akurat watek-nr-1 robilby z tym samym obiektem cos, np. probowal zmienic te same zmienne itp. rezultat latwo(tzn.ciezko) sobie wyobrazic.. trzeba wiec zadbac zeby jakos te watki sie ladnie 'ukladaly' w momencie gdy probuja dotykac rzeczy 'wspolnych'

tutaj, najprosciej zrobic to komunikatami.
np: masz sytuacje ze watek w losowych (z punktu widzenia GUI) momentach chce 'popchnac' pasek postepu do przodu.

  • stworz nowy ID wiadomosci, np. WM_PROGRESSBAR_KICK = (WM_APP+....pierwszywolny...);
  • w watku, kiedykolwiek chcesz popchnac progressbar, wyslij (send/postmessage) do okna glownego (watek musi znac jego hwnd) komunikat o id = WM_PROGRESSBAR_KICK, oraz wparam/lparam jakos (patrz nizej) informujacych o tym ktory progressbar i o ile popchnac
  • w oknie dodaj obsluge komunikatu WM_PROGRESSBAR_KICK (albo wyklikaj w designerze, albo sam wpisz z palca mapowania komunikatow na metode klasy)
  • w tej metodzie: odbierz w/lparam, przetlumacz je sobie znanym (patrz wyzej:) )sposobem na info ktory progressbar i o ile, a nastepnie dokladnie ten i o tyle przesun

no i tyle.. watek bedzie wysylal 'zadania' do wykonania przez okno (->update'y progressbaru) a okno w sobie pasujacych momentach, bezpiecznych, bedzie je odbierac i wykonywac

0
Jemiol napisał(a)

Zacząłem szukać głębiej i temat wątków powraca do mnie nieuchronnie. Próbowałem coś takiego stworzyć, ale wewnątrz mojej funkcji wątku niewidoczne są obiekty i funkcję zadeklarowane gdzie indziej. Ba, obawiam się, że ma to właśnie związek z samą ideą wątku, ale może zupełnie źle kombinuję, bo to moje pierwsze zetknięcie się z wątkami właśnie.
Jeśli moje pytania są naiwne, proszę wybaczcie. Moja sytuacja wygląda następująco - mam na główne okno programu wrzucone te nieszczęsne paski postępu (progress bar), czy istnieje możliwość obsługi stanu tych obiektów wewnątrz nowego wątku? Czy musiałbym tworzyć te obiekty dynamicznie, w momencie wywołania wątku?

Bardzo pomocny byłby też jakiś przykład kodu, jak to wszystko się realizuje, bo w sieci znalazłem milion strzępów, każdy niepodobny do innego.

Coś w stylu static_cast<CProgresBar*>(theApp.dialog.GetDlgItem(IDC_PROGRESS_BAR1))->SetStep(costam) (pisze z pamięci..)
Zresztą - o ile chodzi tylko o spowolnienie wyświetlania - pobieraj czas systemowy i porównuj z poprzednim, jeśli < wymagane nie rob nic.
A najlepiej zrób event wyrzucany co x ms który wywoułuje tą metodę.

0

staticcast(...) - co nie zmieni faktu, ze bedzie to proba operowania na obiekcie MFC utworzonym i nalezacym do innego watku, w wyniku czego mamy calkiem niezla szanse ze kiedys-tam po paru zmianach w programie nagle przestanie to dzialac albo w ogole zacznie sypac 0xc00005tkami

spowolnienie - erm.. albo ja albo Ty czegos nie doczytalismy..

event - nie interesuje nas timer, bo progressbar ma byc sterowany postepem prac. jak masz na mysli event=komunikat, to patrz moj post wyzej. aaa.. chyba ze chodzi Ci o .Net event i delegaty? to oops, to C++/MFC a nie C++/CLI

0

Po pierwsze - dzięki za odpowiedzi ;-)

Co do mojego problemu. Mogłaby to być jak najbardziej jakaś wariacja na temat timera, jak najbardziej. Chodzi tu o przedstawienie raczej kolejności i sposobu obsługi tych procesów, nie o ich faktyczny stan, trochę taki przebieg na sucho. Jeśli wcześniej się nie wyraziłem jasno, to pozostaje mi przeprosić. Gdy pobieram czas systemowy i każe mu nie robić nic do interesującego mnie momentu, efekt jest identyczny jak przy funkcji sleep (rozumiem, że działa to w pętli, chyba że znów popełniam jakiś błąd w sztuce). Co wydaje mi się efektem spodziewanym, bo albo program jest zajęty obsługą mojej wizualizacji albo przebiegami pustej pętli.
Bardzo chętnie wywoływałbym całość co ileś sekund, w tym cały problem, że nie wiem jak, i tu zwracam się do bardziej doświadczonych ;-)

0

w takim razie widac ja nie doczytalem.. tutaj timer jak raz.

  • na starcie odliczania - SetTimer - spowoduje uruchomienie timera ktory co n milisekund bedize wysylal wm_timer do okna
  • w designerze okna, podczep sie pod message WM_TIMER/OnTimer - ta metoda sie wywola za kazdym ticknieciem timera i w niej mozesz smialo uzyc CBar->Step
  • po dojsciu do 100% - KillTimer
0

BOSKO!
Działa ślicznie ;-) Wielkie, wielkie dzięki, naprawdę wielkie ;-)

0

Przepraszam, że tak w wielu postach po sobie, ale nie zarejestrowałem się i nie mogę edytować własnych wiadomości...

Ostatni chyba już problem przede mną. Może nie jest to najlepsze miejsce, ale przynajmniej wszystkie podstawowe dane są podane. Szukam i rozglądam się, ale nie widzę a choć raz trzeba to przejść - jak zmusić Visuala do stworzenia instalatora lub wyodrębnienia paczki plików potrzebnych do uruchomienia mojego programu na innym komputerze? Przeniesienie samego .exe nic nie daje, bo inny komputer wypluwa "nie można uruchomić aplikacji ponieważ jej konfiguracja jest niewłaściwa. Problem ten może rozwiązać ponowne zainstalowanie aplikacji."

Słowo daje, ostatnia prosta przede mną ;-)

0

zapoznaj sie z http://4programmers.net/Forum/viewtopic.php?id=121562 tam przyczyna i rozwiazania tego bledu sa dosc rozpisane.
w skrocie:

  • instalator Ci nie potrzebny
  • musisz kompilowac w trybie Release
  • musisz sie upewnic ze na docelowym kompie sa zainstalowane redisty odpowiadajace Twojemu visualowi
0

Wybacz za opóźnienie, ale przynajmniej teraz podziękuję ;-) Kłaniam się nisko, temat myślę do zamknięcia ;-)

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