A Windows rendszerben az erőforrás egy gyűjtőfogalom, amely alatt az ikonokat, sztringtáblákat, bittérképeket, menüket, kurzorokat, gyorsítóbillentyűket (hotkey) értünk. Az erőforrások az exe fájlban találhatók de nem részei az adatszegmensnek. Az erőforrások esetében be lehet állítani, hogy mikor töltődjenek be a memóriába. Álta 17517s1812r lában a program indításakor a Windows betölti a programot a memóriába, de az erőforrásokat nem. Ezek akkor kerülnek a memóriába, ha szükség van rájuk. Az erőforrásokat (a bittérképek kivételével ) megosztva használják a példányok. A felszabadítás akkor történik, ha a programnak az utolsó példánya is kilépett. Az erőforrások készítéséhez számos eszköz áll rendelkezésre. Mint említettem az előző fejezetben a Workshop és az App Studio használhatók főleg erre a célra. Ezeknek az eszközöknek a kimenete az erőforrás fájl. Az erőforrás fájl lehet szöveges RC vagy bináris RES kiterjesztésű. Általában az RC a kedvezőbb, hiszen ehhez a fájlhoz bármikor egy tetszőleges text editorral tudunk hozzáadni elemeket, természetesen a szintaktika betartása mellett.
A különböző erőforrás elemekre természetesen szükségünk van a programban. Ahhoz, hogy tudjunk ezekre hivatkozni, minden elemet ellátunk egy számmal. Egy ablakon belül ennek a számnak egyedinek kell lennie. Mivel a sok számra nem fogunk később emlékezni, ezért szokás minden elemnek egy azonosító nevet adni. Az azonosítók általában egy h (header) fájlban lesznek deklarálva. Ezt a fájlt is be kell inkludolni a C fájlunkba, ahhoz, hogy tudjunk rá hivatkozni. Természetesen az azonosítók definiálásánál érdemes betartani azt a szabályt, hogy az azonosítókat nagy betűvel írjuk egy prefixummal. Pl. a prefixumok lehetnek ID_ (általános) azonosító, IDI_(Ikon azonosító), IDC_ (Kurzor), IDM_(Menü), IDS_(String), stb...
Példa:
egy RC fájl a következőképpen néz ki:
MENUDEMO.RC resource script
----- ----- --------- ----- -----*/
#include "menudemo.h"
IDI_IKON1 ICON "Myicon1.ico"
IDB_BITMAP1 BITMAP "MyBitmap1.bmp"
IDC_CURSOR1 BITMAP "MyCursor1.cur"
MenuDemo MENU
POPUP "&Edit"
POPUP "&Background"
POPUP "&Timer"
POPUP "&Help"
}
DIALOGUS_ABLAK DIALOG 18, 18, 165, 104
STYLE WS_OVERLAPPED | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "GYERMEK_ABLAK"
BEGIN
EDITTEXT ID_MEZO, 13, 27, 122, 12, ES_LEFT|WS_CHILD| WS_VISIBLE |WS_BORDER|WS_TABSTOP
CONTROL "",ID_COMBOBOX,"COMBOBOX",CBS_DROPDOWN|WS_CHILD| WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 13, 43, 120, 33
CHECKBOX "Check box", ID_CHECKBOX, 111, 56, 50, 12, WS_CHILD | WS_VISIBLE | WS_TABSTOP
RADIOBUTTON "Radio button", ID_RADIOBUTTON, 111, 71, 51, 12, WS_CHILD | WS_VISIBLE | WS_TABSTOP
CONTROL "OK", ID_OK, "BorBtn", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 14, 75, 32, 20
CONTROL "Cancel", ID_CANCEL, "BorBtn", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 52, 75, 32, 20
LTEXT "Írja ide a szöveget :", -1, 11, 15, 126, 8
END
STRINGTABLE
BEGIN
IDS_STRING1, "Első elem"
IDS_STRING2, "Második elem"
IDS_STRING3, "Harmadik elem"
IDS_STRING4, "Negyedik elem"
IDS_STRING5, "Ötödik elem"
END
MyAccell ACCELERATORS
BEGIN
"^C", IDM_COPY, NONINVERT
"^X", IDM_CUT, NONINVERT
VK_DELETE,IDM_CUT, NONINVERT, VIRTKEY,SHIFT
"^V", IDM_PASTE,NONINVERT
VK_INSERT,IDM_PASTE,NONINVERT, VIRTKEY,SHIFT
END
Az ehhez az erőforrás fájlhoz tartozó header fájl a következőképpen néz ki:
MENUDEMO.H header file
----- ----- --------------*/
#define IDI_IKON1 201
#define IDB_BITMAP1 202
#define IDS_STRING1 0
#define IDS_STRING2 1
#define IDS_STRING3 2
#define IDS_STRING4 3
#define IDS_STRING5 4
#define IDM_NEW 101
#define IDM_OPEN 102
#define IDM_SAVE 103
#define IDM_SAVEAS 104
#define IDM_EXIT 105
#define IDM_UNDO 110
#define IDM_CUT 111
#define IDM_COPY 112
#define IDM_PASTE 113
#define IDM_DEL 114
#define IDM_WHITE 120
#define IDM_LTGRAY 121
#define IDM_GRAY 122
#define IDM_DKGRAY 123
#define IDM_BLACK 124
#define IDM_START 130
#define IDM_STOP 131
#define IDM_HELP 140
#define IDM_ABOUT 141
#define ID_MEZO 101
#define ID_CANCEL 102
#define ID_OK 103
#define ID_CHECKBOX 104
#define ID_RADIOBUTTON 105
#define ID_COMBOBOX 106
#define DIALOGUS_ABLAK 1
Minden erőforrásra való hivatkozás előtt be kell tölteni az erőforrást és egy annak az erőforrásnak megfelelő típusú leíróban kell tárolni:
LoadXxxxxx(hInstance,MAKEINTRESOURCE(IDX_XXXXX))
Ahol az X,x -ek megfelelő karakterrel helyettesítendők.
Az ikont kétféleképpen lehet definiálni
1. Ikon1 ICON "Myicon1.ico"
2. IDI_IKON1 ICON "Myicon1.ico"
A létrehozott ikont be lehet hívni, például a példa1.c ben szereplő osztály regisztrálás előtt a
wndclass.hIcon=LoadIcon(hInst,"ikon1")//az első definíció
wndclass.hIcon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_IKON1) //a 2.
Ha az ablaknak az ikonját utólag akarjuk módosítani, akkor
SetClassWord(hWnd,GCW_HICON, LoadIcon(hInst,"ikon1"))
Ha az ikont meg is akarjuk jeleníteni a képernyőn, akkor
HICON hIkon1;
hIkon1=LoadIcon(hInst,"ikon1");
DrawIcon(hdc, x, y, hIkon);
programrészt kell bírni, ahol az x,y az ikon bal felső sarkának a koordinátai. (a valódi pozíció függ a koordináta rendszertől, amiben éppen dolgozunk (kliens, ablak, képernyő). Erről részletesebben lesz szó a GDI tárgyalásánál. Vannak előre definiált ikonok, amiket esetleg fel lehet használni, amennyiben nem akarunk sajátot rajzolni. IDI_APPLICATION, IDI_HAND, stb...
A kurzorok kezelése hasonlít az ikonokéhoz. Azzal az eltéréssel, hogy az ICON helyett CURSOR-t kell írni. A kurzort meg lehet jeleníteni és el lehet rejteni a következő függvénnyel:
int ShowCursor(BOOL fShow)
Más jellegű felhasználásra példa a homokóra esete. Ha hosszú műveletet indítottunk a programunkban és tudatni akarjuk a felhasználóval, hogy várjon egy kicsit, akkor kitesszük a homokóra jelet, és amikor befejeztük a műveletet visszaállítjuk az eredeti mutatóra. Ezt a következő függvénnyel lehet elérni:
HCURSOR SetCursor(LoadCursor(hInstance, MAKEINTRSOURCE(IDC_CURSOR))
A visszatérési értéke a régi kurzor, amely a beállítás előtt volt.
Ennek az az előnye, hogy a szövegeket nem a programba írjuk, hanem szintén az erőforrás fájlba (Lásd a fent írt RC fájl STRINGTABLE része). Amikor szükségünk van rájuk, akkor betöltjük őket.
int LoadString(HINSTANCE hInst, UINT ResourceID, LPSTR, lpszBuffer, in cbBuffer)
Ez a függvény betölti a ResourceID azonosítójú stringet az lpszBuffer bufferbe és a cbBuffer azt jelzi, hogy hány karakter kerüljön a bufferbe. A függvény a buffer végére egy '\0' karaktert is hozzáfűz. A visszatérési érték a ténylegesen átmásolt karakterek száma.
A String erőforrások rendszerint takarékoskodnak a memóriával. Az erőforrás-fordító az azonosítószámtól függően különböző szegmensekbe osztja a stringeket, miközben hozzáadja őket az EXE fájlhoz. A szegmensek mindegyike max. 16 stringet tartalmaz. Az elsőbe kerülnek azok a Stringek, amelyeknek az azonosítójuk 0-15-ig , a másodikba a 16-31-ig, és így tovább. Amikor egy stringet töltünk be a LoadString függvénnyel az adott stringhez tartozó teljes szegmens is betöltésre kerül.
A menüket szintén az erőforrás-editor segítségével szerkeszthetjük. Minden menüelemhez egy azonosítót rendelünk hozzá. Be lehet állítani a menüelem állapotát is (CHECKED, GRAYED, Stb..) . A menühasználatára a fent említett RC fájl mutat példát.
7. ábra
A fenti ábra WinWord 6.0 menüjét mutatja. Az Edit menü kiválasztásakor egy legördülő (PopUp) menü jelenik meg, amely számos menüelemet tartalmaz. A jobb oldalon látható
billentyű kombinációk a gyorsítók. Ez azt jelenti, hogy ezekkel a gyorsítókkal ugyanazt a hatást tudjuk elérni, mint a menü elemkiválasztásakor. A "..." jelölés azt jelenti, hogy amennyiben ezt a menüelemet választjuk, akkor egy gyermekablak (Lásd következő fejezet) jelenik meg, amiből választani illetve beírni lehet. a jel azt mutatja, hogy újabb legördülő menü fog megjelenni. Egy menüelemet lehet szürkíteni (pl. a Links). A menü használatához pl. az ablakosztály regisztrálása előtt érdemes beállítani a megfelelő menüt.
wndclass.lpszMenuName="MenuDemo"
Utólag is tehetjük ugyanazt természetesen a következőképpen:
hMenu=LoadMenu(hInstance,"MenuDemo")
SetMenu(hWnd,hMenu)
DrawMenuBar(hWnd)
Legördülő menüt a programban is tudunk létrehozni a CreateMenu függvénnyel. Ehhez a létrehozott menühöz bármikor tudunk hozzáadni elemeket illetve törölni az AppendMenu, InsertMenu, RemoveMenu függvényekkel. A menü módosítása után a DrawMenuBar függvénnyel tudjuk a módosításokat megjeleníteni. Le lehet kérdezni a menüelem állapotát, azonosítóját, szövegét a GetMenuState, GetMenuItemID, GetMenuString függvényekkel.
Lehetőség van arra, hogy a "hagyományos" menükön kívül egy adott pontban egy legördülő menüt jelenítsünk meg a TrackPopupMenu függvénnyel. Ez általában az egér jobb gombjának a lenyomásához szokás kötni.
Amikor a Menüből egy adott legördülő menüt választunk, akkor egy WM_INITMENUPOPUP üzenet keletkezik. Ebben az esetben a wParam értéke a legördülő menü leírója, az lParam alsó szava a legördülő menü indexe, a felső szava pedig azt jelzi , hogy az üzenet rendszermenü üzenet vagy sem (1 ha rendszermenü, 0 ha nem). A menüelem kiválasztásakor egy WM_COMMAND üzenet keletkezik. Ilyenkor a wParam értéke a menüelem azonosítója, az lParam értéke 0. Amennyiben az üzenet rendszermenü üzenet, akkor az üzenet WM_SYSCOMMAND és az lParam a kurzor pozícióját tartalmazza.
Megjegyzés: A \PELDAK\PELDA2 könyvtárban levő program megmutatja, a menü és a gyermekablakok használatát.
Az eddigiek a bittérképekre is igazak. Ez az erőforrás annyiban más mint a többi, hogy ez egy GDI (Graphical Device Interface) elem (később kerül részletezésre). A bittérkép nem kerül megosztásra a példányok között és nem törlődik automatikusan a memóriából a program kilépésekor, ezért nekünk kell gondoskodnunk a törléséről a programból való kilépéskor.
A gyorsítóbillentyűk általában egy menüelem gyors elérésére használjuk. A definiálásuk hasonlít a többi erőforráshoz A NONINVERT jelzővel azt érjük el, hogy amennyiben a gyorsítóbillentyűk egy menüelemnek felel meg, ne látszódjon a menü villanása az adott billentyű kombináció kiválasztása esetén. Az üzenet kezelő ciklus a gyorsítóbillentyűk esetén a következőképpen néz ki:
hAccel=LoadAccelerators(hInstance, "MyAccel")
while (GetMessage (&msg, NULL, 0, 0))
}
A TranslateAccelerator függvény megvizsgálja a GetMessage által feltöltött msg üzenetet, hogy billentyűzetről származik-e. Ha igen, akkor ha az üzenet rendszermenü üzenet, akkor WM_SYSCOMMAND üzenetet küld az ablakkezelő függvénynek, különben WM_COMMAND-t. A függvény visszatérési értéke nem nulla, ha sikerült elküldenie az üzenetet az ablakkezelő függvénynek, különben 0. Ha sikerült az üzenet küldése, akkor abban az esetben a TranslateMessage és DispatchMessage-re nem kerül a vezérlés. Érdemes megemlíteni, hogy a TranslateMessage függvény felülírja az msg-ben tárolt hwnd-t az ő hWnd argumentumával, tehát a gyorsítóbillentyű üzenetei ugyanannak az ablaknak mennek akkor is ha másik ablaknál van az input fókusz. A TranslateMessage nem hajtja végre a billentyűzet üzeneteket, ha az inputfókusz egy dialógusablaknál vagy üzenetablaknál van.
|