Laboratorium wirtualne 1/Moduł 2 - ćwiczenie 2/część 2

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania

wersja beta


LABORATORIUM WIRTUALNE 1

Ćwiczenie 2 - Środowisko programistyczne LabWindows/CVI

Część 2

LW1 M2 CZ2 Slajd intro.png Temat ćwiczenia:

Mechanizm obsługi zdarzeń

Cel ćwiczenia:

Materiał zaprezentowany w czasie prezentacji ma za zadanie zaznajomić słuchacza z mechanizmem obsługi zdarzeń w środowisku LabWindows/CVI.

Słuchacz posiądzie niezbędne wiadomości z dziedziny obsługi zdarzeń oraz odbierania i wysyłania wartości do i z elementów interfejsu użytkownika.


LW1 M2 CZ2 Slajd01.png Plan prezentacji.

LW1 M2 CZ2 Slajd02.png Budowanie szkieletu aplikacji

LW1 M2 CZ2 Slajd03.png Budowę aplikacji zaczynamy od stworzenia nowego projektu. W tym celu z menu głównego wybieramy:
File > New > Project (*.prj)

Jest to nic innego jak stworzenie pustego obszaru roboczego oraz pliku zawierającego informacje o plikach składowych projektu.


LW1 M2 CZ2 Slajd04.png Kolejnym etapem o którym była mowa we wcześniejszych prezentacjach jest zbudowanie interfejsu użytkownika. W przykładach kursu będziemy starali się stosować zasadę umieszczania jak najmniejszej ilości elementów na interfejsie użytkownika przed procesem generacji kodu aplikacji. Pozwala ona stopniowe dodawanie funkcjonalności a co za tym idzie na częste uruchamianie programu po wykonaniu drobnych zmian. Prawdopodobieństwo pomylenia zmiennych jest znacznie mniejsze niż w przypadku generacji kodu z całego interfejsu. Pozwala tez na szybkie wykrycie błędów i ich usunięcie – co ma szczególne znaczenie w przypadku niedoświadczonych użytkowników.

Aby utworzyć interfejs użytkownika wybieramy z menu głównego:

File > New > User Interface (*.uir)



LW1 M2 CZ2 Slajd05.png Stosując się do poznanych zasad określamy następujące właściwości panelu interfejsu użytkownika:
  • w polu CONSTANT NAME wpisujemy PANEL (domyślnie środowisko powinno wpisać tą nazwę),
  • w polu Panel Title wpisujemy Program obsługi zdarzeń (w oknie podglądu powinien ukazać się zmieniony napis na pasku górnym interfejsu),
  • zaznaczamy pola Auto Center Vertically i Auto Center Horizontally powodujące wyśrodkowanie okna interfejsu na pulpicie w momencie startu aplikacji.

Resztę właściwości pozostawiamy bez zmian i naciskamy przycisk OK zatwierdzający wprowadzone zmiany.


LW1 M2 CZ2 Slajd06.png Kolejnym etapem budowy interfejsu użytkownika będzie dodanie przycisku kończącego działanie aplikacji. Skoro mówione było wcześniej że umieszczamy na interfejsie jak najmniej elementów to dlaczego umieszczamy przycisk Wyjście? Wynika to z właściwości kreatora kodu który umożliwia automatyczne wygenerowanie kodu dla przycisku kończącego działanie aplikacji dodając w funkcji obsługi zdarzenia odpowiednią funkcję zamykającą interfejs (a tym samym kończącą działanie aplikacji).

W celu dodania do interfejsu przycisku Wyjście należy z menu głównego wybrać polecenie Create a następnie Command Button i wybrać Square Command Buton (oba sposoby dodawania zostały zaprezentowane na następnym slajdzie). Jest to typowy przycisk funkcyjny jaki można spotkać we wszystkich aplikacjach dla Windows. Po naciśnięciu go przez użytkownika zostaje wywołane zdarzenie obsługi, ale o tym w dalszej części kursu.


LW1 M2 CZ2 Slajd07.png Następnie przechodzimy do właściwości elementu (poprzez dwukrotne klikniecie lewym przyciskiem myszy na elemencie). W oknie podglądu powinniśmy zobaczyć widok przycisku. Jeżeli go nie widać to znaczy że niechcący kliknęliśmy inny element np. Panel.

Zmieniamy następujące własciwości przycisku:

Constant Name – wpisujemy WYJSCIE

Określamy funkcję Controll Callback jaka ma być wywoływana po naciśnięciu przycisku Wyjście – wpisujemy Wyjscie.

Zmieniamy etykietę jak ma być wyświetlana na przycisku Label na __Wyjście.


LW1 M2 CZ2 Slajd08.png Wprowadzone zmiany w formularzu właściwości zatwierdzamy przyciskiem OK. Widok panelu UI powinien wyglądać podobnie jak przedstawiony na slajdzie.

LW1 M2 CZ2 Slajd09.png Generacja kodu C aplikacji.

LW1 M2 CZ2 Slajd10.png Zani zostanie wygenerowany kod C aplikacji należy we właściwościach kreatora włączyć dodatkowe zdarzenia jakie mają być uwzględnione w czasie wstawiania kodu C. z menu należy wybrać:

Code > Preferences > Default Control Events


LW1 M2 CZ2 Slajd11.png W formularzu zaznaczamy zdarzenia jakie chcemy aby kreator uwzględnił przy budowaniu kodu C aplikacji. Należy zaznaczyć następujące zdarzenia:
EVENT_COMMIT
EVENT_VAL_CHANGED
EVENT_RIGHT_CLICK
EVENT_RIGHT_DOULE_CLICK
EVENT_TIMER_TICK

LW1 M2 CZ2 Slajd12.png Wybrane typy zdarzeń:
  • EVENT_COMMIT – domyślne zdarzenie wywoływane w momencie gdy użytkownik zakończy interakcję z elementem,
  • EVENT_VAL_CHANGED – wywoływane w momencie zmiany wartości elementu,
  • EVENT_RIGHT_CLICK – wywoływane w momencie kliknięcia prawego klawisza myszy na elemencie
  • EVENT_RIGHT_DOULE_CLICK - wywoływane w momencie dwukrotnego kliknięcia prawego klawisza myszy na elemencie
  • EVENT_TIMER_TICK – zdarzenie obsługi timera

Pozostałe zdarzenia zostaną poznane i omówione w dalszej części prezentacji.


LW1 M2 CZ2 Slajd13.png Przystępujemy do generacji kodu C aplikacji. W tym celu w przestrzeni roboczej wybieramy okno zawierające interfejs użytkownika. W menu głównym będzie dostępna pozycja Code z której wybieramy:
Code > Generale > All Code

Spowoduje to otworzenie formularza określającego właściwości generowanego kodu aplikacji. Jeżeli do tej pory nie zapisaliśmy pliku interfejsu użytkownika to pojawi się monit o wykonanie tej czynności. Po naciśnięciu przycisku Yes pojawi się okno w którym możemy wybrać lokalizację katalogu gdzie ma zostać zapisany plik interfejsu. Zaleca się aby utworzyć katalog dla tworzonego projektu. Pozwala to na zachowanie porządku i łatwą identyfikacje plików należących do konkretnego projektu.


LW1 M2 CZ2 Slajd14.png W naszym przypadku należy podać następujące dane:

Target file – wybieramy opcję: Create New Project.

Target Type – ponieważ ma to być aplikacja wybieramy Executable.

Project i Source Filename – pozostawiamy bez zmian.

Generale WinMain() instead of main() – zaznaczamy aby kreator wygenerował funkcję WinMain ().

Select Panels to load and display at startup – mamy jeden panel więc go zaznaczamy.

Panel Variable Name – pozostawiamy domyślną nazwę panelHandle.

Program Termination – zaznaczamy funkcję Wyjście aby generator wstawił funkcję kończąca działanie aplikacji.

Po wprowadzeniu zmian naciskamy przycisk OK co spowoduje przejście do kolejnego etapu..


LW1 M2 CZ2 Slajd15.png Ostatnią czynnością jaką trzeba wykonać przed wygenerowaniem kodu jest ustawienie właściwości dla nowo tworzonego projektu (ponieważ taką opcje wybraliśmy w polu Target File). Zaznaczmy Create Project In New Workspace celem zdefiniowania nowej przestrzeni roboczej dla projektu. Z ustawień poprzedniego projektu przenosimy jedynie opcje Build Options.

Zatwierdzamy zmiany przyciskiem OK. W tym momencie powinien zostać wygenerowany kod C aplikacji.


LW1 M2 CZ2 Slajd16.png W obszarze roboczym projektu pojawiło się nowe okno zawierające kod C aplikacji. Wygenerowany plik z kodem został automatycznie dodany do plików projektu.

LW1 M2 CZ2 Slajd17.png

LW1 M2 CZ2 Slajd18.png W poprzednich krokach został zbudowany interfejs użytkownika oraz wygenerowany kod C aplikacji. Na tym etapie można już uruchomić aplikację. Na slajdzie przedstawione zostały dwa sposoby uruchamiana aplikacji w środowisku LabWindows/CVI.

LW1 M2 CZ2 Slajd19.png Zbudowany został szkielet do budowy dowolnej aplikacji. Funkcjonalność jest obecnie ograniczona jedynie do przycisku Wyjście kończącego działanie programu

LW1 M2 CZ2 Slajd20.png

LW1 M2 CZ2 Slajd21.png Działanie aplikacji zbudowanej w środowisku LabWindows/CVI jest oparte o procedurę obsługi zdarzeń. Procedura obsługi zdarzeń stosuje bardzo proste zasady dzięki którym jest w stanie poradzić sobie ze napływającymi zdarzeniami zarówno od użytkownika jak i urządzeń. Po uruchomieniu programu procedura obsługi zdarzeń przejmuje kontrolę nad wykonaniem aplikacji i oczekuje w pętli nieskończonej na nadejście zdarzenia lub do momentu wystąpienia instrukcji kończącej działanie programu. Schemat działania procedury obsługi zdarzeń został zaprezentowany na slajdzie.

LW1 M2 CZ2 Slajd22.png Działanie procedury obsługi zdarzeń można opisać w kilku punktach. Jak już wspomniano wcześniej procedura obsługi zdarzeń (skrócie nazywana POZ) przejmuje kontrolę nad wykonaniem programu zaraz po uruchomieniu aplikacji. W momencie zaistnienia zdarzenia od użytkownika. POZ ustala źródło powstania zdarzenia czyli panel i element wywołujący zdarzenie. Następnie sprawdzane jest czy element posiada zdefiniowana funkcje obsługi zdarzenia. Jeśli nie to procedura przechodzi w stan oczekiwania na nadejście zdarzenia. W przypadku gdy funkcja obsługi zdarzenia (callback function) istnieje POZ sprawdza czy w funkcji obsługi zdarzenia został zaimplementowany kod obsługi wywołanego zdarzenia (instrukcja switch-case). Jeśli tak to zostaje wykonany kod obsługi zdarzenia. W przeciwnym wypadku funkcja obsługi zdarzenia zwraca sterowanie do POZ i następuje oczekiwanie na następne zdarzenie. Jeżeli w kodzie obsługi zdarzenia pojawi się funkcja QuitUserInterface to następuje zakończenie działania aplikacji.

LW1 M2 CZ2 Slajd23.png

Typy zdarzeń oraz ich działanie najlepiej zaobserwować na przykładzie. Szkielet programu jaki został utworzony wcześniej zostanie uzupełniony o elementy umożliwiające sterowanie zdarzeniami.


LW1 M2 CZ2 Slajd24.png Zadaniem budowanej aplikacji jest sterowanie poziomem zbiornika za pożsrednictwem zadajnika.

LW1 M2 CZ2 Slajd25.png W środowisku LabWindows/CVI możemy wyróżnić dwa zasadnicze typy elementów. Pierwsza grupę stanowią elementy pozwalające na zmianę stanu czy przekazanie informacji z interfejsu do kodu programu. SA to tak zwane zadajniki. Przykładowe zadajniki zostały przedstawione na slajdzie.

Drugą grupę elementów stanowią wskaźniki czyli elementy służące do wizualizacji danych.


LW1 M2 CZ2 Slajd26.png Budowę aplikacji prezentującej obsługę zdarzeń zaczniemy od zmodyfikowania interfejsu użytkownika. Pierwszym elementem jaki trzeba dodać jest przełącznik binarny który ma posłużyć jako selektor zdarzenia.

LW1 M2 CZ2 Slajd27.png Aby dostosować przełącznik do potrzeb aplikacji należy zmodyfikować pewne właściwości;

W polu Constant name wpisujemy ZDARZENIE. Należy pamiętać o sposobie nazewnictwa elementów omawianym w części pierwszej.

Funkcję control callback pozostawiamy pustą. Powstaje pytanie dlaczego, skoro chcemy zmieniać typ zdarzenia. Pozostawiamy ją pusta gdyż nie jesteśmy w stanie w prosty sposób wymusić typ zdarzenia jaki chcemy obsłużyć. Prościej będzie sprawdzić jakie jest zdarzenie i porównać z ustawioną wartością.

W polu initial state zmieniamy stan początkowy przełącznika na ON.

W polach ON Text oraz OFF Text wpisujemy odpowiednio EVENT_COMMIT oraz EVENT_VAL_CHANGED. W polach ON Value i OFF Value znajdują się wartości przypisane tym stanom – pozostawiamy je bez zmian.

Po wprowadzeniu zmian zatwierdzamy przyciskiem OK.


LW1 M2 CZ2 Slajd28.png Kolejnym elementem jaki dodamy na interfejsie będzie suwak który będzie sterował poziomem w zbiorniku.

LW1 M2 CZ2 Slajd29.png W formularzu właściwości suwaka definiujemy jego nazwę (constant name) na ZADAJNIK oraz podajemy nazwę funkcji control callback; Zadajnik. Proszę zwrócić uwagę na pole Data Type określające typ danych jakie będą używane do określenia położenia suwaka. Jest to typ double. Informacja ta będzie przydatna w czasie uruchamiania aplikacji. Po zmianie etykiety elementu można zatwierdzić zmiany przyciskiem OK.

LW1 M2 CZ2 Slajd30.png Ostatnim elementem dodawanym na interfejsie użytkownika jest element typu Tank reprezentujący poziom w zbiorniku. Dane z suwaka będą przekazywane do tego elementu i będą określały bieżący poziom.

LW1 M2 CZ2 Slajd31.png Wymagane zmiany we właściwościach zbiornika to:

Constant name: ZBIORNIK

Label: Zbiornik

Funkcję callback pozostawiamy pustą – nie będziemy obsługiwali użytkownika i zbiornika


LW1 M2 CZ2 Slajd32.png Ponieważ kod aplikacji został wcześniej wygenerowany więc nie znajduje się tam funkcja obsługi zdarzenia elementu zadajnik. Aby wygenerować funkcję obsługi zdarzenia należy nacisnąć prawy klawisz myszy i wybrać z menu podręcznego pozycję Generate Control Callback.

LW1 M2 CZ2 Slajd33.png Jeżeli element nie będzie posiadał we właściwościach zdefiniowanej funkcji obsługi zdarzenia to opcja Generate Control Callback nie będzie dostępna. Na poprzednim slajdzie poza funkcją Generate Control Callback dostępna jest też opcja View Control Callback po naciśnięciu której użytkownik zostanie przeniesiony do kodu c w miejsce gdzie znajduje się funkcja obsługi zdarzenia ego elementu.

LW1 M2 CZ2 Slajd34.png Po wybraniu funkcji Generate Control Callback została wygenerowana funkcja obsługi zdarzenia.

Została ona dodana na końcu pliku z kodem C. zawiera ona prawie wszystkie zdarzenia które zostały zaznaczone w trakcie generacji kodu. Nie zostało dodane jedynie zdarzenie obsługi Timera.

Jeżeli w trakcie budowy aplikacji okaże się ze potrzebne jest dodatkowe zdarzenie którego nie zaznaczyliśmy w fazie budowy szkieletu aplikacji to można z poziomu menu głównego:

Code > Preferences > Default Control Events

włączyć potrzebne zdarzenie. Od tej pory kreator funkcji obsługi zdarzeń będzie uwzględniał dodane zdarzenie.


LW1 M2 CZ2 Slajd35.png Posiadając funkcję obsługi zdarzenia można przystąpić do oprogramowania niezbędnych funkcji programu. Na początku zbierzemy dane z zadajnika i z przełącznika typu zdarzenia jakie chcemy obsłużyć.

LW1 M2 CZ2 Slajd36.png W miejscu oznaczonym strzałką wstawiona zostanie funkcja Get Control Value pobierająca położenie z przełącznika binarnego o nazwie ZDARZENIE (element o etykiecie Typ zdarzenia).

LW1 M2 CZ2 Slajd37.png Organizacja biblioteki funkcji ma postać drzewa o różnych głębokościach. Funkcje zostały umieszczone w odpowiednich grupach dotyczących elementu bądź czynności. Funkcja Get Control Value jest jedną z najczęściej używanych funkcji. Grupa User Interface zawiera funkcje służące do obsługi interfejsu użytkownika. Na slajdzie widoczne są też inne grupy funkcji:

Advanced Analysis – grupa funkcji służących do wykonywania szeroko pojętych obliczeń i operacji matematycznych. Zawierają się tu funkcje generujące przebiegi, obliczające widmo sygnału, operacje macierzowe itp.

Formating and I/O – grupa funkcji sterujących wejściem/wyjściem, formatowaniem danych wejściowych, operacje na łańcuchach znakowych itp.

Utility – grupa funkcji zawierająca między innymi funkcje sterowania wątkami, procesami, portami itp.

ANSI C – funkcje standardowe z bibliotek języka ANSI C.

W środowisku LabWindows/CVI funkcje są pogrupowane intuicyjnie.


LW1 M2 CZ2 Slajd38.png Ścieżka dostępu do funkcji Get Control Value.

LW1 M2 CZ2 Slajd39.png Ścieżka dostępu do funkcji Get Control Value.

LW1 M2 CZ2 Slajd40.png Ścieżka dostępu do funkcji Get Control Value.

Library > User Interface > Controls/Graphs/Strip Charts > General Functions

Jak widać na przykładzie dostęp do funkcji jest intuicyjny. W czasie wyszukiwania interesującej nas funkcji należy kierować się zasadami:

Czego dotyczy funkcja? Interfejs użytkownika, obliczenia, wejście/wyjście, komunikacja sieciowa itp.

Jaka jest podstawowa grupa funkcji? Element interfejsu, panel, okno dialogowe, operacje macierzowe, FFT, generacja sygnału, DataSocket itp.

Jaka podgrupa funkcji? Funkcje podstawowe, rysowanie wykresów, tabelki, operacje na macierzach jednowymiarowych, domena częstotliwościowa, nawiązywanie połączenia itp.

Głębokość drzewa może zawierać jeszcze parę poziomów w zależności jak można pogrupować funkcje.


LW1 M2 CZ2 Slajd41.png Formularz funkcji Get Control Value. Opis poszczególnych agumentów funkcji znajduje się na kolejnych slajdach.

LW1 M2 CZ2 Slajd42.png Pole PanelHandle jest uchwytem (wskaźnikiem) do Panelu na którym znajduje się element z którego zamierzamy odczytać dane. Uchwyt do panelu został zdefiniowany na etapie generacji kodu. W projekcie może być zdefiniowanych wiele Paneli. Środowisko ułatwia użytkownikowi zarządzanie zmiennymi oraz ich wybór za pomocą formularzy dostępnych po naciśnięciu przycisku select variable lub skrótu klawiaturowego Ctrl + A

LW1 M2 CZ2 Slajd43.png W oknie wyświetlona zostanie lista zmiennych pasujących (typem) do pola. Jeżeli pozostawiliśmy domyślna nazwę uchwytu do panelu w czasie konfigurowania właściwości generowanego kodu to zmienna będzie nazywać się panelHandle (nazwa zgodna ze sposobem nazywania elementów – część 1 prezentacji). Należy ją wybrać i nacisnąć OK.

Jeżeli użyte zostaną biblioteki zewnętrzne zawierające deklarację dużej ilości zmiennych korzystanie z formularza może być uciążliwe. Z pomocą przychodzi pole Show Project Variable pozwalające na wyświetlenie zmiennych zadeklarowanych jedynie w kodzie budowanej aplikacji.


LW1 M2 CZ2 Slajd44.png Jeżeli nie wyświetlają się zmienne bądź w śród nich nie ma zmiennej którą chcemy użyć należy przekompilować projekt za pomocą przycisku Build The Project. Sytuacja taka ma miejsce gdy nie korzystamy z kreatorów do deklaracji zmiennych.

LW1 M2 CZ2 Slajd45.png Po wybraniu nazwy w formularzu i w podglądzie funkcji pojawi się wybrana wartość.

LW1 M2 CZ2 Slajd46.png Następnym polem jest Control ID. Jest to nic innego jak informacja (uchwyt) o elemencie z którego chcemy pobrać wartość (w naszym przypadku będzie to położenie przełącznika). Aby wybrać uchwyt należy w polu Control ID ustawić kursor i nacisnąć enter lub z menu głównego wybrać Select Atribute/UIR Constant…

LW1 M2 CZ2 Slajd47.png Z listy elementów wybieramy nazwę elementu z którego chcemy odczytać wartość. Wybieramy PANEL_ZDARZENIE i naciskamy przycisk OK. Nazwa elementu zostanie wstawiona do pola Control ID formularza.

LW1 M2 CZ2 Slajd48.png Ostatnim polem formularza jakie trzeba wypełnić jest pole Value. Jest to nazwa zmiennej, do której funkcja zwróci wartość z elementu (w naszym przypadku położenie przełącznika). Jeżeli mamy taką zmienną zadeklarowaną to możemy ją wybrać tak jak w przypadku zmiennej panelHandle.

W naszym przypadku nie posiadamy takiej zmiennej więc będzie trzeba ja zadeklarować. Sposoby są dwa: ręczne zadeklarowanie zmiennej lub użycie kreatora do deklaracji zmiennej


LW1 M2 CZ2 Slajd49.png Aby zadeklarować zmienną należy ustawić kursor w odpowiednim polu formularza (jeżeli tego nie zrobimy kreator nie będzie wstanie przechwycić typu zmiennej) i nacisnąć przycisk Declare Variable.

LW1 M2 CZ2 Slajd50.png Typ zmiennej (Variable type) został automatycznie ustawiony na typ oczekiwany przez formularz funkcji. Klikając w strzałki obok typu zmiennej (int) lub w białe pole można zmienić typ zmiennej. W pole Variable Name wpisujemy nazwę zmiennej – w naszym przypadku będzie to „zdarzenie”.

Kreator umożliwia deklarację zmiennych lokalnych i zmiennych globalnych. Zmienne lokalne umieszczane są wewnątrz bloku kodu i mają zasięg jedynie w jego obrębie. Zmienne globalne są dostępne w całym programie. Kreator umieszcza je na początku kodu C.

Wypełniamy odpowiednie pola i naciskamy OK.


LW1 M2 CZ2 Slajd51.png W formularzu w polu Value została wstawiona zmienna którą zadeklarowaliśmy. Należy zwrócić uwagę że przed nazwą zmiennej został automatycznie dodany znaczek & (symbol adresu) powodujący przekazanie adresu zmiennej a nie kopii zmiennej. W języku C podczas wywołania funkcji argumenty wejściowe odkładane są na stos. Zatem funkcja wykonuje swoje zadanie dysponując kopiami pobranych zmiennych. Funkcja GetCtrlVal a także i inne rozpoczynające przedrostkiem Get... zwracają wynik w jednym z argumentów wejściowych dlatego wymagają dostępu do oryginału zmiennej a nie do jej kopii. Zapewnione jest to przez podanie adresu zmiennej. Powyższa informacja (pojawianie się symbolu &) dotyczy jedynie wielkości skalarnych (pojedynczych zmiennych). W przypadku wektorów i tablic sama nazwa jest adresem tego typu zmiennych. Zatem po zdefiniowaniu i wstawieniu tego typu zmiennych symbol & nie występuje.

Pole Status pozostawiamy puste – nie będziemy w tej funkcji używać statusu wykonania operacji. Status używa się najczęściej w funkcjach z dostępem do sprzętu gdzie potrzebujemy informację o statucie wykonania operacji.


LW1 M2 CZ2 Slajd52.png Wstawiamy funkcję Get Control Value do kodu. Na slajdzie uwidoczniona została wstawiona funkcja oraz deklaracja zmiennej.

LW1 M2 CZ2 Slajd53.png W podobny sposób jak poprzednio wstawiamy funkcję Get Control Value pobierającą dane z elementu Zadajnik. Proszę zwrócić uwagę na typ zmiennej jaka ustawił kreator. Na slajdzie dotyczącym właściwości elementu Zadajnik ustawiliśmy typ zmiennej double. Kreator popełnił błąd, jednakże proszę go nie poprawiać. Na jego podstawie zostanie zaprezentowana sygnalizacja Bledu wykonania programu.

LW1 M2 CZ2 Slajd54.png Własciwości elementu Zadajnik.

LW1 M2 CZ2 Slajd55.png Wstawiwnie funkcji do programu.

LW1 M2 CZ2 Slajd56.png W kolejnym kroku wstawimy niezbędny kod do sprawdzenia położenia przełącznika „Typ Zdarzenia” oraz wysłania wartości do elementu Zbiornik. W pierwszej kolejności uzupełnimy kod zdarzenia EVENT_COMMIT. W miejscu oznaczonym strzałką należy wstawić instrukcję warunkową if(…).

