Autor podstrony: Krzysztof Zajączkowski

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

Wstęp

Kolejnym często spotykanym w wielu programach standardowym oknem systemu Windows jest okno wyboru czcionki, które w polskiej wersji językowej ma nazwę Czcionka. Do wywołania tego okna służy funkcja ChooseFont, która przyjmuje jako jedyny parametr wskaźnik do struktury typu CHOOSEFONT. Aby skorzystać z tej funkcji konieczne jest załączenie do projektu biblioteki:

#include <commdlg.h>

Wykorzystam funkcję w projekcie myNotepad by w praktyczny sposób pokazać, jak można w prosty sposób zwiększyć funkcjonalność tego programu.

Okno dialogowe Czcionki
Rys. 1
Okno dialogowe Czcionki

Dodawanie modyfikacja menu programu myNotepad

Zanim zacznę modyfikację samego kodu programu warto dodać do menu głównego dodatkowe menu Ustawienia i w tej pozycji dodatkową pozycję Czcionka, identyfikator tej pozycji powinien być z automatu ustawiony na ID_USTAWIENIA_CZCIONKA, jeżeli tak nie jest to proszę to zmienić. Do zasobów można się dostać wciskając kombinację Ctrl+Shift+E lub wybierając z menu View->Resource View i pojawi się okno o nazwie Resource View, w którym na rozwijanej liście można znaleźć menu z projektu. Kliknięcie tej pozycji otworzy edytor graficzny tegoż menu, które po wprowadzeniu modyfikacji powinno wyglądać jak na poniższym rysunku.

Zmodyfikowane menu projektu myNotepad
Rys. 2
Zmodyfikowane menu projektu myNotepad

Wprowadzenie poprawek do kodu programu myNotepad

Menu zostało zmodyfikowane, trzeba teraz na samym początku projektu załączyć wcześniej wspomniany plik commdlg.h. Teraz zaraz za bibliotekami załączonymi do projektu wstawić trzeba następującą funkcję odpowiedzialną za pozyskiwanie uchwytu czcionki:

#include <windows.h> #include <commdlg.h> #include <locale.h> #include "resource.h" #define ID_EDIT 3 // identyfikator kontrolki edit do przechowywania tekstu HFONT GetChooseFont(HWND hWnd, LOGFONT *lf, COLORREF *c){ CHOOSEFONT cf; ZeroMemory(&cf, sizeof(cf)); // zerowanie pól struktury cf.lStructSize = sizeof(cf); // ustawienie pola określającego rozmiar struktury cf.hwndOwner = hWnd; // uchwyt okna cf.lpLogFont = lf; // wskaźnik do struktury LOGFONT cf.Flags = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS | CF_EFFECTS; // flagi: użyj wskaźnika do struktury lpLogFont do zainicjalizowania ustawień; wyświetlanie tylko czcionek wspieranych przez system; wyświetlaj dodatkowe opcje podkreślenia, przekreślenia i wyboru koloru czcionki if(ChooseFont(&cf)){ // wywołanie okna *c = cf.rgbColors; // pobieram kolor czcionki return CreateFontIndirect(lf); // tworzę uchwyt i go zwracam } return NULL; // zwracam NULL gdy nie została wybrana żanda czcionka }

Powyższy fragment kodu wstawiłem wraz z bibliotekami, które wcześniej zostały załączona aby wiadomo było, gdzie funkcję dodać do projektu. Jak widać, jeżeli funkcja ChooseFont zwróci TRUE to zwracam utworzony za pomocą funkcji CreateFontIndirect uchwyt do czcionki. Funkcja GetChooseFont przyjmuje trzy parametry, pierwszym jest oczywiście uchwyt okna rodzica, drugim jest wskaźnik na strukturę typu LOGFONT opisującą czcionkę natomiast trzeci to zmienna 24-bitowa typu COLORREF opisująca kolor w formacie rgb. Zmienna ta będzie używana do zmiany koloru czcionki rysowanej w kontrolce hedit.

Na sam początek w funkcji hwndProc dodać należy takie zmienna:

LRESULT CALLBACK hwndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ static RECT wndSize; static HWND hedit; static HFONT hf; // uchwyt czcionki static LOGFONT lf; // struktura opisująca czcionkę static COLORREF c; // kolor czcionki static OPENFILENAME ofn;

W powyższym wyrywku kodu opisane zostały komentarzem jedynie te elementy, które zostały dodane. Teraz w komunikacie WM_CREATE musi nastąpić znacząca zmiana:

lf = ncm.lfStatusFont; // tą linijkę trzeba dodać przed wywołaniem funkcji CreateFontIndirect hf=CreateFontIndirect(&ncm.lfStatusFont); // tutaj było HFONT font = .... c = RGB(0,0,0); // ustawienie koloru czcionki SendMessage(hedit, WM_SETFONT, (WPARAM) hf, 0); // tutaj zamiast hf było wcześniej font

Dodać należy do funkcji hwndProc obsługę następującego komunikatu związanego z zmianą koloru czcionki w kontrolce hedit:

case WM_CTLCOLOREDIT: // komunikat umożliwiający zmianę kolorów w kontrolce { if(lParam == (LPARAM)hedit){ // jak lParam jest uchwytem okna hedit to SetTextColor((HDC)wParam, c); // ustawiam kolor dla kontekstu urządzenia zawartego w wParam } return NULL; // zwracam null bo nie chcę zmieniać domyślnego koloru tła }

W komunikacie WM_COMMAND w sekcji związanej z obsługą menu należy dodać kod związany z obsługą kliknięcia dodanej pozycji menu:

switch(LOWORD(wParam)){ // niższe słowo parametru wParam zawiera identyfikator klikniętej pozycji menu case ID_USTAWIENIA_CZCIONKA: // opcja menu { HFONT nf = GetChooseFont(hWnd, &lf, &c); // wywołuję moją funkcję by wyświetlić okno i uzyskać nowy uchwyt czcionki if(nf){ // jeżeli uchwyt nie jest NULL to SendMessage(hedit, WM_SETFONT, (WPARAM) nf, 1); // ustawiam czcionkę kontrolki DeleteObject(hf); // zwalniam uchwyt starej czcionki hf = nf; // i zapamiętuję uchwyt nowej } } break;

W komunikacie WM_DESTROY przed wywołaniem funkcji PostQuitMessage należy zwolnić uchwyt czcionki:

case WM_DESTROY: { DeleteObject(hf); PostQuitMessage(0); } break;

Nowe funkcje i struktury

Lista nowo poznanych funkcji użytych w kodzie programu:

Lista nowo poznanych struktur użytych w kodzie: