![]() | |||
Zune - podręcznik programowaniaWprowadzenieCzym jest Zune?Zune jest zorientowanym obiektowo zestawem narzędzi GUI ( Graficznego Interfejsu Użytkownika ). Jest klonem ( w API, i wyglądzie ) MUI, bardzo dobrze znanym shereware'owym produktem Stenan'a Stuntz'a. Więc programiści MUI będą się czuli jak w domu; pozostali odkryją koncepcję i cechy szczególne, które Zune dzieli z MUI.
Zune jest oparte o BOOPSI, budowa jest wzięta z AmigaOS, dla zorientowanego-obiektowo programowania w C. Klasy Zune nie pochodzą od istniejących gadżetów klas BOOPSI; zamiast tego, klasa notyfikacji ( główna klasa hierarchi Zune ) pochodzi od głównej klasy BOOPSI. PomocePewna wiedza o OO ( zorientowanym-obiektowo ) programowaniu, jest więcej, niż mile widziana. Jeśli nie, to Google może pomóc Ci znaleźć informacje z tego zakresu. Znajomość AROS'a ( lub AmigaOS ) API i koncepcji jak listy Tag oraz BOOPSI jest niezbędna. Posiadanie Amiga Reference Manual ( RKM - podręcznik Amigi ) jest bardzo przydatna. Jako, że Zune jest klonem MUI, cała dokumentacja dotycząca MUI, dotyczy także Zune. W szczególności ostatni dostępny pakiet programistyczny, który znajduje się tutaj. W tym archiwum, 2 dokumenty są szczególnie zalecane:
Dodatkowo, to archiwum zawiera opisy funkcji ( autodocs ) MUI, które nawiązują do wszystkich klas Zune. BOOPSI PodstawyKoncepcjaKlasaKlasa mówi sama za siebie, jest nadrzędną klasą i dyspozytorem ( dispatcher ).
Typ BOOPSI dla klasy to Class * znana jako IClass. ObiektObiekt ma zawartość klasy: każdy obiekt ma własne specyficzne dane, ale wszystkie obiekty tej samej klasy dzielą to samo zachowanie. Obiekt ma kilka klas, jeśli policzymy nadrzędne jego prawdziwych klas, ( najbardziej pochodne ) aż do głównej klasy. Typ BOOPSI dla obiektu to Object *. Nie ma pola, do którego miałbyś bezpośredni dostęp. AtrybutAtrybut jest powiązany z danymi każdego obiektu: nie możesz mieć dostępu do tych danych bezpośrednio, możesz tylko ustawić, bądź pobrać atrybuty dostarczane poprzez obiekt do zmodyfikowania jego wewnętrznego stanu. Atrybut jest załączony jako Tag (wartość ULONG lub edytuj z TAG_USER). GetAttr() i SetAttrs() są używane do modyfikowania atrybutów obiektu. Atrybuty mogą mieć jedną lub więcej flag:
MetodaMetoda BOOPSI jest funkcją, która odbiera obiekt, klasę i wiadomość ( message ) jako parametery:
Aby wysłać wiadomość do obiektu, używaj DoMethod(). Użyje najpierw prawdziwej klasy. Jeśli klasa zawiera tą metodę, wtedy jej użyje. W przeciwnym razie będzie próbować jej nadrzędnej klasy, dopóki wiadomość jest obsługiwana lub główna klasa została osiągnięta ( w tym przypadku, nieznana wiadomość jest niewidocznie odrzucana ). PrzykładyZobaczmy proste przykłady tej budowy OOP: Pobieranie atrybutuBędziemy pobierać zawartość String MUI:
void f(Object *string)
{
IPTR result;
GetAttr(string, MUIA_String_Contents, &result);
printf("Zawartość String to: %s\n", (STRPTR)result);
}
Aplikacje Zune częściej używają makr get() i XGET() zamiast: get(string, MUIA_String_Contents, &result); result = XGET(string, MUIA_String_Contents); Ustawianie atrybutuZmieńmy zawartość naszego String: SetAttrs(string, MUIA_String_Contents, (IPTR)"witaj", TAG_DONE);
Odkryjesz użyteczność makra set(): set(string, MUIA_String_Contents, (IPTR)"hello"); Lecz tylko z SetAttrs() możesz ustawić kilka atrybutów naraz:
SetAttrs(string,
MUIA_Disabled, TRUE,
MUIA_String_Contents, (IPTR)"hmmm...",
TAG_DONE);
Wywoływanie metodyZobaczmy najczęściej wywoływaną metodę w Zune, metodę procesu zdarzeń wywoływaną w Twojej pętli głównej: result = DoMethod(obj, MUIM_Application_NewInput, (IPTR)&sigs);
Witaj Świecie
Proste rzeczy najpierw! Wiem, że to się Wam spodoba. ŹródłoPrzestudiujmy nasz pierwszy prawdziwy przykład:
// gcc hello.c -lmui
#include <exec/types.h>
#include <libraries/mui.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/muimaster.h>
#include <clib/alib_protos.h>
int main(void)
{
Object *wnd, *app, *but;
// Tworzenie GUI
app = ApplicationObject,
SubWindow, wnd = WindowObject,
MUIA_Window_Title, "Witaj Świecie!",
WindowContents, VGroup,
Child, TextObject,
MUIA_Text_Contents, "\33cWitaj Świecie!\nJak się masz?",
End,
Child, but = SimpleButton("_W porządku"),
End,
End,
End;
if (app != NULL)
{
ULONG sigs = 0;
// Wciśnij gadżet zamykania, bądź ESC, aby wyjść
DoMethod(wnd, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
(IPTR)app, 2,
MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
// Wciśnij przycisk, aby wyjść
DoMethod(but, MUIM_Notify, MUIA_Pressed, FALSE,
(IPTR)app, 2,
MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
// Otwórz okno
set(wnd, MUIA_Window_Open, TRUE);
// Sprawdź, czy okno zostało otwarte
if (XGET(wnd, MUIA_Window_Open))
{
// Pętla główna
while((LONG)DoMethod(app, MUIM_Application_NewInput, (IPTR)&sigs)
!= MUIV_Application_ReturnID_Quit)
{
if (sigs)
{
sigs = Wait(sigs | SIGBREAKF_CTRL_C);
if (sigs & SIGBREAKF_CTRL_C)
break;
}
}
}
// Zamknij aplikację i wszystkie jej obiekty
MUI_DisposeObject(app);
}
return(0);
}
UwagiOgólneNie będziemy ręcznie otwierać bibliotek, to jest automatycznie robione za nas. Tworzenie GUIUżywamy języka opartego o makra, aby w prosty sposób zbudować nasze GUI. Aplikacje Zune posiadają jeden, i tylko jeden obiekt Application: : app = ApplicationObject, Aplikacja może mieć 0, 1 lub więcej obiektów Window ( czyli okien ). Najczęściej pojedyńcze: : SubWindow, wnd = WindowObject, Bądź miły, podaj tytuł okna: : MUIA_Window_Title, "Witaj Świecie!", Okno musi mieć jedno, i tylko jedno dziecko ( child ), zwykle grupę. Ta jest pionowa, a to oznacza, że jej dzieci będą ustawione pionowo: : WindowContents, VGroup, Grupa musi mieć conajmniej 1 dziecko, a tutaj jest po prostu text: : Child, TextObject, Zune akceptuje różne rodzaje kodów ESC ( tutaj, aby wyrównać tekst ) i nowe linie: : MUIA_Text_Contents, "\33cWitaj Świecie!\nJak się masz?", Makro End kończy każde rozpoczęte makro xxxObject ( tutaj, TextObject): : End, Dodajmy drugie dziecko do naszej grupy, przycisk! Wraz ze skrótem klawiaturowym w rozpoczęte poprzez podkreślnik:
: Child, but = SimpleButton("_Ok"),
Zakończ grupę: : End, Zakończ okno: : End, Zakończ aplikację: : End; Kto więc jeszcze potrzebuje programu do tworzenia GUI? :] Kontrola błędówJeśli któryś z obiektów w drzewie aplikacji nie może zostać utworzony, wtedy Zune zamyka wszystkie obiekty dotychczas stworzone, i tworzenie aplikacji zostaje przerwane. Jeśli nie, to masz w pełni działającą aplikację:
: if (app != NULL)
: {
: ...
Gdy już skończyłeś, po prostu wywołaj MUI_DisposeObject() na swoim obiekcie aplikacji, aby zamknąć wszystkie obiekty z Twojej aplikacji, i uwolnij wszystkie zasoby: : ... : MUI_DisposeObject(app); : } PowiadomieniaPowiadomienia są najprostszą drogą do odpowiedzi na zdarzenia. Zasada? Chcemy być powiadamiani, gdy pewne atrybuty określonego obiektu są ustawione do wybranej wartości: : DoMethod(wnd, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, Tutaj nasłuchujemy MUIA_Window_CloseRequest naszego obiektu Window i będziemy powiadamiani, gdy tylko atrybut będzie miał wartość TRUE. Więc co się dzieje, gdy powiadomienie wystąpi? Wtedy wiadomość jest wysyłana do obiektu, i to tutaj mówimy naszej aplikacji o tym, aby zwróciła MUIV_Application_ReturnID_Quit, przy kolejnej iteracji pętli: : (IPTR)app, 2, : MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit); Jak już określimy wszystko, czego nam potrzeba, tak teraz musimy podać liczbę dodatkowych parameterów, które dostarczamy do MUIM_Notify: tutaj, 2 parametery. Dla przycisku, nasłuchujemy jego MUIA_Pressed atrybutu: jest ustawiony na FALSE gdy tylko przycisk zostaje uwolniony ( odpowiadanie gdy przycisk zostaje wciśnięty jest złym nawykiem, bo przecież będziesz chciał anulować wybór, poprzez przesunięcie kursora poza przycisk - i chcemy przecież zobaczyć jak wygąda, gdy jest wciśnięty ). Zadanie jest to samo co poprzednio, wyślij wiadomość do aplikacji: : DoMethod(but, MUIM_Notify, MUIA_Pressed, FALSE, : (IPTR)app, 2, : MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit); Otwieranie oknaOkna nie są otwarte, aż do momentu, w którym je o to nie poprosimy: : set(wnd, MUIA_Window_Open, TRUE); Jeśli wszystko idzie dobrze, Twoje okno powinno być wyświetlone w tym momencie. Ale może coś pójść nie tak! Więc nie zapomnij sprawdzić, poprzez zapytanie atrybutu, czy zwraca TRUE: : if (XGET(wnd, MUIA_Window_Open)) Pętla głównaPozwól, że zapoznam Cię - mój mały przyjacielu - z idealną pętlą zdarzeń: : ULONG sigs = 0; Nie zapomnij zinicjować signals do 0 ... test pętli jest metodą MUIM_Application_NewInput: : ... : while((LONG) DoMethod(app, MUIM_Application_NewInput, (IPTR)&sigs) : != MUIV_Application_ReturnID_Quit) Jako wejście pobiera signals ze zdarzeń, które musi przetworzyć ( wynik z Wait() lub 0 ), zmodyfikuje tą wartość do miejsca, gdzie sygnały Zune czekają na ( do następnego Wait()) i zwrócą wartość. Ten mechanizm zwracania wartości, był historycznie jedną drogą do odpowiedzi na zdarzenia, ale był brzydki i został zarzucony w wizji wspaniałych zaawansowanych klasach i obiektowo-zorientowanej budowie. Całość tej pętli jest całkiem pusta, my tylko czekamy na sygnały Ctrl-C aby przerwać pętlę:
: {
: if (sigs)
: {
: sigs = Wait(sigs | SIGBREAKF_CTRL_C);
: if (sigs & SIGBREAKF_CTRL_C)
: break;
: }
: }
WniosekTen program pozwala Ci na rozpoczęcie zabawy z GUI Zune, lecz na nic więcej. Zadania powiadomieńJak widzisz w hello.c, używasz MUIM_Notify do wywołania metody jeśli zostanie spełniony określony warunek. Jeśli chcesz aby Twoja aplikacja oddziaływała w określony sposób na zdarzenia, to możesz użyć jednego z poniższych schematów:
|
Copyright (C) 1995-2008, The AROS Development Team. Wszystkie prawa zastrzeżone. Amiga(R), AmigaOS(R), Workbench i Intuition are znakami towarowymi Amiga Inc. Wszystkie inne znaki towarowe należą do ich prawnych właścicieli. |