Winapi Juha Järvensivu juha.jarvensivu@tut.fi 2007
Sisällys Osa 1 Ikkunan päivittäminen Resurssikuvaustiedosto Valikot Dialogien luonti Osa 2 Winapi ja olio-ohjelmointi (esimerkki)
Yksinkertainen winapi-sovellus Sisältää: Pääohjelman WinMain Ikkunaluokan rekisteröinnin ja ikkunan luomisen Sanomasilmukan Sanomakäsittelijän WndProc Sisältää varsinaisen ohjelmalogiikan
Ikkunan alustus WM_CREATE Ensimmäinen ikkunaproseduurille lähetettävä sanoma. Kutsutaan kun ikkuna luodaan CreateWindow-funktiolla Käsittelijässä suoritetaan kertaluonteisia ikkunan alustustoimenpiteitä (vrt.net InitializeComponent)
Ikkunan päivittäminen WM_PAINT Piirtää näytön uudelleen Piirron aloittaminen BeginPaint Piirron lopettaminen EndPaint Oletustoteutus asettaa vain ikkunan kelvolliseksi, mutta ei piirrä mitään uudelleen UpdateWindow(hwnd); Ikkunan päivittäminen ohjelmallisesti
Grafiikan piirto Piirto aloitetaan pyytämällä kahva piirtopintaan BeginPaint-funktiolla HDC dc= BeginPaint(hwnd,&ps); Suoritetaan tarvittavat piirtotoimenpiteet kutsumalla tarvittavia GDI-rajapinnan funktioita DrawText(dc, ); Vapautetaan piirtopinta kutsumalla EndPaintfunktiota EndPaint(hwnd,&ps);
Piirtostruktuuri struct PAINTSTRUCT { HDC hdc; BOOL ferase; RECT rcpaint; BOOL frestore; BOOL fincupdate; BYTE rgbreserved[32]; }
Sovelluksen sulkeminen WM_DESTROY Kertoo ohjelmalle, että ikkunaa ollaan tuhoamassa käyttäjän toimesta Ohjelma suljetaan kutsumalla PostQuitMessage-funktiota, joka aiheuttaa WM_QUIT = 0 sanoman lähettämisen WM_DESTROY WM_QUIT Sovellus sulkeutuu
DefWindowProc Sanomien oletuskäsittelijä-funktio Jos sanomakäsittelijässä ei reagoida sanomaan, se pitää välittää oletuskäsittelijälle Oletuskäsittelijä voi olla tyhjä toteutus, mutta se voi synnyttää myös uusia sanomia Esim Valitaan järjestelmävalikosta valinta Sulje WM_SYSCOMMAND WM_CLOSE WM_DESTROY WM_QUIT Sovellus sulkeutuu
DefWindowProc Oletustoteutus WM_PAINT sanomalle case WM_PAINT: BeginPaint( ); EndPaint( ); return 0; Ohjelmoija vastaa itse siitä, että toteuttaa sanomakäsittelijät oikein. Esimerkki Virheellisestä WM_PAINT käsittelijästä case WM_PAINT: return 0; // Virhe!!!
Näppäintapahtumat WM_KEYDOWN (vrt.net KeyDown) WM_CHAR (vrt.net KeyPress) WM_KEYUP (vrt.net KeyUp) while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
TranslateMessage This function translates virtual-key messages into character messages. The character messages are posted to the calling thread's message queue, to be read the next time the thread calls the GetMessage or PeekMessage function.
DispatchMessage This function dispatches a message to a window procedure. It is typically used to dispatch a message retrieved by the GetMessage function.
Lapsikontrollit Esimerkki ListBox Lista-komponentin luominen HWND hlista = CreateWindow(_T("LISTBOX"), _T("Lista"), WS_CHILD WS_VISIBLE WS_BORDER, 100, 0, 200, 200, hwnd, (HMENU) 1, hinst, NULL); Alkion lisääminen listaan SendMessage(hwndLista, LB_ADDSTRING, 0, (LPARAM) buf); Alkion poistaminen listasta SendMessage(hwndLista, LB_DELETESTRING, 0, (LPARAM) NULL); Muita sanomia: LB_FINDSTRING, LB_GETCOUNT, LB_GETTEXT
Resurssikuvaustiedosto Resurssit määritellään resurssikuvaustiedostossa Tavallinen ASCII-tiedosto, jonka tunniste on.rc Resurssityyppejä Merkkijonjot Valikot Pikanäppäimet Dialogit jne.
Resurssien kääntämnien.rc.res Resurssikuvaustiedosto Käännetty resurssitiedosto DemoProject.rc DemoProject.res
Valikko (Menu) Toteutetaan resurssien avulla Valikkoalkiohin liitetään yksikäsitteinen IDtunnus Valikko voidaan liittää suoraan ikkunastruktuuriin tai vasta ikkunan luonnin yhteydessä Ikkunastruktuurille wndclass.lpszmenu = MyMenu ; Ikkunan luonnin yhteydessä hmenu = LoadMenu(hInstance, MyMenu ); hwnd = CreateWindow(...,hMenu,...);
MAKEINTRESOURCE This macro converts an integer value to a resource type compatible with Windows resource-management functions. This macro is used in place of a string containing the name of the resource. LPTSTR MAKEINTRESOURCE( WORD winteger; );
Valikko resurssi Menu.rc resurssikuvaustiedosto MenuDemo MENU { POPUP &Tiedosto { MENUITEM Item 1 1 MENUITEM SEPARATOR MENUITEM Item 2 2 } POPUP &Muokkaa { MENUITEM Item 3 3 } }
Dialogiresurssi Myös dialogit toteutetaan usein resurssien avulla DialogBox(HINSTANCE, LPCTSTR, HWND, DLGPROC); BOOL CALLBACK DialogWndProc(HWND, UINT, WPARAM, LPARAM)
Dialogiresurssi IDD_ABOUTBOX DIALOG 22, 17, 230, 75 STYLE DS_SETFONT DS_MODALFRAME WS_CAPTION WS_SYSMENU CAPTION "About" FONT 8, "System" BEGIN ICON IDI_WINAMPUI,IDC_MYICON,14,9,16,16 LTEXT WinampUI",IDC_STATIC,49,10,119,8,SS_NOPREFIX LTEXT "Copyright (C) 2006",IDC_STATIC,49,20,119,8 DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP END
Dialogin avaaminen #define IDD_ABOUTBOX 103 DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, About); // Dialogi-ikkunan sanomakäsittelijä INT_PTR CALLBACK About(HWND hdlg, UINT message, WPARAM wparam, LPARAM lparam) { switch(imsg) { // } }
Omistajan ja parentin selvittäminen HWND GetWindow(HWND hwnd, UINT cmd) cmd GW_CHILD, GW_ENABLEDPOPUP, GW_HWNDFIRST, GW_HWNDLAST, GW_HWNDNEXT, GW_HWNDPREV, GW_OWNER HWND GetParent(HWND hwnd);
Pääikkunan päivittäminen dialogista HWND hwnd = GetWindow(hDlg, GW_OWNER); UpdateClientRect(hwnd,NULL,true); UpdateWindow(hwnd);
Winapi ja olio-ohjelmointi
WinApi OO HWND WinMain() Application Window MessageMap RegisterWindow() CreateWindow() + InitApplication() MyApplication + Create() + OnPaint() MyWindow WndProc + InitApplication() + Create() + OnPaint()
Oman oliokirjaston luominen class TestWindow: public Window { protected: void OnPaint(HDC); }; class TestApplication: public Application { protected: BOOL InitApplication(); }; BOOL TestApplication::InitApplication() { mainwindow = new TestWindow(); mainwindow->create("api to OO"); return true; } void TestWindow::OnPaint(HDC hdc) { ::TextOut(hdc, 0, 0, "Testing...", 10); }
Oman kirjaston luominen Application Käynnistää sovelluksen WinMain Toteuttaa sanomasilmukan MessageLoop Window Ikkunan toiminnallisuus Ikkunaluokan rekisteröinti Ikkunan luominen Tapahtumankäsittelijät (OnPaint) WndProc
Ongelmakohtia 1. Kuinka sovellus saadaan käynnistymään ilman, että muutetaan WinMain-metodia? Staattisen jäsenmuuttujan avulla 2. Kuinka viestit saadaan välitettyä Window-luokan sanomakäsittelijöille? WM_CREATE sanoman avulla
Lähteitä Charles Petzold Programming windows http://www.charlespetzold.com/pw5/