Windows

Aplikace & zprávy

Zdroják -> compile -> link -> .exe. Ve Win – zdroje: „resources“ - kvůli nim – resource compiler. Připojí k *.exe *.res, nakonec - *.exe – Windowsí program. (musí jím projít vždy!). Dnešní devenv se o to postará sám. S vloženými resourcemi je jednodušší práce:

Hodně funkcí - ( LoadIcon, LoadCursor ), používajících resource pracuje s parametrem typu HINSTANCE – handle na instanci programu (32-bit integer). Dá se zjistit např. GetModuleHandle( NULL ); (můj exe) / GetModuleHandle( „kernel32.dll“ )- konkrétní modul, daj se z něho pak tahat resource. Je to i vstupní parametr mého programu. Nalezení resource – hModule = LoadLibrary( "icons.dll" ), hResource = FindResource( hModule, "nazev", typ ) - typ: RT_MENU, RT_ICON atd.

Struktura programu:

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,LPCSTR cmdLine,int nShow ){
...
        while ( GetMessage( &msg, ... )){
                ...
                DispatchMessage( &msg, ... );
        }
        return msg.wParam; // na co program umřel
}


LRESULT CALLBACK WindowProc( HWND hWin, UINT msg, WPARAM wParam, LPARAM lParam ){
        switch( msg ){
                case WM_PAINT:
                ...
                case WM_COMMAND:
                ...
        }
}

1 fce WinMain & ke každému vlastnímu oknu Win-Procedura. WinMain – smyčka zpráv. Vybírání z fronty, přeposílání podoknům (knoflíky, editboxy atp. - všechno okna, mají defaultní WinProc). GetMessage vrací true, dokud nedostane zprávu o konci programu (WM_QUIT).

WinMain – hInst – handle na instanci programu, hPrevInst – předchozí instance (Win16), dnes vždy 0.

Vytvoření okna – nejdřív inicializace struktury WNDCLASSEX popisující vlastnosti okna, pak RegisterClassEx - zaregistruje u systému novou třídu oken. Potom vytvoření okna - hWindow = CreateWindowEx( ... ) <- lze popsat další parametry, vrací handle na okno. Std. okna (knoflík) jsou už zaregisrována. Po vytvoření okna – nutné zobrazit – ShowWindow( hWindow, ...), UpdateWindow( hWindow, ...) (pošle zprávu o překreslení).

Smyčka zpráv – TranslateMessage( &msg ) - pro vstupy z klávesnice. Dispatch – pošle zprávu přísl. oknu. Zprávy přímo pro aplikaci – vyjímky ( WM_QUIT, HWND_BROADCAST ), PostThreadMessage.

Zprávy - typedef struct { HWND hWindow, UINT message, WPARAM wParam, LPARAM lParam, DWORD time, POINT pt } MSG;. U větš. procedur čas a polohu kurzoru nepotřebuju (nebo je dostanu ve wParam&lParam).

Id zpráv – 0 – 0x3FF předdefinované, WM_USER ( 0x400 ) - 0x7FF – pro posílání v rámci 1 třídy oken (defaultní okna často mají takové zprávy), WM_APP ( 0x800 ) - 0xBFF – k volnému použití v rámci aplikace, 0xC00 – 0xFFF – dají se uzmout v rámci systému k posílání jiným aplikacím pomocí RegisterWindowMessage() (ta vybere vždy správnou hodnotu).

Posílání zpráv – bool PostMessage( HWND hWin, UINT message, WPARAM wParam, LPARAM lParam ) , LRESULT SendMessage( ...) - SendMessage v podstatě rekurzivní volání WindowProc (pro vlastní okno, jinak přidává na zač. fronty); PostMessage – na konec fronty. Fronta – víc, prioritní: 1. poslané SendMessage, 2. normální PostMessage, 3. WM_QUIT, 4. od uživatele ( WM_MOUSEMOVE ... ), 5. WM_PAINT (max.1), 6. WM_TIMER (fronta). Zprávy ze SendMessage GetMessage rovnou zpracuje & vybere. U timerů – pravidla na zahazování prošlých. PostThreadMessage( DWORD threadId, ... ) – posílání zpráv do fronty konkrétní aplikaci/vláknu.

Zjištění stavu fronty – DWORD GetQueueStatus( UINT flag ) (QS_ALLEVENTS, QS_PAINT, QS_MOUSE...), vrací id typů zpráv ve frontě. Výběr z fronty - bool GetMessage( LPMSG lpMsg, HWND hWin, UINT MsgFilterMin, UINT MsgFilterMax ) - filtry zpráv = 0, 0 – všechny, hWin = NULL – zprávy pro lib. okno mé aplikace. bool PeekMessage( ..., UINT wRemoveFlag ) - jen otestuje jestli mám zprávy a hned se vrátí; wRemoveFlag – PM_REMOVE, PM_NOREMOVE; navíc se dá || s PM_NOYIELD – aby systém neprobudil jiná vlákna čekající na tohle ("jen kvůli kompatibilitě"). PeekMessage – často použité u aplikací s DirectX.

Zpracování zpráv – ve WindowProc switch za zprávy, zprávy které nezpracovávám – default: return DefWindowProc( hWin, msg, wParam, lParam ); . Jednotlivé casy končí rovnou return 0 (většinou – některé zprávy mohou vracet i něco jiného). Zprávy – WM_CREATE (vytvoření okna), WM_PAINT (překreslení – nutné BeginPaint() a EndPaint() ), WM_CLOSE (zavření okna, pokud ošetřuji sám musím volat DestroyWindow() ), WM_DESTROY (odalokování – defaultně posílá PostQuitMessage() - WM_QUIT ). Pokud volám PostQuitMessage přímo – neodalokuje paměť.

Okna

3 druhy – Window, Dialog, MessageBox (v .NET je to jedno). Okno – defWindowProc, zpracování lib. zprávy vlastním způsobem.

Dialog – může reagovat sám jen na 2 zprávy – WM_INITDIALOG, WM_COMMAND, defaultní dialogová procedura – jiná než okenní, umí toho víc (tabstop), na všechno ale nereaguje (timer). Umí WM_USER, ale jiné ne (např. WM_PAINT ne!!!).

MessageBox – úplně nejjednodušší – jen zpráva, ikona, tlačítka (& vrací ID stisknutého tlačítka), většinou jde vytvořit i při nedostatku paměti.

Window

Aktivní okno – top-level, se kterým uživatel pracuje. Input-focus – jen jeden z konkr. potomků (vstup z klávesnice). Mouse-input – std. pro okno nad kterým je kurzor (jde ale na chvíli narušit).

Vlastnosti okna : umístění, normal/minimized/maximized, always-on-top, visible/hidden (meziapp. komunikace), enabled/disabled, parent/child (kvůli zprávám), top-level (nemá parent (desktop)), owner (=top-level)/slave, active/inactive (pro top-level), overlapped (hl.okno)/pop-up (child, může být kdekoliv)/child (vidět jen hl. okně své aplikace).

WindowClass – typ okna, lokální z hlediska aplikace. Vytváření – struct WNDCLASSEX – členové – lpszClassName – string, jméno třídy; hInstance – exáč, povinný; lpfnWndProc – pointer na win-proceduru, lpszMenuName – jméno resource s hl. menu (MAKEINTRESOURCE), hCursor – kurzor nad oknem (=LoadCursor( NULL, IDC_ARROW)), hIcon = LoadIcon( NULL, IDI_APPLICATION), hIconSm = LoadImage( hInstance, MAKEINTRESOURCE(...), IMAGE_ICON, x, y, LR_DEFAULTCOLOR ); hbrBackground = (HBRUSH) COLOR_APPWORKSPACE; cbSize = sizeof(WNDCLASSEX); cbStyle = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE | CS_OWNDC ... ; zbytek – NULL ( bajty navíc apod.).

hWindow = CreateWindowEx( extendedStyle, className, windowTitle, windowStyle, x = CW_USEDEFAULT, y -"-, sizeX -"-, sizeY -"-, parentWindow, menu = NULL (pokud nechci jiné než má třída), hInstance, lpParam = NULL (pointer který dostane win-proc ve WM_CREATE) );. Styly – WS_EX_TOPMOST, WS_OVERLAPPED/WS_POPUP/WS_CHILD; WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME (dá se resizovat) | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, WS_POPUPWINDOW = WS_POPUP | WS_BORDER (nedá se měnit velikost) | WS_SYSMENU; WS_VISIBLE – běžně se používá ShowWindow, WS_TABSTOP, WS_DISABLED; WS_CLIPCHILDREN, WS_CLIPSIBLINGS – pro MDI; WS_VSCROLL | WS_HSCROLL – scrollbary. Jsou i další styly – pro dialog, static text, edit, listbox, combobox, box; většinou lze dávat všechno všude, ale ne vždy má efekt.

Extended styles – ACCEPTFILES, TOPMOST, TOOLWINDOW, LAYERED – pro průhlednost - SetLayeredWindowAttributes( hWnd, 0, 180 (průhlednost max.253), LWA_ALPHA/LWA_COLORKEY ). Je jen pro WinNT+ - musí být def. makro _WIN32_WINNT. Stdafx.h to blokuje.

Změna vlastností třídy – SetClassLongPtr( hWin, offset, newValue ), GetClassLongPtr; konstanty – CGL(P)_STYLE, ICON apod. Vlastnosti 1 okna – GetWindowLongPtr( -"- ), SetWindowLongPtr, konstanty – GWL(P)_... . Změna se projeví nejdřív po překreslení, někdy vůbec. Změnit se dá i WinProc.

Zjištění okna – FindWindow( className, windowName ), WindowFromPoint( POINT pt ), ChildWindowFromPoint( hParent, pt ), EnumWindows((WNDENUMPROC) lpEnumFunc, LPARAM lParam ) / EnumChildWindows( hParent, -"- ) - předá všechny proceduře EnumFunc( hWnd, lParam ).

Úprava titulku – v CreateWindowEx, potom – SetWindowText( hWin, "titulek" ), Zjištění – len = GetWindowTextLenght( hWin ), GetWindowText( hWin, &buffer, len ).

ShowWindow( hWin, nShow ) - má víc hodnot, zvl. případ SendMessage – SW_SHOWDEFAULT, SW_SHOW, SW_HIDE, SW_MINIMIZE, SW_RESTORE ... .

MoveWindow( hWin, x, y, width, height, BOOL update ) - je-li update = false, okno musí volat explicitně UpdateWindow, pokud chce překreslit uživ. část okna, je-li = true, chová se (dnes!) stejně. Novější – SetWindowPos( hWin, hWinAfter (za které okno se schovat), x, y, width, height, flag (SWP_NOMOVE, NOSIZE, SHOWWINDOW, HWND_(NO)TOPMOST (jediná možnost nastavení!)).

Vypínání okna – EnableWindow( hWin, BOOL enabled ), je spec. případ SendMessage. Aktivace okna – hOldActive = SetActiveWindow( hWind ), GetActiveWindow (v rámci aplikace), SetForegroundWindow(), GetForegroundWindow() - globálně. BringWindowToTop( hWin ) - přenese okno do popředí, aktivuje jeho vlastníka(top-most).

Blikání – FlashWindow( hWin, BOOL ) - blikne/vrátí, složitější – FlashWindowEx.

Neobdélníková okna – okno=to co měl předtím & to co mu přidám – HRGN rg = CreateRoundRectRgn/CreateEllipticRgn; SetWindowRgn( hWin, rg, BOOL ), CombineRgn( hDestrgn, hRg1, hRg2, RGN_DIFF ).

Ikony

Předdefinované ikony – HICON hIcon = LoadIcon( NULL, IDI_EXCLAMATION (WARNING,ASTERISK,QUESTION,ERROR) ), vlastní ikony – LoadIcon( hInstance, resourcename ), ExtractIcon( hInst, filename, index ). Malé ikony: LoadImage( hInst, resourcename, IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR (typ úpravy barev) ).

Určení ikony pro okno – ve WNDCLASSEX ( hIcon, hIconSm ), zjištění ikony – GetClassLongPtr( hWin, GCLP_HICON / HICONSM ), změna – SetClassLongPtr (až po překreslení).

Ikona u hodin – patří systému, ten na požádání vykreslí – struct NOTIFYICONDATA { cbSize(sizeof), uFlags (NIF_ICON, NIF_MESSAGE, NIF_TIP <- kteří z členů obsahují data), hIcon, hWnd, uID (zvolím), uCallbackMessage (volím), LPCSTR szTip ). Přidání k hodinám – BOOL Shell_NotifyIcon( NIM_ADD (DELETE, MODIFY), LPNOTIFYICONDATA ). Bublinový tooltip – NIF_INFO ( Win2000 - #define _WIN32_WINNT, _WIN32_IE ) - další – szInfoTitle, szInfo, dwInfoFlags.

Handlování ikony – dostanu zprávu co si zvolím při vytvoření, ve wParam je moje uID, v lParam skutečná zpráva ( WM_RBUTTONDOWN ... ). Pro vytváření popup-menu: SetForegroundWindow( hWin ) (aby aplikace dostala zprávu o zmizení), TrackPopupMenuEx( hMenu, fuFlags, x, y, hWnd, lpTpmparams = NULL ), PostMessage( hWin, WM_NULL, 0, 0 ) ( ztrácí se 1 zpráva ).

Reakce na restart taskbaru (exploreru) – ikony u hodin se samy neobjeví. Zaregistrovat zprávu ( RegisterWindowMessage( TEXT("TaskbarCreated")) ) - dostanu její číslo; explorer mi při restartu tuhle zprávu pošle (proměnná -> nemůže být ve switchi).

Zákaz maximalizace – case WM_QUERYOPEN: return 0;, zákaz minimalizace – nejde na 100% - odebrat ze stylu třídy okna CS_MINIMIZEBUTTON (SetClassLongPtr), zpráv minimalizujících okno je hodně a dělají i něco jiného -> nejde snadno, lze ale po minimalizaci okamžitě restorovat.

Kurzory

Předdefinované kurzory – HCURSOR hC = LoadCursor( NULL, IDC_ARROW ( APPSTART, HAND, HELP ... ) );, moje vlastní – LoadCursor( hInst, resourcename), LoadCursorFromFile( "kurzor.cur" );. Určení kurzoru pro okno – ve WNDCLASSEX.

Zjištění kurzoru – přes GetClassLongPtr, CGLP_HCURSOR nebo HCURSOR hC = GetCursor(); Změna – přes SetClassLongPtr( ... ) & hStary = SetCursor( hNovyCursor ) - oboje dohromady, jinak nefunguje!

Sbírání zpráv o pohybu myši – hPrevious = SetCapture( hWin );, ReleaseCapture();, program pak dostává WM_MOUSEMOVE, WM_LBUTTONDOWN atp. Můžu pak změnit kurzor jen SetCursorem, po ReleaseCapture se vrátí starý. Capture mi systém vezme když uživatel klikne mimo mé okno.

Skrytí kurzoru: ShowCursor( BOOL visible ); . Omezení pohybu – struct RECT { left, top, bottom, right }, ClipCursor( LPRECT ), ClipCursor( NULL ) ruší. Nefunguje úplně – okna ve WinXP nejsou úplně čtvercová.

Menu

Konvence pro položky - & = podtržení následujícího písmene (hotkey – Alt+písmeno), \t odsadí zbytek doprava, vyvolání dialogu -> mělo by mít za sebou 3 tečky.

Vytvoření menu – HMENU hM = LoadMenu( hInstance, resourcename ), za běhu – HMENU hM = CreateMenu();, DestroyMenu( hMenu );. Popup-menu & sub-menu – jiné než hlavní menu: HMENU hM = CreatePopupMenu();, DestroyMenu( hM ).

Naplnění menu – AppendMenu( hM, MF_STRING ( ENABLED, GRAYED, POPUP, SEPARATOR, BITMAP ), uIDItem, lpData ), nebo InsertMenu( hM, nOrd, MF_BYPOSITION (BYCOMMAND) | ..., uID, lpData );. ModifyMenu - změní existující (param. stejné jako předch., do MF_* lze naandovat MF_GRAYED, MF_CHECKED, MF_POPUP (uID – handle na podmenu), MF_ENABLED (uID – nove IDC_ ), MF_SEPARATOR ). DeleteMenu( hM, nOrd, MF_BYPOSITION ) - smaže položku. EnableMenuItem( hM, nOrd, MF_BYPOSITION | MF_DISABLED | MF_GRAYED ).

Určení menu pro okno – ve WNDCLASSEX. Překreslení – nutné pro hl. menu okna pro okamžité změny: DrawMenuBar( hWindow ). Zaškrtnutí položky – CheckMenuItem( hM, nOrd, MF_BYPOSITION | MF_UNCHECKED ).

Zpracování zpráv menu – WM_COMMAND, LOWORD( wParam ) == IDC; popup / separator – žádný IDC nemají.

WindowsMenu – po zmáčknutí ikony v levém horním rohu. Společné 1 třídě oken. HMENU sysMenu = GetSystemMenu( hWin, FALSE ) (TRUE vrací zpět defaultní ). Pak je nutné reagovat na WM_SYSCOMMAND, switch( wParam ), IDC přidaných položek musí být < 0xF000.

PopupMenu – zjištění pozice kurzoru – GetCursorPos( LPPOINT ), zobrazení popup-menu – TrackPopupMenu( hM, TPM_LEFTALIGN (TOPALIGN, HORPOSANIMATION, VERNEGANIMATION, LEFTBUTTON (výběr jen levým tlačítkem), RETURNCMD (vrací vybrané, jinak vrací 0/1) ). Pro animaci popup-menu nutné povolit animace: SystemParametersInfo( SPI_SETMENUANIMATION, 0, (LPVOID) TRUE, 0 ); SystemParametersInfo( SPI_SETMENUFADE, 0, FALSE, 0 );, nelze najednou! Dobrý je přes SPI_GET*** přečíst co tam je nastavený a pak vrátit. TrackPopupMenuEx – navíc parametr lpTpmparamsstruct { cbSize (sizeof), RECT rcExclude (popup nesmí překrývat)};.

Toolbar

Před vytvářením toolbaru nutné inicializovat common controls – struct INITCOMMONCONTROLSEX { dwSize (sizeof), dwICC (co se má nahrát – ICC_BAR_CLASSES ) } icex;, InitCommonControlsEx( &icex ).

Vytvoření – HANDLE CreateWindowEx( 0, TOOLBARCLASSNAME, (LPCSTR) NULL, WS_CHILD | WS_VISIBLE | CS_ADJUSTABLE (povolí uživateli upravovat) | TBSTYLE_WRAPABLE (přes víc řádek) | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS, 0, 0, 0, 0, hParentWindow, (HMENU) IDC_TOOLBAR, hInst, NULL );

Přidání tlačítek: struct TBADDBITMAP { hInst, nID } - pokud je hInst = NULL, potom je nID handle na bitmapu s tlačítky, jinak je to resource-id bitmapy. Pokud je hInst = HINST_COMMCTRL, je nID číslo std. bitmapy ( IDB_STD_LARGE_COLOR ... ). Potom zavolat SendMessage( hToolbar, TB_ADDBITMAP, bmpCount, lpTbAddBitmap );. Samotná tlačítka – struct TBBUTTON [bmpCount] { index (I_IMAGENONE, STD_FILE_OPEN, ...), idcCommand, fsState (TBSTATE_ENABLED | PRESSED | CHECKED | HIDDEN ... ), fsStyle (BTNS_BUTTON | SEP | CHECK | GROUP | CHECKGROUP ), dwData = 0, lpstrCaption );. <- inicializovat, potom poslat SendMessage( hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0 );, SendMessage( hToolbar, TB_ADDBUTTONS, bmpCount, lpTbButton (pole!!) ). Nakonec – SendMessage( hToolbar, TB_AUTOSIZE, 0, 0 );.

Rebar – lišta, která může obsahovat Toolbary a další věci. Inicializace – jako Toolbar, icex.dwICC = ICC_COOL_CLASSES. Vytvoření – CreateWindowEx( 0, REBARCLASSNAME, (LPCSTR) NULL, WS_CHILD | WS_VISIBLE | CCS_ADJUSTABLE | RBS_AUTOSIZE , 0, 0, 0, 0, hParentWindow, IDC_REBAR, hInst, NULL );.

Vložení objektu – SendMessage( hRebar, RB_INSERTBAR, index, &REBARBANDINFO );. Změna – SendMessage( hRebar, RB_SETBANDINFO, index, &REBARBANDINFO );. REBARBANDINFO – složitá struktura popisující vlastnosti vkládaného.

Statusbar

Inicializace stejně jako toolbar přes InitCommonControlsEx, icex.dwICC = ICC_BAR_CLASSES; Vytvoření – CreateWindowEx( 0, STATUSCLASSNAME, (LPCSTR) NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP (resizovací věc v pravém rohu), 0,0,0,0, hParentWindow, IDC_STATUSBAR, hInst, NULL ).

Rozdělení na několik částí – SendMessage( hStatus, SB_SETPARTS , nParts, lpIntArrayPartRightEdges ); ( pravý konec na -1 = ke konci okna ). Nastavení ikony části StatusBaru – SendMessage( hStatus, SB_SETICON, partIndex, hIcon );, Nastavení textu – SendMessage( hStatus, SB_SETTEXT, partIndex, lpcstrText );. ID části – SB_SIMPLEID = jen jedna část. Tooltip – stejně, jen SB_SETTIPTEXT.

MessageBox

result = MessageBox( hParentWindow, lpcstrText, lpcstrCaption, MB_*** ); . Konstanty MB_ - ikony & tlačítka – MB_ICONEXCLAMATION, MB_OK, MB_ICONERROR, MB_YESNOCANCEL, MB_ABORTRETRYIGNORE ... . Výsledek – IDOK, IDCANCEL, IDABORT, IDRETRY, IDIGNORE, IDYES, IDNO. hParentWindow – toto okno se zobrazí po odklepnutí. Předdefinované ikony se dají použít i jinde, nejde víc než jedna.

Dialog

2 typy – modální, modeless. Modální – z resource: nResult = DialogBox( hInst, resourcename, hParentWindow, lpfnDialogProc );. Testování na IDOK apod. Nemodální – hDlg = CreateDialog( hInst, resourcename, hParentWindow, lpfnDialogProc ); ShowWindow( hDlg, SW_SHOW );, DestroyWindow( hDlg );.

Dialogová procedura – BOOL CALLBACK dlgProc( hDlg, msg, wParam, lParam ), uvnitř typicky switch( msg ), ošetření jen některých zpráv – typicky WM_INITDIALOG, WM_COMMAND ( stisk tlačítek ) - switch( LOWORD( wParam ) ). Ukončení dialogu – EndDialog( hDlg, returnValue );.

Nemodální dialogy – nutné v hlavní message loop programu mít: if ( !((hDlg != NULL ) && IsDialogMessage( hDlg, &msg ) ) ), pokud tato podmínka neplatí, zprávy nedispatchovat ( není spolehlivé ).

Očíslování ovl. prvků – podle HWND, IDC, tabstop (takovýto ovl. prvek musí mít styl WS_TABSTOP ), nejlíp se nastavuje v editoru dialogů. Pokud má prvek IDC == -1, jde o statický text/obrázek, moje aplikace po kliku na něj nedostane zprávu ( pokud jde o statický text, zprávu nedostanu ani s kladným id, ale může se hodit např. pro dynamické změny nápisu ). Zjištění HWND ovládacího prvku – GetDlgItem( hDlg, IDC_CONTROL );. Naopak – z HWND na IDC – GetDlgCtrlID( hControl );.

Posílání zpráv prvkům dialogu – buď přes GetDlgItem a SendMessage, nebo přes SendDlgItemMessage( hDlg, IDC, msg, wParam, lParam );. Např. ShowWindow, EnableWindow, SetFocus( hControl );. Nastavení fontu – WM_SETFONT, wParam – HFONT, lParam – MAKELPARAM( boolPrekreslit, 0 ).

Dialog lze zobrazit i jako hl. okno aplikace (prostě ve WinMain zavolám DialogBox). Přenos dat – nutno nějak ošetřit, nedělá se samo.

Std. Dialogy – funkce – GetOpenFileName( &OPENFILENAME ), GetSaveFileName, PrintDlg(Ex), PageSetupDlg, ChooseColor, ChooseFont, FindText, ReplaceText. Zjištění chyby během dialogu – DWORD CommDlgExtendedError();.

Controls

"Normální okna", posílají rodičovskému notifycation messages. Dělení – standardní, common, VBX, OCX (OLE), ActiveX. Vytvoření – HANDLE hControl = CreateWindowEx( 0, CLASS, (LPCSTR) NULL, WS_CHILD | WS_VISIBLE | ..., 0, 0, 0, 0, hParentWindow, (HMENU) IDC, hInst, NULL );.

Standardní – třídy: STATIC, EDIT, BUTTON, LISTBOX, COMBOBOX, SCROLLBAR, RICHEDIT_CLASS. Common – Header, Drag List Box, ComboBoxEx, Tab, ProgressBar, Date & Time, ToolTip, HotKey, IP Address, Flat Scroll Bar, Image List, ToolBar, Rebar, StusBar, List-view, Tree-view...

Styly – common controls: CCS_ADJUSTABLE, CCS_TOP, CCS_BOTTOM (pro toolbar), CCS_NODIVIDER (neoddělí od ost.), CCS_NOMOVEY (neresizuje se), CCS_NOPARENTALIGN (nepřesouvá se), CCS_NORESIZE (žádná default velikost), CCS_NOHILITE.

Pro std. dialogy – WM_COMMAND: LOWORD(wParam) – IDC, HIWORD(wParam) – notification message, lParam – hControl. Common – wParam – IDC, lParam – lpNMHDR: struct NMHDR { hControl, idcControl, msgCode };. Notification messages: NM_SETFOCUS, NM_KILLFOCUS, NM_CLICK, NM_DBLCLK, NM_RCLICK, NM_RETURN, NM_OUTOFMEMORY.

Button

vytvoření CreateWindowEx( ... ) - třída: BUTTON, styly: BS_PUSHBUTTON (posílá WM_COMMAND rodičovskému oknu ), BS_OWNERDRAW (za překreslování zodpovědné rodičovské okno), BS_NOTIFY (rozlišuje víc klikacích notifications); BS_CHECKBOX, BS_TEXT, BS_ICON, BS_LEFT, BS_CENTER (align textu), BS_(AUTO)RADIOBUTTON ....

inicializace – SetDlgItemText( hDlg, IDC, lpcstrCaption ); (nebo) SetDlgItemInt( hDlg, IDC, number, boolSigned ); - číselný popisek, CheckDlgButton( hDlg, IDC, 0/1/2(grayed) ); = SendDlgItemMessage( hDlg, IDC,BM_SETCHECK, .. );. Zjištění info – IsDlgButtonChecked( hWnd, IDC ); = SendMessage(
.., BM_GETCHECK, ... );
. CheckRadioButton( hDlg, firstIDC, lastIDC, checkedIDC );

Static

pro CreateWindowEx jako class – STATIC. Styly – WS_CHILD | WS_VISIBLE | SS_SIMPLE ( SS_LEFT, SS_LEFTNOWORDWRAP ... ). Inicializace – SetDlgItemText, SetDlgItemInt. Styly pro obrázek – SS_ICON, SS_BITMAP, SS_ENHMETAFILE, SS_CURSOR, inicializace – SendDlgItemMessage( hDlg, IDC, STM_SETIMAGE, IMAGE_ICON (BITMAP...), hImage );. Statický obdélník – SS_WHITERECT (GRAY,BLACK), SS_WHITEFRAME.

Styl SS_OWNERDRAW -> rodičovské okno je zodpovědné za překreslení staticu. Dostává zprávu WM_DRAWITEM, kde wParam = IDC & lParam = lpDRAWITEMSTRUCT (info o staticu & jeho stavu ).

Edit

Vytvoření – CreateWindowEx, class – EDIT. Styly – ES_LEFT (align), ES_UPPERCASE, ES_MULTILINE, ES_NUMBER, ES_PASSWORD, ES_AUTOVSCROLL, ... Inicializace – SetDlgItemText, SetDlgItemInt. Čtení – GetDlgItemText( hDlg, IDC, lpBuffer, nMaxLength );, n = GetDlgItemInt( hDlg, IDC, &returnCode, bSigned );.

Omezení délky – SendDlgItemMessage( hDlg, IDC, EM_LIMITTEXT, nLimit, NULL );. Kontrola obsahu – pod přijetím NM_KILLFOCUS ( ve WM_COMMAND) .

Klávesnice

Po stisku klávesy: hardware interrupt -> keyboard driver -> raw input thread – test na Alt-Tab &pod., zjištění kdo má focus -> fronta zpráv okna. Focus – dá se oknu předat: SetFocus( hWin );, jen pro vlastní okna. Notifikace o focusu – NM_SETFOCUS, NM_KILLFOCUS. Zprávy klávesnice pro moje okno – WM_KEYDOWN (SYSKEYDOWN (+Alt), KEYUP), ve wParam dostanu zprávu o klávese, v lParam další podrobnosti. Konstany – klávesy: VK_0 ... VK_9 ... VK_A ... VK_Z ... VK_F1, VK_CONTROL, VK_MENU, VK_RETURN, VK_SNAPSHOT (PrtScr), VK_CANCEL (Ctrl-Break). lParam - 0-15.bit – opakování, 16-23 – scan code, 24 – isExtendedKey, 29 – context code (Alt?), 30 – previous state, 31 – transition (DOWN=0, UP=1).

Funkce TranslateMessage udělá z WM_KEYDOWN a WM_KEYUP zprávu WM_CHAR (SYSCHAR, DEADCHAR, SYSDEADCHAR). - sys = Alt, dead = ˇ´¨ atp. Zjištění stavu klávesnice – GetKeyState( VK_... ) - v okamžiku generování zprávy. GetAsyncKeyState – okamžitý stav. GetKeyboardState( lp256bytesArray ); - zjištění stavu všech kláves v okamžiku generování zprávy.

Akcelerátory = kláv. zkratky. V resourcích se vytvoří tabulka akcelerátorů – klávesa <-> IDC. Nahrání – hAccel = LoadAccelerators( hInst, resourcename );, v hlavní message loop – if ( !TranslateAccelerator( hWnd, hAccel, &msg ) ){ ... }; - předřadí se DispatchMessage a TranslateMessage. Funkce překládá WM_KEYDOWN na WM_COMMAND s přísl. IDC.

Myš

Zjištění přítomnosti myši v systému – GetSystemMetrics( SM_MOUSEPRESENT );. Zprávy myši – dostávám na uživ. obl. okna – WM_MOUSEMOVE, WM_L(R,M,X)BUTTONDOWN, UP, BUTTONDBLCLK (na to musí mít okno třídu WS_DOUBLECLICK). Při zprávě – v lParamLOWORD = x, HIWORD = y – relativní k levému rohu mého okna, wParam – stisknuté klávesy ( &MK_LBUTTON (R,M,X), MK_SHIFT, MK_CONTROL ).

Zprávy WM_NCMOUSEMOVE, WM_NCLBUTTONDOWN ... - v neklientské oblasti okna, lepší nezpracovávat, větš. se netýká mě, ale systému. (Mohu tak ale např. zakázat hýbání oknem). Parametry – lParam – souřadnice, wParam – kam jsem kliknul (do jaké části okna – konstanty: HTMENU, HTMAXBUTTON, HTNOWHERE ... ). To můžu i sám ovlivnit zpracováváním zprávy WM_HITTEST (a vracet co sám chci – můžu tak třeba zablokovat myši) – DefWindowProc testuje kde myš je a vrací správnou hodnotu.

Přivlastnění myši – SetCapture( hWin );, ReleaseCapture();.

Paint

Windows – nepamatují si co mám v okně, všechno zůstává tak dlouho, jak je to vidět přímo na obrazovce. Obnovení – posílání zprávy WM_PAINT. Od Windows2000 – GDI32/GDI+ - off-screen layered window – v paměti až do zrušení okna (jinak by při změně 1 okna bylo nutno měnit vše pod/nad ním). MSHTML – jazyk pro popis GUI, DOM, omezené možnosti. DirectX, WinFX – spec.

Fce WinAPI – TextOut, DrawText, LineTo, Rectangle, Ellipse, Pie, Arc, Chord, Polyline, Polygon, DrawIcon, BitBlt, StretchBlt. Pro kreslení do okna potřebuji Device-Context (std. fce – chtějí jako parametr). Okení styly – CS_OWNDC, CS_CLASSDC (vlastní device kontext pro okno?). hDC – dostanu z GetDC, BeginPaint jako návr. hodnotu. DC je málo -> co nejdřív vracet (zabírá paměť), okna která mají CS_OWNDC, CS_CLASSDC, mohou hDC držet furt (voláním GetDC a nezavoláním ReleaseDC ). Při reakci na 1 zprávu mohu mezi GetDC a ReleaseDC kreslit, ale nic si Windows nezapamatují.

WM_PAINT – dozvím se kdykoliv musím překreslit část okna: ScrollWindow, ScrollDC, InvalidateRect a InvalidateRgn; při změně velikosti pro styly CS_HREDRAW a CS_VREDRAW, odstranění dialogu/message boxu, uzavření pulldown-menu, pohybu kurzoru přes okno, pohybu ikony přes okno.

Zpracování WM_PAINT – hDC = BeginPaint( hWnd, &paintInfo ); (nevolat mimo WM_PAINT), EndPaint( hWnd, &paintInfo ); (odstraní teprve zprávu z fronty). paintInfo: struct PAINTSTRUCT { hDC, boolEraseBackg, rectInvalidated, boolRestore, boolIncUpdate, lp16byteReservedArray }; - v rectInvalidated dostanu část okna kterou musím překreslit. Clipping region – oblast obrazovky na kterou se nekreslí. BeginPaint nastaví na celou oblast mimo update region. Má-li se vyčistit pozadí oblasti, pošle WM_ERASEBACKGROUND (nutné mít nastavené pozadí ve třídě okna, jinak bude průhledné; nebo zajistit nakreslení pozadí sám – zpracovávát zprávu).

WM_PAINT si nesmím posílat sám!!! - nemůžu nastavit parametry. Požadavek na překreslení okna: pomocí InvalidateRect( hWnd, lpRectInvalidated, boolEraseBackg );(nepoužívat uvnitř WM_PAINT), obdélník vytvořím SetRect( lpRectInvalidated, left, top, right, bottom );. Vrátit se dá – ValidateRect( hWnd, lpRectInvalidated );. Zjištění klientské části okna – GetClientRect( hWnd, lpRect );. Pro okamžité překreslení – UpdateWindow( hWnd ); - místo SendMessage (nic ale sama nezneplatňuje). Pokud nechci obdélník – HRGN hRgn = CreateEllipticRgn( ..., CreateRectRgn( ..., CombineRgn( ..., volání InvalidateRgn( hWnd, hRgn, boolEraseBackg ); - ve WM_PAINT se dozvím nejmenší obdélník, který tento region obsahuje.

Kreslení – nutné vytvořit štětec – CreateBrushIndirect( &LOGBRUSH );, struct LOGBRUSH { lbStyle (BS_DIBPATTERN, BS_SOLID ... ), lbColor ( RGB(r,g,b), 0, pokud má bitmapa DIB barvy v sobě – DIB_PAL_COLORS, DIB_RGB_COLORS ), lbHatch (0 / HS_BDIAGONAL, HS_VERTICAL ... - pokud je styl LB_HATCHED, handle na bitmapu, pokud je styl BS_DIBPATTERN ) }., nebo – HBRUSH hBrush = GetStockObject( WHITE_BRUSH );. Zvolení štětce – oldBrush = SelectObject( hDC, newBrush );. Pero – hPen = GetStockObject( BLACK_PEN ); (WHITE_PEN, NULL_PEN), hOldPen = SelectObject( hDC, hPen ); <- zvolím pero. Vytvoření nového pera – hPen = CreatePen( PS_SOLID (DASH, DOT, DASHDOT, NULL, INSIDEFRAME) , width, dwColorRGB );.

Text – TextOut( hDC, x, y, lpcstrText, length ); - délka musí být správně, jinak jde i přes nulový byte. Souřadnice – default: levý horní roh, změna pomocí : SetTextAlign( hDc, TA_LEFT | TA_TOP (BOTTOM, RIGHT, CENTER, UPDATECP ). Barva – SetTextColor( hDC, dwColorRGB (RGB(r,g,b)) );. Zjištění barvy – GetTextColor( hDC );. Víc možností než TextOut - DrawText( hDc, lpcstrText, length (je-li -1, napíše až k null-byte), lpRectangle (sem se text musí vejít), DT_SINGLELINE (nedám-li, bude zalomený) (WORDBREAK, TOP, VCENTER, EXPANDTABS, NOPREFIX, CALCRECT <-spec. hodnota – nekreslí, počítá kam se text vejde – dám šířku řádku, spočítá výšku textu ) );.

Čárová grafika – MoveToEx( hDC, x, y, NULL ); LineTo( hDC, x, y); Rectangle( hDC, left, top, right, bottom ); Ellipse( hDC, left, top, right, bottom ); Pie( hDc, left, top, right, bottom, x3, y3, x4, y4 ); Arc( --"-- ); Chord( --"-- ); - po směru hod. ručiček. PolyLine( hDc, lpPointArray, pointCount );, Polygon( hDC, lpPointArray, pointCount );. - uzavře obrazec, vybarví barvou pozadí. SetPolyFillMode( hDc, ALTERNATE nebo WINDING );. ALTERNATE – vybarví jen lichý počet vrstev (při překrývání částí polygonu).

Dynamická ikona okna – ve WNDCLASSEX nastavím icon na NULL, starám se o ní ve WM_PAINT. Minimalizace okna se dá testovat funkcí IsIconic( hWnd );, nesmí dojít k přepnutí DC během malování (ani MessageBox). Vykreslení ikony – pomocí DrawIcon( hDC, 0, 0, hIcon );, DrawIconEx( hDC, 0, 0, hIcon, width = 0, height = 0, frameCountAnimCursor = 0, hBrushFlickerFree = NULL, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE );. Dá se tak nakreslit i doprostřed okna.

Pozadí – dá se nastavit ve Win-Class, nebo: pro DC: SelectObject( hDC, hBrush ). Pozadí šrafování & textu (std. stejné jako pozadí okna)– SetBkColor( hDC, dwColorRGB ); (lze zjistit – GetBkColor). Pro DC – SetBkMode( hDc, OPAQUE, TRANSPARENT ); - pro podklad textu (dá se zase zjistit – GetBkMode). Pokud mezi BeginPaint, EndPaint měním DC, měl bych vrátit původní hodnoty (kvůli uvolnění paměti).

Bitmapa – HBITMAP hBitmap = LoadBitmap( hInst, resourcename ); - v resourcech, LoadImage( hInst, resourcename, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE ); - jiná možnost; ze souboru – LoadImage( NULL, fileName, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE );. Vytvoření nové bitmapy v paměti (zatím nemá obsah) – HBITMAP hBitmap = CreateCompatibleBitmap( hDC, width, height ); - bude mít stejnou paletu jako DC. Pozor – obecně nejde použít SelectObject( hDC, hBitmap ); !!! - přesměruji DC z okna do bitmapy & neumím vrátit ! Z bitmapy se dá udělat brush & použít jako pozadí okna: LOGBRUSH brush; brush.lbStyle = BS_PATTERN; brush.lbColor = 0; brush.lbHatch = hBitmap; HBRUSH hBrush = CreateBrushIndirect( &brush ); windowClass.hBrBackground = hBrush; - jde o dlaždicové uspořádání. Problém – WM_PAINT vždy začne od levého rohu bitmapy (i uprostřed okna ) ... jde změnit.

Memory device context – kreslení do paměti: hMemDC = CreateCompatibleDC( hDC ); hBitmap = CreateCompatibleBitmap( hDC, width, height ); SelectObject( hMemDC, hBitmap ); - tady můžu bitmapu přesměrovat, protože CreateCompatibleDC vytvoří bitmapu 1x1 pixel 1 BPP – nepoužitelné. Může sloužit jako pamět pro všechno co nakreslím – dělám 2x ty samé fce ( 1 v paměti, 1 na obrazovce ). Kopírování bitmap – BitBlt( hDestinationDC, destX, destY, width, height, hSourceDC, srcX, srcY, dwRasterOperation = SRCCOPY ); - dá se použít jako reakce na WM_PAINT – jen zkopíruji zneplatněný obdélník z paměti. Raster operations – SRCCOPY – zkopírování, SRCPAINT – OR s původním, SRCERASE – AND, SRCINVERT – XOR, ... NOT**, PAT** - se štětcem zvoleným v DC, ... layers, mirror apod. Roztažení – StrechBlt( hDestinationDC, destX, destY, destWidth, destHeight, hSourceDC, srcX, srcY, srcWidth, srcHeight, dwRasterOperation );.

Pokročilejší oprace – SetGraphicsMode( hDC, GM_ADVANCED ); (původně – GM_COMPATIBLE). Potom lze: SetMapMode( hDC, MM_ANISOTROPIC ); <- přepočítávání jednotek jak si sám zvolím ( SetWindowOrgEx, SetViewportOrgEx, - posunutí, SetWindowExtEx, SetViewportExtEx - roztažení; window – logické jedn. (lze měnit – pro funkce používající hDC), viewport - fyzické ). Jiné MM: MM_TEXT, MM_ISOTROPIC, MM_LOMETRIC, MM_HIENGLISH, MM_TWIPS. Další – struct XFORM { eM11, eM12, eM21, eM22, eDx, eDy }; SetWorldTransform( hDC, &XFORM ); - transformace: x' = x * eM11 + y * eM21 + eDx, y' = x * eM12 + y * eM22 + eDy. Transformace – 2 úrovně: WORLD (paměť) -> SetWorldTransform -> PAGE (paměť) -> SetMapMode -> DEVICE. (vše Win95+).