Windowsin sanomanvälitys Juha Järvensivu juha.jarvensivu@tut.fi 2007
Sisällys Windowsin sanomat Sanomanvälitysmekanismi Ikkunan kahva Sanomien lähettäminen Esimerkki winamp
Tapahtumapohjainen toiminta Windows-sovellus käsittelee tapahtumat sanomina (Message) Ohjelma käsittelee sanomat saapumis- ja tärkeysjärjestyksessä (sanomajono, message queue) Windows lähettää viestin ikkunalle = Windows kutsuu ikkunaan liitettyä funktiota, ikkunaproseduuria
Sanoma WM_PAINT, WM_SIZE, WM_COMMAND Define avainsanalla määriteltyjä numerovakioita define WM_SIZE 0005 Käyttäjän omille sanomille varattu oma lukualue WM_USER through 0x7FFF
Sanoma Sanomaan liitetään 2 parametria WPARAM = 32bit integer LPARAM = 32bit integer Parametrien merkitys riippuu sanomasta Esim ID = WM_MOUSEMOVE fwkeys = wparam; xpos = LOWORD(lParam); ypos = HIWORD(lParam);
Sanomastruktuuri MSG struct MSG HWND hwnd; UINT message; WPARAM wparam; LPARAM lparam; DWORD time; Point pt; // Ikkunan kahva // viestin ID // viestin parametri // viestin parametri. // aika jolloin viesti on lähetetty // Kursorin sijainti
Sanoman vastaanotto WM_PAINT WM_SIZE Sanomajono WM_DESTROY WM_COMMAND Ohjelma Sanomasilmukka IkkunaProseduuri Sanomakäsittelijä Sanomakäsittelijä Sanomakäsittelijä Sanomakäsittelijä Sanoman oletuskäsittelijä DefWindowProc
Sanomajono Kun windows-sovellus käynnistyy, windows luo ohjelmalle (säikeelle) sanomajonon Käyttöjärjestelmä laittaa ikkunoille lähetetyt viestit sanomajonoon, josta sovellus käy ne hakemassa
Sanomasilmukka Hakee sanomat yksitellen sanomajonosta ja lähettää ne edelleen oikealle ikkunaproseduurille while (GetMessage(&msg, NULL, 0, 0)) TranslateMessage(&msg); DispatchMessage(&msg);
Ikkunaproseduuri Funktio, joka käsittelee ikkunalle lähetetyt sanomat Ikkunaproseduuri liittyy tiettyyn ikkunaluokkaan, joten useampi ikkuna (ilmentymä) voi käyttää samaa ikkunaproseduuria
Ikkunaluokka Ikkunat perustuvat ikkunaluokkaan Esim Button Ikkunaluokka pitää rekisteröidä ennen ensimmäisen ikkunan luomista WNDCLASSEX wndclass RegisterClassEx (&wndclass) ;
HWND Ikkunan kahva yksikäsitteinen ikkunan tunniste, jonka käyttöjärjestelmä luo ikkunan luontivaiheessa HWND hwnd = CreateWindow ( IkkunaLuokka", )
Winapi-sovellus Sisältää: Pääohjelman WinMain Ikkunaluokan rekisteröinnin ja ikkunan luomisen Ikkunaluokan sanomakäsittelijän WndProc Sanomasilmukan
Koodiesimerkki WinMain ja sanomasilmukka #include <windows.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; void MyRegisterClass(HINSTANCE hinstance); void MyCreateWindow(HINSTANCE hinstance, int icmdshow); int WINAPI WinMain (HINSTANCE hinstance, HINSTANCE hprevinstance, PSTR szcmdline, int icmdshow) MSG msg ; MyRegisterClass(hInstance); MyCreateWindow(hInstance, icmdshow); // Sanomasilmukka while (GetMessage (&msg, NULL, 0, 0) == TRUE) TranslateMessage (&msg) ; DispatchMessage (&msg) ; return msg.wparam ; // käyttöjärjestelmälle palautuva arvo
Koodiesimerkki Ikkunaluokan alustaminen ja rekisteröinti void MyRegisterClass(HINSTANCE hinstance) WNDCLASSEX wndclass ; wndclass.cbsize = sizeof (wndclass) ; // struktuurin koko wndclass.style = CS_HREDRAW CS_VREDRAW ; // ikkunan tyyli wndclass.lpfnwndproc = WndProc ; // ikkunaproseduurin nimi wndclass.cbclsextra = 0 ; // ikkunan luokan sisältä ohjelman... wndclass.cbwndextra = 0 ; //...omaan käyttöön varattua tilaa wndclass.hinstance = hinstance ; // ohjelman ilmentymän kahva wndclass.hicon = LoadIcon (NULL, IDI_APPLICATION) ; // suuri ikoni wndclass.hcursor = LoadCursor (NULL, IDC_ARROW) ; // kursori wndclass.hbrbackground = (HBRUSH) COLOR_WINDOW ; // taustaväri wndclass.lpszmenuname = NULL ; // valikon kahva wndclass.lpszclassname = "OmaLuokka" ; // ikkunan luokan nimi wndclass.hiconsm = LoadIcon (NULL, IDI_APPLICATION) ; // pieni ikoni RegisterClassEx (&wndclass) ; // ikkunan luokan rekisteröinti
Koodiesimerkki WinMain ja sanomasilmukka #include <windows.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; void MyRegisterClass(HINSTANCE hinstance); void MyCreateWindow(HINSTANCE hinstance, int icmdshow); int WINAPI WinMain (HINSTANCE hinstance, HINSTANCE hprevinstance, PSTR szcmdline, int icmdshow) MSG msg ; MyRegisterClass(hInstance); MyCreateWindow(hInstance, icmdshow); // Sanomasilmukka while (GetMessage (&msg, NULL, 0, 0) == TRUE) TranslateMessage (&msg) ; DispatchMessage (&msg) ; return msg.wparam ; // käyttöjärjestelmälle palautuva arvo
Koodiesimerkki Ikkunaolion luominen ja piirto ruudulle void MyCreateWindow(HINSTANCE hinstance, icmdshow) HWND hwnd = CreateWindow ("OmaLuokka", // ikkunan luokan nimi "Päivää maailma!", // ikkunan otsikko WS_OVERLAPPEDWINDOW, // ikkunan tyyli CW_USEDEFAULT, // x-positio aluksi CW_USEDEFAULT, // y-positio aluksi CW_USEDEFAULT, // leveys aluksi CW_USEDEFAULT, // korkeus aluksi NULL, // emoikkunan kahva NULL, // ikkunan valikon kahva hinstance, // ohjelman ilmentymän kahva NULL) ; // luontiparametrit ShowWindow (hwnd, icmdshow) ; // ikkunan piirto
Koodiesimerkki WinMain ja sanomasilmukka #include <windows.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; void MyRegisterClass(HINSTANCE hinstance); void MyCreateWindow(HINSTANCE hinstance, int icmdshow); int WINAPI WinMain (HINSTANCE hinstance, HINSTANCE hprevinstance, PSTR szcmdline, int icmdshow) MSG msg ; MyRegisterClass(hInstance); MyCreateWindow(hInstance, icmdshow); // Sanomasilmukka while (GetMessage (&msg, NULL, 0, 0) == TRUE) TranslateMessage (&msg) ; DispatchMessage (&msg) ; return msg.wparam ; // käyttöjärjestelmälle palautuva arvo
Koodiesimerkki Sanomakäsittelijä LRESULT CALLBACK WndProc (HWND hwnd, UINT imsg, WPARAM wparam, LPARAM lparam) switch (imsg) case WM_DESTROY: PostQuitMessage (0); return 0; // Sanoman oletuskäsittelijä return DefWindowProc (hwnd, imsg, wparam, lparam) ;
Koodiesimerkki WinMain ja sanomasilmukka #include <windows.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; void MyRegisterClass(HINSTANCE hinstance); void MyCreateWindow(HINSTANCE hinstance, int icmdshow); int WINAPI WinMain (HINSTANCE hinstance, HINSTANCE hprevinstance, PSTR szcmdline, int icmdshow) MSG msg ; MyRegisterClass(hInstance); MyCreateWindow(hInstance, icmdshow); // Sanomasilmukka while (GetMessage (&msg, NULL, 0, 0) == TRUE) TranslateMessage (&msg) ; DispatchMessage (&msg) ; return msg.wparam ; // käyttöjärjestelmälle palautuva arvo
Viestin lähettäminen SendMessage(hwnd,msg,wParam,lParam) Palaa vasta kun vastaanottaja on käsitellyt viestin PostMessage(hwnd,msg,wParam,lParam) Palaa heti kun viesti on lähetetty
Sanoman lähettäminen toiselle ohjelmalle 1. Selvitetään ikkunan kahva 2. Selvitetään mitä sanomia ohjelma kuuntelee 3. Lähetetään sanoma SendMessage funktiolla
Sovelluksen käynnistäminen vain kerran int WinMain( ) HWND prev; prev = FindWindow(szWindowClass,NULL); if(prev!= NULL) // Sovellus on jo käynnissä SetForegroundWindow(prev); return 0; else // Käynnistä sovellus.
Pikanäppäimet HACCEL hacceltable; hacceltable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINAMPUI)); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) if (!TranslateAccelerator(msg.hwnd, hacceltable, &msg)) TranslateMessage(&msg); DispatchMessage(&msg);
Resurssitiedosto.rc ///////////////////////////////////////////////////////////////////////////// // // Accelerator // IDC_WINAMPUI ACCELERATORS BEGIN "/", IDM_ABOUT, ASCII, ALT, NOINVERT "?", IDM_ABOUT, ASCII, ALT, NOINVERT "P", ID_ACCELERATOR32773, VIRTKEY, CONTROL, NOINVERT END
Esimerkki winamp WM_COMMAND
Lähteitä Charles Petzold Programming windows http://www.charlespetzold.com/pw5/ How to communicate with Winamp http://forums.winamp.com/showthread.php?th readid=180297