/* tabhand.h */ /***************************************************************************** PROGRAM: tabhand.h PURPOSE: Tyypit viestien taulukkokäsittelylle. Editor: Vesa Lappalainen 13.6.1994 -> 22.10.1994 UPADTE: 1.10.1994/vl + WC-loppuisia makroja ja näistä johtuvia aliohjelmien muutoksia (kuitenkin yhteensopiva edellisen kanssa), jotta luokan tietoihin voi vaikuttaa enemmän 22.10.1994/vl + WC-makrot ja aliohjelmat muutettu käyttämään struktuuria (tCreWndSt) jossa on sekä luokan luontiparametrit että ikkunan luontiparametrit (esim. ikkunan kokoa ei voi aina muuttaa WM_CREATE -viestin yhteydessä, jos kutsutaan aliohjelmaa joka kysyy Get??Rect-funktiolla ikkunan koon). Tästä mahd. seuraa pieni epäyhteensopivuus ajalla 1.10-22.10 tehdyille ohjelmille. Eron huomaa kuitenkin jo onneksi käännösvaiheessa. USAGE: 0) Projektiin: ALI\tabhand.c ALI\mdialog.c - jos mdialogi-ominaisuuksia ALI\checker.c - jos checker.c -ominaisuuksia 1) Käyttäjän on kirjoitettava kullekin viestille oma käsittelijäfunktio, joka on tyyppiä: static EVENT MyMove(tMSGParam *msg) Jos funktion jälkeen halutaan kutsua oletuskäsittelyä, palautetaan DEFRETURN, muuten arvo, joka halutaan palauttaa. Jos käsittelijän jälkeen halutaan jatkaa muilla käsittelijöillä, niin pitää palauttaa CONTINUE_TABLE (lähinnä aliohjelmakirjastojen haarataulukot). Jos käsittelijässä ei käytetä parametria msg, voidaan käsittelijä esitellä myös TVOID-tyyppiseksi: static EVENT WM_create(TVOID) 2) Kirjoitetaan taulukko (tai luodaan automaattisesti, ks. 11), jossa sanotaan mikä käsittelijäfunktio vastaa mihinkäkin viestiin: #define DoC DONT_CARE tMSGEntry MsgTbl[] = { TABLE_LOOK(LanguageMsgTbl), // Käytetätään ensin tätä taulukkoa EV_HANDLE_WM_DESTROY, // Valmis käsittelijä { WM_COMMAND , IDEDIT,EN_CHANGE,MyEdit,0}, { WM_PAINT , DoC , DoC, MyDraw ,1 }, { WM_MOUSEMOVE, DoC , DoC, MyMove ,1 }, { WM_CREATE , DoC , DoC, MyCreate ,0 }, { WM_CHAR , 'h' , DoC, MyAdd ,0 , 1}, { WM_COMMAND , TRANGE, DoC, lisaa_num,0, SAME_AS_W, N0,N9}, { WM_COMMAND , TTABLE, DoC, operaatio,0, FROM_TABLE, (LONG)op_table }, // a b c d e f g h { 0 } }; Taulukossa parmetrit ovat järjetyksessä: a) Viesti johon vastataan. Jos viesti on TB_LOOK_TABLE, niin tällöin käsittelijän kohdalla tulee olla lisätaulukon osoite. Tämän hoitaa makro TABLE_LOOK. TABLE_LOOK -makron avulla voidaan tehdä aliohjelmakirjastoista haarataulukoita. Viestiä etsitään käymällä taulukkoa ylhäältä alaspäin ja mahdolliset haarataulukot kokonaan niiden esiintymis- kohdassa. Jos samaan viestiin halutaan useamman aliohjelman käsittelyä, voi käsitelijä palauttaa CONTINUE_TABLE. Tosin tässä on järkeä vain haarataulukoiden kohdalla. Esim. taulukossa LanguageMsgTbl voi olla WM_DESTROY -käsittelijä, joka hoitaa tarvittavat muistin vapautukset. Itse hävittäminen voidaan jättää seuraavalle käsittelijälle, joka esimerkin tapauksessa on valmis oletuskäsittelijä. b) Viestin wParam arvo, joka täytyy toteutua tai TRANGE, jos halutaan antaa väli tai TTABLE, jos arvot halutaan luetella taulukossa Jos viesti on jokin myöhemmin mainituista tutkittavista viesteistä (mm. WM_COMMAND), niin tämä on GET_WM_COMMAND_ID -makron palauttama arvo ( Win 3.1:ssä wParam ja Win32:ssa LOWORD(wParam) ) c) Viestin lParam arvo, joka täytyy toteutua Jos viesti on jokin myöhemmin mainituista tutkittavista viesteistä (mm. WM_COMMAND), niin tämä on GET_WM_COMMAND_CMD -makron palauttama arvo ( Win 3.1:ssä HIWORD(lParam) ja Win32:ssa HIWORD(wParam) ) d) Funktio, joka käsittelee viestin e) Luodaanko (=1, MAKE_DC) ennen funktion kutsua valmis DisplayContext Jos luodaan, niin WM_PAINT-viestiä varten luonti tehdään BeginPaint-kutsulla ja muita viestejä varten CreateDC-kutsulla f) Extra-viestissä palautettava lisätunnus. Jos SAME_AS_W, niin arvo sama kuin wParam FROM_TABLE, niin arvo otetaan taulukosta (jos ei taulukkoa TTABLE, niin wParam). g) ex1 = alaraja jos wParam == TRANGE = taulukon osoite jos wParam == TTABLE Taulukko voisi olla esimerkiksi: tMsgTTable op_table[] = { { YNNAA , PLUS }, { VAHENNA , MIINUS }, { KERRO , KERTO }, { LASKETULOS , LASKE }, { DoC,DoC } }; missä 1 arvo on tarvittava wParam arvo ja toinen sitä vastaava extra-arvo h) ex2 = yläraja jos wParam == TRANGE i) alustus ja lopetus funktio-osoitetietueen osoite Voi jättää antamatta jollei tarvita ( => NULL). Esim. makro DO_EVENT_LOCK luo tällaiset funktiot ja niille osoitetietueen, jonka osoitetta voidaan sitten käyttää tässä kohdassa: DO_EVENT_LOCAL_LOCK(pLocalStruct,InitScaling, EventLock,EventUnLock, EventBA); #define LOCK 0,0,0,0,&EventBA ... { WM_INITDIALOG,DoC,DoC,WM_initdialog,LOCK}, ... 3) Luodaan ikkunafunktio, joka käsittelee ko. taulukko makrolla: TWINDOWPROC(MsgTbl,MainWndProc) 4) Ikkunan rekisteröinnissä ilmoitetaan ko. funktio käsittelijäksi: wc.lpfnWndProc = MainWndProc; 3b) Jos halutaan käyttää checker.c:n tarkistuksia kesken piirron, luodaankin ikkunafunktio makrolla TWINDOWPROC_C(MsgTbl,MainWndProc) 3c) Dialogien käsittelyä varten ikkunafunktiot luodaan kutsuilla TDIALOGPROC(MsgTbl,MyDlgProc) tai vastaavalla _C kutsulla jos halutaan käyttää checker.c:tä 3d) Jos dialogi on luotu luokkana (lahinna pääikkunana olevat dialogit) voidaan luoda luokan ikkunafunktio kutsulla: TCDIALOGPROC(MsgTbl,MyDlgProc) tai vastaavalla _C kutsulla jos halutaan käyttää checker.c:tä CLASS-dialogille tarvitaan kaksi funktiota: 1. WND hoitaa luokan ( DefDlgProc -kelpaa oletukseksi ) 2. DLG hoitaa dialogin WND-funktio saa mm. WM_CREATE-viestin muttei WM_INITDIALOG viestiä ja DLG-funktiolla asiat on päinvastoin. Usein riittää pelkkä DLG-funktion tekeminen ja TCDIALOGPROC -makro on turha, koska funktio voidaan korvata DefDlgProc-funktiolla. 5) Lisätään projektiin tabhand.c 6) Samaa käsittelijäfunktiota voidaan käyttää useammassa eri taulukossa. 7) Samaa taulukkoa voidaan käyttää usealla eri ikkufunktiolla. Tässä on järkeä, jos esim. toinen ikkunafunktio käsittelee dialogeja ja toinen tavallisia ikkunoita (muuten ei). Sama ikkunafunktion nimi ei saa esiintyä kuin kerran T*PROC-makroissa 8) Aliohjelmakirjastossa on valmiita oletuskäsittelijäfunktioita, jotka voidaan lisätä taulukkoon niiden makroihin viittaamalla: - EVENT EVENT_handler_WM_destroy(tMSGParam *msg) EV_HANDLE_WM_DESTROY, - lähettää PostQuitMessage(0) EV_HANDLE_WM_CLOSE, - lähettää PostQuitMessage(0) - EVENT EVENT_handler_About(tMSGParam *msg); - About käsittelijä, msg->Extra on joko NULL tai &Version-tietue (ks. mdialog.c) EV_HANDLE_MABOUT(message,wParam,Version) - käsittelijä, jolla voidaan ilmoittaa message ja wParam, Version pitää olla versiotietueen osoite (ks. mdialog.c) tai NULL, jos Vesrion-tietoa ei käytetä EV_HANDLE_WM_COMMAND_CM_HELPABOUT(Version) - kuten edellä, mutta viesti kiinnitetty 9) Käytettävissä on valmis RESP.BAT-komento, joka luo taulukon automaattisesti, jos käsittelijäfunktiot on nimetty oikealla tavalla. Ks. RESTABLE.SED ja OLDTABLE.SED Tätä voidaan kutsua myös suoraan esim. Borland C++ 4.0:n IDE:stä jos lisätään uusi työkalu täyttäen dialogi seuraavasti: Name: RespTable Path: C:\DOS\COMMAND.COM Command line: /C C:\BAT\RESP.BAT $NOSWAP $CAP MSG(BORL2MSG.DLL) $SAVE CUR $PROMPT $NAME($EDNAME)$EXT($EDNAME) Menu Text: R&espTable Help Hint: Updates responce table 10) Jos halutaan käyttää Dialogin lokaalia muistia, niin katso makron DO_EVENT_LOCAL_LOCK-kommentit 11) Viestin id, cmd ja chWnd on erotettu valmiiksi seuraaville viesteille: WM_ACTIVATE,WM_CHARTOITEM,WM_COMMAND,WM_MENUSELECT,WM_MENUCHAR, WM_PARENTNOTIFY,WM_VKEYTOITEM,WM_HSCROLL,WM_VSCROLL,WM_SCROLL, Liuille (Scroll Bar) id haetaan vähän mutkan kautta. Ikkunan pääliuille id==0 (vert) tai 1 (horz). Liuille cmd = SB_DOWN jne. Jos kyseessä on ikkunan pääliuku, niin chWnd = hWnd. 12) Koko pääohjelma voidaan tehdä jollakin makroista: TblClassDlgMAIN(dclass,icon,accel,dial,MsgTbl) TblDlgMAIN(accel,dial,MsgTbl) TblClassWindowMAIN(dclass,icon,wtitle,MsgTbl,more_style) ks. ko. makron kommentit. Näiden käyttämiseksi pitää laittaa myös #include "mdialog.h" Projektiin lisäksi mdialog.c. Jos pääikkunana on yksinkertainen ikkuna eikä ohjelmassa käytetä dialogeja, voidaan koko pääohjelma luoda kutsulla: TblClassSWindowMAIN(dclass,icon,wtitle,MsgTbl,more_style) 13) Liuille (Scroll Bar) on erotettu lisäksi valmiiksi arvo (msg->value) ja liun tunnus (msg->flag, SB_CTL, SB_VERT, SB_HORZ). Kaiken tämän tarkoitus on, että käsittelijäfunktio voi esim. asettaa liulle arvon vain kutsulla: SetScrollPos(msg->chWnd,msg->flag,new_value,TRUE); tai SetScrollPosID(msg->hWnd,msg->id,new_value,TRUE); tai SendScrollPosID(msg->hWnd,msg->id,new_value); // infor. myös liukua Lisäksi liukujen helpompaa säätämistä varten on funktio: int SetNewScrollPos(tMSGParam *msg,int pagesize,BOOL modify) joka hoitaa liun eri kommentojen tulkitsemisen ja palauttaa liun arvon tulkinnan jälkeen. Jos modify == TRUE, niin myös muutetaan samalla liun asentoa (ja msg->value). pagesize on liun hyppy, kun on tulee esim. SB_PAGEDOWN viesti. Tätä aliohjelmaa saa kutsua vain kun msg on liukuviestin jäljiltä! id-tunnus liulle on joko sen oikea ID tai SB_VERT (1) tai SB_HORZ (0). Lisäksi on uusi viesti: WM_SCROLL, joka voidaan sijoittaa taulukkoon ja tulkitaan riippumatta siitä, onko kyseessä viesti WM_VSCROLL vai WM_HSCROLL. Tästä huolimatta msg->message on joko WM_VSCROLL tai VM_HSCROLL. 14) Valmis ikkunan ja luokan luonti: DoClassWindowCmd(hInstance,wclass,icon,phWnd,wtitle, wfun,more_style,nCmdShow,wcHandler); DoClassWindow(hInstance,wclass,icon,phWnd,wtitle,wfun,more_style) wcHandler ks. kohta 16). 15) Valmiita pääohjelmia tekeviä makroja (ks. ko. makrojen kommentit): TblClassDlgMAIN(dclass,icon,accel,dial,MsgTbl) TblDlgMAIN(accel,dial,MsgTbl) TblClassSWindowMAIN(dclass,icon,wtitle,MsgTbl,more_style) TblClassWindowMAIN(dclass,icon,wtitle,MsgTbl,more_style) (tämä tarvitsee mdialog.c) Lisäksi kaikista _C -loppuiset makrot, joissa on checker.c:n vaatimat muutokset. Jos näitä käytetään ja itse luodaan DC:tä, pitää DC:n vapauttamisen jälkeen kutsua CheckDelayMessage, jos DC:n elinaikana mahdollisesti on käytetty kutsua CheckMessage. Lisäksi kaikista Class-makroista vielä WC-loppuiset makrot, joissa käyttäjä voi itse märitellä oman wc-tietueen (WNDCLASS) ja cs-tietueen (CREATESTRUCT) arvojen muuttamisen ennen varsinaista ikkunan luontia: void setwc(tCreWndSt *c) { c->wc.style = CS_OWNDC;} TblClassSWindowMAINWC("TblMopoClass",NULL,"MopoCad",MsgTbl,0,setwc); 16) Muita funktioita: POINT tGetClientLost(HWND hWnd) - palauttaa paljonko client alue on pienempi kuin koko ikkuna. void tGetClientWindowRect(HWND hWnd,HWND hWndc,RECT &rcc) palauttaa ikkunan koordinaatin isäikkunan client alueen suhteen Tutkittava: - DefDialogProc - pitääkö tätä varten tehdä oma funktio? + Tehty! - voiko EX? pakata tietueeseen ja TABLE yms. lipuiksi - ei taida auttaa! *****************************************************************************/ #ifndef TABHAND_H #define TABHAND_H #ifndef PORTABLE_H /* Ottaa mm. windowsx.h:n, jollei sitä ole */ #include "portable.h" #endif #ifndef CHECKER_H #include "checker.h" #endif #ifndef MDIALOG_H #include "mdialog.h" #endif #define WM_SCROLL (WM_USER+1134) #define DONT_CARE (0x7fff) #define DoC DONT_CARE #define DEFRETURN (0x1234ffffL) #define CONTINUE_TABLE (0x1234fffeL) #define TBL_ENTRY_NOTFOUND (0x1234fffdL) #define SAME_AS_W (0x12347fffL) #define FROM_TBL (0x12347ffdL) #define TRANGE (0x7ffe) #define TTABLE (0x7ffd) #define EVENT LONG #define TB_LOOK_TABLE (0x7ffe) #define MAKE_DC 1 #define NO_DC 0 #ifdef __cplusplus #define TVOID tMSGParam * #else #define TVOID #endif #ifdef __cplusplus extern "C" { #endif typedef struct { /* Käsittelijälle tuotava tietue */ HWND hWnd; /* Ikkunan kahva */ UINT message; /* Viestin numero */ WPARAM wParam; /* Viestin lyhyempi osa */ LPARAM lParam; /* Viestin pisempi osa */ HDC hDC; /* Mahdollisesti luotu laiteyhteys (=0 jos ei) */ LPARAM extra; /* Lisäparametrin arvo. */ HWND chWnd; /* Lapsi-ikkunan mahdollinen kahva (ei aina) */ WPARAM id; /* Viestistä muodostuva id-tunnus (ei aina) */ WPARAM cmd; /* Viestistä muodostuva komento-osa (ei aina) */ LONG LocalInfo; /* Lokaalin tiedon arvo. */ int value; /* Esim. scrollbarilla liun arvo */ int flag; /* Esim. scrollbarilla liun asetustunnus */ } tMSGParam; typedef LONG (*tMSGHandler)(tMSGParam *); #ifndef __WIN32__ typedef void (WINAPI *EndPaintHandler)(HWND, const PAINTSTRUCT FAR *); #else typedef BOOL (WINAPI *EndPaintHandler)(HWND, const PAINTSTRUCT FAR *); #undef FreeProcInstance #define FreeProcInstance(lProc) ((void)(lProc)) #endif typedef struct { /* Ennen ja jälkeen käsittelyn suoritettavat funktiot */ tMSGHandler before; tMSGHandler after; } tMSGFunctions; typedef struct { /* Käsittelytaulukon tietue */ UINT message; /* Viesti, joka pitää käsitellä */ WPARAM wParam; /* wParam, joka pitää täsmätä */ LPARAM lParam; /* lParam, joka pitää täsmätä */ tMSGHandler handler; /* Osoitin käsittelijään */ char make_hDC; /* Luodaanko hDC (0=ei) */ LPARAM extra; /* Lisäparametrin arvo. */ LONG ex1; LONG ex2; tMSGFunctions *pMSGFunctions; } tMSGEntry; typedef struct { WPARAM wParam; LPARAM extra; } tMsgTTable; int SetNewScrollPos(tMSGParam *msg,int pagesize,BOOL modify); HWND DoClassWindowCmd(HINSTANCE hInstance, char *classname, char *iconname, HWND phWnd,char *wtitle, WNDPROC MainWndProc, DWORD more_style,int nCmdShowt, tWNDCLASSHandler wcHandler); #define DoClassWindow(hInstance,wclass,icon,NULL,wtitle,wfun,more_style) \ DoClassWindowCmd(hInstance,wclass,icon,NULL,wtitle,wfun,more_style,SW_SHOW,NULL) int tMessageLoop(void); POINT tGetClientLost(HWND hWnd); void tGetClientWindowRect(HWND hWnd,HWND hWndc,RECT *rcc); LONG MSGTableHandler(const tMSGEntry *MsgTbl, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, EndPaintHandler EndPaint); /*****************************************************************************/ /* Ikkunafunktiot eri tilanteita varten. Periaatteessa funktioita on */ /* kolmea luokkaa: */ /* - tavallisia ikkunoita varten ( WINDOW ) */ /* - tavallisia dialogeja varten ( DIALOG ) */ /* - luokkana luotuja dialogeja varten ( C ) (ikkunafunktiolle */ /* dialogin fnk:lle ei C) */ /* Kustakin luokasta on vielä mahdollisuus valita lisäksi */ /* checker.c:tä käyttävä versio ( _C ) */ /*****************************************************************************/ /*****************************************************************************/ /* Aluksi pari apumakroa, jottei tarvitse kirjoittaa niin paljoa: */ /* (tosin näitäkin voi käyttää suoraan. Esim. jos halutaan jokin muu */ /* oletuskäsittelijä kuin DefWindownProc tai DefDlgProc) */ #define NULL_CALL(hwnd,message,wParam,lParam) #define DEFFALSE(hWnd, message, wParam, lParam) FALSE #define NULL_C NULL_CALL #define DFALSE DEFFALSE #define CHECK_W CHECK_CHECKER_WIN #define CHECK_D CHECK_CHECKER_DIALOG #define TWINDOWPROC_PAR(TYPE,MsgTbl,name,DEF,PRE,ENDPAINT,RET) \ extern tMSGEntry MsgTbl[]; \ TYPE CALLBACK _export name(HWND hWnd, UINT message, \ WPARAM wParam, LPARAM lParam) \ { \ LONG ret; \ PRE(hWnd,message,wParam,lParam); \ ret = MSGTableHandler(MsgTbl,hWnd,message,wParam,lParam,ENDPAINT); \ if ( ret != DEFRETURN ) return RET; \ return DEF(hWnd, message, wParam, lParam); \ } #define TWINDOWPROC(MsgTbl,name) TWINDOWPROC_PAR(LONG,MsgTbl,name,DefWindowProc,NULL_C , EndPaint , ret) #define TWINDOWPROC_C(MsgTbl,name) TWINDOWPROC_PAR(LONG,MsgTbl,name,DefWindowProc,CHECK_W, CheckEndPaint, ret) #define TDIALOGPROC(MsgTbl,name) TWINDOWPROC_PAR(BOOL,MsgTbl,name,DFALSE ,NULL_C , EndPaint , TRUE) #define TDIALOGPROC_C(MsgTbl,name) TWINDOWPROC_PAR(BOOL,MsgTbl,name,DFALSE ,CHECK_C, CheckEndPaint, TRUE) #define TCDIALOGPROC(MsgTbl,name) TWINDOWPROC_PAR(LONG,MsgTbl,name,DefDlgProc ,NULL_C , EndPaint , ret) #define TCDIALOGPROC_C(MsgTbl,name) TWINDOWPROC_PAR(LONG,MsgTbl,name,DefDlgProc ,CHECK_W, CheckEndPaint, ret) /*****************************************************************************/ /* TCDIALOGPROC ============= ( Tässä järjestetään myös CLASS-dialogeille WM_INITDIALOG-viesti: Temppu: CLASS-dialogi saa WM_CREATE-vietin, jota tavallinen dialogi ei saa. Tämä on kuitenkin liian aikaista vielä luoda mitään. Kaikki dialogit saavat WM_SHOWWINDOW-viestin vähän ennenkuin dialogi pitäisi näyttää heti WM_INITDIALOGin jälkeen tavallisilla dialogeilla. Järjestetään niin, että WM_CREATE-viestin tullessa laitetaan dialogi "odottamaan" seuraavaa WM_SHOWWINDOW-viestiä ja sitten kun ko. viesti sitten saapuu, niin laitetaankin ensin käsittelyyn WM_INITDIALOG-viesti. Tästä seuraa rekursio, muttei se tässä mitään haittaa! Ongelmana on vielä lParamin järjestäminen CreateDialogParam-kutsusta! Nyt toimii jotenkin, jos tabhand.h on ennen mdialog.h-kutsua ja dialogit luodaan kutsuilla DoM..DialogParam. Tämä osuus on tarpeeton kun laitetaan luokkadialogin ikkunafunktioksi DefDlgProc ja tehdään dialogille vielä tavallinen dialogin funktio. -----------------------------------------------------------------------------*/ #define MAX_WAITINGS 10 typedef struct { int n; HWND hwnds[MAX_WAITINGS]; } tWaitingShow; int AddWaiting(HWND hWnd,tWaitingShow *WaitShow); int IsWaiting(HWND hWnd,tWaitingShow *WaitShow); #if 0 #define GetDialogCreateLParam(hWnd) 0 #define CLASSDLGPRE(hwnd,message,wParam,lParam) \ static tWaitingShow WaitShow={0}; \ if ( message == WM_CREATE ) AddWaiting(hWnd,&WaitShow); \ else if ( message == WM_SHOWWINDOW && IsWaiting(hWnd,&WaitShow) ) \ SendMessage(hWnd,WM_INITDIALOG,0,GetDialogCreateLParam(hWnd)); \ #endif /*****************************************************************************/ /* Makro, joka tekee pääohjelman, johon voi itse valita viestisilmukan */ #define tClassWindowMAINLoop(wclass,icon,wtitle,wfun,more_style,loop,wch) \ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, \ LPSTR lpCmdLine, int nCmdShow) \ { \ HWND hWnd; \ (void)hPrevInstance;(void)nCmdShow;(void)lpCmdLine; \ hWnd = DoClassWindowCmd(hInstance,wclass,icon,NULL,wtitle,wfun, \ more_style,nCmdShow,wch); \ if ( !hWnd ) return 1; \ return loop(); \ } /*****************************************************************************/ /* Seuraava makro tekee pääohjelman käyttäen yksinkertaista ikkunaa */ #define tClassSWindowMAIN(wclass,icon,wtitle,wfun,more_style) \ tClassWindowMAINLoop(wclass,icon,wtitle,wfun,more_style,tMessageLoop,NULL) /*****************************************************************************/ /* Pääohjelma, jossa voi olla myöhemmin myös dialogeja (tämä tarv. mdialog.c)*/ #define tClassWindowMAIN(wclass,icon,wtitle,wfun,more_style) \ tClassWindowMAINLoop(wclass,icon,wtitle,wfun,more_style,mMessageLoop,NULL) /*****************************************************************************/ /* Seuraava makro tekee pääohjelman käyttäen yksinkertaista ikkunaa */ #define tClassSWindowMAINWC(wclass,icon,wtitle,wfun,more_style,wch) \ tClassWindowMAINLoop(wclass,icon,wtitle,wfun,more_style,tMessageLoop,wch) /*****************************************************************************/ /* Pääohjelma, jossa voi olla myöhemmin myös dialogeja (tämä tarv. mdialog.c)*/ #define tClassWindowMAINWC(wclass,icon,wtitle,wfun,more_style) \ tClassWindowMAINLoop(wclass,icon,wtitle,wfun,more_style,mMessageLoop,wch) /*****************************************************************************/ /* Seuraavat makrot tekevät kaikki yksinkertaisessa pääohjelmassa */ /* tarvittavat määritykset: */ /* Parametrit: */ /* dclass - luokan nimi (dialogille sama kuin .RC-tiedostossa) */ /* icon - ikonin nimi (sama kuin .RC-tiedostossa) */ /* accel - pikanäppäintaulukon nimi (sama kuin .RC) */ /* dial - dialogin nimi (sama kuin .RC) */ /* MsgTbl - Responce-taulukon nimi */ /*---------------------------------------------------------------------------*/ /* SWindow - nimisissä ei voi käyttää muita kuin modal-dialogeja */ /* WC - loppuiset voivat märitellä WNDCLASS käsitelijän */ /* m - merkityt tarvitsevat mdialog.c:n */ /*---------------------------------------------------------------------------*/ #define TblClassSWindowMAIN(dclass,icon,wtitle,MsgTbl,more_style) \ TWINDOWPROC(MsgTbl,MainWndProc) \ tClassSWindowMAIN(dclass,NULL,wtitle,MainWndProc,more_style) #define TblClassWindowMAIN(dclass,icon,wtitle,MsgTbl,more_style) \ TWINDOWPROC(MsgTbl,MainWndProc) \ tClassWindowMAIN(dclass,icon,wtitle,MainWndProc,more_style) /* m */ #define TblDlgMAIN(accel,dial,MsgTbl) \ TDIALOGPROC(MsgTbl,MainDlgProc) \ mDlgMAIN(accel,dial,MainDlgProc) /* m */ #define TblClassDlgMAIN(dclass,icon,accel,dial,MsgTbl) \ TDIALOGPROC(MsgTbl,MainDlgProc) \ mClassDlgMAIN(dclass,icon,accel,dial,DefDlgProc,MainDlgProc) /* m */ #define TblClassSWindowMAINWC(dclass,icon,wtitle,MsgTbl,more_style,wch) \ TWINDOWPROC(MsgTbl,MainWndProc) \ tClassSWindowMAINWC(dclass,NULL,wtitle,MainWndProc,more_style,wch) #define TblClassWindowMAINWC(dclass,icon,wtitle,MsgTbl,more_style,wch) \ TWINDOWPROC(MsgTbl,MainWndProc) \ tClassWindowMAINWC(dclass,icon,wtitle,MainWndProc,more_style,wch) /* m */ #define TblClassDlgMAINWC(dclass,icon,accel,dial,MsgTbl,wch) \ TDIALOGPROC(MsgTbl,MainDlgProc) \ mClassDlgMAINWC(dclass,icon,accel,dial,DefDlgProc,MainDlgProc,wch) /* m */ #define TblClassDlgMAINWCPROC(dclass,icon,accel,dial,MsgTbl,wch,proc) \ TDIALOGPROC(MsgTbl,MainDlgProc) \ mClassDlgMAINWC(dclass,icon,accel,dial,proc,MainDlgProc,wch) /* m */ #define TblClassDlgMAINWCPROCVBX(dclass,icon,accel,dial,MsgTbl,wch,proc) \ TDIALOGPROC(MsgTbl,MainDlgProc) \ mClassDlgMAINWCVBX(dclass,icon,accel,dial,proc,MainDlgProc,wch) /* m */ /*---------------------------------------------------------------------------*/ /* Edellisistä versiot, joissa tarvitaan checker.c */ #define TblClassSWindowMAIN_C(dclass,icon,wtitle,MsgTbl,more_style) \ TWINDOWPROC_C(MsgTbl,MainWndProc) \ tClassSWindowMAIN(dclass,NULL,wtitle,MainWndProc,more_style) #define TblClassWindowMAIN_C(dclass,icon,wtitle,MsgTbl,more_style) \ TWINDOWPROC_C(MsgTbl,MainWndProc) \ tClassWindowMAIN(dclass,icon,wtitle,MainWndProc,more_style) /* m */ #define TblDlgMAIN_C(accel,dial,MsgTbl) \ TDIALOGPROC_C(MsgTbl,MainDlgProc) \ mDlgMAIN(accel,dial,MainDlgProc) /* m */ #define TblClassDlgMAIN_C(dclass,icon,accel,dial,MsgTbl) \ TDIALOGPROC_C(MsgTbl,MainDlgProc) \ mClassDlgMAIN(dclass,icon,accel,dial,DefDlgProc,MainDlgProc) /* m */ /*****************************************************************************/ /* DO_EVENT_LOCAL_LOCK Seuraava makro luo sekä ennen, että jälkeen kutsua suoritettavat funktiot sekä taulukon ko. funktioista, joka voidaan lisätä MSG-taulukkoon. Kutsussa on parametrina: pLocalStruct - tyyppi, joka on osoite lokaaliin tietueeseen Init - käyttäjän oma funktio, joka alustaa lokaalin alueen EventLock - ennen kutsua suoritettavan funktion nimi Tämä funktio lukitsee ja tarvittaessa varaa ja alustaa lokaalin muistialueen. Alueen osoite palautetaan kentässä msg->LocalInfo, joka on LONG tyypiä, joten alueen käyttöä varten tämä pitää tietysi "typecast"ta oikeaksi tyypiksi esim määrittelemällä makro: #define LP ((pLocalStruct)(msg->LocalInfo)) Nyt lokaalia aluetta voidaan käyttää LP->scale jne... EventUnLock - kutsun jälkeen suoritettavan funktion nimi EventBA - taulukon nimi, johon sijoitetaan ennen ja jälkeen funktioiden osoitteet Jotta kutsut saadaan MSG-taulukkoon, voidaan tehdä esim makro #define LOCK 0,0,0,0,&EventBA ja laittaa jokaisen tarvittavan MSG-taulukon rivin perään ,LOCK -----------------------------------------------------------------------------*/ #define DO_EVENT_LOCAL_LOCK(pLocalStruct,Init,EventLock,EventUnLock,EventBA) \ \ static EVENT EventLock(tMSGParam *msg) \ { \ pLocalStruct lp = (pLocalStruct)DialogLock(msg->hWnd); \ if ( !lp ) { \ lp = (pLocalStruct)DialogAlloc(msg->hWnd,sizeof(*lp)); \ if ( !lp ) return 1; \ Init(lp); \ } \ msg->LocalInfo = (LONG)lp; \ return 0; \ } \ \ static EVENT EventUnLock(tMSGParam *msg) \ { \ return DialogUnlock(msg->hWnd); \ } \ \ static tMSGFunctions EventBA = {EventLock,EventUnLock} \ /*****************************************************************************/ #define LOOK_TABLE(tbl) { TB_LOOK_TABLE,DoC,DoC,(tMSGHandler)tbl } /*****************************************************************************/ /* Valmiita käsittelijöitä: */ EVENT EVENT_handler_WM_destroy(tMSGParam *msg); #define EV_HANDLE_WM_DESTROY \ { WM_DESTROY, DoC , DoC ,EVENT_handler_WM_destroy } #define EV_HANDLE_WM_CLOSE \ { WM_CLOSE, DoC , DoC ,EVENT_handler_WM_destroy } EVENT EVENT_handler_About(tMSGParam *msg); #define EV_HANDLE_MABOUT(message,wParam,Version) \ { message , wParam , DoC , EVENT_handler_About, 0, ((LPARAM)(void far *)(Version)) } #define EV_HANDLE_WM_COMMAND_CM_HELPABOUT(Version) \ EV_HANDLE_MABOUT(WM_COMMAND,CM_HELPABOUT,Version) /*****************************************************************************/ #ifdef __cplusplus } #endif #endif /* TABHAND_H */