ALTE DOCUMENTE
|
||||||||||
A Windows-ban a dialógusablakok fontos szerepet játszanak. Ezeken keresztül történik a párbeszéd a felhasználó és a program között. A dialógusablak definíciója, beállításai az erőforrás fájlban szerepelnek (Lásd az előző fejezet DIA 828x234i LOGUS_ABLAK definíciója). Ehhez az ablakhoz tartozik egy ablakkezelő függvény, ami gondoskodik az ablak üzeneteinek kezeléséről. Ennek a függvénynek is _export típusúnak kell lennie. A dialógusablakon szokás elhelyezni a gyermekablakokat. A dialógusablak definiálását és beállítását szintén egy erőforrás editor segítségével tehetjük meg a legegyszerűbben. Egy dialógusablakon maximum 255 gyermekablakot helyezhetünk el. Két dialógusablak típus létezik a modális és a nem modális. A modális ablak esetén addig nem kapcsolunk át egy másik ablakra, amíg ez az ablak nem fejezi be a működését. Mint említettem a menüknél, a "..." jelű menük arra utalnak, hogy kiválasztásukkor egy dialógusablak jelenik meg.
Az dialógusablak meghívása a következőképpen történik
FARPROC lpfnProc;
case WM_COMMAND:
switch (wParam)
break ;
}
return TRUE;
A DialogBox és DialogBoxParam függvények visszatérési értéke megegyezik az EndDialog függvény második argumentumával. Érdemes megemlíteni, hogy amennyiben egy üzenetet szeretnénk közölni a felhasználóval, akkor a MessageBox függvényt kell használni
MessageBox(HWND hDlg, LPSTR lpszUz, LPSTR lpszCap, Int nOPcio)
az lpszUz az üzenetre mutató pointer, az lpszCap az ablak fejléc szövege, az nOpcio-val különböző gombokat, ikonokat tehetünk az üzenetablakra pl. MB_OK | MB_ICONSTOP stb.
A dialógusablakon levő gyermekablakok kezelésére gyakran a SendMessage helyett a SendDlgItemMessage-t használjuk.
SendDlgItemMessage(HWND hDlg, UINT nID, UINT iMes, WPARAM wParam, LPARAM lParam)
továbbá a következő függvények fontos szerepet játszanak a dialógusablakok gyermekablakainak a kezelésére:
egy edit mező (gyermekablak) értékének beállítására és lekérdezésére
SetDlgItemText(HWND hDlg, UINT nID, LPSTR lpszSoveg )
GetDlgItemText(HWND hDlg,UINT nID,LPSTR lpszBuffer,UINT cbBuf)
SetDlgItemInt(HWND hDlg, UINT nID, int n)
GetDlgItemInt(HWND hDlg, UINT nID, int n)
egy mező ablak, fókusszal rendelkező és szülőablak leírójának kérdezése
HWND GetDlgItem(HWND hDlg, UINT nID)
HWND GetFocus()
HWND GetParent(HWND hDlg)
A modális dialógusablakokkal ellentétben a nem modális ablakok esetén lehetőség van arra, hogy egy másik ablakra kapcsoljunk át, amikor szükségünk van erre. A nem modális ablakok létrehozására nem a DialogBox-ot használjuk, hanem a CreateDialog és a CreateDialogParam függvényeket. A paraméterek értelmezése teljesen ugyanaz mint a DialogBox és DialogBoxParam.
A visszatérési érték ebben az esetben a létrehozott ablak leírója. Általában ez a leíró egy globális változó szokott lenni, hiszen több helyen lehet szükségünk rá. Lehetőség van arra, hogy az üzenetkezelő ciklust módosítsuk annak érdekében, hogy amennyiben az üzenet a nem modális ablaknak szól, akkor azt közvetlenül küldjük neki
hDlgModeless=CreateDialog(hInstance, "DIALOG_2", hwnd, MakeProcInstance(MyDlgProc,hInsytance);
hAccel=LoadAccelerators(hInstance, "MyAccel");
while (GetMessage (&msg, NULL, 0, 0))
}
}
Ha az üzenet a nem modális ablakhoz érkezik, akkor az IsDialogMessage függvény ennek az ablaknak a kezelő függvényének küldi, és ilyenkor nem kerül sor a TranslateMessage és DispatchMessage-re.
A nem modális ablak bezárása előtt gondoskodni kell az ablak megsemmisítéséről a következőképpen:
DestroyWindow(hDlgModeless);
hDlgModeless=0;
A Windows rendszerben lehetőség arra, hogy a meglévő szokásos dialógusablakokat a saját programunkban hívjuk meg. Ezek a Find, Replace, FileOpen, FileSave, Print, PrintSetup, Font, Color ablakok Ezeknek a kezeléséhez szükség van egy struktúrára, amely definiálja a különböző ablakokhoz tartozó információkat.
HWND FindText(FINDREPLACE FAR *)
HWND ReplaceText(FINDREPLACE FAR *)
BOOL ChooseColor(CHOOSECOLOR FAR *)
BOOL PrintDlg(PRINTDLG FAR *)
BOOL GetOpenFileName(OPENNFILENAME FAR *)
BOOL GetSaveFileName(OPENNFILENAME FAR *)
BOOL ChooseFont(CHOOSEFONT FAR *)
Ezek megvalósításához szükségünk van arra, hogy lefoglaljuk a megfelelő méretű memóriát, inicializáljuk a struktúrát és meghívjuk a megfelelő függvényt. Az említett struktúráknak a felépítése a mellek1.doc -ban található. A továbbiakban olyan példát mutatunk, amely illusztrálja a fileopen és filesave működését (A példa a \PELDAK\PELDA3 könyvtárban található).
#include <windows.h>
#include <commdlg.h>
#include <stdlib.h>
#include "filedemo.h"
extern char *szAppName;
#define UNTITLED "(untitled)"
static OPENFILENAME ofn ;
void PopFileInitialize (HWND hwnd)
;
ofn.lStructSize = sizeof (OPENFILENAME) ;
ofn.hwndOwner = hwnd ;
ofn.hInstance = NULL ;
ofn.lpstrFilter = szFilter[0];
ofn.lpstrCustomFilter = NULL ;
ofn.nMaxCustFilter = 0 ;
ofn.nFilterIndex = 0 ;
ofn.lpstrFile = NULL;//Set in Open and Close func.
ofn.nMaxFile = _MAX_PATH ;
ofn.lpstrFileTitle = NULL;//Set in Open and Close func.
ofn.nMaxFileTitle = _MAX_FNAME + _MAX_EXT ;
ofn.lpstrInitialDir = NULL ;
ofn.lpstrTitle = NULL ;
ofn.Flags = 0;// Set in Open and Close func.
ofn.nFileOffset = 0 ;
ofn.nFileExtension = 0 ;
ofn.lpstrDefExt = "Sim" ;
ofn.lCustData = 0L ;
ofn.lpfnHook = NULL ;
ofn.lpTemplateName = NULL ;
}
BOOL PopFileOpenDlg (HWND hwnd, LPSTR lpstrFileName,
LPSTR lpstrTitleName)
BOOL PopFileSaveDlg (HWND hwnd, LPSTR lpstrFileName,
LPSTR lpstrTitleName)
static long PopFileLength (int hFile)
void DoCaption (HWND hwnd, char *szTitleName)
void OkMessage (HWND hwnd, char *szMessage, char *szTitleName)
short AskAboutSave (HWND hwnd, char *szTitleName)
az ofn.lpfnHook paraméter egy úgynevezett Hook függvénynek a címét tartalmazza. Ez egy olyan Callback függvény, amely a közös ablak üzeneteit az ablakkezelő függvény előtt kapja meg.
Számos Windows program létezik, amely több típusú objektumot kezel vagy egy adott objektumot több nézetben. Ezen multi-objektum programok szabványosítására a Microsoft bevezetette az MDI szabványt. Ebben a fejezetben röviden ismertetjük az MDI fogalmát és felhasználási lehetőségeit, majd a VC++ részben visszatérünk ennek részletezésére, hiszen a VC++ számos dolgot takar el ebből, és az MDI kezeléséből csak egy kis rész hárul a programozóra.
Az MDI bevezetése megkönnyítette olyan programok megírását, amelyek több ablakkal (dokumentummal) dolgoznak. Az interfész 3 fajta ablakot vezetett be: az MDI Frame, amely az applikáció főablakaként funkcionál, az MDI Child a dokumentumok különféle megjelenítésére és az MDI Client, amely menedzseli az MDI frame gyermekablakait(MDI Child). Az MDI legnagyobb előnye, hogy a gyermekek menedzselése automatikusan történik. Nincs szükség a gyermekablakok viselkedésének az implementálására. Az MDI programozásnak a legnehezebb aspektusa az üzenet küldés az MDI résztvevők között. Az üzenetek mehetnek a gyermektől a kliensnek, a klienstől a szülőnek, a szülőtől a kliensnek, vagy közvetlenül a gyermektől a szülőnek.
MDI-ként működik a Program Manager. Minden MDI applikációra érvényesek a megszokott billetyűkombinációk (Ctrl-F4) ablak bezárás, (Ctrl-F6) váltogatás az aktív dokumentumok között. Továbbá érvényes az ablakok elrendezése (Cascade, Tile, Minimized).
A frame létrehozását a szokásos CreateWindow függvénnyel kell megvalósítani. Ilyenkor a WM_CREATE üzenet kezelésében kell létrehozni a klienst szintén a CreateWindow függvénnyel, de az ablakát nem jelenítjük meg. A gyermek létrehozásához egy WM_MDICREATE üzenetet kell küldeni. A kliens létrehozásához szükségünk van az MDICLIENT struktúrára, amely információkat hordoz a kliensről. A gyermek létrehozásakor pedig az MDICREATESTRUCT-re. A struktúrák felépítése a mellek1.doc ban szerepelt. Az említettek jobb megértése érdekében nézzük a következő példát:
long FAR PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,LPSTR lpszCmdLine, int nCmdShow)
// Obtain handles to three possible menus & submenus
hMenuInit = LoadMenu (hInst, "MdiMenuInit") ;
hMenuGraph = LoadMenu (hInst, "MdiMenuGraph") ;
hMenuSystem = LoadMenu (hInst, "MdiMenuSystem") ;
hMenuInitWindow = GetSubMenu (hMenuInit,INIT_MENU_POS);
hMenuGraphWindow = GetSubMenu(hMenuGraph,GRAPH_MENU_POS);
hMenuSystemWindow=GetSubMenu(hMenuSystem,SYSTEM_MENU_POS);
// Load accelerator table
hAccel = LoadAccelerators (hInst, "MdiAccel") ;
// Create the frame window
hwndFrame = CreateWindow (szFrameClass,
"Neural Networks Simulation Program",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_MAXIMIZE | WS_VISIBLE |WS_VSCROLL | WS_HSCROLL |WS_MAXIMIZEBOX |WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, hMenuInit, hInstance, NULL) ;
hwndClient = GetWindow (hwndFrame, GW_CHILD) ;
ShowWindow (hwndFrame, SW_SHOWMAXIMIZED) ;
UpdateWindow (hwndFrame) ;
SetFocus(hwndClient);
// Enter the modified message loop
while (GetMessage (&msg, NULL, 0, 0))
}
return msg.wParam ;
}
long FAR PASCAL _export FrameWndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
return 0 ;
case IDM_NEWSYSTEM:
// Create a System child window
mdicreate.szClass = szSystemClass ;
mdicreate.szTitle = "System" ;
mdicreate.hOwner = hInst ;
mdicreate.x = 0 ;
mdicreate.y = 60 ;
mdicreate.cx = 400 ;
mdicreate.cy = 300 ;
mdicreate.style = 0 ;
mdicreate.lParam = NULL ;
hwndChild = SendMessage (hwndClient, WM_MDICREATE, 0,
(LONG) (LPMDICREATESTRUCT) &mdicreate);
ShowWindow(hwndChild,SW_SHOWMAXIMIZED);
return 0 ;
Tehát a kliens létrehozásához fel kell tölteni a megfelelő struktúrát és ezt felhasználni a CreateWindow függvényben. Hasonló a helyzet az MDI gyermek esetén is csak más struktúrával.
|