Osnovne Windows usluge i API funkcije. Windows api - skup funkcija operacijskog sustava. Zašto odmah o WinAPI-ju?

Dođi! Dođi! Danas konačno ponovno otvaramo Windows prozor. Zbogom jadna konzolo!

Do tada morate biti upoznati sa sintaksom C++, razumjeti kako koristiti petlje i petlje te razumjeti kako funkcije dobro rade. Ako ste bili uhvaćeni u pomorskoj bitci, možete zabilježiti što ste zarobili.

Ugorsk obrazac za registraciju

Sav kod koji koristi WinAPI napisan je u ukrajinskom obliku. Dobro je dobro napisati kôd.

Čije slovo kob treba staviti ispred naziva promjene. Sve riječi u nazivima važnih funkcija počinju velikim slovom.

Os prefiksa:

b – promjena tipa bool.
l - promjena vrste dugog cijelog broja.
w – riječ (riječ) – 16 bita. Naziv kratkog tipa bez predznaka.
dw – dvostruka riječ (double word) – 32 bita. Zminna tip unsigned long.
sz - niz završava nulom. Samo jednostavan red koji smo dosljedno koristili.
p ili lp – pokazivač. lp (kao dugi pokazivač) – ovi indikatori su preneseni iz prošlosti. Zajedno lp i p znače isto.
h – opis (tip ručice).

Na primjer, os se zove ovako:

void * pData;

Ovaj obrazac za prijavu zaštićen je autorskim pravima Microsofta. Mnogo je ljudi koji kritiziraju ovu metodu imenovanja promjenjivih veličina. Ali slični govori (osobito o kodiranju) su vitalni za velike tvrtke.

Dopustite da vas podsjetim da se stalni identifikatori temelje na velikim slovima: WM_DESTROY. WM_DESTOY - vrijednost 2, konstanta je definirana putem define.

Osim toga, winAPI ima mnogo vrsta preraspodjele. Os na ovoj stranici je http://msdn.microsoft.com/en-us/library/aa383751(VS.85).aspx, možete pronaći opise svih vrsta Windowsa (na engleskom).

I još jedan govor, koji nismo razumjeli. Tuševima se često daju NULL vrijednosti. Imajte na umu da je ovo jednostavno 0 i potpisnici kojima je dodijeljena vrijednost NULL (nula), ne označavaju dijeljenje memorije.

Windows API (WinAPI)

Svi Windows programi koriste posebno programsko sučelje, WinAPI. Skup funkcija i struktura u Movi C čini vaš program dobrim radom u sustavu Windows.

Windows API ima velike mogućnosti za rad s operativnim sustavom. Može se reći – bez granica.

Ne možemo promatrati samo stotinu mogućnosti WinAPI-ja. Trenutno želim uzeti više materijala, ali to bi potrajalo puno sati, a nakon preuzimanja WinAPI-ja u močvare, došli bismo do DirectX-a za nekoliko kamena. Opis WinAPI-ja, uzet ćemo dvije lekcije (uključujući i ovu) Gledat će samo okvir programa Windows.

Program za Windows, kao i program za DOS, ima glavnu funkciju. Ovdje se ova funkcija zove WinMain.

WinMain funkcija

Windows program se sastoji od sljedećih dijelova (sve je pohranjeno u WinMain):

Izrada i registracija prozora razreda. Neka vas ne zbune C++ klase. WinAPI je napisan u C-u, ima puno klasa u onome što nam je poznato kao uobičajena riječ.
Izrada prozora programa.
Glavni ciklus u kojem se formira znanje.
Obrada se prijavljuje u završnom postupku. Prozorska procedura je primarna funkcija.
Os i nekoliko točaka osnova su Windows programa. Proširenjem ove nove lekcije sve ćemo detaljno razriješiti. Ako se izgubite u opisu programa, vratite se na ove točke.

Hajdemo sada sve srediti:

WinAPI: struktura WNDCLASS

Prvo trebamo kreirati i spremiti strukturnu promjenu WNDCLASS, a zatim na temelju nje registrirati konačnu klasu.

Os izgleda ovako:

moj c++ kod typedef struct ( UINT stil; // stil prozora WNDPROC lpfnWndProc; // indikator za prozorsku proceduru int cbClsExtra; // dodatni bajtovi nakon klase. Prvo postavljeno na 0 int cbWndExtra; // dodatni bajtovi nakon instance prozora. Prvo postavljeno na 0 / instanca lar programa: Proslijeđeno u obliku parametra u WinMain HICON hIcon; // ikona programa HCURSOR hKursor; // programski kursor HBRUSH hbrBackground; // boja pozadine LPCTSTR lpszMenuName; ;

Struktura WNDCLASS u WinAPI skladištu definira osnovne mogućnosti prozora koji se kreira: ikone, prikaz kursora miša, izbornik prozora, koji dodatak će biti u prozoru...

Nakon što ste spremili ovu strukturu, možete registrirati konačnu klasu na ovoj osnovi. Ne postoje iste klase kao u C++. Sada se možete sjetiti da je ovo predložak koji ste registrirali u sustavu i sada možete izraditi novi predložak na temelju ovog predloška. I svim ovim danima vladat će vlasti, kao što ste naučili iz strukturne promjene WNDCLASS-a.

WinAPI: funkcija CreateWindow

Nakon registracije nove klase, na temelju nje se stvaraju glavni programi (prešli smo na drugu točku). Isprobajte ovu dodatnu funkciju CreateWindow. Možda postoji uvredljivi prototip:

moj c++ kod HWND CreateWindow(LPCTSTR lpClassName // ime klase LPCTSTR lpWindowName // ime prozora (prikazano u naslovu) DWORD dwStyle // stil prozora int x // vodoravna koordinata lijevog ruba zaslona int y // okomita koordinata gornjeg ruba ekran int nWidth, // širina prozora int nHeight, // visina prozora HWND hWndParent, // očev prozor HMENU hMenu, // opis izbornika HINSTANCE hInstance, // instanca programa LPVOID lpParam // parametar; uvijek postavljen na NULL);

Budući da su klasi prozora (WNDCLASS struktura) dane osnovne ovlasti prozora, onda su ovdje specifični parametri skin prozora: veličina prozora, koordinate...

Ova funkcija rotira prozor opisa. Za daljnji opis možete otići do prozora koji je sličan identifikatoru.

Imajte na umu da ovdje postoji mnogo novih vrsta. Zapravo, sav smrad je star, samo preimenovan. Na primjer: HWND nije preraspodjela u tip HANDLE, što je na svoj način preraspodjela u PVOID, što je također preraspodjela u void*. Istina je tako duboko zakopana! Uostalom, tip HWND nije znak praznine.

Prozor se sastoji od mnogo dijelova. Naime, u svakom programu vidjet ćete: naslov prozora, izbornik sustava (kliknite na ikonu programa u gornjem lijevom dijelu prozora), tri sistemska gumba za rad s prozorom: svjetlo, cijeli zaslon i Zatvoriti. Također, praktički uvijek pored toga postoji i jelovnik. Osovina onog preostalog sigurno neće biti u nama. I, naravno, najveći dio prozora zauzimaju tzv. klijentsko područje u kojem kupac radi.

Ovo je bolje od prozorskog režima. Ako nastavimo vježbati s DiectX-om dulje vrijeme, nećemo koristiti način rada preko cijelog zaslona.

Rukovanje porukama

Glavna prednost svih naprednih programa pod Windowsima je obrada ažuriranja.

Na primjer, kada korisnik pritisne tipku na tipkovnici, generira se obavijest da je tipka pritisnuta. Tada ćete morati otići na program koji je bio aktivan kada ste pritisnuli tipku.

Ovdje imamo događaj - tipka je pritisnuta.

Radnje mogu biti: pomicanje pokazivača miša, promjena fokusa programa, pritiskanje tipki na tipkovnici, zatvaranje prozora. Prilično je bogato. Duje! U sekundi se u operativnom sustavu mogu kreirati deseci poruka.

Dakle, ako postoji bilo kakav odgovor, operativni sustav generira obavijest: kada se pritisne tipka, mijenjaju se koordinate pokazivača miša i otvara se novi prozor.

Informacije mogu stvarati i operativni sustav i razni programi.

Struktura i izgled nadolazeće narudžbe:

moj c++ kod typedef struct tagMSG ( HWND hwnd; // prozor koji označava obavijest UINT poruku; // kod obavijesti WPARAM wParam; // parametar LPARAM lParam; // parametar DWORD vrijeme; // sat kada je obavijest izdana POINT pt; // koordinira pokazivač miša) MSG;

Obratite pozornost na činjenicu da se strukture ponovno dodjeljuju pomoću typedef-a.

Za izradu ove strukture možete brzo upotrijebiti sljedeći kod:

moj c++ kod msg.messgae == 2; // ovo su dva reda ekvivalentnih fragmenata msg.message == WM_DESTROY; // konstanta WM_DESTROY stara dva

Ovdje je polje, u yaku, kod din (izi yem dinemalen, i Constanta Wm_Destroy. WM - vid Windows poruka (Vice Windows). WM_Destroy - TSEVDENSH, JAK GENTED BY SELECTION (DSTROY - DESTROI).

Kodovi su naznačeni iza dodatnih konstanti i prefiksa WM_: WM_CLOSE, WM_CREATE i drugi.

MSG struktura ima tip HWND - Window Handle (ručica prozora i opis prozora). Ovo je vrsta stvari koja opisuje svijet. Cijena je za simbol identifikatora (ime prozora).

Zapamtite ovu riječ - ručka (opisati, deskriptor). U sustavu Windows ovo je vrlo česta tema zlostavljanja. Također, sve vrste Windowsa koje počinju s H su opisi: opis ikone, opis fonta, opis instance programa. Ima ih tridesetak, koliko se sjećam.

Sve interakcije između aplikacija u sustavu Windows odvijaju se pomoću ovih opisa prozora (HWND).

Postoji još jedan važan deskriptor - deskriptor programa (HINSTANCE - prvi parametar WinMain) - ovo je jedinstveni identifikator programa, jer bilo koji operativni sustav ne može pomiješati dva različita programa. Ovo je otprilike kao crtični kod. Kasnije ćemo ga pogledati.

Sada, kada izvršite bilo koju radnju, obavijest se stvara i pamti: postavlja se opis prozora u kojem možete vidjeti obavijest, postavlja se identifikator obavijesti, spremaju se parametri, sprema se sat (trenutni), a vi odredite Možete promijeniti koordinate pokazivača miša (možete vidjeti strukturu).

Nakon ove obavijesti prijeđite na sljedeću obavijest operativnog sustava. Kada su u pitanju naše informacije, one će biti poslane u traženi prozor (Windows zna kako poslati informacije o koži stručnjacima). Ako ste upoznati s programima, morat ćete biti informirani o programima. Teško je doći do dna, postaje dosadno.

Nevjerojatno je da u ovom trenutku, kada je korisnik izvršio bilo koju radnju (poruka je prikazana i poruka je generirana) iu ovom trenutku, kada je program reagirao na tu radnju (poruku je generirao program), ima puno informacija. Čak i ako koristite Windows, također možete dobiti mnogo informacija iz programa. Prvi može imati oko stotine, drugi može imati barem nekoliko.

Prozorska procedura - WndProc

Nastavljamo od trenutka kada je informacija potrošena do kraja programa. Samo se dugo čeka, i počinje se rušiti. Za obradu imajte na umu da program skin ima posebnu funkciju - postupak prozora. Zove se WndProc (od Window Procedure). Prozor procedure proširenja izvodi se u glavnoj programskoj petlji i dovršava se tijekom svake iteracije ciklusa.

Informacije (u obliku strukturnih promjena MSG) primjenjuju se na ovu funkciju u obliku parametara: opis prozora, identifikator obavijesti i dva parametra. Imajte na umu da se polja vremena i točke ne prosljeđuju u proceduru prozora. Totto, da ti kažem, to je već "rozíbran".

U sredini postupka prozora, prekidač se deinstalira, što uključuje provjeru ID-a obavijesti. Os je primjer jednostavne prozorske procedure (potpuno radi):

moj c++ kod// ne gubite vrijeme na HRESULT i __stdcall. Pogledat ćemo ih kasnije. ) // prevodilac odlučuje obavijestiti )

Ostajem – glavni ciklus. Vin je još jednostavniji. Svaku iteraciju ciklusa provjerava program. Čim imate informacije, izvučeni ste iz svijeta. Ciklus će tada biti upitan da klikne na postupak prozora za obradu informacija.

Osovina je u punom zamahu i sve je za danas. Već je jasno da je program pod WinAPI puno sličniji programu pod DOS-om. Kao što sam već napisao, u nadolazećoj lekciji ćemo pogledati kod programa koji radi.

Imam pravo kreirati novi projekt. U prozoru New Project odaberite predložak – Win32Project (prethodno smo odabrali Win32 Console Application). U jednom od nadolazećih prozora nemojte postaviti oznaku Prazan projekt i IDE će generirati pripremljeni program.

Ako pažljivo pogledate kod u datoteci project_name.cpp, vidjet ćete sve stvari o kojima smo razgovarali: strukturnu promjenu MSG-a, popunjavanje strukture WNDCLASS, stvaranje prozora funkcijom CreateWindow, glavnu programsku petlju . Osim toga, datoteci je dodijeljena funkcija WndProc. Morate obraditi niz informacija u preklopnim okvirima: WM_COMMAND, WM_PAINT, WM_DESTROY. Pronađite sve u datoteci.

Osim onoga što smo vidjeli, program sadrži mnogo dodatnog koda. U sljedećem izdanju ćemo pogledati programski kod, kako bi se sve provjerilo. Bit će mnogo jednostavniji i inteligentniji od onoga što IDE generira.

Odricanje

Mislio sam da će WinAPI izaći u susjedstvu. Odavno je jasno da postoji veliki broj cross-platformskih okvira, Windows nije samo na stolnim računalima, a i sam Microsoft u svojoj trgovini ne libi se dodati dodatke koji bi opravdali ovo čudovište. Postoje tisuće članaka o tome kako stvarati na WinAPI-ju, ne samo ovdje, već i diljem interneta, koji se broje u tisućama, kako u predškolskoj dobi, tako i izvan nje. Cijeli proces seciranja više se ne temelji na atomima, već na subatomskim česticama. Što bi moglo biti jednostavnije i inteligentnije? I evo me...

Ali nije sve tako jednostavno kao što se čini.

Zašto sad WinAPI?

Jednog dana, dok sam bio iscrpljen istom dobrom stvari, pomislio sam: Što je ovo, dovraga, a u uređivaču nema tako jednostavnog jezika kao što je navigacija kroz tipke tipkovnice, kao u svakom normalnom uređivaču.

o cemu ja pricam I šifra osovine:

Case WM_KEYDOWN: MessageBox(hwndDlg,"Umri!","Mrtav sam!",MB_YESNO|MB_ICONINFORMATION);
Na taj su način autori željeli dodati podršku tipkovnici, ali realnost arhitekture dijaloških prozora u Windowsima oštro je kaznila takvo samozadovoljavanje. Svatko tko je koristio emulator ili kontroler, želi li to znati?
U čemu je problem?

Odgovor je sljedeći: ne možete tako raditi!

I, vraćajući se na početnu stranicu WinAPI-ja: ima previše popularnih, a ne toliko, projekata da bi se ovaj nastavio koristiti u ovom trenutku, jer Ukratko, ne možete držati puno govora o čistom API-ju (ovdje možete beskrajno povlačiti analogije s niveliranjem visokokvalitetnog jezika i asemblera, ali ne uopće). Zašto ne? Samo vikorist i to je to.

O problemu

S dijaloškim prozorima lakše je raditi nego s GUI-jem, a istovremeno nam daju mogućnost da stvari radimo sami. Na primjer, informacija WM_KEYDOWN/WM_KEYUP, koja se nalazi u proceduri prozora, nalazi se u pododjeljcima DefDlgProc, uključujući riječi kao što su: navigacija tabulatorom, obrada tipki Esc, Enter, itd. Osim toga, ne morate ručno stvarati dijaloške okvire: samo dodajte gumbe, popise, uređivač resursa, kliknite WinMain CreateDialog/DialogBox i gotovi ste.

Lako je zaobići takve druge tajne. I to minimalno dva potpuno legalna načina:

  1. Kreirajte vlastitu klasu preko RegisterClassEx i dodajte WM_KEYDOWN u proceduru obrade klase i preusmjerite je na samu proceduru obrade dijaloga. Tako tako! Možete stvarati dijaloge s vlastitim razredom i koristiti VS uređivač koji vam omogućuje da postavite naziv razreda za dijalog. Zna li itko za ovo i koristi li se sebi?
    Očigledni nedostatak: Potrebno je prijaviti još jednu klasu, pa postoji još 1 CALLBACK procedura, čija će se bit izgubiti u emitiranju oklade. Osim toga, ne znamo kudi Oni će biti prekršeni i policija će biti na oprezu.
  2. Koristiti implementaciju akceleratorskog mehanizma. I nikada nećemo morati promijeniti kod procedure dijaloga! Pa, zašto ne dodati jedan red prekidaču / kućištu, ali cijena je niža.

Tutoriali?

Ne bojim se to reći Brkovi Vodiči za kreiranje prozora putem WinAPI-ja počinju s takvim jednostavnim kodom, koji pokazuje kako se ciklus obrade prijavljuje (izostavit ću pojedinosti o pripremi klase prozora i drugih veza):

Dok (GetMessage(&msg, nullptr, 0, 0)) ( TranslateMessage(&msg); DispatchMessage(&msg); )
Ovdje je vrlo jednostavno:

  1. GetMessage() vrišti đavolju poruku, i ključna stvar: blokira protok jer je prazan
  2. TranslateMessage() s WM_KEYDOWN/WM_KEYUP oblikuje obavijest WM_CHAR/WM_SYSCHAR (ovo je neophodno ako želite kreirati vlastiti uređivač teksta).
  3. DispatchMessage() šalje obavijest prozorskoj proceduri (kakva jest).
Jasno je da nije sigurno koristiti ovaj kod, i to je razlog zašto. Vratite poštovanje vinu:
Stoga povratna vrijednost može biti različita od nule, nula ili -1, izbjegavajte kod poput ovog:
dok (GetMessage(lpMsg, hWnd, 0, 0)) ...
Í nišanite kundak niže u ispravnom ciklusu.

Varto je rekao da VS predlošci za Win32 imaju iste pravopisne dodatke pogrešno ciklus. I stvarno je ludo. Iako malo ljudi ulazi u ono što su sami autori sastavili, to je a priori točno. A netočan kod se množi s greškama, koje je vrlo teško uhvatiti.

Nakon ovog fragmenta koda, u pravilu, slijedi rasprava o akceleratorima i dodaje se nekoliko novih redaka (s obzirom na MSDN, potičem vas da napišete ispravnu petlju):

HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) break; if (!TranslateAccelerator(msg.hwnd, hAccel, &msg)) ( TranslateMessage(&msg); DispatchMes ; ) )
Najčešće preferiram ovu opciju. pobjeđujem ( ta-dam) Znovu nije u redu!

Govorit ću o onima koji su se promijenili (a zatim o problemima s ovim kodom):

U prvom redu resursa odabrana je tablica ključeva, a kada kliknete na bilo koji od formata, prikazat će se obavijest WM_COMMAND s pripadajućim ID-om naredbe.

TranslateAccelerator radi ovo: kako dohvatiti WM_KEYDOWN i ključni kod koji se nalazi na ovom popisu, zatim (opet, ključna točka) formatirati WM_COMMAND (MAKEWPARAM(id, 1)) poruku i poslati je tipovima One day for window rukovanje navedeno u prvom argumentu, postupci obrade.

Preostalom frazom je, valjda, postalo jasno u čemu je problem s prethodnim kodom.
Dopustite mi da objasnim: GetMessage je odabran za SVE objekte tipa "prozor" (uključujući djecu: gumbe, popise itd.), a TranslateAccelerator će poslati generiranu WM_COMMAND kamo? Tako je: natrag na gumb/popis. Dodali smo WM_COMMAND našoj proceduri, što znači da je moramo ukloniti iz nje.

Ispada da se TranslateAccelerator mora koristiti za naš kreirani prozor:

HWND hMainWnd = Stvori prozor(...); HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) break; if (!TranslateAccelerator(hMainWnd, hAccel, &msg)) ( TranslateMessage(&msg); DispatchMess )
I sada je sve dobro i divno: sve smo sredili do detalja i sve radi savršeno.

Opet znam. :-) Učinimo to kako treba dokle god imamo samo jedno - naše. Čim se pojavi nemodalni novi prozor (dijalog), sve tipke koje će biti pritisnute u novom prozoru prevode se u WM_COMMAND i šalju kamo? I dopustite mi da to kažem ispravno: naša glavobolja je loša.

U ovoj fazi savjetujem vam da ne blokirate policiju iz najgluhije situacije, već radije pogledajte govore koji su već ranije (ili možda nisu razjašnjeni) u udžbenicima.

IsDialogMessage

Na temelju naziva ove funkcije, mogli biste pomisliti da to znači: biti svjestan bilo kakvog dijaloga. Ale, prije svega, što ti znaš? Drugim riječima, koja je vrijednost ovih informacija?

Stvarno se isplati platiti malo više, strši iz naziva. I sebi:

  • Kroz podređene kontrole možete se kretati pomoću gumba Tab/Shift+Tab/gore/dolje/desno/lijevo. Plus još nešto, to nam je dovoljno
  • Nakon pritiska na ESC formira se WM_COMMAND(IDCANCEL)
  • Nakon pritiska na Enter formira se WM_COMMAND(IDOK) ili nakon pritiska na gumb na retku
  • Mijenja tipke iza priključaka (okvir takvih tipki je malo svjetliji od ostalih)
  • Pa, i još više različitih stvari koje robotu dopisnika olakšavaju dijalog
Što nam daje? Prije svega, ne trebamo razmišljati o navigaciji u sredini prozora. Toliko moramo štedjeti sve. Prije nego što progovorite, navigacija karticama može se postići dodavanjem stila WS_EX_CONTROLPARENT našem glavnom prozoru, ali to nije baš korisno i nije toliko funkcionalno.

Na drugi način možemo olakšati život iza rešetaka točaka navedenih na popisu (i još nekoliko).

Vzagali, vi koristite ovdje na vrhu Windowsa za sigurnost robota modalni dijaloški prozori, a programerima se daje mogućnost da kliknu na njih za nemodalne dijaloge. Međutim, ovo možemo koristiti za dobru mjeru:

Štoviše, dijaloška funkcija funkcije koristi se za modeliranje dijaloških okvira, možete je koristiti s bilo kojim prozorom, tako da su znakovi karavane konfigurirani i prozori, kako bi se osiguralo da je sama tipkovnica odabrana, tako da je možete odabrati Dostupno u dijaloškom okviru.
Tobto. Sada oblikujmo petlju ovako:

HWND hMainWnd = Stvori prozor(...); HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) break; if (!TranslateAccelerator(hMainWnd, hAccel, &msg)) ( if (!IsDialogMessage(hMainWnd) TranslateMessage(&msg) ; Otpremna poruka(&msg); ) ) )
Tada ćemo konačno koristiti navigaciju, baš kao u drugim Windows dijalozima. Ali sada su nas odnijela dva nedostatka:

  1. Ovaj će se kod također ljubazno koristiti samo s jednim (nemodalnim) prozorom;
  2. Nakon što smo oduzeli sve prednosti dijaloške navigacije, moramo dodati WM_KEYDOWN/WM_KEYUP u pogled (samo za sam prozor, a ne za podređene kontrole);
I u ovoj fazi svi vodiči završavaju i počinje hrana: Kako rukovati događajima na tipkovnici u standardnom dijalogu winapi?
Ovo je prva stvar objavljena na Googleu, ili na Internetu: na tisuće njih. O predloženom rješenju (najznačajnije, potrebno je stvoriti vlastitu klasu dijaloga, o čemu sam gore pisao, prije potklasiranja i RegisterHotKeya. Ovdje ću naučiti “najkraću” od metoda: vikorize Windows Hooks).

Došlo je vrijeme za razgovor o tome što nedostaje u tutorijalima i videima.

U pravilu (u pravilu! Ako netko želi više, možete prijaviti svoj razred za dijaloge i nastaviti ovako. A ako vam nije stalo, mogu dodati ovaj članak) WM_KEYDOWN želite ovo ako želite dovršiti pritisak na tipka koja odabire funkciju bez obzira na potrebnu kontrolu u uredu – tj. Ovo je vitalna funkcija za ovaj određeni dijalog. A ako je tako, zašto onda brzo ne predstaviti bogate mogućnosti kojima nas sam WinAPI uči: TranslateAccelerator.

Kroz vikoryst točno jedan tablicu akceleratora, pa čak i glavni prozor. Pa, istinu govoreći: postoji samo jedan ciklus petlje GetMessage i postoji samo jedna tablica. Gdje bi trebali ići?

Zapravo, GetMessage-petlje mogu biti doprinosa. Zadivimo se još jednom opisu PostQuitMessage:

Funkcije PostQuitMessage objavljuje WM_QUIT poruku u red poruka niti i odmah se vraća;
Dobivam poruku:
Ako je funkcija ažuriranje WM_QUIT poruke, povratna vrijednost je nula.
Dakle, dolazi do izlaza iz GetMessage-petlje, kako zovemo PostQuitMessage u prozorskoj proceduri. Što to znači?

Možemo za kožni nemodalni Ovo je prozor za naš program za stvaranje vlastitog ciklusa nalik na snagu. Ako je DialogBoxParam prikladan za nas, jer Nemoguće nam je vrtjeti vlastiti energetski ciklus. Međutim, ako kreirate dijalog putem CreateDialogBoxParam ili prozor putem CreateWindow, možete pokrenuti drugu petlju. Kada je u pitanju kožni Za ovu vrstu dijaloga obavezni smo kliknuti PostQuitMessage:

HWND hMainWnd = Stvori prozor(...); HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) break; if (!TranslateAccelerator(hMainWnd, hAccel, &msg)) ( if (!IsDialogMessage(hMainWnd) TranslateMessage(&msg) ; DispatchMessage(&msg); ) ))) // .... hInstance, MAKEINTRESOURCE(IDD_MYDIALOG), hwnd, MyDialogBoxProc), HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR_FOR_MY_DIALOG)); wnd, FALSE);// onemogući nadređeni prozor, jer je dijaloški prozor modalan dok (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) break; if (!TranslateAccelerator(hDlg, hAccel) , &msg)) ( if (!IsDia , &msg)) ( TranslateMessage(&msg); DispatchMessage(&msg); ) ) ) EnableWindow(hwnd, fSavedEnabledState); // Omogući nadređeni prozor. wparam, LPARAM lparam) (switch(umsg) (case WM_CLOSE: (// EndDialog(hwnd, 0)); - NE RADITE TO! // EndDialog je ispravan samo za modificiranje dijaloga kreiranih s DialogBox(Param) DestroyWindow(hwnd) ; break; ) case WM_DESTROY: ( PostQuitMessage(0); break; ) // .... ) return 0; )
Vratite poštovanje: sada za novi prozor kože u našem programu koji možemo dodati prije obrade Vlasnu stol akceleratora. WM_QUIT uklanja GetMessage iz dijaloške petlje, a vanjska petlja se ne pokreće. Zašto si tako uzbuđena?

S desne strane je da trenutni ciklus "ustaje" na kliku DispatchMessage, koji se klikne na našu proceduru, kako okrenuti njegovu snagu unutarnje Petlja GetMessage sa samom ovom porukom DispatchMessage. Klasični wiki privici (na adresi DispatchMessage). Stoga vanjska petlja ne poništava WM_QUIT i završava u ovoj fazi. Sve ide glatko.

Pa, ovdje postoje neki nedostaci:
Koža je svjesna ovog ciklusa samo za “vaš” prozor. Za druge ovdje ne znamo. To znači da će, ako se ovdje pojavi još jedan ciklus, svi oni morati obraditi svoje poruke pomoću para TranslateAccelerator/IsDialogMessage.

Eto, došlo je vrijeme da vratimo poštovanje i napišemo i odlučimo o ispravnoj obradi svega kako bismo vas informirali o svim rezultatima našeg programa. Želim poštovati da je nagrada za jedan stream niža. Jer Ako tok kože dopusti svojoj strukturi da postane svjestan, tada će tok kože morati stvoriti svoje strukture. Bojati se čak i trivijalnih promjena koda.

Robimo je lijep

Jer Ako je ispravno postavljanje zadatka pola rješenja, onda prvo trebam ispravno postaviti zadatak.

Prije svega, logično bi bilo da samo aktivniji Sada primam obavijesti. Tobto. Za neaktivan prozor ne prevodimo akcelerator i ne šaljemo obavijesti IsDialogMessage-u.

Na drugi način, ako tablica akceleratora nije postavljena za prozor, tada se nema što prevoditi, samo obavijest u IsDialogMessage.

Kreirajmo jednostavnu std::map koja će mapirati deskriptor prozora u deskriptor tablice akceleratora. Os je ovakva:

Std::map l_mAccelTable;
A u svijetu kreiranih prozora nastavit ćemo dodavati novi prozor s deskriptorom u vašu omiljenu tablicu (ili nulu, jer takva obrada nije potrebna).

BOOL AddAccelerators(HWND hWnd, HACCEL hAccel) ( if (IsWindow(hWnd)) ( l_mAccelTable[ hWnd ] = hAccel; return TRUE; ) return FALSE; ) BOOL AddAccelerators(HWNDhW LoadAccelerators( hInstance, accel));) BOOL AddAccelerators(H WND hWnd, int ubrzanje)
I nakon što zatvorite prozor, otiđite. Os je ovakva:

Void DelAccel(HWND hWnd) ( std::map ::iterator me = l_mAccelTable.find(hWnd); if (me != l_mAccelTable.end()) ( if (me->second) ( DestroyAcceleratorTable(me->second); ) l_mAccelTable.erase(me); ) )
Sada, kada stvorimo novi dijalog/prozor, kliknite AddAccelerators(hNewDialog, IDR_MY_ACCEL_TABLE). Kako zatvoriti: DelAccel(hNewDialog).

Imamo popis potrebnih deskriptora. Evo kako mijenjamo našu glavnu petlju obrade:

// ... HWND hMainWnd = CreateWindow(...); AddAccelerators(hMainWnd, IDR_ACCELERATOR); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) break; if (!HandleAccelArray(GetActiveWindow(), msg)) ( TranslateMessage(&msg); DispatchMessage ) // .. .
Puno bolje! Što je tu s HandleAccelArray i što je sljedeće s GetActiveWindow()?

Malo teorije:

Postoje dvije funkcije koje rotiraju ručicu aktivnog prozora GetForegroundWindow i GetActiveWindow. Važnost prvog nad drugim u potpunosti je opisana u opisu drugog:

Povratna vrijednost je ručica aktivnog prozora pridruženog redu poruka pozivajuće niti. U suprotnom, povratna vrijednost je NULL.
Ako prvo rotirate deskriptor bilo kojeg prozora u sustavu, tada će samo ostatak kako je vikoristova riječ obavijestiti naš tok. Jer Nastavit ćemo živjeti samo u svom potoku (i oni koji će propasti do naših dana), onda ćemo ostati.

Dakle, os HandleAccelArray, koju prenosi deskriptor na aktivnom prozoru, također je vidljiva na našoj karti, a kako je tamo, šalje poruku prijevodu TranslateAcceleratora, a zatim (kao da prvi nije dodajte potrebne ) u IsDialogMessage. Ako poruka još nije poslana, postavite FALSE da biste prošli kroz standardnu ​​proceduru TranslateMessage/DispatchMessage.

Ovako izgleda:

BOOL HandleAccelWindow(std::map ::const_iterator mh, MSG & msg) ( const HWND & hWnd = mh->first; const HACCEL & hAccel = mh->second; if (!TranslateAccelerator(hWnd, hAccel, &msg)) ( // poruka nije za Prevoditelj Pokušajte to s IsDialogMessage if (!IsDialogMessage(hWnd, &msg)) ( // dakle, zadane stvari vraćaju FALSE; ) ) // ok, poruka je prevedena. (HWND hActive, MSG & msg) ( if (!hActive) return FALSE; // nema aktivnog prozora Ništa za napraviti std::map ::const_iterator mh = l_mAccelTable.find(hActive); if (mh != l_mAccelTable.end()) ( // Shvaćam! Pokušajte prevesti ovu poruku za aktivni prozor return HandleAccelWindow(mh, msg); ) return FALSE; )
Sada svako dijete ima pravo dodati svoju omiljenu tablicu akceleratora i mirno uhvatiti i unijeti WM_COMMAND sa traženim kodom.

Što još postoji o jednom retku u kodu WM_COMMAND?

Opis u TranslateAcceleratoru da kaže:
Kako bi bilo jasno da funkcija slanja s porukama znači izbornik ili kontrole, vrlo učinkovita riječ s wParam parametrom WM_COMMAND ili WM_SYSCOMMAND poruka sadrži vrijednost 1.
Kod za obradu WM_COMMAND izgleda ovako:

Switch(HIWORD(wParam)) ( case BN_CLICKED: // Naredba iz gumba/izbornika ( switch(LOWORD(wParam))) ( case IDC_BUTTON1: DoButton1Stuff(); break; case IDC_BUTTON2: DoButton2Stuff ) break; ) )
Sada to možete napisati ovako:

Switch(HIWORD(wParam)) ( case 1: // akcelerator case BN_CLICKED // Naredba s gumba/izbornika ( switch(LOWORD(wParam))) ( case IDC_BUTTON1: DoButton1Stuff(); break; case IDC_BUT // ... ) pauza; ) )
A sada, okrećući se istom fceuxu, dodavši samo jedan red U kodu za obradu naredbi za gumbe uklanjamo sljedeće: koristite program za ispravljanje pogrešaka s tipkovnice. Dovoljno je dodati malu ljusku blizu petlje glave i novu tablicu akceleratora s podređenima VK_KEY => IDC_DEBUGGER_BUTTON.

PS: Malo ljudi zna je li moguće stvoriti vlastitu tablicu akceleratora, a sada je izravno zamrznuti.

P.P.S.: Jer DialogBox/DialogBoxParam rotiraju ciklus napajanja, a onda kada se preko njih pozove dijalog, akceleratori ne rade i naš ciklus (ili ciklusi) je u "mirovanju".

P.P.P.S.: Nakon klika na HandleAccelWindow kartice l_mAccelTable se mogu promijeniti, jer TranslateAccelerator ili IsDialogMessage kliknite DispatchMessage i tamo se možete pridružiti AddAcceleratorima ili DelAccelu u našim procesorima! Stoga je najbolje ne zanemariti ove funkcije.

Možete unijeti šifru. Temeljio se na kodu generiranom iz standardnog predloška MS VS 2017.

Oznake: Dodajte oznake

C WinAPI je glavni skup Microsoftovih programskih sučelja (API-ja) dostupnih u operativnim sustavima. Rana verzija zvala se Win32 API.

Unesi

WinAPI je sučelje za programiranje aplikacija koje se koristi za kreiranje Windows programa. Za početak, programer mora koristiti Windows SDK, prethodno poznat kao Platform SDK.

Spojite datoteke zaglavlja, biblioteke, slike, dokumentaciju i alate koji se koriste za razvoj programa. API za jezično programiranje u C i C++. Ovo je najizravniji način kreiranja dodataka u operativnom sustavu tvrtke.

Pomoću WinAPI-ja možete ga podijeliti u nekoliko područja:

    osnovne usluge;

    sigurnost;

  • Koristuvalnytsky sučelje;

    multimedija;

    Windows školjka;

    Merezhevy usluge.

Osnovne usluge će osigurati pristup osnovnim resursima. To uključuje funkcije WinAPI-ja, datotečne sustave, uređaje, procese, niti, registar i obradu pogrešaka. Sigurnosno područje sadrži sučelja, objekte i druge programske elemente za provjeru autentičnosti, autorizaciju, kriptografiju i druge sigurnosne zadatke. Grafički podsustav pruža funkcionalnost za prikaz grafike na monitorima, pisačima i drugim uređajima za prikaz. Sučelje korisnika pružit će funkcionalnost za stvaranje prozora i elemenata korisnika.

Multimedijska komponenta pruža alate za rad s video, audio i ulaznim uređajima. Funkcije sučelja ljuske omogućuju programima pristup funkcijama koje pruža ljuska operativnog sustava. Usluge Merezhevi pružaju pristup u najvećoj mogućoj mjeri u sustavu Windows.

Komponente

Kada WinAPI radi, imat ćete pristup osnovnim mogućnostima Windows API-ja, koje se mogu organizirati u sedam kategorija. Pogledajmo kožu njihovog izvješća.

Glavne usluge omogućuju pristup osnovnim resursima sustava u sustavu Windows. Primjene: datotečni sustav, periferni uređaji, procesi, pristup registru sustava i sustav kernela. Te su funkcije pohranjene u datotekama kernel.exe, krnl286.exe ili krnl386.exe za 16-bitne sustave i kernel32.dll i advapi32.dll za 32-bitne sustave.

Grafičko sučelje omogućit će pristup resursima za prikaz na monitorima, pisačima i drugoj perifernoj opremi. Pohranjuje se u datoteci gdi.exe na 16-bitnim sustavima i gdi32.dll na 32-bitnim sustavima.

Sučelje korisničkog sučelja karakterizira izgled osnovnih elemenata, kao što su gumbi i skrolanje, informacije o tipkovnici i miševima, kao i funkcije povezane s njima. Ove su funkcije pohranjene u datoteci user.exe na 16-bitnim sustavima i user32.dll comctl32.dll na 32-bitnim sustavima. Počevši od verzije XP, kontrole su grupirane u comctl32.dll.

Tajni dijalozi - Prikaz podataka za otvaranje i spremanje datoteka, odabir boja i fontova. Datoteka je comdlg.dll na 16-bitnim sustavima i comdlg32.dll na 32-bitnim sustavima.

Windows Shell je WinAPI komponenta koja programima omogućuje pristup funkcijama koje pruža ljuska operativnog sustava.

Mrežne usluge omogućuju pristup maksimalnim mogućnostima operativnog sustava. Njegove podkomponente uključuju NetBIOS, Winsock, RPC. Starije verzije imaju NetDDE.

Verzije

Win16, Win32 i Win32s standardni su skupovi komponenti koje omogućuju aplikacijskom softveru izvršavanje funkcija različitih operativnih sustava iz obitelji Windows.

Win32, nasljednik Win16, predstavljen je 1993. u 32-bitnim proizvodima obitelji Windows, kao što je Windows NT, 2000, 95. Ovo softversko sučelje implementira tri softverske biblioteke: Kernel32.dll, User32.dll i GDI32.dll2. Iste Win32 značajke dostupne su u svim Windows proizvodima, a ovisno o proizvodu, dodavanje ovih značajki može uzrokovati probleme s uslugom.

Mogućnosti Win32 uključuju komunikaciju između programa, kontrolu procesa, računalne datoteke, pisače, poslužitelje i komunikacijske priključke.

Specifikacija

WinAPI je apstraktna specifikacija za programsko sučelje za operativni sustav Windows. Sastoji se od deklaracija funkcija, veza, struktura, tipova podataka, makronaredbi, konstanti i drugih programskih elemenata. WinAPI je opisan u zaglavlju i nalazi se u zaglavljima Windows C. Službena implementacija funkcije WinAPI nalazi se u dinamičkim bibliotekama (DLL): na primjer, kernel32.dll, user32.dll, gdi32.dll i shell32.dll u sustavu imenik. Postoje implementacije Windows API-ja trećih strana: prije svega projekt Wine i projekt ReactOS.

Windows API je dinamički objekt. Broj funkcija postupno raste sa svakom novom verzijom OS-a i novim paketima ažuriranja. Također postoje važne razlike između poslužiteljskih verzija i desktop verzija operacijskog sustava. Ove funkcije nisu službeno dokumentirane.

Pelles C

Pelles C je program bez softvera i najmoćniji C prevodilac i integrirani razvojni mehanizam (IDE) za programiranje na jeziku C. Podržava 32-bitni Windows (x86) i 64-bitni Windows (x64). Implementira standarde C99 i C11. Pelles može uključivati ​​uređivač resursa, bitmap sliku, ikonu, uređivač kursora i uređivač šesnaest ispisa. Otkrio švedski trgovac na malo Pelle Orinius. Naziv sastavljača nosi ime svog autora. Uključeno u SDK, programer može odmah ispisati kreirani program bez daljnje instalacije.

Svrhovita arhitektura

Za izradu Windows API programa morate omogućiti Microsoftova proširenja. Iza toga stoji smrad, u vezi s kojim kompajler vidi poruku o pogrešci, kao da se radi o C WinAPI aplikaciji s pokvarenom strukturom: fatalna greška #1014: #greška: “Nema ciljne arhitekture.” Da biste omogućili Microsoftovo proširenje, idite na parametre projekta i odaberite karticu "Compiler". Na ovoj kartici je aktivirana opcija "Onemogući Microsoftova proširenja".

MSDN

Ovo je središnji portal za instalaciju Windowsa. Ovo je sjajna zbirka materijala vezanih uz razvoj programa iz raznih Microsoftovih alata. Sveobuhvatna baza podataka s dokumentacijom iz razvoja desktop aplikacija i popisom Windows API-ja.

Zastosuvannya DLL u WinAPI C

Biblioteka naprednih elemenata omogućit će pristup naprednim funkcijama operativnog sustava, kao što su redovi, indikatori prozora, alatne trake i kartice. Ove se naredbe nalaze u biblioteci commctrl.dll u 16-bitnim sustavima i comctl32.dll i grupirane su sa sučeljem klijenta.

DLL je dinamički format datoteke biblioteke koji se koristi za spremanje nekoliko kodova i procedura za Windows programe. DLL datoteke stvorene su na takav način da brojni programi mogu trenutačno pristupiti njihovim informacijama, čime se štedi memorija. Korisnicima omogućuje uređivanje koda u više programa bez njihovog mijenjanja. DLL biblioteke mogu se pretvoriti u statičke, koristeći MSIL Disassembler ili DLL za Lib 3.00.

Winapi Yak INTERFAS primijenjenog testa za Windows Proponovi obrazaca poplave, Yaki dopuštaju pohranjivanje njihovih znakova, jasno je da je to jednostavno uključivanje datoteka u zatvorenike grafičkih interfija za postupke Nizorivniye pogona.

Prije nego počnete programirati s WinAPI-jem, trebate postaviti sredinu za kod u sustavu Windows. Iako nije distribucija Linuxa, nema ugrađen kompajler za izradu dodataka. Pogledajmo sljedeće opcije za kompajliranje koda:


Za Windows je dostupan komplet za razvojne programere koji pruža dokumentaciju i alate koji programerima omogućuju stvaranje softvera s Wikimedia API-jem i povezanim tehnologijama.

Windows API - skup funkcija operacijskog sustava

Skraćenica API-ja mnogim se programerima početnicima čini nejasnom i zbunjujućom. Zapravo, Application Programming Interface (API) samo je gotov skup funkcija koje mogu koristiti dobavljači dodataka. U formalnom smislu, ovaj koncept je ekvivalentan onome što se ranije često nazivalo knjižnicom potprograma. Međutim, imajte na umu da pod API-jem postoji posebna kategorija takvih knjižnica.

Tijekom procesa razvoja krajnjem korisniku se formira skup specifičnih internih funkcija, potrebnih za implementaciju određenog programa, koji se naziva MyApplication API. Međutim, često se otkrije da se te funkcije mogu učinkovito koristiti za stvaranje drugih programa, uključujući druge programe. Na koji način autori, temeljem strategije prodaje svog proizvoda, biraju prehranu: zašto dopuštaju pristup kojem setu vanjskim kupcima? Ako se potvrdi, opis softverskog paketa kao pozitivna karakteristika uključuje izraz: "Paket uključuje opsežan skup API funkcija" (ili za dodatni novac).

Dakle, najčešće pod API-jem postoji skup funkcija koje su dio jednog programa, ali koje su dostupne za korištenje u drugim programima. Primjerice, Excel, osim sučelja za krajnjeg korisnika, ima skup Excel API funkcija kojima se može pristupiti npr. programima izrađenim pomoću VB-a.

Očigledno, Windows API je skup funkcija koji je dio samog operativnog sustava, au isto vrijeme je dostupan bilo kojem drugom programu, uključujući i onaj napisan pomoću VB-a. Ovaj plan je potpuno analogan skupu sistemskih BIOS/DOS nadjačavanja, što je zapravo DOS API.

Prednost funkcionalnosti Windows API-ja, s jedne strane, mnogo je šira od one DOS-a, s druge strane, ne uključuje mnogo mogućnosti za izravnu kontrolu računalnih resursa dostupnih programima na bivšem OS-u. Osim toga, veza s Windows API-jem temelji se na dodatnim proceduralnim parametrima, a DOS funkciji se pristupa putem posebne naredbe procesorskog stroja pod nazivom Interrupt.

Najpotrebniji Win API za VB programere

Bez obzira na to što VB nema raznolike funkcije, u procesu koliko-toliko ozbiljnog razvoja otkriva se da njihove mogućnosti često nisu dostatne za obavljanje potrebnih zadataka. U ovom slučaju programeri početnici često počinju štedjeti na nedostacima VB-a i razmišljaju o promjeni alata, ne sumnjajući da njihovo računalo ima veliki skup troškova i da ih treba brzo unijeti.

Kada se upoznate s Win API-jem, ispada da postoji puno korištenih VB funkcija koje nisu ništa drugo nego proširene na specifične procedure sustava, već samo implementirane prema sintaksi ovog jezika. Na temelju potrebe za brzim API-jem, dostupne opcije su:

  1. API funkcije koje su općenito implementirane u obliku VB funkcija. Vrijeme nije manje, u kojem slučaju će možda biti potrebno prijeći na stagnaciju API-ja, tako da vam omogućuje brzo povećanje produktivnosti (osim nepostojanja nepotrebnih promjena u parametrima koji se prenose).
  2. Kreirane VB funkcije implementirane su samo kao dio API funkcija. Evo jednostavnije opcije. Na primjer, CreateDirectory API funkcija ima veće mogućnosti u usporedbi s VB MkDir operatorom.
  3. Postoji veliki broj API funkcija koje nemaju analoge u trenutnoj verziji VB jezika. Na primjer, nije moguće izbrisati imenik pomoću VB - za to morate koristiti funkciju DeleteDirectory.

Također treba napomenuti da se određenim API funkcijama (neke od njih u Win API-ju su čak i beznačajne) ne može pristupiti iz VB programa kroz brojna jezična sučelja, na primjer, zbog nedostatka mogućnosti rada s memorijskim adresama. Međutim, u brojnim slučajevima mogu pomoći netrivijalne tehnike programiranja (u slučaju istih adresa).

Autorova posebna ideja je da umjesto proširenja verzije na verziju funkcija koje koristi VB, sljedeće bi dalo dobar opis najčešćih API funkcija. U isto vrijeme, želio bih zamoliti programere da ne čekaju pojavu nove verzije značajke s proširenim funkcijama, već da uzmu u obzir zalihu izvornog Win API-ja - potpuno je jasno da mogućnosti koje potreba mogla se implementirati već u verziji í̈ VB 1.0 izdanje 1991.

Yak vivchati Win API

Nije tako lako zapamtiti da se broj funkcija Win32 API-ja procjenjuje na oko 10 tisuća (nitko ne zna točnu brojku, kao Microsoft).

VB skladište (verzije 4-6) uključuje datoteku s opisom Win API-ja - WIN32API.TXT (izvješće o njegovoj implementaciji bit će naknadno objavljeno). Prije svega, uz ovu pomoć možete vidjeti informacije o značenju ove i drugih funkcija i parametara osim sljedećih mnemoničkih naziva, drugim riječima, funkcija ove datoteke je daleko od iste. U današnje vrijeme (srećom), VB 3.0 ima posebne datoteke s dokazima koncepta koje opisuju Win16 API funkcije. U verziji 4.0 ove su vrijedne informacije već dostupne putem ručnog sučelja.

Dodatne informacije o Win32 API-ju mogu se pronaći u prethodnom Platform Software Development Kitu, koji je također dostupan na CD-ovima MSDN Library uključenim u VB 5.0, 6.0 Enterprise Edition i Office 2000 Developer Edition. Međutim, pronaći potrebne informacije i pristupiti njima nije nimalo jednostavno. Čak ni ne spominjući da je sve tamošnje opise u potpunosti napravio C.

U svijetu najpoznatiji uvod u API programiranje u VB okruženjima je knjiga renomiranog američkog stručnjaka Daniela Applemana. Ova serija Vodiča za Visual Basic Programmer's Guide to Windows API (za Win16, Win32, stotine različitih verzija VB-a) Dana Applemana od 1993. dosljedno je postala bestseler za VB programere. Knjigu Dan Appleman's VB 5.0 Programmer's Guide to the Win32 API, objavljenu 1997., autoru je iz SAD-a donio prijatelj koji je znao za prvu knjižaru malog provincijskog grada.

Ova knjiga, s preko 1500 stranica, uključuje opis naprednih tehnika za programiranje API-ja u VB-u, kao i više od 900 funkcija. CD će sadržavati cijeli tekst knjige i sve softverske aplikacije, kao i brojne dodatne dijelove koji nisu stigli u drugu verziju. Godine 1999. Dan Appleman izdao je novu knjigu, Dan Appleman's Win32 API Puzzle Book and Tutorial for Visual Basic Programmers, koja uključuje preglede još 7600 funkcija (iako ne izvještajne ploče).

Win API i biblioteka dinamičkih veza (DLL)

Skup Win API implementacija kao dinamičkih DLL biblioteka. Zatim ćemo zapravo govoriti o tehnologiji instaliranja DLL-ova u sredini VB-a u aplikaciji biblioteka koje su uključene u Win API skladište. Međutim, kada govorimo o DLL-ovima, potrebno je zaslužiti puno poštovanja.

U ovom slučaju, pod DLL-om, možemo poštivati ​​tradicionalnu verziju dvostrukih dinamičkih biblioteka, koja osigurava izravnu konverziju u potrebne procedure - potprograme ili funkcije (otprilike isto što se očekuje kada se klikne na procedure usred VB projekta) . Takve biblioteke mogu se stvoriti pomoću drugih alata: VC++, Delphi, Fortran i VB (ovisno o tome što se pojavljuje u verziji 7.0) - ostalo može raditi bez ActiveX DLL-a, kojem se pristup konfigurira preko sučelja s OLE automatizacijom.

Datoteke dinamičke biblioteke mogu sadržavati ekstenziju.DLL, ali to nije nužno slučaj (za Win16 ekstenziju.EXE je često zaglavljena); Upravljački programi vanjskih uređaja navedeni su pod dodatnim DRV-om.

Kao što smo već spomenuli, važno je odrediti točan broj Windows API funkcija i datoteka kako bi se one mogle pohraniti u katalog sustava. Ovaj bi plan bolje sagledao skladište knjižnica koje ide do jezgre operativnog sustava i glavne knjižnice s ključnim dodatnim funkcijama.

I sad sam sretna.

Molimo 1. Slijedite ispravno oblikovanje DL najave L-postupci

Hijerarhija programa do DLL procedura izgleda isto kao i do "primarnih" Visual Basic procedura, na primjer:

Poziv DllName ([popis argumenata])

Međutim, za korištenje vanjskih DLL funkcija (uključujući Win API), program ih mora pozvati pomoću naredbe Declare, koja izgleda ovako:

Deklarirajte naziv potprocedure Lib _ “Naziv biblioteke” _ [([Popis argumenata])]

Deklarirajte naziv funkcije funkcije _ Lib “Naziv biblioteke” _ [([Popis argumenata])]

Ovdje su na kvadratnim krakovima naznačeni potrebni elementi operatora, riječi koje se izmjenjuju prikazane su kurzivom, a ključne riječi kurzivom. Napredni sustav dizajniran je kako bi pružio dobar opis sintakse operatora, što određene točke čini manje važnima.

Većina vanjskih funkcija nalazi se u odjeljku Opće deklaracije modula. Ako ga postavite u modul obrasca, morate navesti ključnu riječ Private (ovo će biti dostupno samo u sredini modula) - to je isto za sve postupke modula obrasca.

Skup Win32 API implementacija ograničen je na funkcije (Win16 API je imao mnogo podprograma). To posebno vrijedi za funkcije tipa Long, koje najčešće vraćaju kod završetka operacije.

Operator Declare pojavio se u MS Basicu već za DOS i koristio se za komuniciranje internih procedura u projektu. Visual Basic to ne treba, budući da deklaracije internih procedura automatski opisuju njihove opise pod i funkcija. Prilagođen iz Basic/DOS-a, novi opis mora navesti naziv datoteke biblioteke u kojoj se nalazi procedura. Wip API biblioteke nalaze se u direktoriju sustava Windows; sve što je potrebno je naziv datoteke. Ako radite na DLL-u, morat ćete napisati novu stazu do te datoteke kako biste bili sigurni.

Opis operatora Declare zauzima puno prostora i ne stane u jedan red blizu prozora koda. Stoga preporučujemo da prilikom pisanja programa obratite pozornost na bilo koju vrstu sheme prijenosa redaka, na primjer:

Deklarirajte funkciju GetTempPath _ Lib “kernel32” Alias ​​​​​​“GetTempPathA” _ (ByVal nBufferLength As Long, _ ByVal lpBuffer As String) As Long

I ovdje su opisani svi glavni elementi opisa različitih redaka i dobro ih je pročitati.

Molimo 2. Budite posebno puni poštovanja kada radite s DLL funkcijama

Korištenje Win API-ja i raznih DLL funkcija značajno proširuje funkcionalne mogućnosti VB-a i, najčešće, omogućuje vam povećanje produktivnosti programa. Međutim, cijena koju treba platiti za tu cijenu je smanjenje pouzdanosti robotskih programa, posebno tijekom procesa razvoja.

Jedna od najvažnijih prednosti VB međuprograma je pouzdanost procesa razvoja programa: radeći pod okvirom tumača, programski kod je teoretski nemoguće razbiti Windows i VB robota. Programer možda neće biti jako pažljiv oko ispravnosti prosljeđivanja parametara u funkciju koja se poziva - takve će pogreške lako otkriti sam tumač, bilo tijekom procesa prevođenja koda, ili tijekom njegovog izvođenja. U najgorem slučaju jednostavno će doći do prekida u režimu obrade, kako u smislu, tako i u smislu gdje i što se dogodilo.

Korištenje izravnih funkcija Windows API-ja ili drugih DLL biblioteka preuzima takvu kontrolu nad prijenosom podataka i procesom ulančavanja u kod izvan VB sredine. Stoga, kompromis u vanjskim funkcijama može dovesti do kvara i VB-a i operativnog sustava. Ovo je osobito važno u fazi razvoja programa, ako je prisutnost prednosti potpuno prirodna. Dakle, zbog širokog spektra funkcija osnovnog sustava, programer preuzima odgovornost za ispravnost njihove implementacije.

Problem je dodatno kompliciran činjenicom da različiti programi imaju različite načine prosljeđivanja parametara između procedura. (Točnije, različite metode prijenosa su predmet rasprave, budući da mnogi od nas mogu podržati nekoliko metoda.) Win API je implementiran u C/C++ i moramo razgovarati o prijenosu parametara prihvaćenih u ovom sustavu, kao što su Are isključeno iz standardne VB opcije.

U vezi s tim, valja napomenuti da je pojava VB analoga API funkcija opravdana prilagodbom preostalih VB sintaksi i implementacijom sličnog mehanizma za kontrolu razmjene podataka. Također cijenimo da je u fazi konačnog razvoja programa prilikom izgradnje modula koji se kompajlira bolje odabrati opciju kompilacije P-code umjesto Native Code (strojni kod). U početku program radi pod kontrolom tumača - radije nego korištenjem strojnog koda, ali po mogućnosti gledajući operativni sustav i osiguravajući ručni način rada za prepoznavanje mogućih grešaka.

Porada 3. Deset preporuka Dana Applemana za pouzdano API programiranje u VB međuprogramu

Razne funkcije API-ja zahtijevaju pažljivije programiranje uz korištenje nekih ne tako osnovnih metoda skaliranja procedura (nasuprot VB-u). U budućnosti ćemo postupno izgladnjivati ​​ovu hranu. A sada ćemo predstaviti sažetak rasprava Dana Applemana o ovoj temi (prva verzija pojavila se još 1993.) s nekim našim dodatnim komentarima.

1. Zapamtite ByVal. Najčešći problem koji se javlja kada se API i DLL implementiraju prije funkcija leži u neispravnom rječniku ključne riječi ByVal: ili je zaborave staviti ili je na kraju stave kada za njom nema potrebe.

Ovi primjeri pokazuju unos operatora ByVal za prijenos parametara

Vrsta parametra Z ByVal Bez ByVal-a
Cijeli broj Stog ima 16-bitni kapacitet Stog može primiti 32-bitne adrese 16-bitnog cijelog broja
dugo Stog ima 32-bitni kapacitet Stog može primiti 32-bitne adrese 32-bitnog cijelog broja
Niz Niz se pretvara u format koji se koristi u C-u (s obzirom na nulti bajt na kraju). 32-bitne adrese novog retka stavljaju se na stog Stog sadrži VB deskriptor retka. (Sam Windows API nikada ne prepoznaje takve deskriptore i prepoznaju se samo u DLL-ovima implementiranim posebno za VB.)

Ovdje je vrijedno spomenuti da je prijenos parametara u bilo kojem programskom sustavu, uključujući VB, određen s dva glavna koraka: slanjem (ByRef) ili vrijednosti (ByVal). Prva opcija prima adresu razmjene (ova opcija se koristi u VB za razmjenu), druga prima svoju vrijednost. Načelo valjanosti leži u činjenici da se nakon dodatne poruke osigurava da se program koji poziva vrati na promijenjenu vrijednost proslijeđenog parametra.

Za početak provedite eksperiment pomoću sljedećih programa:

Dim v As Integer v = 2 Call MyProc(v) MsgBox “v = “ & v Sub MyProc (v As Integer) v = v + 1 End Sub

Nakon pokretanja ove aplikacije, vidjet ćete informacije o vrijednostima varijable jednake 3. S desne strane, u ovom slučaju, adrese varijable v, fizički stvorene programom koji klikne, prenose se u potprogram MyProc . Sada promijenite opis postupka u

Sub MyProc (ByVal v As Integer)

Kao rezultat toga, kada pokrenete test, uklanjate v = 2, što znači da se izlazna vrijednost varijable prosljeđuje proceduri - rezultat operacija koje se izvode na njoj ne vraća se programu koji poziva. Način prijenosa vrijednosti također se može promijeniti uz pomoć Pozivnog operatera na sljedeći način:

Sub MyProc (v Kao cijeli broj) ... Poziv MyProc ((v)) '(v) - krakovi pokazuju način prijenosa _ iza vrijednosti.

Međutim, kada se proširuje na interne VB-postupke, upotreba ključne riječi ByVal u Call izjavi je potisnuta - umjesto toga, okrugli krakovi su blokirani. Evo objašnjenja.

U klasičnoj verziji (C, Fortran, Pascal), važnost načina rada ByRef i ByVal ovisi o tome što se nalazi na stogu za razmjenu podataka - adrese ili vrijednosti za razmjenu. U Basicu se povijesno koristila ByVal verzija softverske emulacije - stog uvijek sadrži adrese, osim kada se prosljeđuju vrijednosti za koje se stvara promjena vremena. Kako bismo razlikovali dvije opcije (Classic i Basic), postoje različiti načini za opisivanje načina ByVal. Važno je da emulacija načina rada ByVal u VB-u osigurava veću pouzdanost programa: pomiješanjem oblika pretvorbe, program riskira da program na koji se klikne liši rotiranja (ili nerotiranja) ispravljanjem vrijednosti promijeniti. U "klasičnoj" verziji, takva zabuna može dovesti do fatalne smrti unutar sat vremena od postupka finalizacije (na primjer, ako umjesto memorijske adrese korisnika postoje vrijednosti koje se mogu mijenjati, jednake, recimo, nuli ).

DLL funkcije implementirane su prema “klasičnim” načelima i stoga zahtijevaju jasan opis načina na koji se podaci razmjenjuju sa svakim argumentom. Ovo samo po sebi može poslužiti kao funkcija deklariranja kroz opis Declare (točnije, popis argumenata koji se prosljeđuju). Najčešće se prosljeđivanje parametara Windows API funkciji ili DLL-u navodi pomoću ključne riječi ByVal. Štoviše, može se navesti ili u operatoru Declare ili izravno prilikom pozivanja funkcije.

Nasljeđe netočnog prijenosa parametara lako je prenijeti. Ako odaberete očito nevažeću adresu, vidjet ćete obavijest o GPF (general Protection Fault). Budući da funkcija dohvaća vrijednosti koje izmiču valjanoj adresi, API funkcija ulazi u strano područje (na primjer, u jezgru sustava Windows) sa svim vrstama katastrofalnih posljedica koje rezultiraju.

2. Promijenite vrstu parametara koji se prenose. Jednako je važan točan broj i vrsta parametara koji se prosljeđuju. Potrebno je da argumenti deklarirani u Declare odgovaraju parametrima API funkcije. Najveći problem s prosljeđivanjem parametara vezan je uz razliku između NULL i niza nula - traga memorije, što je jedno te isto.

3. Provjerite vrstu vrijednosti koja se rotira.

VB je tolerantan prema postavljanju raznolikosti tipova vrijednosti koje rotira funkcija, a neke numeričke vrijednosti se rotiraju kroz registre, a ne kroz stog. Sljedeća pravila pomoći će vam da odredite ispravne vrijednosti koje vraća API funkcija:

  • DLL funkcija koja ne rotira vrijednosti (analogno void u 'C') može biti zaglupljena kao VB Sub.
  • API funkcija koja rotira vrijednost (Integer ili Long), može se označiti ili kao Sub ili kao funkcija koja rotira vrijednosti određene vrste.
  • Ova API funkcija ne rotira brojeve s pomičnim zarezom, ali DLL-ovi mogu rotirati ovu vrstu podataka.

4. S velikom pažnjom koristite konstrukciju As Any. Mnoge Windows API funkcije imaju mogućnost prihvaćanja parametara različitih tipova i njihovog korištenja na temelju konstrukcije As Any (tumačenje tipa ovisi o značenju drugih parametara koji se prosljeđuju).

Dobra rješenja mogu imati više funkcija pseudonima (Alias) između dva ili više njih koji dijele iste funkcije, a parametri su naznačeni u svakoj vrsti pjevanja opisa.

5. Ne zaboravite inicijalizirati retke. Win API ima jednostavnu funkciju koja rotira informacije prikupljanjem podataka iz međuspremnika redaka koji se prosljeđuju kao parametar. U svom programu možete učiniti sve ispravno: ne zaboravite na ByVal, ispravno proslijedite parametre funkciji. Ali Windows ne može vjerovati kolika je veličina prostora za pohranu koji se vidi. Veličina retka mora biti dovoljna da primi sve podatke koji se u njega mogu smjestiti. Odgovornost za rezerviranje međuspremnika potrebne veličine leži na VB programeru.

Imajte na umu da je u 32-bitnim Windowsima, s različitim redovima, moguće pretvoriti Unicode (dvobajtno kodiranje) u ANSI (jednobajtno kodiranje) i natrag, ovisno o postavkama nacionalnog sustava. Stoga je za rezerviranje međuspremnika često sigurnije koristiti nizove bajtova umjesto uobičajenih. (Izvješće o tome bit će raspravljeno u nastavku.)

Većina Win API funkcija omogućuje vam da sami postavite maksimalnu veličinu bloka. Na primjer, morate pozvati drugu API funkciju da biste označili veličinu bloka. Na primjer, GetWindowTextLength omogućuje određivanje veličine retka potrebnog za postavljanje naslova prozora koji sadrži funkcija GetWindowText. Iz tog razloga Windows jamči da nećete prijeći granicu.

6. Opcija Vikorize Eksplicitna na oba jezika.

7. Pažljivo provjerite vrijednosti parametara i vrijednosti koje se rotiraju. VB ima potencijal za provjeru tipova. To znači da ako pokušate prenijeti netočan parametar VB funkciji, najgore što se može dogoditi je da odbijete poruku o pogrešci od VB. Nažalost, ovaj mehanizam ne radi kada se nadogradi na Windows API funkciju.

Windows 9x ima sofisticirani sustav za provjeru parametara za većinu API funkcija. Dakle, prisutnost oprosta u ovim podacima ne znači kobnu ispravku, ali nije tako jednostavno utvrditi što ju je uzrokovalo.

Ovdje možete pronaći nekoliko načina za poboljšanje ove vrste mlijeka:

  • Provjerite način podešavanja kože ili Debug.Print da provjerite reakciju kože API funkcije. Pregledajte rezultate ovih klikova kako biste bili sigurni da je sve unutar normalnih granica i da je funkcija ispravno dovršena;
  • Vikorist programer temeljen na sustavu Windows kao što je CodeView i prilagođena verzija sustava Windows (iz Windows SDK-a). Ove funkcije mogu otkriti modifikaciju parametara i što je najvažnije odrediti koju API funkciju treba modificirati;
  • Provjerite dodatne značajke tvrtki trećih strana kako biste provjerili vrste parametara i prihvatljivost njihovih vrijednosti. Takve metode ne samo da mogu pronaći promjene parametara, već i reći VB kodu gdje je promjena napravljena.

Osim toga, potrebno je pažljivo provjeriti rezultat API funkcije.

8. Zapamtite da brojevi u VB i Windowsima nisu isti. Prvo se prisjetimo da pojam “Integer” u VB-u znači 16-bitni broj, dok u Win 32 dokumentaciji znači 32-bitni broj. Na drugi način, cijeli brojevi (Integer i Long) u VB nisu vrijednosti bez znaka (jedna znamenka se koristi kao znak, druga kao mantisa broja), u sustavu Windows - koriste se čak i nepoznati brojevi. Ovu situaciju treba uzeti u obzir ako oblikujete parametar pomoću dodatnih aritmetičkih operacija (na primjer, izračunavanje adrese pomoću dodatne zamjene baze i pomaka). Za koje standardne VB aritmetičke funkcije nisu prikladne. Zašto se bojite ove situacije, razgovarajmo o tome.

9. Budite oprezni s nazivima funkcija. U Win16, nazivi svih Win32 API funkcija osjetljivi su na točnu varijaciju sporednih i velikih slova (Win16 to nije imao). Ako stavljate malog pisca umjesto velikog, tada se tražena funkcija neće pronaći. Također slijedite točan sufiks A ili W u funkcijama za postavljanje parametara retka. (Izvješće o ovome – div. u nastavku.)

10. Spremajte rezultate svog rada što je češće moguće. Kvarovi povezani s neispravnim DLL i Win API skriptama mogu dovesti do pada VB međuprograma, a možda i cijelog operativnog sustava. Obratite pažnju na to da je vaš kod spremljen prije probnog rada. Najjednostavnije je postaviti način za automatsko pisanje modula u projekt prije pokretanja projekta u VB okruženju.

Nakon čitanja prethodnog, možda će vas iznenaditi činjenica da je Win API funkcija uklonjena s desne strane. Usput, to je točno, ali samo u skladu sa sigurnim programiranjem koje sam VB pruža. Međutim, u slučaju blage stagnacije i poznatih mogućih zamki, ovaj rizik je minimalan. Osim toga, često je jednostavno nemoguće nositi se sa stagnacijom Win API-ja - i dalje će biti potreban u slučaju ozbiljnog razvoja.

Prije toga, prethodno smo razmišljali o "podvodnom" kamenju za široku klasu DLL-ova. S Win API-jem sve je puno jednostavnije jer je oblik implementacije ovih funkcija jasno unificiran. Evo glavnih točaka koje treba uzeti u obzir majčino poštovanje:

  1. Funkcije Win32 API-ja su funkcije, odnosno procedure tipa Function (Win16 API je imao puno podprograma). Sve funkcije su tipa Long, pa su njihovi opisi napisani u ovom obliku: Declare Function name ... As Long 'tip funkcije _ naznačen je u eksplicitnom obliku

    Naziv deklaracije funkcije& 'tip funkcije _ označen je dodatnim sufiksom

    Pretvorba u API funkciju izgleda ovako:

Rezultat& = ImeApi& ([ Popis argumenata]
  1. Najvažnija funkcija koja se rotira je kod završetka operacije. Štoviše, vrijednost različita od nule znači normalan završetak, dok vrijednost nula znači izvršenje. Još jednom (ili ne prije), možete razjasniti prirodu izmjene pomoću funkcije GetLastError. Opis ove funkcije izgleda ovako: Declare Function GetLastError& Lib “kernel32” ()

    UVAGA! Kada radite u sredini VB-a, za uklanjanje vrijednosti pročišćenog koda, bolje je koristiti objekt LastDLLError Err, budući da VB također resetira funkciju GetLastError između ažuriranja API-ja i nastavka izvršavanja programa.

    Možete interpretirati kod koji generira GelLastError pomoću dodatnih konstanti zapisanih u datoteci API32.TXT, s nazivima koji počinju sufiksom ERROR_.

    Najčešći tipovi napada su sljedeći kodovi:

    • ERROR_INVALID_HANDLE = 6& - netočna oznaka
    • ERROR_CALL_NOT_IMPLEMENTED = 120& - poziv za Windows 9x funkcije dostupne samo za Windows NT
    • ERROR_INVALID_PARAMETER = 87& - netočna vrijednost parametra

    Međutim, postoji mnogo funkcija za rotiranje vrijednosti određenog parametra (na primjer, OpenFile rotira vrijednosti opisa datoteke). U ovom slučaju, vrijednost se dodjeljuje nekim drugim posebnim Return& vrijednostima, najčešće 0 -1.

  2. Win32 API ima strogo fiksne metode za prijenos najjednostavnijih vrsta podataka. a) ByVal...As Long

    Najmanje 80% prosljeđivanja argumenata obavlja se s dugom vrstom. Revidirajte argument kao prvo prati ključna riječ ByVal, a to, između ostalog, znači da je povezan jednosmjerni prijenos podataka - od VB programa do API funkcije.

    B) ByVal...Kao niz

    Ova vrsta prijenosa također ima tendenciju da se događa često, i s istim argumentom kao prvo ByVal zapne. Kada se pozove API funkcija, adrese redaka se zapisuju u stog, što omogućuje dvosmjernu razmjenu podataka. Kod rada u redovima potrebno je voditi računa o nekim problemima.

    Prvo, rezervaciju memorije za retke provodi program koji poziva, pa ako će API funkcija pohranjivati ​​retke, tada je prije poziva potrebno kreirati red potrebne veličine. Na primjer, funkcija GetWindowsDirectory rotira stazu do Windows direktorija, koji ne mora imati više od 144 znaka. Očigledno, implementacija ove funkcije može izgledati otprilike ovako:

    WinPath$ = Space$(144) ' rezervirani red u _ 144 znaka Result& = GetWindowsDirectory& (WinTath$, 144) _ ' buffer filling ' Result& - stvarni broj znakova u imenu _ direktorija WinPath$ = Left$(WinPath, Result&)

    Drugi problem leži u činjenici da kada se API funkcija pretvori u API funkciju, izlazni red se ponovno kreira na svom internom zaslonu, a kada se izađe iz funkcije, to se događa na isti način. Kao što je u ranim danima Win16 ova operacija trajala manje od dodavanja nultog bajta, na primjer, retka, tada je s pojavom Win32 transformacija dvobajtnog Unicode kodiranja u ANSI i za isto vrijeme bila postignuto. (O tome je izvješteno u članku “Značajke robota s promjenama reda u VB”, Computer Press 10'99 i 01'2000). Značajno je samo da je uz pomoć ByVal... Kao String konstrukcije moguće razmjenjivati ​​redove simboličkih podataka.

    B) ...Kao i bilo koji

    To znači da će vrijednost adrese memorijskog međuspremnika biti smještena na stog, a interpretacija umjesto onoga što će API funkcija obraditi, na primjer, neovisna je o značenju drugih argumenata. Međutim, As Any može se koristiti samo u operatoru Declare - kada se primjenjuje određena funkcija, argumentu se može dodijeliti određena vrijednost.

    D) ... Kao UserDefinedType

    Takva struktura također često zapne kada je potrebno razmijeniti podatke (obećanje prekršitelja) radi neke druge strukture. Zapravo, ovaj dizajn je jednostavna vrsta specifične implementacije oblika prijenosa As Any, samo što svaka funkcija ima fiksnu strukturu.

    Forma strukture podataka određena je specifičnom API funkcijom, a odgovornost je programa da ih ispravno opiše i rezervira istim programom. Ovo je dizajn kao prvo korisnik bez riječi ByVal, tada se prijenos nakon slanja dodaje u ovaj okvir - adresa razmjene se upisuje u stog.

Dotaknite se API funkcije

To je ilustrirano na primjeru dvije osnovne funkcije rada s datotekama - lopen i lread, koje su opisane na sljedeći način:

Deklarirajte funkciju lopen Lib "kernel32" _ Alias ​​​​"_lopen" (_ ByVal lpFileName As String, _ ByVal wReadWrite As Long) Dugo Deklarirajte funkciju lread Lib "kernel32" _ Alias ​​​​"_lread" (_ ByVal hFile As Long, lpBuff _ ByVal wBytes As Long) Kao dugo

U VB-u, njihovi analozi - ponekad precizniji - su operatori Open i Get (za binarni način). Vrlo smo impresionirani korištenjem ključne riječi Alias ​​u praznoj funkciji - to je isti problem, ako ne možete bez nje. Nazivi ovih funkcija u biblioteci počinju simbolom ispod stolca (tipičan stil za film C), što VB ne dopušta.

Operacija otvaranja datoteke može izgledati ovako:

Const INVALID_HANDLE_VALUE = -1 ' nevažeći _ opis vrijednosti lpFileName$ = “D:\calc.bas” ' naziv datoteke wReadWrite& = 2 ' način čitanja i pisanja hFile& = lopen(lpFileName$, wReadWrite&) _ ' valued = INVALID_HANDLE_ VALUE Then _ ' popravi datoteku ' navedite kod popravka CodeError& = Err.LastDllError 'CodeError& = GetLastError _ ' ova konstrukcija ne radi End If

Ovdje moramo naglasiti dvije točke:

  • Kao vrijednost funkcije određujemo vrijednost opisa datoteke. Vrijednost potvrđuje vrijednost -1;
  • U ovom slučaju nije potrebno ići na funkciju GetLastError - da bismo dohvatili navedenu vrijednost pogreške, otišli smo na objekt Err (više smo razgovarali o mogućnosti takve situacije).

Tada možete čitati umjesto datoteke, ali također govori da je program odgovoran za prepoznavanje njezine strukture (kao što je slučaj kod rada s više dvostrukih datoteka). U ovom slučaju, opis funkcije lread može izgledati ovako:

Dim MyVar As Single wBytes = lread (hFile&, MyVar, Len(MyVar) ' čitanje govornog broja, 4 bajta ' wBytes - broj stvarno pročitanih podataka, '-1 - paritet... Tip MyStruct x As Single i Kao Integer End Type Dim MyVar As MyStruct wBytes = lread (hFile&, MyVar, Len(MyVar)) ' čitanje strukture podataka, 6 bajtova

Još jednom pokažite poštovanje: drugi argument funkcije prosljeđuje se pošiljateljima i povratku na vrijednosti.

Dim MyVar As String MyVar = Space$(10) ' rezervni prostor za 10 znakova wBytes = lread (hFile&, ByVal MyVar, Len(MyVar)) ' čitanje znakovnog niza, 10 znakova

Ovdje možete vidjeti važnost prethodno uvedenog stražnjice - promjenu reda nužno prati ključna riječ ByVal.

Čitanje umjesto datoteke u nizu (radi jednostavnosti, koristit ćemo niz od jednog bajta) sastavlja se ovako:

Dim MyArray(1 To 10) As Byte wBytes = lread (hFile&, MyArray(1), _ Len(MyArray(1))* 10) ‘ pročitaj 10 elemenata iz niza

Navodeći prvi element niza kao argument, prosljeđujemo adresu glave memorijskog područja rezerviranog za niz. Očito, možete pohraniti bilo koji fragment niza pomoću ove metode:

WBytes = lread (hFile&, MyArray(4), _ Len(MyArray(1))* 5) čitanje elemenata niza od 4. do 8.

Porada 5. Vickory Alias ​​​​za prijenos Postavke kao i sve

Ovdje, na temelju prednjeg kundka, otkrivamo bit četvrtog za dobrobit Dana Applemana.

Kada radite s funkcijom lread, važno je zapamtiti da je prilikom pokretanja obične varijable prije nje potrebno koristiti ključnu riječ ByVal (inače se informacije o ilegalnoj operaciji neće izgubiti). Radi sigurnosti, možete stvoriti dodatni poseban opis ove funkcije za rad samo s uobičajenim promjenama:

Deklarirajte funkciju lreadString Lib “kernel32” _ Alias ​​​​​​“_lread” (_ ByVal hFile As Long, ByVal lpBuffer As String, _ ByVal wBytes As Long) Sve dok

Kada radite s ovim opisom, više nije potrebno označavati ByVal prilikom ispisa:

WBytes = lreadString(hFile&, MyVarString, _ Len(MyVarString)) ‘

Čini se da vam sintaksa operatora Declare omogućuje stvaranje takvog posebnog opisa za niz:

Deklarirajte funkciju lreadString Lib “kernel32” Alias ​​​​“_lread” (_ ByVal hFile As Long, lpBuffer() As Byte, _ ByVal wBytes As Long) Kao Long

Štiti životinju

WBytes = lreadArray(hFile&, MyArray(), 10)

neizbježno dovesti do kobnog izvršenja programa.

Ovo je nastavak rasprave o osobitostima obrade promjena redaka Visual Basic: VB koristi dvobajtno Unicode kodiranje, Win API - jednobajtni ANSI (i s formatom prihvaćenim u C - s nultim bajtom na kraju). Očito je da se kod promjene reda kao argumenta konverzija iz Unicodea u ANSI automatski provodi kada pozovete API funkciju (točnije, DLL funkciju), a konverzija se provodi kada se okrene.

Suština je ovdje jednostavna: možete razmjenjivati ​​simboličke podatke uz pomoć varijabilnih nizova, ali se oni ne mogu koristiti za razmjenu dovoljno dvostrukih informacija (kao što je bio slučaj pri radu sa 16-bitnim verzijama VB-a). Bolje je koristiti jednodimenzionalni niz bajtova.

Očigledno se tip String može koristiti za opisivanje strukture strukture. Veza s ovim sjećanjem je sljedeća:

  • Kategorički nije moguće koristiti sljedeću konstrukciju za razvoj Win API-ja: Type MyStruct x As Single s As String

    U redoslijedu izmjene, deskriptor reda se prosljeđuje zajedno sa svim nasljeđivanjima u izgledu programa.

  • Moguće je kao strukturni element reda fiksnog udvostručenja: Type MyStruct x As Single s As String*8 ' red fiksnog udvostručavanja End Type

U tom slučaju svakako ponovno izradite kôd.

I poštovanje ostaje: nije moguće konsolidirati niz promjena redaka (i fiksnih i promjenjivih) kada se nadogradi na API funkciju u isto vrijeme. Inače će biti zajamčena pojava "ilegalne operacije".

Posve je jasno da ste u lošoj situaciji ako trebate napisati DLL funkciju u svoju knjižnicu. Potreba će se neizbježno pojaviti ako koristite mješovitu tehnologiju programiranja - kombinaciju dva ili više programa za implementaciju jednog programa.

Značajno je u vezi s činjenicom da je mješovito programiranje primarni cilj provedbe kako bi se postiglo sveobuhvatno izvješće. Doista, jezični jezik (točnije programski sustav temeljen na jeziku) ima svoje prednosti i slabosti, pa je sasvim logično iskoristiti prednosti različitih alata za postizanje različitih zadataka. Na primjer, VB - za stvaranje računalnog sučelja, C - za učinkovit pristup resursima sustava, Fortran - za implementaciju numeričkih algoritama.

Ideja autora je sljedeća: ozbiljnu uključenost u programiranje naglašava programer koristeći dva alata. Očito je u suvremenim umovima vrlo teško biti neovisni stručnjak u dva sustava, što shemu „glavni i dodatni jezik“ čini logičnijom. Ideja je da preuzimanje znanja o "dodatnom" jeziku (napisanom nizom jednostavnih postupaka) može značajno unaprijediti učinkovitost "glavnog" jezika. Važno je da je poznavanje VB-a, kao dodatna pogodnost, sada praktičan uvjet za profesionalnog programera. Prije nego što govorimo, u samo nekoliko sati DOS-a, za svakog programera, pogledajmo Basic, bilo bi izuzetno važno poznavati osnove Assemblera.

Dakle, drugačije je, ali u glavama grupnih robota, kada se programer kože bavi svojim specifičnim poslom, izjave o osobitostima proceduralnog sučelja na različitim jezicima krivi su svi sudionici u projektu. Znam da postoji mnogo sustava za programiranje (uključujući VB), osim sučelja, koje ovisi o razumijevanju, koji vam omogućuje postavljanje drugih metoda, širenje metoda programiranja na procedure, koje vam omogućuju da prilagodite sučelje Drugi jezici.

Kada koristite interproceduralno sučelje, imajte na umu sljedeće moguće zamke:

  • Različiti jezici mogu vas zanimati o pravilima pisanja identifikatora. Na primjer, često se koristi pseudonim naziva procedure koji je skriven u VB. Ovaj problem se lako može objasniti korištenjem ključne riječi Alias ​​u operatoru Declare (izvrstan primjer za 2.3).
  • Možete odrediti redoslijed pisanja argumenata koji se prosljeđuju na stog. Na primjer, u satima DOS-a (iskreno rečeno, ne znam kako to izgleda u sredini Windowsa), zapisivanje argumenata s kraja liste, drugi jezici (Fortran, Pascal, Basic) – s početak.
  • Objašnjeni su različiti principi prijenosa parametara - za upute ili značenja.
  • Rigorozna načela očuvanja reda i staleža. Na primjer, u C-u (isto kao u Fortranu i Pascalu), kraj retka je označen nultim bajtom na njegovom kraju, au Basicu je kraj eksplicitno zapisan u deskriptoru retka. Očito, potrebno je zapamtiti mogućnost mijenjanja različitih kodova simbola.
  • Prilikom prijenosa nizova bogatog svijeta, zapamtite da postoje različite opcije za transformaciju struktura bogatog svijeta u jedan svijet (počevši od prvog indeksa ili od posljednjeg, stotinu dvodimenzionalnih nizova - "u redovima" ili "u redovima" pilići").

Na temelju toga mogu se formulirati sljedeće preporuke:

  • Provjerite najjednostavnije stvari revidiranjem načina na koji se argumenti prosljeđuju DLL funkciji. Standardi usvojeni za Win API potpuno su dosljedni.
  • Svaki put nemojte prebacivati ​​mase običnih vojnika.
  • S poštovanjem vikorist prijenos jednostavnih običnih i bogatih nizova.
  • Svakako pažljivo provjerite funkcionalnost mehanizma za prosljeđivanje argumenata proceduri koja se poziva i natrag. Napišite poseban test za provjeru podataka. Pažljivo provjerite ispravnost prijenosa argumenta kože. Na primjer, ako imate proceduru s mnogo argumenata, prvo provjerite ispravnost prosljeđivanja parametra kože za opciju s jednim argumentom, a zatim za cijeli popis.

Što radi ako je DLL funkcija već napisana, na primjer, u Fortranu, ali ulazno sučelje ne odgovara dobro novom VB standardu? Ovdje možete navesti dva datuma. Prvo: napišite testnu DLL funkciju i uz njezinu pomoć pokušajte metodom pokušaja i pogreške odabrati potrebnu funkcionalnost za VB programe. Drugo: napišite proceduru adaptera u Fortranu koja bi omogućila jednostavno sučelje između VB i DLL funkcije s transformacijom jednostavnih struktura podataka u skladištu (na primjer, transformacija velikog niza bajtova iz niza redova).

Otzhe: korištenje DLL funkcija. Također, sačuvajte slatkoću.

ComputerPress 9"2000

Ovaj je članak namijenjen onima koji su novi u programiranju u C++ i bili su prisiljeni koristiti WinAPI.
Želim biti ispred igre:
Ne pretvaram se da sam C++ ili WinAPI guru.
Tek sam počeo i ovdje želim predstaviti niz aplikacija koje će olakšati korištenje funkcija i mehanizama WinAPI-ja.

U ovom članku pretpostavljam da ste se već upoznali s C++ kako biste mogli kreirati klase i prenositi različite operatore za njih te da ste već “zavoljeli” svoje mehanizme u razred.

Stvaranje i vikoristan konzole

Da poboljšam Win32 programe, ili samo da se čudim kako sve izgleda tamo u sredini, uvijek ću ogrebati konzolu.
Budući da stvarate GUI aplikaciju, a ne konzolnu, konzola se neće povezati. Kako biste kliknuli na internetu, možete pronaći ovaj kod

Ako (AllocConsole())
{



std::ios::sync_with_stdio();
}
Radi jasnoće, Raja to umotava u funkciju. Na primjer:
void CreateConsole()
{
ako (AllocConsole())
{
int hCrt = _open_osfhandle((long)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();
}

Konzola radi samo u prikazu i radi na isti način kao u konzolnim programima. Unesite podatke kao i prije - cout/wcout.
Da bi ovaj kod bio učinkovit, potrebno je uključiti sljedeće datoteke u projekt:
#uključi
#uključi #uključi
i omogućite std imenski prostor u globalnom imenskom prostoru:
korištenje imenskog prostora std;
Naravno, ako ne želite ništa učiniti, jednostavno dodajte std:: svim entitetima koji se nalaze u njemu.

Redukcija objekata za prikaz i aritmiranje. operacija

Nakon što ste kreirali i unijeli "konačno", prvo morate ispisati sve vrijednosti na konzolu.
Na primjer:
Veličinu klijentskog područja prozora određujete pomoću dodatne funkcije GetClientRect, gdje se parametar prosljeđuje na adresu objekta RECT strukture kako bi se ovaj objekt ispunio podacima. Ako trebate znati veličinu snimljenog klijentskog područja, možete je jednostavno upisati u već povezanu konzolu.

Cout<

Ale raditi tako brzo (pogotovo jer često morate raditi ovako) nije lako.
Ovdje nam u pomoć priskače smirenost.
Stvorite klasu koja se otvoreno urušava iz RECT strukture i promijenite namjenu izlazne naredbe<< так, как вам угодно.
Na primjer:

Klasa newrect:javni RECT
{
javnost:
prijatelj ostream& operator<<(ostream &strm,newrect &rect)
{
strm<<"Prtint RECT object:\n";
strm<povratak strm;
}
};

Sada samo upišite objekt koristeći cout/wcout:

Cout<

I sami vidite da je tu sve onako kako vam treba.
Također možete raditi s bilo kojim operaterima koji su vam potrebni.
Na primjer, ako trebate modificirati ili dodijeliti strukture (možda ili RECT ili POINT) - potpuno promijenite operator==() i operator=().
Ako želite implementirati operator manje< что бы быстро сравнивать размеры окна и т.д. перегрузите operator<().
Tako da možete raditi, pretpostavljam, čak i s bilo kojom strukturom i iznad svega, da će sve funkcije koje rade s primarnim objektom RECT strukture dobro raditi s njom.
Također preporučujem da svu ovu ljepotu stavite u zasebnu datoteku koja je povezana i uredite je ako je potrebno.

Tvoj razred

Ne znam za druge, ali ja sam potpuno zelen, odlučio sam napraviti novi projekt za skin funkciju ili za kožni odjeljak/pododjeljak knjige, kako bi sve bilo u redu i kako bi bilo moguće bilo kada trenutak za okrenuti se i osvježiti u sjećanju' Ovo su neophodni trenuci.
Budući da u WinAPI-ju, da biste kreirali jednostavan prozor, morate ispuniti strukturu klase, registrirati je i napisati trivijalnu prozorsku proceduru, nakon trećeg ili četvrtog projekta shvatio sam da još uvijek pišem u C++.
Kao rezultat toga, zgrabio sam sve iz jednostavnog razreda. Ručka prozora, ime prozora, ime klase, adrese prozorske procedure, klasa prozora (WNDCLASS) pohranjeni su u odjeljku privatne klase.
Da biste ih izdvojili, trebate opisati jednostavnu metodu "Get", na primjer:
HWND GetHWND()
LPCTSTR GetClsName() itd.
Obnavljanje i registraciju klase prozora, izradu samog prozora i njegovo izlaganje provodi projektant.
Da biste olakšali stvari, možete promijeniti raspored konstruktora i omotati dovršetak i registraciju klase prozora u privatnu funkciju za klasu i pozvati je iz svakog od konstruktora. Prednost preokreta je u tome što je ponekad potrebno napraviti sasvim jednostavan prozor pa kliknem na konstruktor s dva parametra - imenom prozora i pozadinom programa.
Inače, nije potrebno kreirati prozor s posebnim veličinama, ne sa zadanom procedurom prozora i bilo kojim drugim stilom - kliknem na konstruktor s povezanim parametrima.
Ova klasa ima manje vrijednosti u datoteci koja je izravno uključena, a koja se nalazi u mapi za uključivanje IDE-a.
Predložak za ovu klasu:
klasa BaseWindow
{
WNDCLASSEX_wcex;
TCHAR_className;
TCHAR_windowName;
HWND_hwnd;
bool _Kreacija prozora();
javnost:
BaseWindow(LPCTSTR windowName,HINSTANCE hInstance,DWORD stil,UINT x,UINT y,UINT visina,UINT širina);
BaseWindow(LPCTSTR windowName,HINSTANCE hInstance);
const HWND GetHWND()const(return HWND;)
LPCTSTR GetWndName()const(return _windowName;)
};

Nakon što razmislite i napišete takav sat, olakšat ćete si život i provest ćete više od sat vremena svladavajući i izoštravajući početak pisanja iste stvari odjednom. Tim više, ovo još ljepše poštujem - sami kreirati takvu klasu i nadopunjavati je prema svojim potrebama.

p.s.

Sve opisano vrijedi za:
Platforma - Windows 7 32 bit
IDE - Visual Studio 2010
Možda bi netko htio prozvati smijeh i ironiju, ali ipak smo svi mislili da smo pridošlice/pripravnici/juniori.
Molim vas da budete skrupulozni prije svog posta. Konstruktivna kritika, naravno, odleti. Operativni sustavi (OS)