Rozdzia� 22. MFC i elementy zaawansowanego interfejsu u�ytkownika W tym rozdziale: Zyskanie wi�kszej kontroli nad aplikacj� P�tla modalna Funkcja RunModalLoop () Okna modalne: nie tylko okna dialogowe Wewn�trz p�tli modalnej Tworzenie i zamykanie okien modalnych Dalsza rozbudowa okna modalnego Rysowanie poza obszarem roboczym Budowa przezroczystych bitmap w kontek�cie urz�dzenia Ten rozdzia� rozszerzy Tw� wiedz� o Windows i o bibliotece MFC. Klasy biblioteki MFC i ich domy�lne metody s� pot�nym narz�dziem, kt�re z pewno�ci� wystarczy w ogromnej wi�kszo�ci przypadk�w. Jednak posiadanie wiedzy o bardziej zaawansowanych w�a�ciwo�ciach oraz niskopoziomowych strukturach, na kt�rych zbudowana jest ca�a biblioteka, z pewno�ci� rozszerzy Twoje mo�liwo�ci jako programisty Windows. Na tych podstawach zosta�y zbudowane kolejne warstwy, za� same podstawowe klasy posiadaj� solidne fundamenty w postaci GDI API i definiowanych przez nie typ�w danych i struktur. W tym rozdziale nie b�dziesz tworzy� w�asnych obiekt�w interfejsu, lecz zamiast tego skorzystasz z pewnych niskopoziomowych w�a�ciwo�ci. Czasem potrzeba wi�kszej kontroli W pewnych sytuacjach wa�ne jest, by m�c starannie okre�li� spos�b, w jaki u�ytkownik mo�e wsp�pracowa� z aplikacj�. W rzeczywisto�ci, w pewnych przypadkach konieczne jest ograniczenie u�ytkownikowi mo�liwo�ci interakcji z ca�� reszt� systemu operacyjnego Windows. Nie trzeba jednak tego robi� tylko po to, by go ogranicza�. Na przyk�ad, modalne okna dialogowe omawiane w rozdziale 13., dawa�y programi�cie pewn� dodatkow� kontrol� na tym, co u�ytkownik m�g� zrobi� z aplikacj�. Modalne okno dialogowe jest sposobem na skierowanie uwagi u�ytkownika na pewn� operacj�. Aby m�c przej�� do interakcji z pozosta�� cz�ci� aplikacji, u�ytkownik musi zamkn�� okno dialogowe. Wszystkim nam od czasu do czasu zdarza si� denerwowa� na okna dialogowe, kt�re staj� si� modalne dla ca�ego systemu, mimo �e nie jest to w�a�ciwie konieczne. Pami�tasz te systemowe okna dialogowe, uniemo�liwiaj�ce prac� z systemem przed zamkni�ciem okna? Wi�c znajdujesz si� w takim dialogu, kt�ry chcia�by� pozostawi� otwarty, a w tym samym czasie zrobi� co� innego, cho�by skopiowa� plik. Jednak nie mo�esz tego zrobi�, zanim nie zamkniesz okna dialogowego. Musisz wi�c je zamkn��, trac�c wszystkie ustawienia tylko po to, aby m�c przenie�� plik z jednego miejsca w inne. Takie nieprzemy�lane wymuszanie kolejno�ci pracy z aplikacj� nie jest dobr� praktyk�. Jednak w pewnych sytuacjach konieczne jest zabezpieczenie u�ytkownika przed wykonaniem pewnych dzia�a� lub skupienie jego uwagi na pewien obszar w celu zapewnienia, �e zadanie zostanie doko�czone. Na przyk�ad, za��my, �e w pracowni komputerowej uczniowie korzystaj� z komputerowego samouczka na temat jakiej� aplikacji Windows. Za��my, �e lekcje zosta�y opracowane jako serie krok�w, w kt�rych s� przedstawiane kolejne polecenia i opcje aplikacji. Je�li kiedykolwiek zajmowa�e� si� uczeniem, z pewno�ci� wiesz, �e uczniowie niekoniecznie pod��aj� krok po kroku zgodnie z przebiegiem prezentacji. Zdarzaj� si� uczniowie, kt�rzy boj� si� nawet czegokolwiek dotkn��. Postawieni przed zbyt wieloma przyciskami i opcjami natychmiast si� gubi�, gdy� nie potrafi� odszuka� w�a�ciwych element�w na ekranie, pr�cz samej aplikacji istnieje przecie� tak�e sam system Windows, z jego oknami, paskiem zada�, ikonami, paskami stanu itd. Z kolei inni uczniowie, bardzo ciekawscy i niezale�ni, bez namys�u rzucaj� si� w wir opcji, aby zobaczy�, do czego s�u��. Otwieraj� menu po menu i zmieniaj� ustawienia, kt�rych znaczenia nie znaj�, a� w ko�cu nie mog� wr�ci� do stanu pocz�tkowego. Tak wi�c biedny instruktor musi po�wi�ci� sporo czasu, aby przywr�ci� aplikacj� do odpowiedniego stanu. W�a�nie w takich sytuacjach dobrze jest mie� pe�n� kontrol� nad tym, czego u�ytkownik mo�e dokona�. Aby pozna� tego rodzaju mo�liwo�ci, opracujesz dwa przyk�adowe programy. Poka�emy w nich, jak mo�na obs�u�y� niekt�re z omawianych przed chwil� zagadnie�. Pierwszy program demonstruje spos�b utworzenia okna modalnego. To znaczy, zamiast po prostu tworzy� modalne okno dialogowe za pomoc� AppWizarda, nauczysz si� samemu tworzy� modalne okno, nie b�d�ce oknem dialogowym. Nast�pnie rozszerzysz to okno o kilka dodatkowych element�w, kt�re przygotuj� Ci� do drugiego programu demonstracyjnego. Ten drugi program, oparty na pierwszym, umo�liwi Ci rysowanie na obszarze pulpitu, poza obszarem roboczym aplikacji. Cho� ta mo�liwo�� jest przydatna g��wnie w po��czeniu z oknami modalnymi, jednak takie rysowanie nie jest domen� wy��cznie takich okien. P�tla modalna Modalno�� okna osi�ga si�, korzystaj�c z metody odziedziczonej od klasy cwnd. Okna, bez wzgl�du na to czy s� to okna ramki, okna dialogowe czy jakiekolwiek inne okna wyprowadzone z klasy cwnd, posiadaj� wbudowan� mo�liwo�� stania si� modalnymi. Innymi s�owy, nie musisz wyprowadza� w tym celu swojej w�asnej, specjalnie modalnej klasy, gdy� mo�liwo�� uzyskania modalno�ci jest ju� wbudowana w klas� cwnd. Klasa cwnd posiada funkcj� sk�adow� o nazwie RunModalLoop (), bardzo prost� w wywo�aniu. Wymaga ona tylko jednego parametru, znacznika, wi�c mo�e si� wydawa� r�wnie� prosta w u�yciu. Jednak, tak jak cz�sto dzieje si� to w przypadkach korzystania z pewnych specjalnych mo�liwo�ci, u�ycie jej wymaga specjalnej obs�ugi zar�wno tworzenia, jak i niszczenia okna, kt�re ma sta� si� modalne. Oba zagadnienia zostan� om�wione w trakcie tworzenia aplikacji w tym rozdziale. Sama funkcja jest zadeklarowana nast�puj�co: int RunModa1Loop ( DWORD dwFlags); Przekazywany jest jej pojedynczy argument, okre�laj�cy, jakie komunikaty maj� by� przekazywane do okna - zajmiemy si� tym za moment. Teraz jednak przyjrzyjmy si�, co w�a�ciwie ta klasa robi. Wn�trze funkcji RunModalLoop() Dokumentacja Windows niewiele ma do powiedzenia na temat tej p�tli modalnej. Poza kr�tkim opisem sposobu wywo�ywania funkcji RunModalLoop() w celu pobierania, t�umaczenia i rozsy�ania komunikat�w, nie ma ani s�owa o jej dzia�aniu oraz o specjalnych przygotowaniach do jej u�ycia. Na szcz�cie, w takich przypadkach jak ten masz do dyspozycji ca�y kod �r�d�owy biblioteki MFC, dostarczany jako cz�� pakietu Yisual C++. Gdy kiedykolwiek natkniesz si� na co�, czego nie mo�esz zrozumie�, nie wahaj si� zajrze� �pod mask�". Z pewno�ci� natrafisz tam na rzeczy nie do ko�ca zrozumia�e, jednak znajdziesz tak�e odpowied� na wiele pyta�. Czytaj pliki nag��wkowe. Czytaj pliki .cpp, w kt�rych s� zdefiniowane klasy. W ten spos�b poszerzysz swoj� wiedz� i mo�liwo�ci programistyczne. Podobnie post�pimy w tym rozdziale w przypadku funkcji RunModalLoop(). Cho� poni�sza dyskusja dotyczy bezpo�rednio okien, pomo�e Ci jednak w zrozumieniu dzia�ania tak�e modalnych okien dialogowych. Pami�taj, �e klasa CDialog jest wyprowadzona z klasy cwnd, wi�c proces dzia�ania jest taki sam. Listing 22.1 zawiera aktualny kod implementuj�cy funkcj� RunModalLoop(), odczytany z pliku Wincore.cpp, dostarczanym przez Microsoft wraz z Visual C++. Odczytuj�c ten kod, mo�na natychmiast stwierdzi�, �e funkcja RunModalLoop () sk�ada si� w zasadzie z dw�ch p�tli zawartych w p�tli niesko�czonej. Niesko�czona p�tla ko�czy dzia�anie w momencie otrzymania przez okno komunikatu wyj�cia lub wyzerowania znacznika WF_CONTINUEMODAL. Zajmiemy si� tym za chwil�. Listing 22.1. Fragment kodu z pliku Wincore.cpp Microsoftu int CWnd::RunModalLoop(DWORD dwFlags) { // Okno musi by� utworzone ASSERT(::IsWindow(m_hWnd)); // Okno nie mo�e by� ju� w trybie modalnym ASSERT(!(m_nFlags & WF_MODALLOOP)); // Dla sprawdzania trybu pracy ja�owej BOOL bldle = TRUE; LONG lldleCount = 0; BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle()&WS_VISIBLE); HWND hWndParent = ::GetParent(m_hWnd); m_nFlags 1= (WF_MODALLOOPlWF_CONTINUEMODAL); MSG* pMsg = &AfxGetThread()->m_msgCur; // pobieranie i rozprowadzanie komunikat�w a� do wyj�cia // z trybu ja�owego for (;;) { ASSERT(ContinueModal()); // faza 1: sprawdzenie, czy mo�na wykonywa� prac� // czasu ja�owego while (bldle && !::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE)) { ASSERT(ContinueModal()); // wy�wietlenie dialogu, gdy kolejka komunikat�w // staje si� pusta if (bShowIdle) { ShowWindow(SW_SHOWNORMAL); UpdateWindow(); bShowIdle = FALSE; } // wywo�anie OnldleO w trybie bldle if (.'(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lldleCount == 0) { // wys�anie komunikatu WM_ENTERIDLE do // okna nadrz�dnego ::SendMessage(hWndParent, WM_ENTERIDLE, MSGF DIALOGBOK, (LPARAM)m hWnd); } if ((dwFlags & MLF_NOKICKIDLE) || !SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, HdleCount++) ) { // nast�pnym razem zatrzymanie przetwarzania // w trybie ja�owym bldle = FALSE; } } // faza 2: pompowanie dost�pnych komunikat�w do { ASSERT(ContinueModal()); // pompowanie komunikat�w, ale wyj�cie przy WM_QUIT if (!AfxGetThread()->PumpMessage()) { AfxPostQuitMessage(0); return -1; } // pokazanie okna po zarejestrowaniu pewnych // specjalnych komunikat�w if (bShowIdle && (pMsg->message == 0x118 || pMsg->message== WM_SYSKEYDOWN)) ShowWindow(SW_SHOWNORMAL); UpdateWindow(); bShowIdle = FALSE; } if (! ContinueModal () ) goto ExitModal; // zerowanie stanu ja�owego po "wypompowaniu // zwyk�ego komunikatu if (AfxGetThread ( ) ->IsIdleMessage (pMsg) ) { bldle = TRUE; HdleCount = 0; } } while( : : PeekMessage (pMsg, NULL, NULL, NULL, PM_NOREMOVE) ); } ExitModal: m_nFlags &= ~(WF_MODALLOOPlWF_CONTINUEMODAL); return m_nModalResult; } Pierwsza z wewn�trznych p�tli sprawdza, czy s� obs�ugiwane i zwracane do okna nadrz�dnego komunikaty -trybu ja�owego. Zapewnia tak�e, �e je�li w wywo�aniu funkcji zosta� przekazany parametr MLF_SHOWONIDLE, okno zostanie wy�wietlone po przej�ciu kolejki komunikat�w do trybu ja�owego. Prawdziwa praca odbywa si� w drugiej p�tli. Zwr�� uwag�, �e kod najpierw sprawdza, czy funkcja ContinueModal () zwr�...
Morfeusz__