LW1 M2 CZ2 Slajd57.png Dla osób znających programowanie w języku C może wydać się to stratą czasu aby do tak prostej funkcji używać kreatora. Należy jednak pamiętać że środowisko zostało stworzone z myślą o osobach nie będących programistami a jedynie posiadających wiadomości z dziedziny budowy i działania wirtualnych przyrządów pomiarowych. W związku z tym szereg podpowiedzi i kreatorów zostało dodanych do programu.

LW1 M2 CZ2 Slajd58.png Należy pamiętać ze w języku C porównacie dwóch wartości odbywa się poprzez podwójny znak równości. Pojedynczy znak równości oznacza podstawienie. Jest to częsty błąd, niestety środowisko na etapie kompilacji nie sygnalizuje wystąpienia niejasności w kodzie.

LW1 M2 CZ2 Slajd59.png Instrukacja warunkowa if(...)

LW1 M2 CZ2 Slajd60.png Wstawienie funkcji Set Control Value pozwalającej na ustawienie poziomu w zbiorniku. Funkcje z grupy Set wysyłają dane do elementów. Różnica pomiędzy funkcją Get a Set Control Value jest widoczna w argumencie Value. Przekazujemy tutaj kopię zmiennej a nie adres (bez operatora adresu &).

LW1 M2 CZ2 Slajd61.png Kod obsługi zdarzenia EVENT_COMMIT.

LW1 M2 CZ2 Slajd62.png Kod obsługi zdarzenia EVENT_VAL_CHANGED.

LW1 M2 CZ2 Slajd63.png Wszystkie niezbędne modyfikacje kodu C i interfejsu zostały wprowadzone. Można skompilować i uruchomić aplikację. Aplikacja uruchamia się poprawnie, jednakże przy próbie ruszenia suwakiem aplikacja zgłasza błąd. Oznacza on że aplikacja w linii 45 dostała wskaźnik do zmiennej typu int a powinien być wskaźnik do zmiennej typu double. Takie błędy będą się zdarzały przy korzystaniu z kreatorów. Należy nacisnąć przycisk Break. Następnie aby zatrzymać definitywnie program należy z menu górnego nacisnąć przycisk STOP w przeciwnym razie nie będzie można edytować kodu aplikacji.

LW1 M2 CZ2 Slajd64.png Na slajdzie przedstawiona została informacja o wystąpieniu błędu. Czasami może się zdarzyć że środowisko będzie zgłaszało błąd dopiero w następnej linii. Sytuacja będzie miała miejsce np. gdy nie wstawimy średnika na końcu linii.

LW1 M2 CZ2 Slajd65.png Zgodnie z sugestią środowiska aby usunąć błąd należy zmienić typ zmiennej wartosc z int na typ double. Jak zwykle można to zrobić na wiele sposobów: zmienić ręcznie deklarację lub użyć kreatora. Jeżeli decydujemy się na użycie kreatora należy ustawić kursor na nazwie funkcji GetCtrlVal w linii w której wystąpił błąd i nacisnąć klawisz Ctrl+P aby przywołać formularz funkcji. Następnie w polu Value należy ustawić kursor i nacisnąć przycisk deklaracji zmiennej (Declare Variable…).

LW1 M2 CZ2 Slajd66.png Przywołany zostanie formularz deklaracji zmiennych. W polu Variable Type należy zmienić typ int na double a następnie nacisnąć przycisk OK. Można zamknąć formularz bez ponownego wstawiania funkcji (w argumentach funkcji nic nie uległo zmianie). Kreator deklaracji zmiennych dostawił wpis double wartosc. Niestety pozostał stary wpis deklaracji int wartosc który należy ręcznie usunąć z kodu.

Po tej operacji aplikacja będzie działa poprawnie.


LW1 M2 CZ2 Slajd67.png Poprawny kod obsługi zdarzenia.

LW1 M2 CZ2 Slajd68.png Prezentacja działania zdarzeń.

LW1 M2 CZ2 Slajd69.png

LW1 M2 CZ2 Slajd70.png

LW1 M2 CZ2 Slajd71.png

LW1 M2 CZ2 Slajd72.png

LW1 M2 CZ2 Slajd73.png