Projektowanie i programowanie aplikacji biznesowych Wykład 2
Kontrolki w Windows API Aby korzystać z kontrolek należy dołączyć plik nagłówkowy o nazwie commctrl.h oraz bibliotekę o nazwie libcomctl32.a. Kontrolki dla danego okna tworzy się (zazwyczaj) za pośrednictwem komunikatu WM_CREATE, który jest wysyłany po utworzeniu okna, dzięki czemu zaraz po utworzeniu okna, tworzone są kontrolki na tym oknie. Kontrolki to po prostu takie "małe" okienka, które wchodzą w skład "dużego" okna macierzystego. Tak samo jak "zwykłe" okna, kontrolki tworzymy więc funkcjami CreateWindow oraz CreateWindowEx. Na przykład tworząc przycisk wpisujemy "BUTTON". Pozostałe klasy, których możemy użyć, to m.in.: COMBOBOX, EDIT, LISTBOX, SCROLLBAR, STATIC.
Parę słów o polu edycji (kontrolka Edit) Na początku należy dołączyć plik nagłówkowy o nazwie commctrl.h, a w opcjach projektu bibliotekę libcomclt32.a. Samą kontrolkę tworzy się za pośrednictwem funkcji CreateWindowEx. #include <windows.h> #include <commctrl.h> HWND hedit1; int WINAPI WinMain( HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow ) { wc.lpszclassname = NazwaKlasy; HWND hwnd=createwindowex( WS_EX_CLIENTEDGE, NazwaKlasy, "SQLite w praktyce", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 900, 700, NULL, NULL, hinstance, NULL ); hedit1 = CreateWindowEx( WS_EX_CLIENTEDGE, "EDIT", NULL, WS_CHILD WS_VISIBLE WS_BORDER, 10, 20, 860, 30, hwnd, NULL, hinstance, NULL ); }
Obsługa tekstu w kontrolce Funkcją GetWindowText() pobiera tekst z kontrolki do łańcucha znaków. int GetWindowText(HWND hwnd, LPSTR lpstr, int size) gdzie: HWND hwnd - to uchwyt do kontrolki, z której pobieamy tekst, LPSTR lpstr - to wskaźnik do łańcucha znaków, do którego zostanie zapisany tekst z kontrolki, INT size - określa ile znaków ma zostać przepisane do łańcucha znaków. Jeżeli funkcja się nie powiedzie, zwraca 0, natomiast jeżeli wszystko pójdzie ok, zwraca długość odczytanego tekstu. Funkcja SetWindowText() służy do wstawiania tekstu do kontrolek. BOOL SetWindowText(HWND hwnd, LPCSTR lpstr) gdzie: HWND hwnd to uchwyt kontrolki, do której ma zostać zapisany tekst, LPCSTR lpstr - to wskaźnik do łańcucha znaków, który zostanie zapisany w kontrolce. Jeżeli funkcja się nie powiedzie zwraca 0, jeżeli tak zwraca 1.
Style kontrolki Edit ES_MULTILINE - powoduje, że kontrolka jest "wieloliniowa, ES_LEFT - tekst w kontrolce będzie wyrównywany do lewej strony (wartość domyślna), ES_RIGHT - tekst w kontrolce będzie wyrównywany do prawej strony, ES_CENTER - tekst będzie umieszczany na środku linii, ES_HSCROLL - powoduje, że gdy wyjdziemy poza obszar kontrolki w poziomie podczas pisania, widok tekstu w kontrolce automatycznie będzie się przesuwał (działa tylko z ES_MULTILINE), ES_VSCROL - powoduje, że gdy wyjdziemy poza obszar kontrolki w pionie podczas pisania, widok tekstu w kontrolce automatycznie będzie się przesuwał (działa tylko z ES_MULTILINE), WS_AUTOHSCROLL - powoduje pojawienie się paska przewijania na dole kontrolki (działa tylko z ES_MULTILINE), WS_AUTOVSCROL - powoduje pojawienie się paska przewijania z prawej strony kontrolki (działa tylko z ES_MULTILINE), ES_READONLY - styl ten blokuje pisanie w kontrolce przez użytkownika. Kontrolka nadaje się tylko do odczytu, ES_PASSWORD - styl ten używamy do wpisywania haseł, powoduje, że zamiast liter pojawiają się gwiazdki(kropki).
Kontrolka Combobox czyli pole, które po naciśnięciu rozwija listę wyboru(opcji). HWND hcb1; hcb1 = CreateWindowEx(WS_EX_CLIENTEDGE, "COMBOBOX", NULL, WS_CHILD WS_VISIBLE WS_BORDER CBS_DROPDOWNLIST, 45, 55, 120, 200, hwnd, NULL, hinstance, NULL); Zamiast "COMBOBOX" można zastosować WC_COMBOBOX. Styl CBS_DROPDOWNLIST blokuje możliwość wpisania własnego tekstu co umożliwia styl CBS_DROPDOWN. Listę wyboru możliwych opcji możemy wypełnić poprzez komunikat CB_ADDSTRING wysyłany do ComboBox'a. SendMessage(hCB1, CB_ADDSTRING, 0, (LPARAM) "Treść 1"); SendMessage(hCB1, CB_ADDSTRING, 0, (LPARAM) "Treść 2"); Aby ustawić daną opcję jako aktywną (aktualnie wybraną) należy do kontrolki wysłać komunikat CB_SETCURSEL za pośrednictwem funkcji SendMessage: SendMessage(hCB1, CB_SETCURSEL, (WPARAM)0, 0) gdzie jako trzeci parametr podajemy numer opcji wyboru, liczony od 0 w górę, który stanie się aktywny(wybrany). Aby sprawdzić jaka opcja jest aktualnie wybrana, należy wysłać do kontrolki komunikat CB_GETCURSEL. int index=sendmessage(hcb1, CB_GETCURSEL, 0, 0) Wartość index przyjmie numer aktualnie wybranej opcji (liczonej od 0).
Kontrolki w Windows API - w praktyce Przykład Założenia: realizacja programu w WINAPI, w ramach którego użytkownik będzie mógł wprowadzać dane do dwóch następujących baz (tabel) danych (utworzonych w programie SQLLiteStudio): - Tabela grupa id_grupy (varchar(15), klucz główny), data_utworzenia (date, nie NULL), Wydzial (varchar(10), nie NULL ), Kierunek (varchar(10), nie NULL ), Starosta (integer, nie NULL, domyślna wartość 0) - Tabela student nr_indeksu (integer, klucz główny), nazwisko (varchar(20), nie NULL ), imie (varchar(20), nie NULL ), id_grupy (varchar(15), klucz obcy -> grupa.id_grupy), data_urodzenia (date), SWPE (real, nie NULL, domyślna wartość 0) Ponadto zakłada się ograniczenie możliwości błędnego wprowadzenia danych poprzez stworzenie list zawierających możliwe wartości dla pól Wydzial i Kierunek (z pliku tekstowego) oraz pola id_grupy (lista zawierająca wartości pola grupa.id_grupy).
Utworzenie tabeli grupa
Utworzenie tabeli student
Zdefiniowanie klucza obcego
W specyfikacji założono, że dane dla pól Wydzial i Kierunek wprowadzone zostaną za pośrednictwem pliku tekstowego. W prezentowanym przykładzie do wprowadzenia danych do baz zastosowano kontrolki Edit oraz ComboBox (styl CBS_DROPDOWNLIST czyli bez możliwości wprowadzania własnych danych ). Ponadto w celach weryfikacyjnych postanowiono uwzględnić możliwość realizacji zapytań SQL, które wprowadza się za pośrednictwem kontrolki Edit (styl ES_MULTILINE) a wyniki zapytań wyświetlane są w kontrolce ListBox.
Deklaracja uchwytów do kontrolek oraz funkcji zastosowanych w programie.
Tworzenie kontrolek (wybranych) Funkcje realizujące pobieranie danych wpisywanych do kontrolek (Edit ow i ComboBox ów).
Fragment obsługujący zdarzenie naciśnięcia przycisku Button1, w ramach którego realizowane jest zapytanie SQL. Wypełnienie opcji w ComboBox ach na podstawie danych zawartych w pliku tekstowym. Czyszczenie całych listy wyboru ComboBox a hcb1 zrealizowano następująco: SendMessage( hcb1, CB_RESETCONTENT, 0,0 ) a dopisywanie wartości (wartosc -> string odczytany z pliku tekstowego): SendMessage(hCB1, CB_ADDSTRING, 0, (LPARAM) wartosc.c_str())
Funkcje (wyniksql, wpiszcb3) wykonywane n-krotnie, gdzie n jest liczbą rekordów jakie generuje zapytanie SQL (w ramach funkcji sqlite3_exec). Pod l_kolumn kryje się liczba kolumn jakie zwraca zapytanie natomiast nazwy kolumn i przypisane do nich wartości przechowują zmienne wskaźnikowe wartosci oraz nazwa_kolumny. Funkcja wpiszcb3 realizuje wypełnienie listy wyboru ComboBox a hcb3 zawierającego elementy grupa.id_grupy.
Obsługa zdarzenia naciśnięcia przycisku hbutton3, w ramach którego następuje wprowadzenie danych do tabeli grupa.
Obsługa zdarzenia naciśnięcia przycisku hbutton4, w ramach którego następuje wprowadzenie danych do tabeli student. W prezentowanym kodzie (programie) nie uwzględniono m.in. sprawdzenia czy wszystkie dane zostały wprowadzone jednak sposób realizowania tego elementu powoduje, że brak jakiejkolwiek danej wygeneruje błąd zapytania SQL o czym użytkownik zostanie poinformowany. Poza tym nie zostały uwzględnione niuanse związanie z niektórymi polami (np. pole Starosta, do którego w założeniu powinno wprowadzić numer indeksu studenta pełniącego funkcje starosty w danej grupie).
Wprowadzenie danych opcji wyboru następuje poprzez naciśnięcie przycisku Aktualizuj listy CB
Błąd wpisu danych do tabeli grupa brak wartości w polu starosta.
Modyfikacja umożliwiająca niewprowadzanie danych do pola Starosta (teoretycznie można nie podawać wartości 0 ponieważ na etapie tworzenia tabeli grupa określono wartość domyślną dla tego pola).
Modyfikacja pola (hedit1), za pomocą którego użytkownik realizuje zapytania SQL.
Modyfikacja zawartości pola grupa.starosta. Brak sprecyzowanego warunku spowodował przypisanie jednej wartości (213131) do wszystkich rekordów.
Aktualizacja danych w tabeli grupa.
Zastosowanie funkcji sqlite3_get_table ( łatwiejsza metoda dostępu do danych zawartych w tabelach alternatywa wobec sqlite3_exec).
Efekt realizowania zapytania SQL za pośrednictwem funkcji sqlite_get_table (nazwy kolumn w pierwszym wierszu ). Kolejnym krokiem (usprawnieniem) programu jest uwzględnienie możliwości eksportowania i importowania danych (np. z pliku) oraz możliwości edycji poszczególnych rekordów poprzez modyfikowanie zawartości kontrolek (do realizacji ;)).