Autor podstrony: Krzysztof Zajączkowski

Stronę tą wyświetlono już: 4169 razy

Graficzny interfejs tworzenia szablonów własnych okien dialogowych

Utwórzmy nowy projekt o nazwie PrzeliczanieJednostek, do projektu dodać należy plik wndmain.cpp oraz plik zasobów (w sposób już omawiany wcześniej) poprzez dodanie tylko i wyłącznie jednego elementu Dialog, by oczom naszym ukazał się widok z poniższego rysunku.

Podstawowy szablon okna dialogowego
Rys. 1
Podstawowy szablon okna dialogowego

Wiele osób zarzuca WinApi brak możliwości ręcznego tworzenia interfejsu programu, nie jest to (jak widać) jednak do końca prawdziwym stwierdzeniem. Podstawowe okienko nie ma zbyt wiele elementów, ot dwa przyciski wewnątrz formy (okienka, w którym znajdują się wszystkie kontrolki). Oczywiście ten stan rzeczy można łatwo zmienić, albowiem okazuje się, że wystarczy wcisnąć kombinację klawiszy Ctrl+Alt+X lub (jak kto woli) wybrać z menu View→Toolbox, aby naszym oczom ukazało się jak za dotknięciem czarodziejskiej różdżki okienko z poniższego rysunku.

Okno narzędziowe Toolbox
Rys. 2
Okno narzędziowe Toolbox

Przez grzeczność i szacunek do czytelnika oraz (co tu dużo pisać) szacunek do samego siebie, nie będę tutaj wymieniał i opisywał wszystkich elementów dostępnych na liście okna Toolbox. Jest tych elementów sporo, a jeżeli ktoś chce się nauczyć ich wszystkich to może to zrobić już samodzielnie na własną rękę. Ja postaram się wykorzystać kilka z tych elementów do stworzenia bardzo prostego programu, który będzie przeliczał jednostki długości.

Należy dodać do szablonu okna elementy widoczne na poniższym rysunku, którymi są:

Widok okna dialogowego z dodanymi elementami
Rys. 3
Widok okna dialogowego z dodanymi elementami.

Przydałoby się nadać jakieś konkretne nazwy kontrolkom Static text, tak aby opisywały one poprawnie poszczególne kontrolki pod nimi się znajdujące. Czym prędzej więc zaznaczyć należy pierwszą kontrolkę a następnie wcisnąć kombinację klawiszy Alt+Enter lub (jak kto woli) View→Other windows→Properties window, by ukazało się okno Properties. W oknie tym należy zmienić tekst wpisany w polu Caption z Static na Wartość przeliczana:. Dla kolejnej kontrolki należy zmienić to samo pole na Wartość przeliczona:, dla kolejnego pola: Jednostka początkowa: oraz dla ostatniego Jednostka końcowa:. Dodatkowo w obu tych kontrolkach należy zmienić wartość pola Sort z true na false.

Dla elementów typu Edit control warto też zmienić nazwę zawartą w polu ID, dla pierwszego od lewej z ID_EDIT1 na ID_PRZELICZANE, oraz dla drugiego z ID_EDIT2 na ID_PRZELICZONE.

Dla elementów typu Edit Box warto też zmienić nazwę zawartą w polu ID, dla pierwszego od lewej z ID_EDITBOX1 na ID_JEDN_PRZELICZANE, oraz dla drugiego z ID_EDITBOX2 na ID_JEDN_PRZELICZONE.

Na koniec warto jeszcze zaznaczyć samą formę i zmienić jej właściwości w oknie Properties w polu Caption z Dialog na Przeliczanie jednostek długości oraz pole ID z IDD_DIALOG1 na IDD_WINDOW.

Na koniec pozbądźmy się w perfidny sposób przycisku Cancel, który nie będzie nam potrzebny do szczęścia oraz zmieńmy właściwość przycisku OK na Przelicz w polu Caption okna Properties.

Po wszystkich tych zabiegach szablon okna dialogowego powinien wyglądać tak, jak na poniższym rysunku.

Okno dialogowe po zmianach oraz pasek narzędziowy umożliwiający sterowanie położeniem elementów okna.
Rys. 4
Okno dialogowe po zmianach oraz pasek narzędziowy umożliwiający sterowanie położeniem elementów okna: 1 - włączanie podglądu okna dialogowego; 2 - przyciski umożliwiające wyrównywanie elementów; 3 - przyciski związane z wyrównywaniem względem okna; 4 - wyrównywanie szerokości lub wysokości zaznaczonej grupy kontrolek; 5 - przełącza widok w tryb siatki.

Kod programu

Nadszedł najwyższy czas i najwyższa pora, aby napisać kod programu, który omówię kolejno w komentarzach:

#include <windows.h> #include <stdio.h> // biblioteka potrzebna do zamiany tekstu na liczbę i na odwrót #include "resource.h" // plik zasobów BOOL CALLBACK DlgProcPrzeliczanie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam){ // procedura okna dialogowego static HWND edit_in; // uchwyt kontrolki statycznej edit, do której użytkownik powinien wpisać wartość przeliczaną static HWND edit_out; // uchwyt kontrolki statycznej edit, do której program będzie wypisywał wynik przeliczenia static HWND box_units_in; // kontrolka wyboru jednostki wejściowej static HWND box_units_out; // kontrolka wyboru jednostki wyjściowej static double units_calc[] = {1, 10e-6, 10e-9, 10e-10,0.94605e16, 3.0857e16, 1.496311e11, 1.852e3, 1.852e3, 2.54e-2,0.37594e-3, 0.451128e-2,1.804511e-2}; // tablica przeliczników (kolejność odpowiada kolejności wstawionych elementów kontrolek COMBOBOX switch(msg){ // przetwarzanie komunikatów case WM_INITDIALOG: // inicjalizacja okna dialogowego { edit_in = GetDlgItem(hDlg, ID_PRZELICZANE); // funkcją GetDlgItem mogę pobrać uchwyt okna potomnego o podanym identyfikatorze edit_out = GetDlgItem(hDlg, ID_PRZELICZONE); box_units_in = GetDlgItem(hDlg, ID_JEDN_PRZELICZANE); box_units_out = GetDlgItem(hDlg, ID_JEDN_PRZELICZONE); // =========== DODAWANIE ELEMENTÓW DO PIERWSZEGO COMBOBOXA ======================== SendMessage(box_units_in, CB_ADDSTRING, 0, (LPARAM) L"metr [m]"); SendMessage(box_units_in, CB_ADDSTRING, 0, (LPARAM) L"mikron [μ]"); SendMessage(box_units_in, CB_ADDSTRING, 0, (LPARAM) L"milimikron [mμ]"); SendMessage(box_units_in, CB_ADDSTRING, 0, (LPARAM) L"angstrem [Å]"); SendMessage(box_units_in, CB_ADDSTRING, 0, (LPARAM) L"rok świetlny [-]"); SendMessage(box_units_in, CB_ADDSTRING, 0, (LPARAM) L"parsek [pc]"); SendMessage(box_units_in, CB_ADDSTRING, 0, (LPARAM) L"jednostka astronomiczna długości [AU/UA]"); SendMessage(box_units_in, CB_ADDSTRING, 0, (LPARAM) L"mila morska [-]"); SendMessage(box_units_in, CB_ADDSTRING, 0, (LPARAM) L"kabel [-]"); SendMessage(box_units_in, CB_ADDSTRING, 0, (LPARAM) L"cal [in]"); SendMessage(box_units_in, CB_ADDSTRING, 0, (LPARAM) L"punkt typograficzny [-]"); SendMessage(box_units_in, CB_ADDSTRING, 0, (LPARAM) L"cycero [-]"); SendMessage(box_units_in, CB_ADDSTRING, 0, (LPARAM) L"kwadrat [-]"); // ============== USTAWIENIE POCZĄTKOWEGO POLA ZAZNACZENIA KONTROLKI COMBOBOX ================ SendMessage(box_units_in, CB_SETCURSEL, 0, 0); // =========== DODAWANIE ELEMENTÓW DO DRUGIEGO COMBOBOXA ======================== SendMessage(box_units_out, CB_ADDSTRING, 0, (LPARAM) L"metr [m]"); SendMessage(box_units_out, CB_ADDSTRING, 0, (LPARAM) L"mikron [μ]"); SendMessage(box_units_out, CB_ADDSTRING, 0, (LPARAM) L"milimikron [mμ]"); SendMessage(box_units_out, CB_ADDSTRING, 0, (LPARAM) L"angstrem [Å]"); SendMessage(box_units_out, CB_ADDSTRING, 0, (LPARAM) L"rok świetlny [-]"); SendMessage(box_units_out, CB_ADDSTRING, 0, (LPARAM) L"parsek [pc]"); SendMessage(box_units_out, CB_ADDSTRING, 0, (LPARAM) L"jednostka astronomiczna długości [AU/UA]"); SendMessage(box_units_out, CB_ADDSTRING, 0, (LPARAM) L"mila morska [-]"); SendMessage(box_units_out, CB_ADDSTRING, 0, (LPARAM) L"kabel [-]"); SendMessage(box_units_out, CB_ADDSTRING, 0, (LPARAM) L"cal [in]"); SendMessage(box_units_out, CB_ADDSTRING, 0, (LPARAM) L"punkt typograficzny [-]"); SendMessage(box_units_out, CB_ADDSTRING, 0, (LPARAM) L"cycero [-]"); SendMessage(box_units_out, CB_ADDSTRING, 0, (LPARAM) L"kwadrat [-]"); // ============== USTAWIENIE POCZĄTKOWEGO POLA ZAZNACZENIA KONTROLKI COMBOBOX ================ SendMessage(box_units_out, CB_SETCURSEL, 0, 0); return FALSE; } case WM_COMMAND: // przetwarzanie komunikatów pochodzących od okien potomnych { switch(LOWORD(wParam)){ case IDOK: // gdy przycisk Przelicz wysyła komunikat { if(HIWORD(wParam) == BN_CLICKED){ // jak użytkownik kliknął przycisk to wchar_t val[100]; // bufor GetWindowText(edit_in, val, 100); // pobieram tekst okna kontrolki edit_in double d_val = 0; // bufor na liczbę if(wcslen(val)){ // jak dłigość tekstu jest różna od zera to d_val = _wtof(val); // zamieniaj na double int in = SendMessage(box_units_in, CB_GETCURSEL, 0, 0); // pobieram indeks jednostki wejściowej int out = SendMessage(box_units_out, CB_GETCURSEL, 0, 0); // pobieram indeks jednostki wyjściowej d_val *= units_calc[in] / units_calc[out]; // przeliczanko swprintf_s(val,L"%e", d_val); // zamiana z double na tekst SetWindowText(edit_out, val); // ustawienie tekstu w oknie edit_out }else{ MessageBox(NULL,L"Musisz coś wpisać", L"Błąd",MB_OK); // jak w oknie edit_in nie ma tekstu to trzeba powiadomić o tym użytkownika } } return FALSE; // zwracam fałsz } case IDCANCEL: // gdy przycisk zamykania okna zostanie wciśnięty to { EndDialog(hDlg, TRUE); // kończ żywot okna dialogowego return TRUE; // zwracaj prawdę } break; } } break; } return FALSE; // zwracaj fałsz } int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR , int ){ // ================== OKNO DIALOGOWE =================== DialogBox( hInst, // uchyt instancji programu MAKEINTRESOURCE(IDD_WINDOW), // pobieranie identyfikatora zasobu zawierającego szablon okna dialogowego NULL, // to powinien być uchwyt okna rodzica, ale to okno nie ma rodzica i dlatego NULL DlgProcPrzeliczanie); // wskaźnik do procedury okna dialogowego return 0; // i zwracamy zero }

Użyte po raz pierwszy w kodzie funkcje

Oto lista funkcji, które zostały użyte po raz pierwszy w kodzie programu: