Forum Coders' city Strona Główna Coders' city
Nasza pasja to programowanie!
 

 PomocPomoc   SzukajSzukaj   UżytkownicyUżytkownicy   GrupyGrupy  RejestracjaRejestracja 
Archiwum starego forum + teoria    RSS & Panel/SideBar
 ProfilProfil   Zaloguj się, by sprawdzić wiadomościZaloguj się, by sprawdzić wiadomości   ZalogujZaloguj 

Potrzebuję szybkiej odpowiedzi na moje pytanie... Zasady

[WinAPI/POSIX] Sprawdzenie stanu klawiatury



 
Odpowiedz do tematu    Forum Coders' city Strona Główna -> Biblioteki
Zobacz poprzedni temat :: Zobacz następny temat  
Autor Wiadomość
psrok1



Dołączył: 28 Cze 2011
Posty: 274
Skąd: Olsztyn

PostWysłany: Nie Kwi 06, 2014 11:12 am  OP    Temat postu: [WinAPI/POSIX] Sprawdzenie stanu klawiatury Odpowiedz z cytatem Pisownia

Mam do napisania projekt w C++ stanowiący symulację ruchu drogowego. Problem jest następujący: po uruchomieniu symulacji chciałbym mieć możliwość wstrzymania jej i przejścia do interfejsu umożliwiającego dodawanie pojazdów i inne akcje.
Potrzebowałbym do tego celu np.: sprawdzenia stanu klawisza. Chciałbym jednak, by kod był kompilowalny zarówno pod Windows, jak i Linux. Nie chciałbym też zaprzęgać ncurses/pdcurses do tak prostej rzeczy.
Na razie postanowiłem obsłużyć CTRL-C:
Kod:

#include "CtrlCHandler.h"
#ifdef __linux__
#include <csignal>
#include <unistd.h>
#elif _WIN32
#include <Windows.h>
#include <atomic>
#else
#error "OS not supported: turn off CTRL-C handling"
#endif

namespace CtrlCHandler
{
#ifdef __linux
    volatile sig_atomic_t stop = 0;
    void handler(int s);
#elif _WIN32
    std::atomic<int> stop = 0;
    BOOL __stdcall handler(DWORD dwCtrlType);
#endif
    void Set();
    void Release();
    bool GetState();
}

#ifdef __linux__

void CtrlCHandler::handler(int s)
{
    CtrlCHandler::stop = 1;
}

#elif _WIN32

BOOL __stdcall CtrlCHandler::handler(DWORD dwCtrlType)
{
    if (dwCtrlType == CTRL_C_EVENT)
    {
        CtrlCHandler::stop = 1;
        return TRUE;
    }
    else
        return FALSE;
}

#endif

void CtrlCHandler::Set()
{
    stop = 0;
#ifdef __linux__
    signal(SIGINT, CtrlCHandler::handler);
#elif _WIN32
    SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlCHandler::handler, TRUE);
#endif
};

void CtrlCHandler::Release()
{
#ifdef __linux__
    signal(SIGINT, SIG_DFL);
#elif _WIN32
    SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlCHandler::handler, FALSE);
#endif
}

bool CtrlCHandler::GetState()
{
    bool result = (stop == 1);
    if (result)
        stop = 0;
    return result;
}


Czy istnieje jakieś lepsze rozwiązanie? :)
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość Numer GG
marcin_an
Site Admin


Dołączył: 26 Maj 2005
Posty: 18767

PostWysłany: Pią Kwi 11, 2014 11:08 pm      Temat postu: Odpowiedz z cytatem Pisownia

Ctrl+C, który powinien służyć do zabijania procesów z terminala, obsłużyłeś w zupełnie innym celu. Ale już pomijając to: czym masz zamiar sterować później? SIGTERM będzie dodawał pojazd a SIGCHLD - usuwał go? I jak będziesz te sygnały wywoływał? Z terminala obok? Powiedziałbym, że to kiepski sposób na sterowanie. Mam wrażenie, że jednak wygodniej będzie sterować klawiaturą albo - jeśli koniecznie przez IPC - to przez bardziej nadające się do przesyłania danych. Jeśli klawiaturą, to curses. Po to właśnie takie biblioteki są, żeby ułatwić obsługę terminala. Ewentualnie akceptuj dane ze standardowego wejścia i traktuj je jako polecenia. Jest to najbardziej uniwersalne rozwiązanie, ale oczywiście wymaga opracowania protokołu, żeby sensownie radzić sobie z błędami w poleceniach.

Nie wiem, jak w tej chwili masz wymodelowaną aplikację, ale dla każdego z trzech popularnych scenariuszy:
  • Kontroler symulacji jest w oddzielnym wątku i tylko wysyła aktualizacje lub kopie modelu do widoku
    Umożliwi pauzowanie symulacji. Jeżeli po wykonaniu kroku symulacja zauważy, że dostała polecenie pauzy, zaprzestanie dalszego działania i umożliwi dostęp do modelu innym częściom programu. Gdy te zmodyfikują model, symulacja zostanie odpauzowana.
  • Kontroler symulacji jest w oddzielnym wątku i okresowo zatrzymuje się, udostępniając model widokowi
    Niech udostępnia nie tylko widokowi, ale każdemu chętnemu w celu modyfikacji.
  • Wszystko działa w jednym wątku, a konstroler symulacji okresowo wywołuje aktualizację widoku
    Niech wywołuje także kod modyfikujący model wg wydanych poleceń.
Ten "inny kod" to oczywiście panel sterujący lub coś, co odbiera od niego polecenia. Jeżeli będzie działał w oddzielnym wątku, to całkowicie synchronicznie może czekać na dane z wejścia lub wciśnięcia klawiszy, bo symulacji nie blokuje. Jeśli działa w tym samym wątku, co symulacja, czyli jest to ostatni z przedstawionych przypadków, to będzie musiał asynchronicznie sprawdzać, czy użytkownik coś nacisnął. Jeśli nie, to wraca do symulacji bez zmieniania czegokolwiek. Jeśli tak, to może sobie spokojnie zablokować symulację i resztę komunikacji z użytkownikiem wykonać synchronicznie.
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
Wyświetl posty z ostatnich:   
Odpowiedz do tematu    Forum Coders' city Strona Główna -> Biblioteki Wszystkie czasy w strefie CET (Europa)

Strona 1 z 1

 
Skocz do:  
Możesz pisać nowe tematy
Możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Możesz dodawać załączniki na tym forum
Możesz pobierać pliki z tego forum




Debug: strone wygenerowano w 0.03512 sekund, zapytan = 11
contact

| Darmowe programy i porady Jelcyna | Tansze zakupy w Helionie | MS Office Blog |