|
Pochodzi od: żaden
Dodane klasy: BArchivable
Zadeklarowany w: be/app/Handler.h
Biblioteka: libbe.so
Podsumowanie: więcej...
Obiekt BHandler reaguje na komunikaty, które są przekazywane do niego przez obiekt BLooper. BLooper mówi BHandler'owi o komunikacie przez wywołanie funkcji MessageReceived() obiektu BHandler.
Aby mieć prawo odbierania komunikatów z BLooper'a, obiekt BHandler musi być na liście uprawnionych handlerów BLooper'a (jak wyjaśniono w klasie BLooper). Ta lista uprawnionych handler'ów jest uporządkowana; jeśli "pierwszy" handler nie chce odpowiadać na komunikat który miał odebrać, jest po prostu wywoływana odziedziczona wersja MessageReceived() i komunikat będzie automatycznie przekazany do handlera "następnego" obiektu. (Komunikaty systemowe nie są przekazywane w dół listy.) BLooper do którego należą te wszystkie BHandler'y jest zawsze ostatnim handler'em w liście (BLooper pochodzi od BHandler).Przydzielenie następnego handler'a obiektu BHandler może być zmienione poprzez funkcję SetNextHandler().
Możesz wyznaczać adresata BHandler'a dla większości komunikatów. Wyznaczenie jest dokonywane wówczas gdy wywołujesz funkcję PostMessage() obiektu BLooper lub gdy konstruujesz obiekt BMessenger, który będzie wysyłał komunikat. Komunikaty które użytkownik przeciąga i upuszcza są kierowane do obiektu (BView) który steruje tą częścią okna gdzie komunikat był upuszczony. Mechanizm komunikacji przesyła ostatecznie adresata BHandler'a do funkcji DispatchMessage(), więc te komunikaty mogą być dostarczone do ich miejsc przeznaczenia.
Komunikaty mogą być filtrowane przed ich dostarczeniem - to znaczy, że możesz określić funkcję, która będzie widoczna w komunikacie przed wywołaniem funkcji przechwytującej adresata BHandler'a. Funkcja filtra jest skojarzona z obiektem BMessageFilter, który zapisuje kryteria dla wywoływanej funkcji.Filtry które powinny być zastosowane tylko do komunikatów kierowanych do poszczególnych BHandler'ów są przypisane do BHandler'a przez SetFilterList() lub AddFilter(). Filtry które mogą być zastosowane do komunikatu, który wysyła BLooper, bez względu na ich adresata, są przypisane przez równoległe funkcje BLooper'a SetCommonFilterList() i AddCommonFilter(). Zerknij na te funkcje i klasę BMessageFilter aby dowiedzieć się więcej o szczegółach.
BHandler może być powiadamiaczem. Powiadamiacz jest handler'em, który zarządza jednym lub większą ilością stanów i powiadomień zainteresowanych części gdy stany te się zmieniają. Każdy stan jest identyfikowany przez 32-bitowy kod "co". Zainteresowane części nazywane obserwatorami mogą rejestrować zmiany monitora w jednym lub więcej stanach przez wywołanie funkcji StartWatching() i określenie kodu "co" stanu, który chce być powiadomiony o zmianach.To powiadomienie występuje gdy BHandler wywołuje SendNotices(); wywołanie SendNotices() jest pracą handler'a gdy tylko stan ulegnie zmianie, dla zapewnienia, że obserwatorzy przechowują informację o zmianach. BHandler przekazuje do SendNotices() szablon komunikatu aby został on wysłany do obserwatorów.
Kiedy powiadowmienie jest wysyłane, obserwatorzy odbierają komunikat B_OBSERVER_NOTICE_CHANGE z polem typu int32 B_OBSERVE_WHICH_CHANGE zawierające kod "co" stanu, który się zmienił i pole B_OBSERVE_ORIGINAL_WHAT, zawierające wartość "co", która była w szablonie BMessage.
MessageReceived()
![]() | BHandler() |
BHandler(const char *name = NULL)
BHandler(BMessage *archive)Inicjalizuje obiekt BHandler przez przypisanie mu name i zarejestrowanie go w systemie komunikatów. BHandlers może również być rekonstruowany z archiwum BMessage.
![]() | ~BHandler() |
virtual ~BHandler() Niszczy przypisane do BHandler'a obiekty BMessageFilter.
![]() | Instantiate() patrz BArchivable::Instantiate() |
![]() | AddFilter() patrz SetFilterList() |
![]() | Archive(), |
![]() | FilterList() patrz SetFilterList() |
![]() | GetSupportedSuites() |
virtual status_t GetSupportedSuites(BMessage *message) Zaimplementowane przez klasy pochodne do raportowania zestawów komunikatów i specyfikatorów ich rozumiejących. Ta funkcja jest wywoływana w odpowiedzi na jeden z komunikatów skryptowych B_GET_PROPERTIES dla właściwości "Zestawy" lub komunikat B_GET_SUPPORTED_SUITES.
Każda pochodna klasa powinna dodać do tablicy "zestawy" zmiennych message nazwy zestawów które implementuje. Każdy element w tablicy jest łańcuchem MIME z supertypem "zestaw". W dodatku klasy powinny dodać odpowiednie spłaszczone/wyrównane obiekty BPropertyInfo w tablicy "komunikaty". Typowa implementacja GetSupportedSuites() wygląda następująco:
status_t MyHandler::GetSupportedSuites(BMessage *message)
{
message->AddString("suites", "suite/vnd.Me-my_handler"));
BPropertyInfo prop_info(prop_list);
message->AddFlat("messages", &prop_info);
return BHandler::GetSupportedSuites(message);
}Wartość zwracana przez GetSupportedSuites() jest dodana do message w polu "error" typu int32.
Wersja tej funkcji w obiekcie BHandler dodaje uniwersalny zestaw "suite/vnd.Be-handler" do message wówczas gdy zwraca wartość B_OK.
![]() | LockLooper(), LockLooperWithTimeout(), UnlockLooper() |
bool LockLooper(void) status_t LockLooperWithTimeout(bigtime_t timeout) void UnlockLooper(void) Są to "sprytne" wersje funkcji blokujących BLooper'a (BLooper::Lock() i inne). Różnica między tymi wersjami jest taka, że te funkcje uzyskują dany looper handler'a i blokują go (albo odblokowują go) w operacji pseudoatomowej (tzn. niepodzielnej - przyp. tłum.), unikając w ten sposób możliwość wyścigu (hazardu). Jeśli kiedykolwiek będziesz skuszony, by napisać tekst lub kod programu taki jak ten:
/* NIE RÓB TEGO*/
if (myHandler->Looper()->Lock()) {
...
myHandler->Looper()->Unlock();
}Nie rób tego. Natomiast zrób to:
/* ZAMIAST TEGO ZRÓB TAK*/
if (myHandler->LockLooper()) {
...
myHandler->UnlockLooper();
}Za wyjątkiem dodatkowej zwracanej wartości w LockLooperWithTimeout(), te funkcje są identyczne jak ich odpowiedniki w BLooper'ze. Aby zobaczyć szczegóły popatrz do BLooper::Lock().
ZWARACANE KODY
LockLooper() zwraca true jeśli była zdolna zablokować looper lub jeśli jest on już zablokowany przez wątek wywołujący i false w wypadku przeciwnym. Jeśli handler zmienił loopery podczas wywołania zwracane jest false.
LockLooperWithTimeout() zwraca:
- B_OK. Looper został zablokowany z sukcesem.
- B_TIMED_OUT. Wywołanie przerwane bez blokowania looper'a.
- B_BAD_VALUE. Ten looper handler'a jest nieprawidłwy.
- B_MISMATCHED_VALUES. Handler przełączył loopery podczas wywołania.
![]() | LockLooperWithTimeout() patrz LockLooper() |
![]() | Looper() |
BLooper *Looper(void) const Zwraca obiekt BLooper'a, do którego został dodany BHandler. Funkcja zwraca NULL jeśli obiekt nie został dodany do BLooper'a. BHandler może być skojarzony tylko z jednym BLooper'em na raz.
Zauważ, że obiekt BLooper jest automatycznie dodaje się (jako handler) do siebie (jako looper), a BWindow automatycznie dodaje jego widoki potomne. Aby jawnie dodać handler do looper'a, wywołaj BLooper::AddHandler().
![]() | MessageReceived() |
virtual void MessageReceived(BMessage *message) Zaimplementowane przez klasy pochodne do odpowiadania na komunikaty, które są odbierane przez BHandler. Domyślna implementacja (BHandler) tej funkcji odpowiada tylko na ządania skryptowane. Przekazuje ona wszystkie inne komunikaty do następnego handler'a przez wywołując wersję funkcji MessageReceived() tego obiektu.
Typowa implementacja MessageReceived() rozróżnia komunikaty przez przeglądanie ich stałych polecenia (tj. pola what). Dla przykładu:
void MyHandler::MessageReceived(BMessage *message)
{
switch ( message->what ) {
case COMMAND_ONE:
HandleCommandOne()
break;
case COMMAND_TWO:
HandleCommandTwo()
break;
...
default:
baseClass::MessageReceived(message);
break;
...
}
}Jest konieczne, że wszystkie nieobsłużone komunikaty są przekazywane do implementacji funkcji MessageReceived() klasy bazowej jak pokazano tutaj. Od tego zależy model ciągu handler'a.
Jeśli komunikat dochodzi do końca linii - jeśli niejest rozpoznany a dalej nie ma żadnego handler'a - funkcja tej wersji BHandler'a wysyła odpowiedź B_MESSAGE_NOT_UNDERSTOOD aby zawiadomić źródło komunikatu.
![]()
Nie usuwaj argumentu komunikatu gdy wykonałeś na nim działanie. On nie należy do Ciebie.
![]() | Name() patrz SetName() |
![]() | NextHandler() see SetNextHandler() |
![]() | ResolveSpecifier() |
virtual BHandler *ResolveSpecifier(BMessage *message,
int32 index,
BMessage *specifier,
int32 what,
const char *property)Zaimplementowany przez klasy pochodne do okreśania właściwego handler'a dla komunikatów skryptowych. Komunikat jest kierowany do BHandler'a, ale specyfikatory mogą wskazywać, że powinien on być skojarzony z innym obiektem. Sprawdzanie bieżącego specyfikatora (lub więcej, jeśli to konieczne) jest zadaniem funkcji ResolveSpecifier() i zwracaona obiekt, która powinna też obsługiwać komunikat lub przeglądać następny specyfikator. Ta funkcja jest wywoływana przed wysłaniem komunikatu i przed wywółaniem funkcji filtrujących.
Pierwszy argument, message, wskazuje do rozważenia na komunikat skryptowy. Bieżący specyfikator jest przekazywany w specifier; będzie on pod indeksem index w tablicy specyfikatorów komunikatu. W końcu, what zawiera dane członkowskie what specyfikatora podczas gdy property zawiera nazwę właściwości docelowej.
ResolveSpecifier() zwraca wskaźnik do nastęnego BHandler'a, który powinien przeglądać komunikat. Do zidentyfikowania BHandler'a, próbuje on kolejno takich metod:
Metoda 1: Jeśli specyfikator specifier zidentyfikuje BHandler'a należącego do innego BLooper'a, powinien on wysłać komunikat do BLooper'a i zwrócić NULL. Komunikat będzie obsłużony w pętli komunikatu innego BLooper; nie będzie on dodatkowo przetwarzany w tym looper'ze. Dla przykłądu, BHandler który przechowuje listę pośredników moż użyć kodu takiego jak poniżej:
if ( (strcmp(property, "Proxy") == 0)
&& (what == B_INDEX_SPECIFIER) ) {
int32 i;
if ( specifier->FindInt32("index", &i) == B_OK ) {
MyProxy *proxy = (MyProxy *)proxyList->ItemAt(i);
if ( proxy ) {
message->PopSpecifier();
if ( proxy->Looper() != Looper() ) {
proxy->Looper()->PostMessage(message, proxy);
return NULL;
}
}
. . .
}
. . .
}W chwili gdy ta funkcja znalajdzie specyfikator o indeksie index, wywołuje ona PopSpecifier() aby zmniejszyć indeks przed przesłaniem komunikatu. W przeciwnym wypadku nastęny handler powinien próbować znaleźć ten sam specyfikator.
Metoda 2: Jeśli specyfikator wybierze kolejny obiekt BHandler należący do tego samego BLooper'a, funkcja ResolveSpecifier() może zwrócić ten BHandler. Dla przykładu:
if ( proxy ) {
message->PopSpecifier();
if ( proxy->Looper() != Looper() ) {
proxy->Looper()->PostMessage(message, proxy);
return NULL;
}
else {
return proxy;
}
}W rezultacie daje to zwrócony obiekt w miejsce BHandler'a jako wyszczególniony handler dla komunikatu. BLooper będzie dawał zwróconemu handler'owi szansę odpowiedzi na komunikat lub szukanie następnego specyfikatora.
Ponownie powinna zostać wywołana funkcja PopSpecifier(), żeby nie było próby wykonywania dwukrotnego poszukiwania tego samego specyfikatora .
Metoda 3: Jeśli może to rozwiązać wszystkie pozostawione specyfikatory i rozpoznać komunikat jako taki, który BHandler może obsłużyć sobie sam, to powinna ona zwrócić BHandler (this). Dla przykładu:
if ( (strcmp(property, "Value") == 0) && (message->what == B_GET_PROPERTY) )
return this;Potwierdza to BHandler'a jako adresata komunikatu. ResolveSpecifier() nie powinna być wywoływana ponownie, więc nie jest konieczne aby wywoływać PopSpecifier() przed powrotem.
Metoda 4: Jeśli nie rozpoznaje on właściwości lub nie moż znaleźć specyfikatora powinien on wywołać (i zwrócić wartość przez nią zwracaną) odziedziczoną wersję ResolveSpecifier().
Obiekt BApplication pobiera pierwszą ścieżkę a gdy znajduje on specyfikator dla własności "Window"; wysyła on komunikat do określonego BWindow i zwraca NULL. BWindow podąża drugą ścieżką gdy znajduje specyfikator właściwości "View"; zwraca on określony BView. Zatem komunikat początkowo kierowany do obiektu BApplication może znaleźć swoją drogę do BView.Wersja funkcji ResolveSpecifier() BHandler'a rozpoznaje komunikat B_GET_PROPERTY z bezpośrednim specyfikatorem żądającym "Suite" dla wspieranych zestawów, "Messenger" dla BHandler'a lub "InternalName" BHandler'a (ta sama nazwa, która jest zwracana przez funkcję Name()). We wszystkich trzech przypadkach, wyznacza ona BHandler (this) jako obiekt odpowiedzialny za komunikat.
Dla wszystkich innych specyfikatorów i komunikatów wysyła ona odpowiedź B_MESSAGE_NOT_UNDERSTOOD i zwraca NULL. Komunikat odpowiedzi ma pole "error" z B_SCRIPT_SYNTAX jako błędem i pole "message" z długim tekstowym wyjaśnieniem błędu.
![]() | SetFilterList(), FilterList(), AddFilter(), RemoveFilter() |
virtual void SetFilterList(BList *list) BList *FilterList(void) const virtual void AddFilter(BMessageFilter *filter) virtual bool RemoveFilter(BMessageFilter *filter) Te funkcje zarządzają listą obiektów BMessageFilter skojarzonych z BHandler'em.
SetFilterList() przypisuje BHandler'owi nową listę list filterów; lista musi zawierać wskaźniki do egzemplarzy klas BMessageFilter lub egzemplarzy klas pochodnych od BMessageFilter. Nowa lista zastępuje listę filtrów poprzednio przypisanych. Wszystkie obiekty poprzedniej listy są niszczone, jako BList która je zawiera. Jeśli list jest NULL, bieżąca lista jest niszczona bez zamiany. FilterList() zwraca bieżącą listę filtrów.
AddFilter() dodaje filter do końca listy filtów BHandler'a. Tworzy on obiekt BList jeśli on jeszcze nie istnieje. Domyślnie BHandlers nie zarządza obiektem BList filtrów dopóki nie zostanie on przypisany lub dopóki nie zostanie dodany pierwszy BMessageFilter. RemoveFilter() usuwa filter z listy bez niszczenia go. Zwraca ona true jeśli jest wywołana z sukcesem i false jeśli nie może znaleźć określonego filtra w liście (lub jeśli lista nie istnieje). Zostawia ona BList na miejscu nawet po usunięciu ostatniego filtra.
Dla SetFilterList(), AddFilter() i RemoveFilter() do pracy BHandler musi być przypisany do obiektu BLooper a obiekt BLooper musi być zablokowany.
Popatrz również do: BLooper::SetCommonFilterList(), BLooper::Lock() funkcji klasy BMessageFilter.
![]() | SetName(), Name() |
void SetName(const char *string) const char *Name(void) const Te funkcje ustawiają i zwracają nazwę która określa BHandler'a. Nazwa jest początkowo ustanawiana przez konstruktor. SetName() przypisuje BHandler'owi nową nazwę a Name() zwraca bieżącą nazwę. Łańcuch znaków zwracany przez Name() należy do obiektu BHandler; nie powinien on być zmieniany albo zwalniany.
Popatrz również do: konstruktor BHandler, BView::FindView() w Interface Kit.
![]() | SetNextHandler(), NextHandler() |
void SetNextHandler(BHandler *handler) BHandler *NextHandler(void) const SetNextHandler() przestawia obiekty w łąńcuchu handler'a tak, że handler śledzi ten BHandler. Ten BHandler i handler musi już być częścią tego samego łańcucha a BLooper do którego one należą musi być zablokowany. Kolejność obiektów w łańcuchu handler'a oddziałuje na sposób obsługi nadchodzących komunikatów (jak wyjaśniono w "Inheritance and the Handler Chain". Domyślnie handler'y są umieszczone w kolejności w której były dodawane (poprzez BLooper::AddHandler()).
NextHandler() zwraca w tym obiekcie następny handler. Jeśli ten obiekt jest na końcu łańcucha, zwraca ona NULL.
![]() | StartWatching(), StartWatchingAll(), StopWatching(), StopWatchingAll() |
status_t StartWatching(BMessenger watcher, uint32 what)
status_t StartWatching(BHandler *watcher, uint32 what)status_t StartWatchingAll(BMessenger watcher)
status_t StartWatchingAll(BHandller *watcher)status_t StopWatching(BMessenger watcher, uint32 what)
status_t StopWatching(BHandler *watcher, uint32 what)status_t StopWatchingAll(BMessenger watcher)
status_t StopWatchingAll(BHandller *watcher)Klasa BHandler dostarcza pojęcia powiadamiacza (notifier). Powiadamiacze zarządzają jednym lub wieloma stanami, które inne encje (twory) mogą potrzebować do monitorowania zmian stanów. Te stany są określone przez 32-bitowy kod what. Kolejne encje - BHandler lub BMessenger - mogą oczekiwać na zmiany stanów powiadamiaczy. Te są nazywane obserwatorami (observers).
StartWatching() rejestruje BMessenger lub BHandler określony przez watcher aby zostać powiadomionym gdy tylko zmieni się stan określony przez what. StartWatchingAll() rejestruje określony BMessenger lub BHandler aby zostać powiadomionym gdy jeden z powiadamiaczy zmieni stan.
StartWatching() działa przez wysyłanie komunikatu do BHandler'a, który chcesz obserwować z BMessenger'em zwróconym do obserwatora, więc one obydwa muszą być przyłączone do looper'a w chwili wywołania StartWatching().
![]()
Te formy StartWatching() i StartWatchingAll(), które akceptują BHandler'a mogą być używane do obserwowania handler'a, który jeszcze nie jest przyłączony do looper'a. Jednak pracują one tylko jeśli obydwaj: i obserwator i powiadamiacz są w tym samym looper'ze. StopWatching() zaprzestaje monitorowania stanu what. StopWatchingAll(), przez pewien zbieg okoliczności zatrzymuje całe monitorowanie przez BHandler'a lub BMessenger'a określonych przez watcher.
ZWRACANE KODY
- B_OK. Brak błędu.
- B_BAD_HANDLER. Określony BHandler nie jest prawidłowy.
![]() | UnlockLooper() patrz LockLooper() |
Pole Kod typu Znaczenie "_name" B_STRING_TYPE Nazwa obiektu (patrz SetName()). BHandler zapisuje swoją własną nazwę.
Zestaw: suite/vnd.Be-handler
![]() | "InternalName" |
Komunikat Specyfikatory Typ odpowiedzi B_GET_PROPERTY B_DIRECT_SPECIFIER B_STRING_TYPE Zwraca nazwę handler'a.
![]() | "Messenger" |
Komunikat Specyfikatory Typ odpowiedzi B_GET_PROPERTY B_DIRECT_SPECIFIER B_MESSENGER_TYPE Zwraca BMessenger'a dla handler'a.
![]() | "Suites" |
Komunikat Specyfkatory Typ odpowiedzi B_GET_PROPERTY B_DIRECT_SPECIFIER B_STRING_TYPE array Zwraca tablicę zestawów, które wspierają adresata, określongo przez nazwę (tj. "suite/vnd.Be-handler").
|
Copyright © 2000 Be, Inc. Wszelkie prawa zastrzeżone.