Ablakok.  Vírusok.  Jegyzetfüzetek.  Internet.  hivatal.  Segédprogramok.  Drivers

Ez a cikk azoknak a C++ programozásban kezdőknek szól, mint én, akik véletlenül vagy vágyból úgy döntöttek, hogy megtanulják a WinAPI-t.
Csak figyelmeztetni akarlak:
Nem állítom, hogy C++ vagy WinAPI guru lennék.
Még csak tanulok, és szeretnék itt néhány példát és tippet adni, amelyek megkönnyítik a WinAPI funkcióinak és mechanizmusainak megismerését.

Ebben a cikkben feltételezem, hogy már eléggé ismeri a C ++-t ahhoz, hogy osztályokat tudjon létrehozni és különféle operátorokat túlterhelni, és bizonyos mechanizmusait már „elrejtette” egy osztályban.

Konzol létrehozása és használata

Egy Win32-es alkalmazás hibakereséséhez, vagy csak azért, hogy megnézzem, hogyan megy minden belül, mindig a konzolt használom.
Mivel grafikus felhasználói felületet hoz létre, nem konzolalkalmazást, a konzol nincs csatlakoztatva. Ezt a kódot találták annak érdekében, hogy az internet belsejében hívják

Ha(AllocConsole())
{



std::ios::sync_with_stdio();
}
A kényelem kedvéért azt tanácsolom, hogy csomagolja be egy funkcióba. Például:
void CreateConsole()
{
if (AllocConsole())
{
int hCrt = _open_osfhandle((hosszú)GetStdHandle(STD_OUTPUT_HANDLE), 4);
*stdout = *(::_fdopen(hCrt, "w"));
::setvbuf(stdout, NULL, _IONBF, 0);
*stderr = *(::_fdopen(hCrt, "w"));
::setvbuf(stderr, NULL, _IONBF, 0);
std::ios::sync_with_stdio();
}

A hívott konzol csak kimeneti módban működik, és ugyanúgy működik, mint a konzolalkalmazásokban. Kimeneti információ a szokásos módon - cout/wcout.
Ahhoz, hogy ez a kód működjön, a következő fájloknak kell szerepelniük a projektben:
#beleértve
#beleértve #befoglalni
és foglalja bele az std névteret a globális névtérbe:
névtér használata std;
Természetesen, ha nem akarja ezt megtenni, csak adja hozzá az std:: elemet az összes benne lévő entitáshoz.

Objektumok öröklése a kimenethez és az aritmusokhoz. tevékenységek

Maguk az "ablakok" létrehozása és tanulmányozása során mindig szükségem volt valamilyen értékre a konzolra.
Például:
Az ablak ügyfélterületének méretét a GetClientRect függvény segítségével kapja meg, ahol a RECT struktúra objektumának címe paraméterként kerül átadásra az objektum adatokkal való feltöltéséhez. Ha tudnia kell a fogadott ügyfélterület méretét, egyszerűen kinyomtathatja a már csatlakoztatott konzolra

Cout<

De ezt minden alkalommal megtenni (főleg, ha gyakran kell ilyesmit csinálnia) nagyon kényelmetlen.
Itt jön a segítség az örökség.
Hozzon létre egy osztályt, amely nyilvánosan örökli a RECT struktúrát, és túlterheli a kimeneti operátort<< так, как вам угодно.
Például:

Osztály newrect: public RECT
{
nyilvános:
barát adatfolyam és operátor<<(ostream &strm,newrect &rect)
{
strm<<"Prtint RECT object:\n";
strm<return strm;
}
};

Most csak adja ki az objektumot a cout/wcout paranccsal:

Cout<

És minden megjelenik Önnek kényelmes formában, ahogyan szüksége van rá.
Ugyanezt megteheti bármely szükséges operátorral.
Például, ha struktúrákat kell összehasonlítani vagy hozzárendelni (mondjuk ugyanazt a RECT-et vagy PONT-t) - overload operator==() és operator=() rendre.
Ha kevesebbet szeretne megvalósítani, mint operátor< что бы быстро сравнивать размеры окна и т.д. перегрузите operator<().
Feltételezem, hogy ezt szinte bármilyen szerkezettel megteheti, és ami a legfontosabb, minden olyan függvény, amely egy rendes RECT szerkezetobjektummal működik, jól fog működni az utódjával is.
És azt is javaslom, hogy ezt a szépséget egy külön beépülő fájlba helyezze, és szükség esetén használja.

Saját osztály

A többit nem tudom, de mivel teljesen zöld vagyok, úgy döntöttem, hogy minden tanulmányozott funkcióhoz vagy a könyv minden fejezetéhez/alfejezetéhez készítek egy új projektet, hogy minden a polcokra kerüljön és én bármikor visszatérhetek és felfrissíthetem emlékezetemben a szükséges pontokat.
Mivel a WinAPI-ban még a legegyszerűbb ablak létrehozásához is ki kell tölteni az osztálystruktúrát, regisztrálni és egy triviális ablak eljárást írni, a harmadik-negyedik projekt után eszembe jutott, hogy továbbra is C ++-ban írok.
Végül mindent elrejtettem egy egyszerű osztályban. Az ablak fogantyúja, neve, osztályneve, ablakeljárás címe, ablakosztálya (WNDCLASS) mind el van rejtve az osztály privát részében.
Megszerzésükhöz elegendő egyszerű Get metódusokat leírni, például:
HWND GetHWND()
LPCTSTR GetClsName() stb.
Az ablakosztály kitöltése, regisztrálása, magának az ablaknak a létrehozása és megjelenítése a konstruktorban történik.
A kényelem kedvéért túlterhelheti a konstruktort, és elrejtheti az ablakosztály kitöltését és regisztrációját egy külön privát osztályfüggvényben, és meghívhatja az egyes konstruktorokban. A túlterhelés kényelme, hogy néha nagyon egyszerű ablakot kell létrehoznom, és két paraméterrel hívom meg a konstruktort - az ablak nevével és az alkalmazás tippjével.
Máskor egy adott méretű ablakot kell létrehoznom, nem az alapértelmezett ablak eljárással, és valamilyen más meghatározott stílussal - hívom a konstruktort a hozzá tartozó paraméterekkel.
Ezt az osztályt egy külön include fájlban határoztam meg, amely az IDE include mappájában található.
Sablon egy ilyen osztályhoz:
osztályú BaseWindow
{
WNDCLASSEX_wcex;
TCHAR_osztálynév;
TCHAR_ablaknév;
HWND_hwnd;
bool_WindowCreation();
nyilvános:
BaseWindow(LPCTSTR ablaknév,HINSTANCE hPéldány,DWORD stílus,UINT x,UINT y,UINT magasság,UINT szélesség);
BaseWindow(LPCTSTR ablaknév,HINSTANCE hPéldány);
const HWND GetHWND() const(vissza HWND;)
LPCTSTR GetWndName()const(return _windowName;)
};

Ha alaposan átgondolod és megírod az ilyen órát, akkor könnyebbé válik az életed, és több időt fogsz fordítani a tanulásra és a képességeid csiszolására, mintha minden alkalommal ugyanazt írnád. Sőt, nagyon hasznosnak tartom - saját maga készíteni egy ilyen osztályt, és szükség szerint kiegészíteni.

P.S.

A fentiek mindegyike igaz:
Platform - Windows 7 32 bit
IDE – Visual Studio 2010
Lehet, hogy ezen tippek némelyike ​​nevetést és iróniát vált ki, de mégis, valamikor mindannyian újoncok / gyakornokok / juniorok voltunk.
Kérlek benneteket, hogy a posztot megértéssel kezeljék. Az építő jellegű kritikát természetesen szívesen fogadjuk.

Végül! Végül! Ma elkezdjük egy teljes értékű Windows ablak létrehozását. Viszlát nyomorult konzol!!!

Ezen a ponton már jól ismernie kell a C ++ szintaxist, tudnia kell ágakkal és ciklusokkal dolgozni, és jól kell ismernie a függvények működését. Ha elsajátított egy tengeri csatát, akkor azt tekintheti, hogy mindezt megtanulta.

magyar jelölés

Minden kód, amivel WinAPI-ban találkozunk, magyar formában van írva. Ez egy ilyen kódolási konvenció.

Ebben az esetben a változó nevét a típus kezdőbetűje előzi meg. A változó- és függvénynevekben minden szó nagybetűvel kezdődik.

Íme néhány előtag:

b - bool típusú változó.
l egy long integer típusú változó.
w - szóból (szó) - 16 bit. Előjel nélküli rövid típusú változó.
dw - dupla szóból (kettős szó) - 32 bit. Előjel nélküli hosszú típusú változó.
sz - nullával végződő karakterlánc. Csak egy szokásos karakterlánc, amelyet mindig használtunk.
p vagy lp - mutató (mutatóból). lp (hosszú mutatóból) - ezek a mutatók a múltból elmentek. Most az lp és a p ugyanazt jelenti.
h - leíró (a fogantyúból).

Például a mutatót így hívják:

void*pData;

Ezt a jelölést a Microsoft használja. Sokan kritizálják a változók elnevezésének ezt a módját. De az ehhez hasonló dolgok (kódolási konvenciók) létfontosságúak a nagy cégeknél.

Hadd emlékeztesselek arra, hogy az állandó azonosítók általában csak nagybetűkből állnak: WM_DESTROY. A WM_DESTOY értéke 2, az állandó a define-en keresztül van definiálva.

Ezenkívül a winAPI sok felülírt típust használ. Itt, ezen az oldalon - http://msdn.microsoft.com/en-us/library/aa383751(VS.85).aspx ) minden Windows-típus leírását találja (angol nyelven).

És még egy dolog, amit nem értettünk. A mutatók gyakran NULL értéket kapnak. Tekintsd úgy, hogy csak 0, és a NULL-ra (nullára) beállított mutatók nem mutatnak semmilyen memóriahelyre.

Windows API (WinAPI)

Minden Windows program speciális WinAPI programozási felületet használ. Ez C függvények és struktúrák halmaza, amelyek kompatibilissé teszik a programot a Windows rendszerrel.

A Windows API óriási képességekkel rendelkezik az operációs rendszerrel való együttműködéshez. Akár azt is mondhatnánk, hogy korlátlan.

A WinAPI összes funkciójának még egy százalékát sem fedjük le. Kezdetben több anyagot szerettem volna felvenni, de az túl sok időt vesz igénybe, és a WinAPI mocsarában elakadva pár éven belül eljutunk a DirectX-hez.A WinAPI leírása két tanulságos lesz (ezt is beleértve) Ezekben csak a Windows alatti alkalmazáskeretet fogjuk figyelembe venni.

A Windows programnak, akárcsak a DOS-nak, van egy fő funkciója. Itt ezt a függvényt WinMainnek hívják.

WinMain függvény

A Windows program a következő részekből áll (mindez a WinMainben történik):

Hozzon létre és regisztráljon egy ablakosztályt. Ne keverje össze a C++ osztályokkal. A WinAPI C-ben van írva, a szó nálunk megszokott értelmében nincsenek osztályok.
Programablak létrehozása.
A fő hurok, amelyben az üzenetek feldolgozásra kerülnek.
Programüzenetek kezelése ablakos eljárásban. Az ablakeljárás normál funkció.
Ez a négy pont képezi a Windows program alapját. Ezen és a következő órán mindezt részletesen elemezzük. Ha megzavarodna a program leírásában, térjen vissza ezekre a pontokra.

Most pedig nézzük mindezt részletesen:

WinAPI: WNDCLASS szerkezet

Először is létre kell hozni és feltölteni a WNDCLASS szerkezeti változót, majd ez alapján regisztrálni az ablakosztályt.

Így néz ki a szerkezet:

c++ kód typedef struct ( UINT stílus; // ablakstílus WNDPROC lpfnWndProc; // mutató ablak eljárásra int cbClsExtra; // extra bájtok az osztály után. Mindig 0 int cbWndExtra; // extra bájtok az ablakpéldány után. Mindig 0 HINSTANCE hInstance ; / / alkalmazáspéldány paraméterként átadva a WinMain HICON hIcon számára; // alkalmazás ikon HCURSOR hCursor; // alkalmazás kurzor HBRUSH hbrBackground; // háttérszín LPCTSTR lpszMenuName; // menü neve LPCTSTR lpszClassName; // osztálynév ) WNDCLASS, * PWNDCLASS ;

A WinAPI WNDCLASS struktúrája határozza meg a létrehozott ablak alapvető tulajdonságait: ikonok, az egérkurzor típusa, van-e menüje az ablaknak, melyik alkalmazáshoz fog tartozni az ablak...

A struktúra kitöltése után az alapján regisztrálhat ablakosztályt. Ez nem olyan osztályokról szól, mint a C++. Inkább úgy tekinthetjük, hogy az ablakosztály egy ilyen sablon, ezt regisztráltad a rendszerben, és most több ablak is létrehozható ez alapján. Ezen ablakok mindegyike rendelkezik a WNDCLASS szerkezeti változóban megadott tulajdonságokkal.

WinAPI: CreateWindow függvény

Az ablakosztály regisztrálása után ennek alapján létrejön az alkalmazás főablakja (most továbbléptünk a második pontra). Ez a CreateWindow függvény segítségével történik. A következő prototípussal rendelkezik:

c++ kód HWND CreateWindow(LPCTSTR lpClassName, // osztály neve LPCTSTR lpWindowName, // ablak neve (megjelenik a címsorban) DWORD dwStyle, // ablakstílus int x, // vízszintes koordináta a képernyő bal szélétől int y, // függőleges koordináta int-től nWidth, // ablak szélessége int nMagasság, // ablak magassága HWND hWndParent, // szülőablak HMENU hMenu, // menü fogantyúja HINSTANCE hInstance, // alkalmazáspéldány LPVOID lpParam // paraméter; mindig NULL-ra állítva);

Ha az ablakosztályban (WNDCLASS szerkezet) az ablak alapvető tulajdonságai vannak beállítva, akkor itt - minden ablaknál pontosabban: ablakméret, koordináták ...

Ez a függvény egy ablak fogantyút ad vissza. A leíró segítségével az ablakra lehet hivatkozni, olyan, mint egy azonosító.

Vegye figyelembe, hogy sok új típus található itt. Valójában mind régiek, csak újrafogalmazva. Például: A HWND a HANDLE típus felülírása, ami viszont a PVOID felülírása, ami viszont a void* felülírása. Milyen mély az igazság! De még mindig a HWND típus az érvénytelenség mutatója.

Az ablak több részből áll. Szinte minden programban látni fogja: az ablak címét, a rendszermenüt (ha rákattint az alkalmazás ikonjára az ablak bal felső részén), három rendszergombot az ablakkal való munkavégzéshez: kicsinyítés, maximalizálás és bezárás. Ezenkívül szinte mindig van egy menü az alkalmazásban. Ez csak az utolsó, amit biztosan nem fogunk. És persze az ablak nagy részét az ún. az ügyfélterület, ahol a felhasználó általában dolgozik.

Az ablakos módról van szó. Sokáig a DiectX-et ablakban fogjuk gyakorolni - nem használjuk a teljes képernyős módot.

Üzenetkezelés

Az összes korábbi programunk fő különbsége a Windows alatti programoktól az üzenetfeldolgozás.

Például, amikor a felhasználó megnyom egy billentyűt a billentyűzeten, egy üzenet generálódik, hogy egy billentyűt lenyomtak. Ezt az üzenetet a rendszer elküldi annak az alkalmazásnak, amely aktív volt, amikor a felhasználó megnyomta a gombot.

Itt van egy esemény (esemény) - megnyomtak egy gombot.

Esemény lehet: az egérkurzor mozgatása, az alkalmazás fókuszának megváltoztatása, egy billentyűzet billentyűjének lenyomása, ablak bezárása. Rengeteg esemény van. Nagyon! Egy másodperc alatt több tucat esemény történhet az operációs rendszerben.

Tehát, ha egy esemény bekövetkezik, az operációs rendszer üzenetet hoz létre: ilyen és olyan billentyűt nyomtak meg, megváltoztak az egérkurzor koordinátái, új ablak nyílt meg.

Üzeneteket az operációs rendszer és a különféle alkalmazások is létrehozhatnak.

Az üzenet egy szerkezet, és így néz ki:

c++ kód typedef struct tagMSG ( HWND hwnd; // ablak, amely ezt az üzenetet fogja kapni UINT üzenet; // üzenet kódja WPARAM wParam; // paraméter LPARAM lParam; // paraméter DWORD idő; // az üzenet megjelenésének időpontja POINT pt; // koordináták egér kurzor ) MSG;

Figyelje meg, hogy a typedefs hogyan definiálja újra a struktúrákat.

A struktúra létrehozásához a következő kódot használhatja:

c++ kód msg.messgae == 2; // ez a két sor egyenértékű, mivel msg.message == WM_DESTROY; // konstans WM_DESTROY egyenlő kettővel

Itt az üzenet kódját tartalmazó mező (az üzenet nevét összehasonlítjuk a WM_DESTROY konstanssal. WM - a Windows Üzenetből (Windows üzenet). WM_DESTROY - ez az üzenet, amely az ablak bezárásakor keletkezik (megsemmisítés - megsemmisítés).

Az üzenetkódok konstansok használatával vannak meghatározva, és WM_ előtaggal rendelkeznek: WM_CLOSE, WM_CREATE stb.

Az MSG struktúra tartalmazza a HWND típust - Window Handle-ből (ablak fogantyúja vagy ablak fogantyúja). Ez egy olyan darab, amely "leír" egy ablakot. Ez olyasmi, mint egy azonosító (ablaknév).

Emlékezzen erre a szóra - fogantyú (leíró, leíró). A Windows rendszerben ezt a fogalmat nagyon gyakran használják. Szinte minden H betűvel kezdődő Windows-típus leíró: ikonleíró, betűkészlet-leíró, alkalmazáspéldány-leíró. Emlékeim szerint harmincan vannak.

A Windows alkalmazások közötti összes interakció ugyanezekkel az ablakleírókkal (HWND) történik.

Van még egy fontos leíró - az alkalmazásleíró (HINSTANCE - a WinMain első paramétere) - ez egy egyedi alkalmazásazonosító, amelynek köszönhetően az operációs rendszer nem tud összetéveszteni két különböző programot. Olyan, mint egy vonalkód. Később áttekintjük.

Minden alkalommal, amikor a felhasználó valamilyen műveletet végrehajt, egy üzenet jön létre és kitöltődik: beállítja annak az ablaknak a fogantyúját, amelybe ezt az üzenetet kell kapnia, beállítja az üzenet azonosítóját, kitölti a paramétereket, kitölti az időt (aktuális) és az egérkurzor koordinátái láthatók (lásd a szerkezetet).

Az üzenet ezután az operációs rendszer üzenetsorába kerül. Amikor a sor eléri az üzenetünket, a kívánt ablakba kerül (a leíróknak köszönhetően a windows tudja, hogy melyik ablakot küldje el). Amikor egy üzenet érkezik egy alkalmazáshoz, az az alkalmazás üzenetsorába kerül. Amint a sor eléri, feldolgozásra kerül.

Nézd, a pillanat között, amikor a felhasználó végrehajtott valamilyen műveletet (egy esemény bekövetkezett és egy üzenetet generált), és a pillanat között, amikor a program reagált erre a műveletre (az üzenetet a program feldolgozta), sok esemény történik. Hiszen mind a Windows üzenetsorában, mind az alkalmazás üzenetsorában sok üzenet lehet. Az első esetben több százról, a második esetben legalább néhányról beszélhetünk.

Ablak eljárás (Ablak eljárás - WndProc)

Attól a pillanattól folytatjuk, hogy az üzenet bekerült az alkalmazás üzenetsorába. Amint a várólista elérte, feldolgozásra kerül. Az üzenetek feldolgozásához minden programban szükség van egy speciális funkcióra - egy ablak eljárásra. Általában WndProc-nak hívják (a Window Procedure-hoz). Az ablak eljárás hívása a fő programhurokban található, és a ciklus minden iterációja során lefut.

Az üzenetek (strukturális MSG-változók formájában) paraméterek formájában írják be ezt a függvényt: egy ablak fogantyúja, egy üzenetazonosító és két paraméter. Vegye figyelembe, hogy az idő és a pt mezők nem kerülnek át az ablak eljárásba. Vagyis az üzenet már „elemzve” van.

Az ablak eljáráson belül van egy kapcsoló ág, amelyben az üzenetazonosítót ellenőrizzük. Íme egy példa egy egyszerű ablakeljárásra (teljesen működőképes):

c++ kód// a HRESULT és a __stdcall figyelmen kívül hagyása egyelőre. Később megnézzük őket HRESULT __stdcall WndProc(HWND hWnd, UINT üzenet, WPARAM wParam, LPARAM lParam) ( switch (message) ( eset WM_PAINT: // WM_PAINT üzenetfeldolgozási kód visszatér 0; eset WM_DESTROY: // WM_DESTROY üzenetfeldolgozási kód return 0; ) // kezelő az összes többi üzenethez )

És az utolsó a fő hurok. Ő nagyon egyszerű. A ciklus minden iterációja ellenőrzi az alkalmazás üzenetsorát. Ha van üzenet az üzenetsorban, a rendszer leveszi a sorból. Ezután a ciklus törzsében egy ablak eljárás hívódik meg a sorból vett üzenet feldolgozására.

Általában ennyi mára. Az már világos, hogy egy WinAPI alatti program sokkal bonyolultabb, mint egy DOS alatti program. Ahogy fentebb is írtam, a következő leckében egy működő program kódját elemezzük.

Gyakorlatként hozzon létre egy új projektet. Az Új projekt ablakban válassza ki a sablont (sablont) - Win32Project (eddig a Win32 Console alkalmazást választottuk). A következő ablakok egyikében ne jelölje be az Üres projekt jelölőnégyzetet (üres projekt), és az IDE üres programot generál.

Ha alaposan megnézi a kódot a project_name.cpp fájlban, mindent megtalál, amit megbeszéltünk: az MSG szerkezeti változót, a WNDCLASS struktúra kitöltését, az ablak létrehozását a CreateWindow függvénnyel, a fő programhurkot. Ezenkívül a WndProc függvény definiálva van a fájlban. Számos üzenetet dolgoz fel kapcsoló ágakban: WM_COMMAND, WM_PAINT, WM_DESTROY. Mindezt megtalálja a fájlban.

Az általunk figyelembe vetteken kívül a program sok további kódot is tartalmaz. A következő számban megnézzük a program kódját, amiben minden felesleges ki lesz vágva. Sokkal egyszerűbb és áttekinthetőbb lesz, mint amit az IDE generál.

Az API (Application Programming Interface) egy alkalmazásprogramozási felület, amelyet a szoftverfejlesztők gyakran emlegetnek. Ha az Ön által fejlesztett alkalmazás rendelkezik olyan funkcióval, amely lehetővé teszi más alkalmazásokból való elérését, akkor ez az alkalmazás API-ja. A függvény paraméterei az API-ból származnak, mivel ezek azok az eszközök, amelyek révén más alkalmazások kölcsönhatásba lépnek a funkcióval.

A Windows operációs rendszer számos olyan funkciót kínál, amelyek lehetővé teszik a különféle alkalmazások, köztük a Visual FoxPro alkalmazások, hogy meglehetősen alacsony szinten kommunikáljanak a Windows rendszerrel. Ezeket a funkciókat általában Windows API-nak nevezik. A Windows API Visual FoxPro alkalmazásokban való használata lehetővé teszi olyan szolgáltatások megvalósítását, amelyek a szabványos nyelvi eszközökkel elérhetetlenek.

Windows API függvények deklarálása a Visual FoxPro programban

A Windows API-funkciók dinamikusan összekapcsolt könyvtárakba kapcsolódnak (Dynamic Link Library, DLL). Az ilyen könyvtárak fájljai általában a kiterjesztéssel rendelkeznek dll. Mielőtt egy Windows API függvényt használna az alkalmazásban, meg kell tennie bejelenteni. A DECLARE..DLL parancs egy függvény deklarálására szolgál:

KIJELENT[ cFunctionType] FunctionName BAN BEN LibraryName ; [cParamType1 [@] ParamName1, cParamType2 [@] ParamName2, ...]

Parancs paraméterek:

cFunctionType
opcionális paraméter, megadja a függvény által visszaadott adatok típusát:

cFunctionType Méret,
byte
Leírás
Rövid 16 bites egész szám
Egész, hosszú 4 32 bites egész szám
Egyetlen 4 32 bites valós szám
Kettős 8 64 bites valós szám
Húr - Karakterlánc

FunctionName
a függvény neve a DLL-ben. A függvény neve megkülönbözteti a kis- és nagybetűket, vagyis a GetDC és a GETDC teljesen különböző függvénynevek.

LibraryName
a függvényt tartalmazó DLL neve. A Kernel32.dll, Gdi32.dll, User32.dll, Mpr.dll és Advapi32.dll könyvtárak esetében használhatja a WIN32API szinonimát.

Fedőnév
opcionális paraméter, lehetővé teszi a saját álnév használatát a függvény neve helyett. Az alias helyesírása, a függvénynévvel ellentétben, nem különbözteti meg a kis- és nagybetűket. Általában álnevet használnak, ha a függvény API neve megegyezik egy beépített (vagy az Ön) Visual FoxPro függvény nevével.

cParamType
megadja a függvénynek átadott érték adattípusát:

A paraméter értékkel és hivatkozással is átadható. A "@" karakter jelzi, hogy egy paramétert referenciaként adtunk át.

A Visual FoxPro szempontjából nincs különbség a Long és Integer adattípusok között. Általában az Integer típust az előjeles egész számok, a Long típust pedig az előjel nélküli egészek ábrázolására használják.

ParamName
opcionális paraméter, pusztán leíró jellegű, és általában figyelmen kívül hagyják.

A Windows API minden funkciója, csakúgy, mint maga a Windows, C programozási nyelven van megírva. Ezért, hogy megértsük, hogyan kell helyesen használni az API-függvényeket a Visual FoxPro-ban (amely egyébként szintén C-ben van írva, legalábbis annak magja), ismerkedjünk meg azzal, hogy milyen adattípusokat használnak a C-ben és a Windowsban, és , nem kevésbé fontos, foglalkozzunk az olyan adattípusokkal, mint a felsorolások, struktúrák és mutatók. Ezenkívül megtudhatja, hogy milyen függvényprototípusok vannak C-ben, és az MSDN-ben található függvényprototípus leírása alapján hogyan lehet helyesen deklarálni azt a DECLARE..DLL parancsban.

Alapvető C adattípusok

Ha ismeri a C programozási nyelvet, akkor tudja, milyen egyszerű különféle típusú adatokat létrehozni benne. Elég beírni a következő kódot:

Typedef int INT32;

és itt van egy új típusú INT32, ami teljesen megfelel az int típusnak. De C szemszögéből ezek teljesen különböző típusok, és ha egy INT32 típusú változót próbálunk hozzárendelni egy int típusú változóhoz, az hibát fog eredményezni!

Az adattípusok bősége sok fejlesztőt arra késztet, hogy az API programozás nehézkes. De nem az! A C-ben főként a következő adattípusok használatosak:

    típus char - karakter ANSI formátumban. 8 bit hosszú (egy bájt).

    típus wchar - karakter Unicode formátumban. 16 bit hosszú (két bájt).

    típus int - egész számok. C-ben három típusra oszthatók: int, rövid intÉs hosszú int. Ez utóbbit általában rövidítik rövidÉs hosszú. típus rövid 16 bites, és típusok intÉs hosszú- 32 bites egész számok.

    típus úszó valós számok tört résszel. 32 bitesek (4 bájt).

    típus kettős- dupla pontosságú valós számok. 64 bitesek (8 bájt).

    típus enum - felsorolt ​​adattípus.

    típus üres nulla hosszúságú és értéktelen mennyiségek jelölésére szolgál.

    típus mutató - mutató; nem tartalmaz a hagyományos értelemben vett információt - más C típusokhoz hasonlóan; ehelyett minden mutató annak a memóriahelynek a címét tartalmazza, ahol a tényleges adatokat tárolják. 32 bit (4 bájt) hosszú.

Furcsa módon a C-ben nincs karakterlánc típus. Valójában minden karakterlánc karaktertömbként jelenik meg C-ben.

Egyes típusok előjel nélkülinek nyilváníthatók. Módosító aláírás nélküli (aláíratlan) a következő adattípusokhoz használatos: char, rövid, intÉs hosszú.

Például a következő változódeklaráció C-ben:

Aláírt int változó_neve;

azt jelenti, hogy ez a változó egy előjel nélküli 32 bites egész szám.

Módosító const azt jelzi, hogy a megadott típusú változó konstans, azaz értéke nem változtatható.

Felsorolt ​​típus enum elnevezett konstansok halmazát, úgynevezett felsorolt ​​konstansokat társítja egy változóhoz. A felsorolt ​​típusdeklaráció így néz ki:

Enum tag_field { const1, const2, ... } változó;

Ha tag_field ki van hagyva, akkor a záró göndör kapcsos zárójel után meg kell adni változó. Ha tag_field jelezve, majd nem jelezve változó.

Történelmileg az enum típus egyenértékű az int típussal – vagyis egy felsorolt ​​típusú változó 4 bájtot foglal el a memóriában. Minden felsorolt ​​állandónak van egy értéke, amelyet a listában szereplő sorszáma határoz meg; a számozás nulláról indul. Tekintsük a CombineMode felsorolását:

Enum CombineMode( CombineModeReplace, CombineModeIntersect, CombineModeUnion, CombineModeXor, CombineModeExclude, CombineModeComplement );

Ebben a felsorolásban a CombineModeReplace konstans értéke 0, a CombineModeIntersect állandó értéke 1, és így tovább; a CombineModeComplement állandó értéke 5.

A felsorolt ​​konstansok értékei explicit módon megadhatók, mint a következő példában:

Enum DashCap( DashCapFlat = 0, DashCapRound = 2, DashCapTriangle = 3 );

A felsorolt ​​adattípusok lefedik a Windows API programozásban használt összes adattípus 99%-át. Túl könnyűnek hangzik, nem? Miért tartalmazza az API függvények leírása mindezeket a típusokat – HWND, HINSTANCE, POINT és hasonlók?

Ennek az az oka, hogy C-nek van egy ún szigorú gépelés. Bevezetés után egy azonos típusú változó csak a típusának megfelelő értékeket vehet fel. Nem lehet először egy karakterláncot egy változóban tárolni, majd számot rendelni hozzá. A Visual FoxPro rendszerben ezt általában elnevezési konvenciókon keresztül próbáljuk szimulálni. Például a cName karakter típusú változó, míg az nCount egy numerikus típus. Szigorú gépelés lehetővé teszi új adattípus létrehozását úgy, hogy egy meglévő adattípusnak új nevet ad. Úgy tűnik, hogy minden új típus különbözik a többi típustól, annak ellenére, hogy belsőleg ugyanazt tárolják.

A Windows megnehezíti ennek a koncepciónak a használatát. Például a LONG típus valójában egy long int, míg az UINT típus valójában egy előjel nélküli int. Mindkét típus 32 bites egész szám. A származtatott adattípusokat különféle include-fájlokban határozzák meg (.h kiterjesztésű fájlok). Ha megvásárolta a Visual Studio .NET-et, akkor ezek a fájlok a mappában találhatók ..\VC7\PlatformSDK\Include\.

Windows adattípusok

Az API programozás egyik legnehezebb feladata annak meghatározása, hogy a C alaptípusok közül melyik reprezentálja valójában az API függvényben használt adattípust. Használja a következő szabályt: ha nem talál egy szót float, double, char vagy str bárhol egy függvény vagy paraméter nevében, akkor ez általában egy 32 bites egész szám. Időbe telhet a készségek megértése és fejlesztése, de akkor könnyen konvertálhatja az adattípusokat. Az alábbi táblázat felsorolja a fő Windows-adattípusokat és a hozzájuk tartozó típusokat, amelyeket egy függvény deklarálásakor használnak a Visual FoxPro programban:

Adattípus
ablakok
Írja be a nyilatkozatot
funkciókat
Leírás
BOOL Hosszú 32 bites egész szám. A 0 hamis, minden más igaz.
BOOL Hosszú ugyanaz, mint a BOOL.
BYTE Húr 8 bites egész szám
CHAR Húr 8 bites egész szám
CLSID Húr
SZÍN Hosszú 32 bites egész szám
DWORD Hosszú 32 bites egész szám
KETTŐS Kettős 64 bites valós szám
ÚSZÓ Egyetlen 32 bites valós szám
GUID Húr 128 bites szám (16 bájt)
FOGANTYÚ Hosszú
HBITMAP Hosszú 32 bites előjel nélküli egész szám
HDC Hosszú 32 bites előjel nélküli egész szám
HICON Hosszú 32 bites előjel nélküli egész szám
HGLOBAL Hosszú 32 bites előjel nélküli egész szám
HKL Hosszú 32 bites előjel nélküli egész szám
HLOKÁLIS Hosszú 32 bites előjel nélküli egész szám
ELŐÍRÁS Hosszú 32 bites előjel nélküli egész szám
EREDMÉNY Hosszú 32 bites előjel nélküli egész szám
HWND Hosszú 32 bites előjel nélküli egész szám
HOSSZÚ Hosszú 32 bites egész szám
LPARAM Hosszú 32 bites előjel nélküli egész szám
RÖVID Egész szám 16 bites egész szám
SIZE_T Hosszú 32 bites előjel nélküli egész szám
TCHAR Húr Megfelel a CHAR-nak az ANSI formátumú karakterláncok és a WCHAR-nak az Unicode formátumú karakterláncok esetében
UCHAR Húr Karakter ANSI kódolásban
UINT Hosszú 32 bites előjel nélküli egész szám
ULONG Hosszú 32 bites előjel nélküli egész szám
USHORT Egész szám
UUID Húr 128 bites szám (16 bájt)
ÜRES Nem Nem számít
WCHAR Húr UNICODE karakter
WNDPROC Hosszú 32 bites előjel nélküli egész szám
SZÓ Egész szám 16 bites előjel nélküli egész szám
WPARAM Hosszú 32 bites előjel nélküli egész szám

Mutatók

Egy másik, a C-ben széles körben használt fogalom a mutatók. A mutató egy olyan változó, amely annak a memóriaterületnek a címét tartalmazza, ahol az adatokat tárolják. A mutató típusát mindig az határozza meg, hogy milyen adattípusra mutat; mérete mindig négy bájt. Például egy SHORT típusú változóra mutató mutató 32 bites egész szám, csakúgy, mint bármely más adattípusra mutató mutató. A Windows API programozásban használt mutató leírása az "LP" karakterekkel kezdődik, ami azt jelenti, hogy Long Pointer vagy "long pointer" 32 bites memóriamodellel működik. Ezután a "C" (const) karakter következhet, jelezve, hogy az adatokat nem szabad megváltoztatni. Az alábbiakban annak a változónak az adattípusát ismertetjük, amelynek a címe a mutatóban van tárolva. Például az LPDWORD egy duplaszó-változóra mutató mutató.

A numerikus adatokra mutató mutatók hivatkozással kerülnek átadásra a Windows API függvény deklarálásakor. Példaként tekintsük a GetFileSize függvényt. Íme a prototípusa (a funkcióprototípusokról lentebb):

DWORD GetFileSize(HANDLE hFile, // fájlkezelő LPDWORD lpFileSizeHigh // mutató);

A függvénynek átadott második paraméter egy duplaszó-változóra mutató mutató, amelybe a függvény a fájlméret értékét bájtokban helyezi el.

Ennek a függvénynek a deklarációja a Visual FoxPro-ban:

A GetFileSize NYILATKOZÁSA WIN32API-BAN Hosszú hFile, Hosszú @ FileSizeHight

Mint látható, a FileSizeHight paraméter átadásra kerül a függvénynek link, mert a hivatkozással történő átadás csak egy mutató átadása.

A húrokkal bonyolultabb a helyzet. Mint már említettük, a C karakterláncai tömbök, így az API függvények programozásában a típus str, amely CHAR típusú karakterek tömbjét határozza meg (illetve a típust wstr WCHAR típusú karakterek tömbjét határozza meg). Az alábbi táblázat a karakterláncokra mutató mutatók típusait mutatja be:

mutató típusa
soronként
Leírás
LPSTR Mutasson a módosítandó null-végződésű ANSI formátumú karakterláncra. Hivatkozással átadva
LPCSTR Mutasson egy módosíthatatlan null-végződésű ANSI formátumú karakterláncra. Érték szerint átment
LPTSTR Az ANSI formátumú karakterláncok esetében az LPSTR, az UNICODE formátumú karakterláncok esetében pedig az LPWSTR típusnak felel meg. Hivatkozással átadva.
LPCTSTR Az ANSI formátumú karakterláncok esetében az LPSTR, az UNICODE formátumú karakterláncok esetében pedig az LPWSTR típusnak felel meg. Érték szerint átment.
LPWSTR Mutasson a módosítandó null-végződésű UNICODE karakterláncra. Hivatkozással átadva
LPCWSTR Mutasson egy nem módosítható null-végződésű UNICODE karakterláncra. Érték szerint átment

A karakteradatokra mutató mutatók hivatkozással vagy értékkel is átadhatók - a String típus a függvény deklarációjában a Visual FoxPro-ban mindig átad egy mutatót karakteradatokat tartalmazó változóhoz. Csak akkor használjon karakteradatokat hivatkozással, ha egy API-függvénynek módosítania kell egy paraméter értékét.

szerkezetek

A struktúrát különböző típusú változók halmazának tekinthetjük, amelyek egyetlen egészet alkotnak. C-ben a kulcsszó használatával struktúra jön létre struct majd egy opcionális címke mezőben(címke) és lista elemeket szerkezetek:

Struktúra tag_field { elem_típus elem1; elem_típus elem2; ..... elem_típus elemN; };

Lehetséges egy ilyen szerkezet deklarálása is:

szerkezet( elem_típus elem1; elem_típus elem2; ..... elem_típus elemN; } változó;

Ez a hirdetés hiányzik címke mezőbenés létrejön egy úgynevezett anonim szerkezeti típus; ez a szintaxis lehetővé teszi egy vagy több változó társítását ehhez a struktúratípushoz, amint az a következő példában látható:

Struct(WORD évév; SZÓ wHónap; SZÓ WDayOfWeek; SZÓ wDay; SZÓ whoHour; SZÓ wMinute; SZÓ wMásodszor; SZÓ wMezredmásodperc; ) SYSTEMTIME, *PSYSTEMTIME;

A struktúrák nagyon hasonlítanak a Visual FoxPro táblabejegyzéseihez. Tehát, ha a táblázat bejegyzés személyes mezőket tartalmaz fio,cím,tlf szám és email cím, akkor a következő szintaxist használjuk a tlfnumber mező eléréséhez:

Személyes.tlfszám

A struktúra mezőjéhez való hozzáférés ugyanúgy néz ki:

SYSTEMTIME.wPerc

A Visual FoxPro karakterláncokat tartalmazó változókat használ a struktúrák kialakításához. Például a fent tárgyalt SYSTEMTIME struktúrához egy 16 bájtos változóra van szükség. Ennek a változónak az első két bájtja tartalmazza a mező értékét évév, a következő két bájtban - a mező értéke wHónap, a következő két bájtban - a mező értéke WDayOfWeekés így tovább, amíg a szerkezet teljesen kialakul. És amikor egy API-függvényt deklarál a Visual FoxPro-ban, annak a paraméternek a típusának, amelyben a struktúrát tartalmazó változó átadásra kerül, String típusúnak kell lennie. Kicsit később megtanulja, hogyan kell numerikus adatokat írni egy karakterlánc-változóba.

A Windows API C nyelven történő programozásakor a struktúrára mutató mutató leírása az LP (Long Pointer) karakterekkel kezdődik, amelyeket a struktúra neve követ. Így egy SYSTEMTIME struktúrára mutató mutató LPSYSTEMTIME típusú lesz, a POINT struktúrára mutató mutató LPPOINT típusú lesz, és így tovább. Amint látja, semmi bonyolult, de ennek a koncepciónak köszönhetően rendkívül sok típusú mutató létezik a struktúrákra.

Ha az átvitt struktúrában lévő adatok nem változnak, akkor egy ilyen struktúrára mutató mutatót a következőképpen deklarálunk:

CONST szerkezet_neve *

Itt a CONST módosító azt jelenti, hogy a szerkezetben lévő adatok nem változhatnak, a struktúra neve utáni szimbólum (*) pedig azt, hogy ez az egész sor egy mutató leírása a szerkezetre. A következő példa a CopyRect függvény prototípusát mutatja be, amely az egyik struktúrát a másikba másolja:

BOOL CopyRect(LPRECT lprcDst, CONST RECT * lprcSrc);

Az MSDN funkció prototípusainak leírása

Most, hogy többé-kevésbé minden világossá vált az adattípusokkal, nézzük meg közelebbről az ilyen C-koncepciót, mint a függvényprototípusokat.

Az ANSI szabvány szerint minden C-beli funkciónak prototípussal kell rendelkeznie. A függvény prototípusa meglehetősen egyszerű:

return_type függvény_név( paraméter_típus(ok) paraméter_neve(i));

Ha a prototípus a VOID típust a következőképpen adja meg return_type, ez azt jelenti, hogy a függvény nem ad vissza semmilyen értéket. Ha a VOID típus a következőképpen van megadva paraméter_típus, ez azt jelenti, hogy a függvénynek nincsenek paraméterei.

A Kernel32.dll, Gdi32.dll, User32.dll, Mpr.dll és Advapi32.dll könyvtárakban található Windows API-függvények prototípusairól az MSDN for Visual Studio.NET programban találhat információkat, ha megnyitja a következő súgótémaköröket rendelés: :

MSDN könyvtár

Windows fejlesztési Win32 API SDK dokumentációs referencia

A Referencia részben a funkciók leírását tekintheti meg a következő alszakaszok egyikének megnyitásával:

Itt van egy másik cím az MSDN-n, amely szintén tartalmaz információkat az API-funkciókról:

MSDN könyvtár

Felhasználói felület tervezése és fejlesztése SDK Documentacion Windows Shell Shell referencia Shell Functions

A következő ábra az MSDN Súgó ablakának egy részletét mutatja:

Például a CopyRect függvény leírása az MSDN-ben:

CopyRect

A CopyRect függvény átmásolja az egyik téglalap koordinátáit a másikba.

BOOL CopyRect(
LPRECT lprcDst, // cél téglalap
CONST RECT* lprcSrc// forrás téglalap
);

Paraméterek

lprcDst
Mutató a RECT struktúra, amely megkapja a forrástéglalap logikai koordinátáit.
lprcSrc
Mutasson arra a RECT struktúrára, amelynek koordinátáit logikai egységekben kell másolni.

Visszatérési értékek

Ha a függvény sikeres, a visszatérési érték nem nulla.
Ha a függvény nem működik, a visszatérési érték nulla.
Windows NT/2000/XP: Bővített hibainformációkért hívja a GetLastError alkalmazást.

Megjegyzések

Mivel az alkalmazások különböző célokra használhatnak téglalapokat, a téglalapfüggvények nem használnak kifejezett mértékegységet. Ehelyett az összes téglalap koordináta és mérete előjeles, logikai értékekben van megadva. A leképezési mód és a függvény, amelyben a téglalapot használjuk, meghatározza a mértékegységeket.

Példakód

Példaként lásd Téglalapok használata.

Követelmények

Windows NT/2000/XP: A Windows NT 3.1 és újabb verziója tartalmazza.
Windows 95/98/Me: a Windows 95 és újabb verziókban található.
Fejléc: A Winuser.h-ban deklarálva; tartalmazza a Windows.h.
Könyvtár: Használja a User32.lib.

Amint látja, az információ meglehetősen kimerítő. A függvény egy BOOL típusú értéket ad vissza, két paramétert ad át neki: LPRECT típusú és CONST RECT* - RECT típusú struktúrákra mutató mutatók. Amikor deklarálja ezt a függvényt a Visual FoxPro-ban, meg kell adnia, hogy az első paramétert referencia, a második paramétert pedig érték adja át:

DECLARE Long CopyRect IN User32.dll String @ Dst, Húr src

És hogyan állapítottam meg, hogy ez a funkció a User32.dll könyvtárban van? Nagyon egyszerű. Az ajánlási részben ( Követelmények) a Library záradék ezt mondja: Use User32.lib. Bővítés helyettesítője lib kiterjesztés dll- és ez az! Egyébként ugyanitt a Fejléc bekezdésben közlik, hogy melyik include fájlban található a függvény prototípusának leírása.

De ez még nem minden! Mivel a függvény struktúrákkal működik, leírása tartalmaz egy hivatkozást a RECT struktúrára. Kattintson erre a hivatkozásra, és a struktúra részletes leírása jelenik meg a képernyőn.

Struktúrák alakítása a Visual FoxPro-ban

A Visual FoxPro kilencedik verziója nagyban javítja a BINTOC és a CTOBIN beépített funkcióit. Ezekkel a függvényekkel immár a numerikus adatok struktúrákban való használatra alkalmas formátumba konvertálhatók. Hadd emlékeztesselek arra, hogy a BINTOC függvény egy számot karakterláncsá, a CTOBIN függvény pedig egy karakterláncot számmá alakít.

A BINTOC függvény szintaxisa:

BINTOC( nKifejezés, eFlag)

Az összes lehetséges érték közül, amelyet a paraméter felvehet eFlag, az alábbiakra vagyunk kíváncsiak:

A CTOBIN függvény szintaxisa a következő:

CTOBIN(c kifejezés, eFlag)

Lehetséges paraméterértékek eFlag:

Az alábbiakban példákat mutatunk be ezen funkciók használatára:

CTOBIN(BINTOC(1000.55,"4RS"), "4RS") && Eredmény: 1000 ? CTOBIN(BINTOC(-1000.55,"4RS"), "4RS") && Eredmény: -1000 ? CTOBIN(BINTOC(1000.55"F"), "4N") && Eredmény: 1000.549987929 ? CTOBIN(BINTOC(-1000.55"F"), "4N") && Eredmény: -1000.549987929 ? CTOBIN(BINTOC(1000.55,"B"), "8N") && Eredmény: 1000.55 ? CTOBIN(BINTOC(-1000.55,"B"), "8N") && Eredmény: -1000.55

Példaként írjunk egy RECT struktúrát egy Visual FoxPro változóba. Ezt a struktúrát a korábban tárgyalt CopyRect függvény használja egy téglalap alakú terület koordinátáinak leírására. A struktúra leírása az MSDN-ben a következő:

Typedef struct _RECT ( LONG balra; LONG fent; LONG jobbra; LONG lent; ) RECT, *PRECT;

Mint látható, a RECT struktúra négy mezőt tartalmaz, amelyek mindegyike egy LONG értéket tárol. A Visual FoxPro-ban történő létrehozásához 16 bájtos karakterláncra van szüksége.

Az alábbiakban látható a kód, amely deklarálja a CopyRect függvényt, létrehozza a Dst és Src struktúrákat, hogy azokat paraméterként adja át a függvénynek, majd átmásolja az egyik struktúrát a másikba. A példa a BINTOC függvényt használja egy szám karakterláncsá alakítására:

DECLARE Long CopyRect IN WIN32API String @ Dst, String Src * Form Src szerkezet cSrc = BINTOC(nLeft,"4RS") + BINTOC(nTop,"4RS") + ; BINTOC(nRight,"4RS") + BINTOC(nBottom,"4RS") * Hely előkészítése a Dst struktúrához cDst = REPLICATE(CHR(0),16) nResult = CopyRect(@cDst, cSrc) && Copy

A következő példa bemutatja, hogy a CTOBIN függvény használatával hogyan lehet "elemezni" egy struktúrát a mezőinek számértékeinek lekérésével:

NBal = CTOBIN(SUBSTR(cDst,1,4), "4RS") && RECT.left nTtop = CTOBIN(SUBSTR(cDst,5,4), "4RS") && RECT.top nJobbra = CTOBIN(SUBSTR(cDst, 9,4), "4RS") && RECT.right nBottom = CTOBIN(SUBSTR(cDst,13,4), "4RS") && RECT.bottom

Mutatókat tartalmazó struktúrák

Gyakran előfordul, hogy a Windows API függvénynek átadott struktúra mutatókat tartalmaz. Példaként tekintsük a StartDoc függvényt, amely egy dokumentumot hoz létre a nyomtatón történő nyomtatáshoz. Íme a prototípusa:

Int StartDoc(HDC hdc, // kezeli a DC CONST DOCINFO-t* lpdi// fájlneveket tartalmaz);

Mint látható, a függvénynek átadott második paraméter egy DOCINFO struktúrára mutató mutató. Íme a szerkezet:

Typedef struct ( int cbSize; LPCTSTR lpszDocName; LPCTSTR lpszKimenet; LPCTSTR lpszAdattípus; DWORD fwType; ) DOCINFO, *LPDOCINFO;

A szerkezet első mezője, cbSize, tartalmazza a struktúra hosszát bájtokban. A következő három mező azonban karakteradatokat tartalmazó változókra mutat. Különösen a mező lpszDocName tartalmaz mutató a nyomtatandó dokumentum nevét tartalmazó sorban (ez ugyanaz a dokumentumnév, amelyet a nyomtatandó dokumentumok sorának megtekintésekor lát).

A Visual FoxPro-ban meglehetősen nehéz mutatókat tartalmazó struktúrát kialakítani. Először is le kell foglalnia egy memóriablokkot, és meg kell adnia egy mutatót rá. Másodszor, át kell írni a Visual FoxPro változó értékét ebbe a memóriába - így lesz egy teljesen megvalósított mutató mechanizmusunk. Az utolsó teendő az, hogy a mutató értékét egy szerkezetbe helyezzük. Ebben az esetben egy lényeges követelménynek kell teljesülnie: a lefoglalt memória nem lehet áthelyezhető - különben kiderülhet, hogy a mutatónk egy ponton olyan területre mutat, amelyhez az adatainknak semmi közük!

Számos lehetőség van memóriablokk beszerzésére. Kivehet egy "darabot" mind a Windows általános memóriájából, mind a folyamathoz (azaz az alkalmazásához) lefoglalt memóriából. A második módszer nagyobb teljesítményű, de itt egyszerűbbnek tekintjük a Windows memóriával való munkavégzés módszerét.

A GlobalAlloc függvény a megadott méretű memóriablokkot fogadja a Windowstól, és egy mutatót ad vissza rá. Íme ennek a funkciónak a prototípusa:

HGLOBAL GlobalAlloc(UINT uFlags, // memóriafoglalási attribútumok SIZE_T dwBytes// méret bájtban);

Paraméter uFlags meghatározza, hogy a memória hogyan kerül lefoglalásra. Az MSDN azt mondja, hogy a következő értékek egyikét veheti fel:

A táblázatból az következik, hogy a paraméterre uFlags a GPTR értéket kell használni. De honnan tudod melyik ez az érték? Keresse meg az MSDN-t a GlobalAlloc függvény leírásáért és a szakaszban Követelmények nézze meg, hogy melyik include fájl tartalmazza a prototípusát. Ez a Winbase.h fájl. Ebben kell keresni az állandók értékeinek leírását. Itt van ennek a fájlnak egy töredéke, amely meghatározza a táblázatban felsorolt ​​állandókat:

/* Globális memóriajelzők */ #define GMEM_FIXED 0x0000 #define GMEM_MOVEABLE 0x0002 #define GMEM_NOCOMPACT 0x0010 #define GMEM_NODISCARD 0x0020 #define GMEM_ZEROINIT #define8MOVEABLE #define8x0EM0M _DI SCARDABLE 0x0100 #define GMEM_NOT_BANKED 0x1000 #define GMEM_SHARE 0x2000 #define GMEM_DDESHARE 0x2000 #define Gmem_notify 0x4000 #define gmem_lower gmem_not_banked #define gmem_valid_flags 0x7f72 #define gmem_invalid_handle 0x8000 #define ghnd (gmem_moveable | gmem_zeroinit)

Ezért GPTR = GMEM_FIXED + GMEM_ZEROINIT = 0x0000 + 0x0040 = 0x0040.

Mekkora a lefoglalt memóriablokk mérete? Természetesen megegyezik a dokumentum nevét tároló karakterlánc hosszával. A következő példa bemutatja az API-függvény deklarálásától a memóriablokk lefoglalásáig a lépéseket:

uFlags, Hosszú dwBytes cDocumentName = "Nyomtatandó dokumentum neve" && Dokumentum neve nLenDocumentName = LEN(cDocumentName) && Karakterlánc hossza hGlobal = GlobalAlloc(GPTR, nLenDocumentName)

A következő feladat a cDocumentName változó tartalmának átírása a kapott memóriablokkba. Használjuk ehhez a Visual FoxPro SYS(2600) beépített függvényét. Íme a szintaxisa:

SYS(2600, dwAddress, hossz [, cNewString])

A függvény a paramétertől függően eltérően viselkedik. cNewString vagy nem.

Ha a paraméter cNewString jelzett, akkor a függvény másol hossz bájt változóból cNewString pontban megadott címen a memóriába dwAddress.

Ha a paraméter cNewString nem meghatározott, akkor a függvény visszatér hossz bájt memóriából a megadott címen dwAddress.

Mint látható, a paraméter dwAddress- Ezt mutató.

Írjuk be a cDocumentName karakterlánc tartalmát a GlobalAlloc függvény által lefoglalt memóriába:

SYS(2600, hGlobal, nLenDocumentName, cDocumentName)

Itt található a DOCINFO struktúra kialakításának teljes kódja:

#DEFINE GPTR 0x0040 DECLARE Long GlobalAlloc IN WIN32API Long uFlags, Hosszú dwBytes cDocumentName = "A nyomtatandó dokumentum neve" nLenDocumentName = LEN(cDocumentName) hGlobal = GlobalAlloc(GPTR, nLenDocumentName) SYS(2600, dwAddress, hossz [, cNewString]) * A DOCINFO struktúra kialakításának megkezdése * A cDocInfo egy olyan változó, amelyben a cDocInfo = BINTOC(20,"4RS") && DOCINFO struktúra jön létre. cbSize cDocInfo = cDocInfo + BINTOC(hGlobal,"4RS") && DOCINFO. lpszDocName cDocInfo = cDocInfo + REPLICATE(CHR(0),12) && Egyéb szerkezeti mezők * A struktúra generálásának vége

A szerkezet változóban van kialakítva cDocInfo. Az első négy bájtba a 20-as számot írjuk - ez a struktúra mérete (mező cbSize). A változóhoz hozzáadott következő négy bájt egy mutató arra a memóriaterületre, amelyben a cDocumentName változó tartalma, a dokumentum neve átírásra kerül. Ezután további tizenkét nulla bájtot adunk a változóhoz - ezek a struktúra mezői lpszKimenet, lpszAdattípusÉs fwType, amely a dokumentáció szerint figyelmen kívül hagyható; ez azt jelenti, hogy a mezőknek null értékkel kell rendelkezniük. Így egy 20 bájt hosszúságú karakterláncot kaptunk - amire szükség is volt.

A memóriahasználat jellemzői

Amikor Windows API-funkciókat használ alkalmazásaiban, tudnia kell, hogy a Visual FoxPro nem tudja kezelni az ezen funkciók által lefoglalt memóriát. Ezért ha memóriát foglal le például a GlobalAlloc függvény segítségével, akkor ezt a memóriát használat után a GlobalFree függvény meghívásával vissza kell adnia a Windowsnak. Minden memóriát lefoglaló API-függvényhez van egy antipode funkció, amely felszabadítja a lefoglalt memóriát.

Íme a GlobalFree függvény prototípusa:

HGLOBAL GlobalFree(HGLOBAL hMem // mutató a memóriablokkra);

A függvény csak egy paramétert kap - egy memóriablokkra mutató mutatót. Íme a nyilatkozata és a Visual FoxPro használata:

DECLARE Long GlobalFree IN WIN32API Long hGlobal GlobalFree(hGlobal)

ahol a hGlobal a GlobalAlloc függvény által visszaadott memóriablokk mutatója.

Ha elfelejti visszaadni a lefoglalt memóriát, fennáll a veszélye, hogy memóriaszivárgásnak nevezett problémába ütközik. Egy ilyen szivárgás következményei nagyon szomorúak lehetnek – az alkalmazás meredek lelassulásától, amelyet a memória töredezettsége okozott, az operációs rendszer összeomlásáig.

Átadás egy tömbfüggvénynek

A tömb C kifejezéssel olyan változó, amely több azonos típusú elemet tartalmaz. A tömb egyes elemeihez való hozzáférés egy index segítségével történik. Egy tömb minden eleme azonos méretű, vegyes adattípusú tömböket nem lehet leírni. Az összes tömbelem sorban, egymás után kerül tárolásra a memóriában úgy, hogy a minimális indexérték az első elemnek, a maximális indexérték pedig az utolsónak felel meg.

A Visual FoxPro tömbnek teljesen más a felépítése, amely lehetővé teszi teljesen más típusú adatok tárolását az elemeiben. Ezért nem lehet tömböt átadni a Visual FoxPro-ból egy Windows API-függvénynek úgy, hogy egyszerűen megadja a nevét paraméterként. Ezenkívül a DECLARE..DLL parancsban nincs olyan adattípus, mint a tömbök.

Ennek ellenére van kiút ebből a helyzetből. A struktúrákhoz hasonlóan karakteres változókat használnak a tömbök átadására. A tömbből származó numerikus adatokat karakterláncokká kell konvertálni, amelyeket paraméterként ad át a Windows API függvénynek. A következő példa az ArrayToString függvény kódját mutatja be, amely egy karakterláncot generál egy tömbből. A get függvény kap egy tömböt taArray(link) és zászló tlTypeOfValue, jelzi, hogyan konvertálhatja át a tömbelemek értékeit - egész számokká ( tlTypeOfValue=.Igazából ( tlTypeOfValue=.T.) számok:

FUNCTION ArrayToString PARAMÉTEREK taArray, tlTypeOfValue EXTERNAL ARRAY taArray LOCAL lnLenArray, lnIndex, lcStruct, lcType lcType = IIF(tlTypeOfValue = .t., "F )lLENArray" tömb lcStruct = " " FOR lnIndex = 1 - lnLenArray lcStruct = lcStruct + BINTOC(taArray, lcType) ENDFOR RETURN lcStruct ENDFUNC

A függvény egydimenziós és kétdimenziós tömbökkel is működik.

Karakter adatok kódolása: ANSI és UNICODE formátumok

Az ANSI kódolásban (a Visual FoxPro-ban használatos) minden karaktert egy bájt definiál, így a maximális karakterszám 256, ami természetesen nagyon kevés. Például az oroszosítás során a szabványos ANSI karakterek egy részét cirill karakterekre cserélik. És egyes ábécékben, például a japán kanában, annyi karakter van, hogy egy bájt egyszerűen nem elég a kódolásukhoz. Az ilyen nyelvek támogatására, és ami még fontosabb, a programok más nyelvekre történő "lefordításának" megkönnyítésére fejlesztették ki a Unicode kódolást. A Unicode minden egyes karaktere két bájtból áll, ami lehetővé tette az érvényes karakterkészlet 65536-ra való bővítését.

Meglehetősen sok Windows API-függvény használja a Unicode formátumot a karakterláncokkal való munka során. Az ilyen funkciókkal való munkavégzéshez a karakteradatokat egyik formátumból a másikba kell konvertálni.

A beépített Visual FoxPro STRCONV funkció ANSI-ról UNICODE-ra és fordítva egyaránt konvertálja a karakterláncokat. Íme a szintaxisa:

STRCONV( cExpression, nConversionSetting [, nRegionalIdentifier [, nRegionalIDType]])

Paraméter cExpression a konvertálandó karakterlánc. Paraméter nConversionSetting jelzi az átalakítás természetét. Az összes lehetséges értéke közül csak kettő érdekel minket:

  • 5 - ANSI konvertálása UNICODE-ba
  • 6 - konvertálás UNICODE-ról ANSI-ra

Választható paraméterek nRegionalIdentifierÉs nRegionalIDType további regionális beállításokat határozhat meg, és biztonságosan figyelmen kívül hagyható.

Az alábbiakban példákat mutatunk be az STRCONV függvény használatára:

CUnicodeString = STRCONV(cANSISstring, 5) && Konvertálás Unicode-ra cANSISstring = STRCONV(cUnicodeString, 6) && Konvertálás ANSI-re

A szakasz olvasása közben az a benyomás alakulhat ki, hogy a Visual FoxPro Windows API funkcióival való munka meglehetősen egyszerű. Igen és nem. Egyes API-függvények például a DECLARE..DLL parancs által nem támogatott adattípusokat használnak, például 64 bites egész számokat. Számos függvény is létezik, amelyeket visszahívási függvényeknek neveznek. Egy ilyen függvény prototípusában a CALLBACK módosító a visszatérési típus deklarációja előtt van jelen. Sajnos nem használhat ilyen funkciókat, legalábbis közvetlenül nem. Az is előfordul, hogy egy struktúra tartalmaz egy függvényre mutató mutatót – az ilyen API-k a Visual FoxPro-ban sem használhatók.

A Windows API (applicationprogramminginterface) egy felhasználói módú rendszerprogramozási felület a Windows operációs rendszerek családjához. A Windows 64 bites verzióinak megjelenése előtt a Windows operációs rendszerek 32 bites verzióihoz készült API-t Win32 API-nak hívták, hogy megkülönböztesse a Windows API eredeti 16 bites verziójától (amely programozási felületként szolgált a Windows kezdeti 16 bites verziói).

A Windows API több ezer hívható függvényből áll, amelyek a következő fő kategóriákba sorolhatók:

  • Alapszolgáltatások.
  • Összetevő szolgáltatások.
  • Felhasználói felület szolgáltatások.
  • Grafikai és multimédiás szolgáltatások (Graphics and Multimedia Services).
  • Üzenetküldés és együttműködés (Üzenetküldés és együttműködés).
  • Hálózatépítés.
  • Webszolgáltatások.

A Windows API leírása megtalálható a Windows Software Development Kit (SDK) dokumentációjában. Ez a dokumentáció a www.msdn.microsoft.com címen érhető el. A fejlesztőknek szánt Microsoft Developer Network (MSDN) összes előfizetési szintjéhez is hozzátartozik.

A Microsoft .NET-keretrendszer egy Framework Class Library (FCL) nevű osztálykönyvtárból és egy felügyelt Common Language Runtime (CLR) kódfutókörnyezetből áll. A CLR rendelkezik az éppen időben történő fordítás, a típusellenőrzés, a szemétgyűjtés és a kódelérés biztonságával. Ezekkel a funkciókkal a CLR olyan fejlesztői környezetet biztosít, amely javítja a programozók termelékenységét és csökkenti a leggyakoribb programozási hibákat.

A CLR klasszikus COM-szerverként valósult meg, amelynek kódja egy szabványos Windows DLL-ben található, és felhasználói módban működik. Gyakorlatilag az összes .NET-keretrendszer-összetevő szabványos Windows felhasználói módú DLL-ként valósul meg, a natív Windows API-funkciók tetejére rétegezve. (A .NET Framework egyik összetevője sem fut kernel módban.) Ezen összetevők közötti kapcsolat az ábrán látható.

Szolgáltatások, funkciók és szabványos programok.

A Windows felhasználói és programozási dokumentációjában szereplő egyes kifejezések különböző kontextusokban eltérő jelentéssel bírnak. Például a szolgáltatás szó utalhat az operációs rendszerben meghívott rutinra, egy eszközillesztőre vagy egy szervizfolyamatra. Hogy pontosan mit jelentenek ezek a kifejezések, az a következő listában látható:

  • Windows API-funkciók. Dokumentált, hívható szubrutinok a WindowsAPI-ban. Például CreateProcess, CreateFile és GetMessage.
  • Natív rendszerszolgáltatások (vagy rendszerhívások). Az operációs rendszer dokumentálatlan alapszolgáltatásai meghívva felhasználói módban futnak. Például az NtCreateUserProcess egy belső szolgáltatás, amelyet a Windows CreateProcess függvény hív meg egy új folyamat létrehozásához.
  • Kernel támogató funkciók (vagy szubrutinok). Csak kernel módból hívható szubrutinok a Windows operációs rendszeren belül. Például az ExAllocatePoolWithTag egy rutin, amelyet az eszköz-illesztőprogramok hívnak meg, hogy lefoglalják a memóriát a Windows rendszer dinamikusan lefoglalt területeiből (úgynevezett készletekből).
  • Windows szolgáltatások. A Service Control Manager (Windowsservicecontrolmanager) által elindított folyamatok. Például a Feladatkezelő szolgáltatás felhasználói módú folyamatként fut, amely támogatja az at parancsot (hasonlóan a UNIX at vagy cron parancsaihoz).
  • DLL-könyvtárak (dinamikus linkű könyvtárak – dinamikusan linkelt könyvtárak). Hívható rutinok készlete bináris fájlként összekapcsolva, amelyet dinamikusan betölthetnek az ezeket a rutinokat használó alkalmazások. Ilyen például az Msvcrt.dll (futásidejű könyvtár a C nyelven írt alkalmazásokhoz) és a Kernel32.dll (az egyik Windows API alrendszer-könyvtár). A DLL-eket széles körben használják a felhasználói módban futó Windows-összetevők és alkalmazások. A DLL-ek előnye a statikus könyvtárakkal szemben, hogy egyszerre több alkalmazás is használhatja őket, és a Windows biztosítja, hogy a DLL-re hivatkozó alkalmazások számára a DLL-kódnak csak egy példánya maradjon a memóriában. Vegye figyelembe, hogy a nem végrehajtható .NET-összeállítások DLL-ként vannak fordítva, de exportált rutinok nélkül. A CLR elemzi a lefordított metaadatokat, hogy hozzáférjen a megfelelő típusokhoz és osztálytagokhoz.

A Win32 API története.

Érdekes módon a Win32-t nem az akkori Windows NT néven ismert eredeti programozási felületnek szánták. Mivel a Windows NT projekt az OS/2 2. verziójának helyettesítőjeként indult, az eredeti programozási felület a 32 bites OS/2 PresentationManagerAPI volt. Ám egy évvel a projekt indulása után felszállt a Microsoft Windows 3.0, amely eladásra került. Ennek eredményeként a Microsoft irányt változtatott, és a Windows NT-t tette a Windows termékcsalád jövőbeni helyettesítőjeként, nem pedig az OS/2 helyett. Ebben a tekintetben szükségessé vált a Windows API specifikációjának kidolgozása - ezt megelőzően a Windows 3.0-ban az API csak 16 bites felület formájában létezett.

Bár a Windows API célja sok olyan új funkció bevezetése volt, amelyek a Windows 3.1-ben nem érhetők el, a Microsoft úgy döntött, hogy az új API-t a lehető legnevesebbé, szemantikailag és adattípus-kompatibilissé teszi a 16 bites Windows API-val, hogy megkönnyítse a meglévő portolási terheket. 16 bites Windows. -alkalmazások a Windows NT rendszerben. Valójában ez magyarázza azt a tényt, hogy sok függvény- és interfésznév inkonzisztensnek tűnhet: erre azért volt szükség, hogy biztosítsuk az új Windows API és a régi 16 bites Windows API kompatibilitását.

Az API rövidítése, az Application Programming Interface (API) egyszerűen néhány kész funkciókészlet, amelyet az alkalmazásfejlesztők használhatnak. Általában ez a fogalom egyenértékű azzal, amit korábban gyakrabban szubrutinok könyvtárának neveztek. Leggyakrabban azonban az API az ilyen könyvtárak valamilyen speciális kategóriájára utal.

Szinte minden meglehetősen összetett alkalmazás (MyApplication) fejlesztése során a végfelhasználó számára kialakul egy meghatározott belső funkciókészlet, amely az adott program megvalósítására szolgál, amit MyApplication API-nak neveznek. Gyakran kiderül, hogy ezek a funkciók más alkalmazások létrehozására is hatékonyan használhatók, beleértve más programozókat is. Ebben az esetben a szerzőknek a termékük reklámozási stratégiája alapján kell eldönteniük, hogy megnyitják-e a hozzáférést ehhez a készlethez külső felhasználók számára vagy sem? Pozitív válasz esetén a szoftvercsomag leírásában, mint előnye egy olyan mondat jelenik meg, hogy "a készlet egy nyílt API-funkciót tartalmaz".

Így az API leggyakrabban olyan függvénykészletre utal, amely egy alkalmazás része, de ugyanakkor más programokban is használható. Például az Excel a végfelhasználói felületen kívül egy sor Excel API-funkcióval is rendelkezik, amelyek különösen VB-t használó alkalmazások létrehozásakor használhatók.

Ennek megfelelően a Windows API egy olyan funkciókészlet, amely magának az operációs rendszernek a részét képezi, és ugyanakkor bármely más alkalmazás számára elérhető. És ebben a tekintetben a BIOS / DOS rendszermegszakítási készlettel való analógia, amely valójában egy DOS API, meglehetősen indokolt.

A különbség abban rejlik, hogy a Windows API funkcióinak összetétele egyrészt jóval szélesebb, mint a DOS-ban, másrészt nem tartalmazza a számítógépes erőforrások közvetlen kezelésének számos eszközét, amelyek elérhetőek voltak. programozók az előző operációs rendszerben. Ezenkívül a Windows API-hoz való hozzáférést szokásos eljárási hívásokkal hajtják végre, a DOS-funkciók pedig a processzor speciális gépi utasításán keresztül hívhatók meg, amelyet Interruptnak („megszakításnak”) neveznek.

Win16 API és Win32 API

Mint tudják, a Windows 3.x-ről a Windows 95-re való váltás a 16 bites operációs rendszer architektúráról a 32 bitesre való átállást jelentette. Ezzel egy időben a 16 bites Windows API-t (Win16 API) egy új, 32 bites változatra (Win32 API) váltották fel. Ebben az esetben csak azt kell szem előtt tartani, hogy néhány kivételtől eltekintve a Win32 API készlet ugyanaz a Windows 9x és a Windows NT családok esetében.

A Win API-val való ismerkedés során kiderül, hogy sok beépített függvény nem más, mint a megfelelő rendszereljárások hívása, de csak ennek a nyelvnek a szintaxisa formájában valósul meg. Ennek alapján az API használatának szükségességét a következő lehetőségek határozzák meg:

API-funkciók, amelyek teljes mértékben beépített függvényként vannak implementálva. Ennek ellenére néha ebben az esetben hasznos az API használatára váltani, mivel ez néha jelentősen javíthatja a teljesítményt (különösen az átadott paraméterek szükségtelen konverzióinak hiánya miatt).

A beépített függvények csak a megfelelő API-függvény egy speciális esetét valósítják meg. Ez egy meglehetősen gyakori lehetőség.

Nagyon sok API-függvénynek egyáltalán nincs analógja a fordítók ma létező verziójában. Például VB-vel nem törölhet könyvtárat – ehhez a DeleteDirectory funkciót kell használnia.

Azt is hangsúlyozni kell, hogy egyes API-funkciók (részesedésük a Win API-ban nagyon kicsi) nem hívhatók meg programokból számos nyelvi korlátozás miatt, például a memóriacímekkel való munkaképtelenség miatt. De bizonyos esetekben a nem triviális programozási technikák segíthetnek (különösen ugyanazon címek esetében).

Win APIÉsDinamikus hivatkozási könyvtár (DLL)

A Win API készlet dinamikus DLL-ként van megvalósítva.

Ebben az esetben a DLL alatt a bináris dinamikus könyvtárak hagyományos változatát értjük, amelyek közvetlen hozzáférést biztosítanak az alkalmazások számára a szükséges eljárásokhoz - szubrutinokhoz vagy függvényekhez (hasonlóan ahhoz, ahogy ez egy projekten belüli eljárások meghívásakor történik). Az ilyen könyvtárak különféle eszközökkel hozhatók létre - VC++, Delphi, Fortran, Assembler.

A dinamikus könyvtárfájlok általában .DLL kiterjesztéssel rendelkeznek, de ez egyáltalán nem szükséges. Az .EXE kiterjesztést gyakran használták a Win16-hoz, a külső eszközillesztőket .DRV-vel jelölik.

A Windows API-k és az azokat tartalmazó fájlok pontos számának meghatározása nehéz (de mindegyik a rendszerkönyvtárban van). Ebben a tekintetben jobb kiemelni az operációs rendszer magját alkotó könyvtárak összetételét és a főbb kiegészítő funkciókkal rendelkező főbb könyvtárakat.

A Windows 95/98 operációs rendszer kernelének Win32 API könyvtárai:

KERNEL32.DLL: alacsony szintű funkciók a memória, a feladatok és egyéb rendszererőforrások kezelésére;

USER32.DLL: Itt található a legtöbb felhasználói felület kezelési funkciója;

GDI32.DLL: Graphics Device Interface könyvtár – különféle kimeneti funkciók külső eszközökhöz;

COMDLG32.DLL: Általános célú párbeszédpanelek használatával kapcsolatos funkciók.

Alapkönyvtárak kiterjesztési funkciókkal:

COMCTL32.DLL: További Windows-vezérlők készlete, beleértve a falistát és a gazdag szöveget;

MAPI32.DLL: e-mail funkciók;

NETAPI32.DLL: vezérlők és hálózati funkciók;

ODBC32.DLL: ennek a könyvtárnak a funkciói szükségesek ahhoz, hogy az ODBC protokollon keresztül különféle adatbázisokkal dolgozhassanak;

WINMM.DLL: rendszermédia-hozzáférési műveletek.

Ha hibát észlel, jelöljön ki egy szövegrészt, és nyomja meg a Ctrl + Enter billentyűket
OSSZA MEG: