[ Pobierz całość w formacie PDF ]
.7.Rysunek 5.7.Sposóbrozmieszczeniaposzczególnychkomponentów waplikacjirealizującejtransmisjęszeregową zczasowympróbkowaniemłączaWiększość użytych przycisków pełnić będzie taką samą rolę jak we wcześniejszychprogramach, dlatego nie będziemy w tym miejscu szczegółowo omawiać ich znaczenia.Zastanowimy się jednak dokładniej nad parą zdarzeń ReceiveClick() (przycisk Odbierz,którego cechę Name określiłem jako Receive) oraz CheckCommClick() (przycisk Monitorujłącze CheckComm).Naciskając Odbierz, powodujemy wywołanie funkcji obsługi zdarzenia:void __fastcall TForm1::ReceiveClick(TObject *Sender){if (hCommDev > 0){.CheckComm->Enabled = TRUE;GetCommMask(hCommDev, &fdwEvtMask);SetCommMask(hCommDev, EV_RXCHAR);bResult = Read_Comm(hCommDev, &Buffer_I[0], &Number_Bytes_Read,sizeof(Buffer_I));if (bResult && Number_Bytes_Read != 0){141 RichEdit2->Text = Buffer_I;Edit2->Text= " Dane zostały przetransferowane.";}}.}Możemy albo spokojnie czekać, aż coś się pojawi w buforze wejściowym, albo po uaktywnieniuprzycisku Monitoruj łącze cyklicznie je próbkować w poszukiwaniu pierwszego znaku, który siętam znajdzie.Teraz już wiadomo, dlaczego wcześniej użyliśmy maski EV_RXCHAR.Powybraniu monitoringu łącza aplikacja zapyta, czy naprawdę chcemy to wykonać.Jeżelipotwierdzimy, spowodujemy załączenie funkcji obsługi zdarzenia TimerOnTimer() orazwyświetlenie odpowiedniego komunikatu w komponencie Edit2.W przeciwnym wypadkuprzycisk Monitoruj łącze pozostanie wygaszony i Timer będzie nieaktywny.Załóżmy, żenacisnęliśmy OK.void __fastcall TForm1::CheckCommClick(TObject *Sender){if (Application->MessageBox(" Aącze będzie monitorowane do czasu"" odebrania znaku." , "Uwaga!",MB_OKCANCEL) != IDOK){CheckComm->Enabled = FALSE;Timer1->Enabled = FALSE;Abort();}else{Timer1->Enabled = TRUE; // uaktywnia czasowe próbkowanie// łączaEdit2->Text = "Aącze jest monitorowane.";}.}Uaktywnimy tym samym czasowe, w odstępach 1 milisekundy, wyzwalanie zdarzenia:void __fastcall TForm1::TimerOnTimer(TObject *Sender){if (WaitCommEvent(hCommDev, &fdwEvtMask, NULL) > 0)// sprawdza czy{ // nadszedł znakBeep();Edit2->Text = " Transfer danych.";GetCommMask(hCommDev, &fdwEvtMask);SetCommMask(hCommDev, EV_TXEMPTY);Timer1->Enabled = FALSE;CheckComm->Enabled = FALSE;}}Będzie ono aż do skutku cyklicznie sprawdzać, czy do portu identyfikowanego przez hCommDevprzyszedł jakiś znak.Wykorzystałem tu znaną już, niezwykle pożyteczną funkcjęWaitCommEvent() z uprzednio wybraną dla fdwEvtMask stałą EV_RXCHAR.Jeżeli widoczny142powyżej warunek będzie spełniony, aplikacja da nam sygnał dzwiękowy, że coś już jest w buforze.Można oczywiście w miejscu Beep() umieścić jakiś komunikat, np.w stylu MessageBox().Należy przy tym pamiętać, aby w takiego typu konstrukcjach warunkowych zawsze dla funkcjiWaitCommEvent() ustalać nową maskę, najlepiej EV_TXEMPTY.W przeciwnym raziebędziemy mieli kłopoty z wysłaniem czegokolwiek.Jeżeli po usłyszeniu sygnału (lub zobaczeniuinnego komunikatu) naciśniemy powtórnie Odbierz, będziemy mogli obejrzeć otrzymane dane iewentualnie zapisać je do pliku.Ten typ próbkowania łącza musi się sam wyłączać, dlatego wzapisie funkcji obsługi zdarzenia TimerOnTimer() umieściłem instrukcję:Timer1->Enabled = FALSE;Trzeba zawsze o tym pamiętać, gdyż w przeciwnym razie bardzo łatwo zawiesimy program (i todość poważnie).Ujmując rzecz ogólnie, należy mieć sporo wyczucia przy korzystaniu z niezwykleużytecznego Timera.Na rysunku 5.8 pokazano wygląd naszej aplikacji, której projekt znajduje się w katalogu\KODY\BUILDER\RS_06\p_RS_06.bpr.Wydruk 5.7 przedstawia kompletny kod jej głównegomodułu.Rysunek 5.8.Formularz głównyprojektup_RS_06.bpr pouruchomieniuWydruk 5.7.Kod aplikacji realizującej transmisję plików, wykorzystującej komponent TTimer//--- kompilować z borlndmm.dll oraz cc3250mt.dll --------------//--------RS_06.cpp-----#include#pragma hdrstop#include "RS_06.h"#pragma package(smart_init)#pragma resource "*.dfm"#define cbOutQueue 1024 //rozmiar bufora danych wyjściowych143#define cbInQueue 1024 //rozmiar bufora danych wejściowych#define TIMER_INTERVAL 1 //przedział czasu próbkowania TimeraTForm1 *Form1;AnsiString New_File; // przechowuje nazwę plikuHFILE hfile_s; // identyfikator plikuchar Buffer_O[cbOutQueue]; // bufor danych wyjściowychchar Buffer_I[cbInQueue]; // bufor danych wejściowychDWORD Number_Bytes_Read; // liczba bajtów do czytaniaHANDLE hCommDev; // identyfikator portuLPCTSTR lpFileName; // wskaznik do nazwy portuDCB dcb; // struktura kontroli portu szeregowegoDWORD fdwEvtMask; //informacja o aktualnym stanie transmisjiCOMSTAT Stat; // dodatkowa informacja o zasobach portuDWORD Errors; // reprezentuje typ ewentualnego błęduBOOL bResult ; // zmienna boolowska//--------------------------------------------------------------------int __fastcall Close_Comm(HANDLE hCommDev){CloseHandle(hCommDev);return TRUE;}//--------------------------------------------------------------------int __fastcall Write_Comm(HANDLE hCommDev,DWORD nNumberOfBytesToWrite){DWORD NumberOfBytesWritten;GetCommMask(hCommDev, &fdwEvtMask);SetCommMask(hCommDev, EV_TXEMPTY);if (WriteFile(hCommDev, &Buffer_O[0],nNumberOfBytesToWrite, &NumberOfBytesWritten, NULL) > 0){WaitCommEvent(hCommDev, &fdwEvtMask, NULL);return TRUE;}elsereturn FALSE;}//--------------------------------------------------------------------int __fastcall Read_Comm(HANDLE hCommDev,LPDWORD lpNumberOfBytesRead, DWORD Buf_Size){DWORD nNumberOfBytesToRead;ClearCommError(hCommDev, &Errors ,&Stat);if (Stat.cbInQue > 0){if (Stat.cbInQue > Buf_Size)nNumberOfBytesToRead = Buf_Size;elsenNumberOfBytesToRead = Stat.cbInQue;ReadFile(hCommDev, &Buffer_I[0], nNumberOfBytesToRead,lpNumberOfBytesRead, NULL);144 }else*lpNumberOfBytesRead = 0;return TRUE;}//--------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner){}//--------------------------------------------------------------------void __fastcall TForm1::CloseCommClick(TObject *Sender){Timer1->Enabled = FALSE;CheckFileSave();Close_Comm(hCommDev);Application->Terminate();}//--------------------------------------------------------------------void __fastcall TForm1::CheckFileSave(void){if (RichEdit1->Modified){switch(MessageBox(NULL, "Zawartość pliku lub okna została"" zmieniona
[ Pobierz całość w formacie PDF ]