Windowsning asosiy xizmatlari va api funktsiyalari. Windows api - operatsion tizim funktsiyalari to'plami. Nima uchun bir vaqtning o'zida WinAPI haqida?

Qo'ysangchi; qani endi! Qo'ysangchi; qani endi! Bugun biz nihoyat Windows oynasini yana ochamiz. Xayr bechora konsol!

Ungacha siz C++ sintaksisi bilan tanishishingiz, sikl va tsikllardan qanday foydalanishni tushunishingiz va funktsiyalar qanday ishlashini tushunishingiz kerak. Agar siz dengiz jangida qo'lga tushgan bo'lsangiz, qo'lga kiritgan narsalaringizni yozib olishingiz mumkin.

Ugorsk ro'yxatga olish shakli

WinAPI tomonidan ishlatiladigan barcha kodlar ukraincha shaklda yozilgan. Kodni yaxshi yozish yaxshi fikr.

O'zgartirish nomidan oldin kimning harfi qo'yilishi kerak. Muhim funktsiyalar nomlaridagi barcha so'zlar katta harf bilan boshlanadi.

Prefikslar o'qi:

b - bool turini o'zgartirish.
l - uzun butun son turini o'zgartirish.
w - so'z (so'z) - 16 bit. Imzosiz qisqa turning nomi.
dw - qo'sh so'z (ikki so'z) - 32 bit. Zminna turi unsigned long.
sz - satr tugatilgan nolga teng. Biz doimiy ravishda vikorizatsiya qilgan oddiy qator.
p yoki lp - ko'rsatgich. lp (uzun ko'rsatkich sifatida) - bu ko'rsatkichlar o'tmishdan ko'chirilgan. Birgalikda lp i p bir xil ma'noni anglatadi.
h – tavsif (turi dastagi).

Misol uchun, eksa quyidagicha chaqiriladi:

void * pData;

Ushbu ariza shakli Microsoft tomonidan mualliflik huquqi bilan himoyalangan. O'zgaruvchan nom berishning bu usulini tanqid qiluvchilar ko'p. Ammo shunga o'xshash nutqlar (ayniqsa kodlash haqida) buyuk kompaniyalar uchun juda muhimdir.

Sizga shuni eslatib o'tamanki, doimiy identifikatorlar katta harflarga asoslangan: WM_DESTROY. WM_DESTOY - qiymat 2, doimiy aniqlash orqali aniqlanadi.

Bundan tashqari, winAPI ko'plab qayta tayinlash turlariga ega. Ushbu sahifadagi o'q - http://msdn.microsoft.com/en-us/library/aa383751(VS.85).aspx, siz Windowsning barcha turlarining tavsiflarini topishingiz mumkin (ingliz tilida).

Va yana bir nutq, biz tushunmadik. Dushlarga ko'pincha NULL qiymatlari beriladi. Esda tutingki, bu oddiygina 0 va NULL (nol) qiymatiga ega bo'lgan imzolovchilar xotira ulushini ko'rsatmaydi.

Windows API (WinAPI)

Barcha Windows dasturlari maxsus dasturlash interfeysi, WinAPI dan foydalanadi. Movi C-dagi funktsiyalar va tuzilmalar to'plami dasturingizni Windows-da yaxshi ishlashiga imkon beradi.

Windows API operatsion tizimi bilan ishlash uchun ajoyib imkoniyatlarga ega. Aytish mumkin - chegarasiz.

Biz WinAPI-ning yuzlab imkoniyatlarini ko'rib chiqa olmaymiz. Hozir men ko'proq material olishni xohlayman, lekin bu juda ko'p soatlarni oladi va WinAPI-ni botqoqlarga yuklab olib, biz WinAPI-ning bir nechta tavsifida DirectX-ga boramiz, biz ikkita dars olamiz (shu jumladan). . Ular faqat Windows tizimiga qarashadi.

Windows uchun dastur xuddi DOS uchun dastur kabi asosiy funktsiyaga ega. Bu erda bu funksiya WinMain deb ataladi.

WinMain funktsiyasi

Windows dasturi quyidagi qismlardan iborat (hamma narsa WinMain-da saqlanadi):

Sinf oynasini yaratish va ro'yxatdan o'tkazish. C++ sinflari bilan adashmang. WinAPI C tilida yozilgan, umumiy so'z sifatida bizga tanish bo'lgan sinflar juda ko'p.
Dastur oynasini yaratish.
Bilimlar shakllanadigan asosiy tsikl.
Qayta ishlash yakuniy protsedurada xabar qilinadi. Oyna protsedurasi asosiy funksiya hisoblanadi.
Eksa va bir nechta nuqtalar Windows dasturlarining asosi hisoblanadi. Ushbu yangi darsni kengaytirish orqali biz hamma narsani batafsil tartibga solamiz. Agar siz dasturlarning tavsifida adashib qolsangiz, ushbu nuqtalarga qayting.

Endi hammasini tartibga solamiz:

WinAPI: WNDCLASS tuzilishi

Biz birinchi navbatda WNDCLASS tarkibiy o'zgarishini yaratishimiz va saqlashimiz kerak, so'ngra uning asosida yakuniy sinfni ro'yxatdan o'tkazishimiz kerak.

Eksa quyidagi tuzilishga o'xshaydi:

mening c++ kodim typedef struct ( UINT uslubi; // oyna uslubi WNDPROC lpfnWndProc; // oyna protsedurasi uchun indikator int cbClsExtra; // sinfdan keyin qo'shimcha baytlar. Avval 0 int cbWndExtra ga o'rnating; // oyna misolidan keyin qo'shimcha baytlar. Birinchi marta o'rnating. 0 / lar dasturi: WinMain HICON hIcon-da ko'rish parametri bilan o'tkazildi // dastur belgisi HCURSOR hbrBackground // fon rangi LPCTSTR;

WinAPI omboridagi WNDCLASS tuzilmasi yaratilgan oynaning asosiy vakolatlarini belgilaydi: piktogramma, sichqoncha kursorining ko'rinishi, oynaning menyusi, oynada qaysi plagin bo'ladi...

Ushbu tuzilmani saqlaganingizdan so'ng, yakuniy sinfni shu asosda ro'yxatdan o'tkazishingiz mumkin. C++ dagi kabi sinflar mavjud emas. Endi siz bu tizimda ro'yxatdan o'tgan shablon ekanligini eslay olasiz va endi siz ushbu shablon asosida yangi shablon yaratishingiz mumkin. Va siz WNDCLASS tuzilmaviy o'zgarishidan bilib olganingizdek, bu kunlarning barchasi hokimiyat tomonidan boshqariladi.

WinAPI: CreateWindow funktsiyasi

Yangi sinfni ro'yxatdan o'tkazgandan so'ng, uning asosida asosiy dasturlar yaratiladi (biz boshqa nuqtaga o'tdik). CreateWindow qo'shimcha funksiyasini sinab ko'ring. Hujumkor prototip bo'lishi mumkin:

mening c++ kodim HWND CreateWindow(LPCTSTR lpClassName // sinf nomi LPCTSTR lpWindowName // oyna nomi (sarlavhada ko'rsatilgan) DWORD dwStyle // oyna uslubi int x // ekran chap chetining gorizontal koordinatasi int y // yuqori chetining vertikal koordinatasi ekran int nWidth, // oyna kengligi int nHeight, // oyna balandligi HWND hWndParent, // ota oynasi HMENU hMenu, // menyu tavsifi HINSTANCE hInstance, // dastur namunasi LPVOID lpParam // parametr har doim NULL;

Deraza sinfiga (WNDCLASS strukturasi) derazaning asosiy vakolatlari berilganligi sababli, deraza oynasining o'ziga xos parametrlari: oyna o'lchami, koordinatalar ...

Bu funksiya tavsif oynasini aylantiradi. Qo'shimcha tavsif uchun siz identifikatorga o'xshash oynaga o'tishingiz mumkin.

E'tibor bering, bu erda juda ko'p yangi turlar mavjud. Darhaqiqat, barcha badbo'y hidlar eski, faqat o'zgartirilgan. Misol uchun: HWND HANDLE turiga qayta tayinlash emas, bu o'ziga xos tarzda PVOID ga qayta tayinlash, bu ham bekor qilish*. Haqiqat juda chuqur ko'milgan! Axir, HWND turi bekorchilik belgisi emas.

Deraza ko'p qismlardan iborat. Aslida, har bir dasturda siz quyidagilarni ko'rasiz: oynaning sarlavhasi, tizim menyusi (oynaning yuqori chap qismidagi dastur belgisini bosing), oyna bilan ishlash uchun uchta tizim tugmasi: yorug'lik, to'liq ekran va yaqin. Bundan tashqari, deyarli har doim qo'shimcha ravishda menyu mavjud. Qolganining o'qi, albatta, bizda bo'lmaydi. Va, albatta, derazaning ko'p qismi atalmish tomonidan ishg'ol qilinadi. mijoz ishlaydigan mijoz hududi.

Bu deraza rejimidan yaxshiroqdir. Agar biz DiectX bilan uzoq vaqt mashq qilishni davom ettirsak, biz to'liq ekran rejimidan foydalanmaymiz.

Xabar bilan ishlash

Windows ostidagi barcha ilg'or dasturlarning asosiy afzalligi yangilanishlarni qayta ishlashdir.

Misol uchun, foydalanuvchi klaviaturadagi tugmachani bosganda, tugma bosilganligi haqida bildirishnoma hosil bo'ladi. Keyin tugmani bosganingizda faol bo'lgan dasturga o'tishingiz kerak bo'ladi.

Bu erda bizda voqea bor - tugma bosildi.

Amallar quyidagilar bo'lishi mumkin: sichqoncha kursorini siljitish, dasturlarning fokusini o'zgartirish, klaviatura tugmachalarini bosish, oynani yopish. Bu juda boy. Duje! Bir soniya ichida operatsion tizimda o'nlab xabarlar yaratilishi mumkin.

Shunday qilib, agar javob bo'lsa, operatsion tizim bildirishnoma hosil qiladi: tugma bosilganda sichqoncha kursorining koordinatalari o'zgaradi va yangi oyna ochiladi.

Axborot ham operatsion tizim, ham turli dasturlar tomonidan yaratilishi mumkin.

Kelgusi buyurtmaning tuzilishi va ko'rinishi:

mening c++ kodim typedef struct tagMSG ( HWND hwnd; // bildirishnoma UINT xabarini bildiruvchi oyna; // WPARAM wParam bildirishnoma kodi; // LPARAM lParam parametri; // parametr DWORD vaqti; // bildirishnoma berilgan soat POINT pt; // sichqoncha kursorini muvofiqlashtiradi) MSG;

Iltimos, typedefs yordamida tuzilmalar qayta tayinlanishiga e'tibor bering.

Ushbu tuzilmani yaratish uchun siz tezda quyidagi koddan foydalanishingiz mumkin:

mening c++ kodim msg.messgae == 2; // bular ikki qator ekvivalent fragmentlar msg.message == WM_DESTROY; // doimiy WM_DESTROY eski ikki

Mana, dala, yakuda, dinning kodi (izi divodelene, Konstantin WM_Destroy bilan yirtilgan. WM - vid Windows Xabari (Vitse Windows). WM_Destroy - Tser Poldodlennya, Jek General Strivet qachon (Destroy - Destroy).

Kodlar qo'shimcha konstantalar va WM_ prefiksi ortida ko'rsatilgan: WM_CLOSE, WM_CREATE va boshqalar.

MSG strukturasi HWND turiga ega - Oyna tutqichi (oyna dastagi va oyna tavsifi). Bu dunyoni tasvirlaydigan narsadir. Narx identifikator belgisi (oyna nomi) uchun.

Ushbu so'zni eslang - tutqich (ta'riflash, tavsiflovchi). Windows-da bu juda keng tarqalgan suiiste'mol mavzusi. Shuningdek, H harfi bilan boshlanadigan Windowsning barcha turlari tavsifdir: piktogramma tavsifi, shrift tavsifi, dastur misoli tavsifi. Esimda, ularning o‘ttizga yaqini bor.

Windows-dagi ilovalar o'rtasidagi barcha o'zaro ta'sirlar ushbu oyna tavsiflari (HWND) yordamida amalga oshiriladi.

Yana bir muhim deskriptor mavjud - dastur deskriptori (HINSTANCE - WinMain-ning birinchi parametri) - bu noyob dastur identifikatoridir, chunki har qanday operatsion tizim ikki xil dasturni aralashtira olmaydi. Bu taxminan shtrix-kodga o'xshaydi. Biz buni keyinroq ko'rib chiqamiz.

Endi, har qanday harakatni amalga oshirganingizda, bildirishnoma yaratiladi va eslab qolinadi: siz bildirishnomani ko'rishingiz mumkin bo'lgan oyna tavsifi o'rnatiladi, bildirishnoma identifikatori o'rnatiladi, parametrlar saqlanadi, soat (joriy) saqlanadi va siz ko'rsatasiz Sichqoncha kursorining koordinatalarini o'zgartirishingiz mumkin (siz strukturani ko'rishingiz mumkin).

Ushbu bildirishnomadan so'ng, operatsion tizimning keyingi bildirishnomasiga o'ting. Bizning ma'lumotlarimizga kelganda, u kerakli oynaga yuboriladi (Windows teri ma'lumotlarini mutaxassislarga qanday yuborishni biladi). Agar siz dasturlardan xabardor bo'lsangiz, dasturlar haqida ma'lumot olishingiz kerak bo'ladi. Pastga tushish qiyin, zerikarli bo‘layapti.

Ajablanarlisi shundaki, hozirgi vaqtda foydalanuvchi biron bir harakatni amalga oshirganida (xabar ko'rsatilgan va xabar yaratilgan) va dastur ushbu harakatga munosabat bildirganida (xabar dastur tomonidan yaratilgan), juda ko'p narsa bor. ma'lumotlardan. Windows-dan foydalansangiz ham, dasturlardan ko'p ma'lumotlarni ham olishingiz mumkin. Birinchisida taxminan yuzlab, ikkinchisida kamida bir nechta bo'lishi mumkin.

Oyna protsedurasi - WndProc

Biz ma'lumot sarflangan paytdan boshlab dasturning oxirigacha davom etamiz. Bu uzoq vaqt o'tdi va u parchalana boshladi. Qayta ishlash uchun, iltimos, teri dasturi maxsus funktsiyaga ega ekanligini unutmang - oyna protsedurasi. U WndProc deb ataladi (Oyna protsedurasidan). Kengaytirish protsedurasining oynasi asosiy dastur siklida bajariladi va tsiklning har bir iteratsiyasi davomida tugallanadi.

Ma'lumot (tarkibiy o'zgarishlar MSG shaklida) ushbu funktsiyaga parametrlar ko'rinishida qo'llaniladi: oyna tavsifi, bildirishnoma identifikatori va ikkita parametr. E'tibor bering, vaqt va pt maydonlari oyna protsedurasiga o'tkazilmaydi. Totto, sizga aytsam, bu allaqachon "rozybran".

Oyna protsedurasining o'rtasida kalit o'chiriladi, bu bildirishnoma identifikatorini tekshirishni o'z ichiga oladi. Eksa oddiy oyna protsedurasining namunasidir (u to'liq ishlaydi):

mening c++ kodim// HRESULT va __stdcallga vaqtingizni behuda sarflamang. Biz ularni keyinroq ko'rib chiqamiz. ) // kompilyator xabar berishga qaror qiladi)

Men qolaman - asosiy tsikl. Vin bundan ham oddiyroq. Tsiklning har bir iteratsiyasi dastur tomonidan tekshiriladi. Ma'lumotga ega bo'lishingiz bilanoq, siz dunyodan tortib olasiz. Keyin tsikl ma'lumotni qayta ishlash uchun oyna protsedurasini bosishni taklif qiladi.

Eksa qizg'in pallada va hamma narsa bugungi kun uchun. WinAPI ostidagi dastur DOS ostidagi dasturga ancha o'xshashligi allaqachon aniq. Men allaqachon yozganimdek, kelgusi darsda biz ishlaydigan dastur kodini ko'rib chiqamiz.

Men yangi loyiha yaratish huquqiga egaman. Yangi loyiha oynasida shablonni tanlang - Win32Project (biz avvalroq Win32 Console ilovasini tanlaganmiz). Kelgusi oynalardan birida Empty Project bayrog'ini o'rnatmang va IDE tayyorlangan dasturni yaratadi.

Agar siz project_name.cpp faylidagi kodni diqqat bilan ko'rib chiqsangiz, biz muhokama qilgan barcha narsalarni ko'rasiz: MSG ning tarkibiy o'zgarishi, WNDCLASS strukturasini to'ldirish, CreateWindow funksiyasi orqali oyna yaratish, asosiy dastur tsikli. . Bundan tashqari, faylga WndProc funksiyasi tayinlangan. Kommutator qutilarida bir qator ma'lumotlarni qayta ishlashingiz kerak: WM_COMMAND, WM_PAINT, WM_DESTROY. Fayldagi hamma narsani toping.

Biz ko'rgan narsalarga qo'shimcha ravishda, dasturda juda ko'p qo'shimcha kod mavjud. Keyingi nashrda biz dastur kodini ko'rib chiqamiz, shunda hamma narsa tekshiriladi. Bu IDE yaratgan narsadan ancha sodda va aqlliroq bo'ladi.

Rad etish

Men WinAPI qo'shni eshikdan chiqadi deb o'ylagan bo'lardim. Ko'p sonli o'zaro faoliyat platformalar mavjudligi uzoq vaqtdan beri ma'lum bo'ldi, Windows nafaqat ish stollarida, va Microsoft o'z do'konida bu yirtqich hayvonni oqlaydigan qo'shimchalarni qo'shishdan tortinmaydi. WinAPI-da qanday yaratish haqida nafaqat bu yerda, balki butun Internetda minglab maqolalar mavjud, ularning soni minglab, maktabgacha va undan tashqarida. Butun parchalanish jarayoni endi atomlarga emas, balki subatomik zarrachalarga asoslanadi. Nima oddiy va aqlliroq bo'lishi mumkin? Va men shu yerdaman...

Ammo hamma narsa ko'rinadigan darajada oddiy emas.

Nega endi WinAPI haqida?

Bir kuni, xuddi shu yaxshi narsadan charchaganimda, men shunday deb o'yladim: bu nima jahannam, va muharrirda oddiy muharrirda bo'lgani kabi klaviatura tugmalari bo'ylab harakatlanish kabi oddiy til yo'q.

Men nima haqida gapiryapman? Va aks kodi:

Case WM_KEYDOWN: MessageBox(hwndDlg, "O'l!", "Men o'ldim!", MB_YESNO|MB_ICONINFORMATION);
Shu tarzda, mualliflar klaviaturaga qo'llab-quvvatlashni qo'shishni xohlashdi, ammo Windows-dagi dialog oynalari arxitekturasining haqiqati bunday o'zini o'zi yoqtirishni qattiq jazoladi. Emulator yoki kontrollerdan foydalangan har bir kishi buni bilishni xohlaysizmi?
Muammo nimada?

Javob shunday: siz bunday ishlay olmaysiz!

Va WinAPI-ning boshoqli ozuqasiga qaytadigan bo'lsak: hozirda uni vikorizatsiya qilishni davom ettirish uchun juda ko'p mashhur va unchalik ko'p emas loyihalar mavjud, chunki Muxtasar qilib aytganda, siz sof API-da juda ko'p nutq so'zlay olmaysiz (bu erda siz yuqori sifatli til va assemblerni tekislash uchun cheksiz o'xshashliklarni chizishingiz mumkin, lekin umuman emas). Nega yo'q? Faqat vikorist va bu shunday.

Muammo haqida

Dialog oynalari bilan ishlash GUI-ga qaraganda osonroq, shu bilan birga bizga o'zimiz ish qilish imkoniyatini beradi. Masalan, oyna protsedurasida joylashgan WM_KEYDOWN/WM_KEYUP ma'lumotlari DefDlgProc kichik bo'limlarida joylashgan bo'lib, jumladan: Tab navigatsiyasi, Esc ni qayta ishlash, Enter tugmachalari va boshqalar. Bundan tashqari, dialog oynalarini qo'lda yaratishingiz shart emas: shunchaki tugmalar, ro'yxatlar, resurs muharriri qo'shing, WinMain CreateDialog/DialogBox-ni bosing va ish tugadi.

Bunday boshqa sirlarni aylanib o'tish oson. Va, hech bo'lmaganda, ikkita mutlaqo qonuniy yo'l:

  1. RegisterClassEx orqali o'z sinfingizni yarating va sinfni qayta ishlash protsedurasiga WM_KEYDOWN ni qo'shing va uni dialogni qayta ishlash protsedurasining o'ziga yo'naltiring. Shunday! Siz o'z sinfingiz bilan dialoglar yaratishingiz va dialog uchun sinf nomini o'rnatish imkonini beruvchi VS muharriridan foydalanishingiz mumkin. Kimdir bu haqda biladi va o'ziga xizmat qiladimi?
    Aniq kamchilik: Yana bitta klassni ro'yxatdan o'tkazish kerak, shuning uchun yana 1 ta QO'NG'IRISH protsedurasi mavjud bo'lib, uning mohiyati tikish translyatsiyasida yo'qoladi. Bundan tashqari, biz bilmaymiz qudi Ular huquqbuzarlik qiladilar va politsiya qidiradi.
  2. Vikoristovat tezlatgich mexanizmini amalga oshirish. Va biz hech qachon dialog protsedurasi kodini o'zgartirishimiz shart emas! Xo'sh, nima uchun kalitga / korpusga bitta qator qo'shmaslik kerak, lekin narx pastroq.

Darslar?

Men buni aytishdan qo'rqmayman Mo'ylov WinAPI orqali derazalar yaratish bo'yicha qo'llanmalar ishlov berish tsikli qanday xabar qilinishini ko'rsatadigan shunday oddiy kod bilan boshlanadi (men oyna sinfini va boshqa ulanishlarni tayyorlash tafsilotlarini o'tkazib yuboraman):

Holbuki (GetMessage(&msg, nullptr, 0, 0)) ( TranslateMessage(&msg); DispatchMessage(&msg); )
Bu erda juda oddiy:

  1. GetMessage() shaytonning xabarini qichqiradi va asosiy nuqta: oqimni bloklaydi, chunki u bo'sh
  2. WM_KEYDOWN/WM_KEYUP bilan TranslateMessage() WM_CHAR/WM_SYSCHAR bildirishnomasini hosil qiladi (agar siz o'zingizning matn muharriringizni yaratmoqchi bo'lsangiz, bu zarur).
  3. DispatchMessage() bildirishnomani oyna protsedurasiga yuboradi (xuddi shunday).
Ushbu kodni vikorizatsiya qilish xavfsiz emasligi aniq va shuning uchun ham. Sharobga hurmatni qaytarish:
Shuning uchun, qaytarish qiymati noldan farqli, nol yoki -1 bo'lishi mumkin, quyidagi koddan saqlaning:
esa (GetMessage(lpMsg, hWnd, 0, 0)) ...
I to'g'ri tsiklda dumbani pastga qarating.

Vartoning aytishicha, Win32 uchun VS shablonlari bir xil imlo qo'shimchalariga ega noto'g'ri tsikl. Va bu haqiqatan ham aqldan ozgan. Garchi mualliflarning o'zlari tuzgan narsalarni kam odam o'rgansa-da, bu apriori to'g'ri. Va noto'g'ri kod xatolar bilan ko'payadi, uni qo'lga olish juda qiyin.

Ushbu kod bo'lagidan so'ng, qoida tariqasida, tezlatgichlar haqida bahs yuritiladi va bir nechta yangi qatorlar qo'shiladi (MSDN-ga nisbatan, men sizni to'g'ri tsiklni yozishni tavsiya qilaman):

HACCEL hAccel = Load Accelerators(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; ) )
Men bu variantni ko'pincha afzal ko'raman. men vin ( ta-dam) Znovu noto'g'ri!

Men o'zgarganlar haqida gapiraman (va keyin ushbu kod bilan bog'liq muammolar haqida):

Resurslarning birinchi qatorida kalitlar jadvali tanlanadi va har qanday formatni bosganingizda, tegishli buyruq identifikatori bilan WM_COMMAND bildirishnomasi ko'rsatiladi.

TranslateAccelerator buni amalga oshiradi: WM_KEYDOWN va ushbu ro'yxatdagi kalit kodini qanday olish kerak, so'ngra (yana asosiy nuqta) WM_COMMAND (MAKEWPARAM(id, 1)) xabarini formatlang va uni bir kun oyna uchun turlarga yuboring. birinchi argumentda ko'rsatilgan tutqich , ishlov berish tartiblari.

Qolgan ibora bilan, o'ylaymanki, oldingi kod bilan qanday muammo borligi aniq bo'ldi.
Tushuntirishga ijozat bering: GetMessage “oyna” turidagi BARCHA obyektlar uchun tanlangan (jumladan, bolalar: tugmalar, ro‘yxatlar va h.k.) va TranslateAccelerator yaratilgan WM_COMMANDni qayerga yuboradi? To'g'ri: tugma/ro'yxatga qaytish. Biz protseduramizga WM_COMMAND qo'shamiz, ya'ni uni undan olib tashlashimiz kerak.

Ma'lum bo'lishicha, TranslateAccelerator bizning yaratilgan oynamiz uchun ishlatilishi kerak:

HWND hMainWnd = CreateWindow(...); HACCEL hAccel = Load Accelerators(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 )
Va hozir hammasi yaxshi va ajoyib: biz hamma narsani batafsil saralab oldik va hamma narsa a'lo darajada ishlaydi.

Yana bilaman. :-) Bizda faqat bitta narsa bor ekan, buni to'g'ri qilaylik - o'zimizniki. Modal bo'lmagan yangi oyna (muloqot) paydo bo'lishi bilanoq, yangi oynada bosiladigan barcha tugmalar WM_COMMAND ga tarjima qilinadi va qayerga yuboriladi? To‘g‘risini aytsam: bosh og‘rig‘imiz yomon.

Ushbu bosqichda men sizga politsiyani eng kar bo'lgan vaziyatdan to'sib qo'ymaslikni maslahat beraman, balki o'quv qo'llanmalarida allaqachon ilgari bo'lgan (yoki tozalanmagan) nutqlarga qarang.

IsDialogMessage

Ushbu funktsiyaning nomidan kelib chiqib, siz bu ma'noni anglatadi deb o'ylashingiz mumkin: har qanday dialogdan xabardor bo'lish. Ale, birinchi navbatda, siz nimani bilasiz? Boshqacha qilib aytganda, bu ma'lumotlarning qiymati nimada?

Bu, albatta, bir oz ko'proq to'lashga arziydi, bu nomdan ajralib turadi. Va o'zingizga:

  • Tab/Shift+Tab/yuqoriga/pastga/o‘ngga/chap tugmalari yordamida bolalar boshqaruvlari bo‘ylab harakat qilishingiz mumkin. Bundan tashqari, yana bir narsa, bu bizga etarli
  • ESC tugmachasini bosgandan so'ng u WM_COMMAND (IDCANCEL) hosil qiladi.
  • Enter tugmasini bosgandan so'ng WM_COMMAND(IDOK) hosil bo'ladi yoki chiziqdagi tugmani bosgandan so'ng.
  • Ulanishlar orqasidagi tugmalarni almashtiradi (bunday tugmalarning ramkasi boshqalarga qaraganda bir oz yorqinroq)
  • Xo'sh, va undan ham ko'proq turli xil narsalar, bu muloqot bilan muxbirning robotini osonlashtiradi
Bu bizga nima beradi? Avvalo, biz oynaning o'rtasida navigatsiya haqida o'ylashimiz shart emas. Biz hamma narsani shunchalik tejashimiz kerak. Gapirishdan oldin, asosiy oynamizga WS_EX_CONTROLPARENT uslubini qo'shish orqali tab navigatsiyasiga erishish mumkin, lekin u unchalik foydali emas va unchalik funktsional emas..

Boshqa yo'l bilan, biz ro'yxatda sanab o'tilgan nuqtalar panjarasi ortida hayotni osonlashtiramiz (va yana bir nechta).

Vzagali, siz robot xavfsizligi uchun Windows-ning yuqori qismida vikoristlik qilyapsiz modal dialog oynalari, va dasturchilarga modal bo'lmagan dialoglar uchun ularni bosish imkoniyati beriladi. Biroq, biz buni yaxshi o'lchov uchun ishlatishimiz mumkin:

Bundan tashqari, funktsiyaning dialog funktsiyasi dialog oynalarini modellashtirish uchun ishlatiladi, siz uni istalgan oyna bilan ishlatishingiz mumkin, shunda karvon belgilari sozlangan va derazalar, klaviaturaning o'zi tanlanganligini ta'minlash uchun siz uni tanlashingiz mumkin Mavjud dialog oynasida.
Tobto. Endi siklni quyidagicha formatlaymiz:

HWND hMainWnd = CreateWindow(...); HACCEL hAccel = Load Accelerators(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);
Keyin biz Windowsning boshqa dialog oynalarida bo'lgani kabi navigatsiyadan ham foydalanamiz. Ammo endi bizni ikkita kamchilik olib tashladi:

  1. Bu kod ham faqat mehr bilan ishlatiladi bitta (modal bo'lmagan) oyna bilan;
  2. Muloqot oynasi navigatsiyasining barcha afzalliklaridan mahrum bo'lganimizdan so'ng, biz WM_KEYDOWN/WM_KEYUP ni ko'rinishga qo'shishimiz kerak (faqat oynaning o'zi uchun, bolalar boshqaruvi uchun emas);
Va bu bosqichda barcha darsliklar tugaydi va ovqatlanish boshlanadi: Winapi standart muloqot oynasida klaviatura hodisalarini qanday boshqarish kerak?
Bu Google yoki Internetda e'lon qilingan birinchi narsa: ulardan minglab. Taklif etilayotgan yechim haqida (eng muhimi, pastki sinf va RegisterHotKeydan oldin men yuqorida yozgan suhbatlar sinfini yaratish kerak. Bu erda men usullarning "eng qisqasi" ni o'rganaman: vikorize Windows Hooks).

Qo'llanmalar va videolarda etishmayotgan narsalar haqida gapirish vaqti keldi.

Qoidaga ko'ra (qoidaga ko'ra! Agar kimdir ko'proq istasa, siz o'z sinfingizni dialoglar uchun ro'yxatdan o'tkazishingiz va shunga o'xshash ishlashingiz mumkin. Va agar sizga ahamiyat bermasangiz, men ushbu maqolani qo'shaman) WM_KEYDOWN agar siz kalitga bosimni qayta ishlashni xohlasangiz. ofisda kerakli nazoratdan qat'i nazar, funktsiyani tanlaydi - ya'ni. Bu alohida dialog uchun muhim vazifadir. Agar shunday bo'lsa, nima uchun WinAPI bizga o'rgatgan boy imkoniyatlarni tezda kiritmasligingiz kerak: TranslateAccelerator.

Vikoryst orqali aynan bitta tezlatgichlar jadvali va hatto asosiy oyna. To'g'risini aytish kerak: faqat bitta GetMessage-loop sikli mavjud va faqat bitta jadval mavjud. Ular qayerga borishlari kerak?

Aslida, GetMessage-loops bo'lishi mumkin hissalar. Keling, PostQuitMessage tavsifiga yana bir bor hayron qolaylik:

Funktsiyalar PostQuitMessage WM_QUIT xabarini mavzuning xabarlar navbatiga joylashtiradi va darhol qaytadi;
Men xabar olaman:
Agar funktsiya WM_QUIT xabarini yangilash bo'lsa, qaytariladigan qiymat nolga teng.
Shunday qilib, GetMessage-loop-dan chiqish, biz oyna protsedurasida PostQuitMessage-ni chaqirganimizdek sodir bo'ladi. Bu qanday ma'nono bildiradi?

Biz uchun mumkin teriga xos modal bo'lmagan Bu bizning dasturimiz uchun o'zining quvvatga o'xshash aylanishini yaratish uchun oynadir. Agar DialogBoxParam biz uchun mos bo'lsa, chunki Biz o'z energiya aylanishimizni aylantirishimiz mumkin emas. Biroq, agar siz CreateDialogBoxParam orqali dialog yoki CreateWindow orqali oyna yaratsangiz, boshqa tsiklni ishga tushirishingiz mumkin. Gap kelganda teriga xos Bunday muloqot uchun biz PostQuitMessage tugmasini bosishimiz shart:

HWND hMainWnd = CreateWindow(...); HACCEL hAccel = Load Accelerators(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 hAccelerators (hInstance, MAKEINTRESOURCE(IDR_ACCELERATORY)_ALG); wnd, FALSE);// asosiy oynani o'chirib qo'ying, chunki dialog oynasi modal bo'lganda (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) sinishi; agar (!TranslateAccelerator(hDlg, hAccel)) , &msg)) ( agar (!IsDia , &msg)) ( TranslateMessage(&msg); DispatchMessage(&msg); ) ) ) EnableWindow(hwnd, fSavedEnabledState); // Ota-oynani yoqish. wparam, LPARAM lparam) (switch(umsg) (holat WM_CLOSE: (// EndDialog(hwnd, 0)); - BUNI QILMANG! // EndDialog faqat DialogBox(Param) DestroyWindow(hwnd) yordamida yaratilgan dialog oynalarini o'zgartirish uchun to'g'ri keladi; break; ) case WM_DESTROY: ( PostQuitMessage(0); break; ) // .... ) 0; )
Hurmatni qaytaring: endi dasturimizdagi yangi teri oynasi uchun biz qayta ishlashdan oldin qo'shishimiz mumkin Vlasnu tezlatgich stoli. WM_QUIT GetMessage ni dialog oynasidan olib tashlaydi va tashqi sikl ishlamaydi. Nega hayajondasan?

O'ng tomonda joriy tsikl DispatchMessage tugmachasini bosish orqali "turadi", bu bizning protseduramizda bosiladi, uning quvvatini qanday aylantirish kerak ichki Ushbu DispatchMessage bilan GetMessage tsiklining o'zi. Klassik viki qo'shimchalari (DispatchMessage da). Shuning uchun tashqi tsikl WM_QUITni bekor qilmaydi va shu bosqichda tugaydi. Hammasi muammosiz ketmoqda.

Xo'sh, bu erda ba'zi kamchiliklar mavjud:
Teri bu tsikldan xabardor faqat "sizning" oynangiz uchun. Biz bu erda boshqalar haqida bilmaymiz. Bu shuni anglatadiki, agar bu erda boshqa tsikl paydo bo'lsa, ularning barchasi TranslateAccelerator/IsDialogMessage juftligidan foydalanib o'z xabarlarini qayta ishlashlari kerak bo'ladi.

Xo'sh, barcha hurmat-ehtiromlaringizni qaytarib olish va dasturimizning barcha natijalari haqida sizni xabardor qilish uchun hamma narsani to'g'ri qayta ishlash haqida yozish va qaror qabul qilish vaqti keldi. Men bitta oqim uchun mukofot pastroq bo'lishini hurmat qilmoqchiman. Chunki Agar teri oqimi uning tuzilishini bilishga imkon bersa, teri oqimi uning tuzilmalarini yaratishi kerak bo'ladi. Koddagi arzimas o'zgarishlardan ham qo'rqish.

Robimo go'zal

Chunki Agar vazifani to'g'ri qo'yish yechimning yarmi bo'lsa, men birinchi navbatda vazifani to'g'ri belgilashim kerak.

Birinchidan, bu mantiqiy bo'lar edi faolroq Men hozir bildirishnomalar olaman. Tobto. Faol bo'lmagan oyna uchun biz tezlatgichni tarjima qilmaymiz va IsDialogMessage-ga bildirishnomalarni yubormaymiz.

Boshqacha qilib aytganda, agar tezlatkich jadvali oyna uchun o'rnatilmagan bo'lsa, unda tarjima qilish uchun hech narsa yo'q, faqat IsDialogMessage-da bildirishnoma.

Keling, oddiy std::map yarataylik, u oyna deskriptorini tezlatgich jadvali deskriptoriga moslashtiradi. Eksa quyidagicha:

Std :: xaritasi l_mAccelTable;
Va yaratilgan oynalar dunyosida biz sizning sevimli jadvalingizga identifikatorli yangi oyna qo'shishni davom ettiramiz (yoki nolga teng, chunki bunday ishlov berish talab qilinmaydi).

Bool Ecacccriceratorlari (HWNDELD, HACCELD HACCES) (l_maccleTable [hwnd]) (hwnd] = gwndww loadercereratorkorlar (hindhw loadercerereratorlari (hindhw loadercerererator);) Bool Ecaccriceratorlar hWnd, int accel)
Va derazani yopgandan so'ng, keting. Eksa quyidagicha:

Void DelAccel(HWND hWnd) ( std::map :: iterator me = l_mAccelTable.find(hWnd); agar (me != l_mAccelTable.end()) ( if (me->ikkinchi) ( DestroyAcceleratorTable(me->ikkinchi); ) l_mAccelTable.erase(me; ) )
Endi biz yangi dialog/oyna yaratganimizda AddAccelerators (hNewDialog, IDR_MY_ACCEL_TABLE) tugmasini bosing. Qanday yopish kerak: DelAccel(hNewDialog).

Bizda kerakli deskriptorlar ro'yxati mavjud. Asosiy ishlov berish tsiklimizni qanday o'zgartiramiz:

// ... 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 ) // .. .
Juda yaxshi! HandleAccelArray bilan nima bor va GetActiveWindow() bilan keyingi nima?

Bir oz nazariya:

GetForegroundWindow va GetActiveWindow faol oyna dastagini aylantiruvchi ikkita funksiya mavjud. Birinchisining boshqasidan muhimligi ikkinchisining tavsifida to'liq tasvirlangan:

Qaytish qiymati qo'ng'iroq qiluvchi ipning xabarlar navbatiga biriktirilgan faol oynaning tutqichidir. Aks holda, qaytarish qiymati NULL bo'ladi.
Agar siz avval tizimdagi istalgan oynaning deskriptorini aylantirsangiz, qolganlari faqat aylanadi vikoristning so'zi bizning oqimimizni qanday xabardor qilishdir. Chunki Biz faqat o'z oqimimizda yashashni davom ettiramiz (shuningdek, bizning kunlarimizgacha isrof bo'ladiganlar), keyin qolamiz.

Shunday qilib, faol oynadagi deskriptor tomonidan uzatiladigan HandleAccelArray o'qi bizning xaritamizda ham ko'rinadi va u mavjud bo'lganidek, TranslateAccelerator tarjimasiga xabar yuboradi va keyin (go'yo birinchisi bo'lmagandek) IsDialogMessage-da kerakli ) ni qo'shing. Agar xabar hali yuborilmagan bo'lsa, standart TranslateMessage/DispatchMessage protsedurasidan o'tish uchun FALSE ni aylantiring.

Bu shunday ko'rinadi:

BOOL HandleAccelWindow(std::map ::const_iterator mh, MSG & msg) ( const HWND & hWnd = mh->birinchi; const HACCEL & hAccel = mh->ikkinchi; agar (!TranslateAccelerator(hWnd, hAccel, &msg)) ( // xabar tarjima qilish uchun emas u IsDialogMessage bilan agar (!IsDialogMessage(hWnd, &msg)) ( // shunday qilib, sukut bo'yicha ma'lumotlar FALSE qaytaradi; ) ) // ok, xabar tarjima qilingan (HWND hActive, MSG & msg) ( agar (!hActive) FALSE qaytariladi; // faol oyna yo'q std::map ::const_iterator mh = l_mAccelTable.find(hActive); if (mh != l_mAccelTable.end()) ( // Tushunarli! Ushbu xabarni faol oyna uchun tarjima qilishga urinib ko'ring return HandleAccelWindow(mh, msg); ) FALSE qaytaring; )
Endi har bir bola o'z sevimli tezlatkich jadvalini qo'shish va WM_COMMAND ni kerakli kod bilan xotirjam tutish va kiritish huquqiga ega.

WM_COMMAND kodida bitta qator haqida yana nima bor?

TranslateAccelerator-dagi tavsif:
Xabarlar bilan jo'natish funksiyasi menyu yoki boshqaruv elementlarini anglatishini aniq ko'rsatish uchun wParam parametri WM_COMMAND yoki WM_SYSCOMMAND xabari bilan yuqori samarali so'z 1 qiymatini o'z ichiga oladi.
WM_COMMAND ishlov berish kodi quyidagicha ko'rinadi:

Switch(HIWORD(wParam)) ( BN_CLICKED holi: // Tugmalar/menyulardan buyruq ( switch(LOWORD(wParam))) ( IDC_BUTTON1: DoButton1Stuff(); break; IDC_BUTTON2: DoButton2Stuff ) tanaffus; ) )
Endi siz buni shunday yozishingiz mumkin:

Switch(HIWORD(wParam)) ( 1-holat: // tezlatuvchi registr BN_CLICKED // Tugmalar/menyulardan buyruq ( switch(LOWORD(wParam))) ( IDC_BUTTON1: DoButton1Stuff(); break; IDC_BUT // ... ) tanaffus;
Va endi, xuddi shu fceuxga o'girilib, qo'shilgan faqat bitta qator Tugmalar uchun buyruqlarni qayta ishlash kodida biz quyidagilarni olib tashlaymiz: klaviaturadan tuzatuvchidan foydalaning. Bosh pastadir yaqinidagi kichik qobiqni va ma'lum turdagi VK_KEY => IDC_DEBUGGER_BUTTON bo'lgan yangi tezlatgichlar jadvalini qo'shish kifoya.

PS: O'zingizning tezlatgich jadvalingizni yaratishingiz mumkinligini kam odam biladi va endi uni to'g'ridan-to'g'ri muzlatib qo'ying.

P.P.S.: Chunki DialogBox/DialogBoxParam quvvat aylanishini aylantiradi, keyin ular orqali dialog chaqirilganda, tezlatgichlar ishlamaydi va bizning tsiklimiz (yoki tsiklimiz) "bo'sh" bo'ladi.

P.P.P.S.: HandleAccelWindow kartalarini bosgandan so'ng l_mAccelTable o'zgartirilishi mumkin, chunki TranslateAccelerator yoki IsDialogMessage DispatchMessage-ni bosing va u erda siz AddAccelerators yoki DelAccel-ga protsessorlarimizga qo'shilishingiz mumkin! Shuning uchun, bu funktsiyalarni e'tiborsiz qoldirmaslik yaxshiroqdir.

Siz kodni kiritishingiz mumkin. U standart MS VS 2017 shablonidan yaratilgan kodga asoslangan edi.

Teglar: teglar qo'shish

C WinAPI - bu operatsion tizimlarda mavjud bo'lgan Microsoft dastur interfeyslarining (API) asosiy to'plami Win32 API deb nomlangan.

Kirish

WinAPI - bu Windows dasturlarini yaratish uchun ishlatiladigan amaliy dasturlash interfeysi. Boshlash uchun ishlab chiquvchi ilgari Platforma SDK sifatida tanilgan Windows SDK dan foydalanishi kerak.

Sarlavhali fayllarni, kutubxonalarni, rasmlarni, hujjatlarni va dasturlarni ishlab chiqishda foydalaniladigan vositalarni birlashtiring. C va C++ tillarida dasturlash uchun API. Bu kompaniyaning operatsion tizimida qo'shimchalarni yaratishning eng to'g'ridan-to'g'ri usuli.

WinAPI yordamida siz uni bir necha sohalarga bo'lishingiz mumkin:

    asosiy xizmatlar;

    xavfsizlik;

  • Koristuvalnitskiy interfeysi;

    multimedia;

    Windows qobig'i;

    Merezhevy xizmatlari.

Asosiy xizmatlar asosiy resurslardan foydalanishni ta'minlaydi. Bularga WinAPI, fayl tizimlari, qurilmalar, jarayonlar, mavzular, ro'yxatga olish kitobi va xatolarni qayta ishlash funktsiyalari kiradi. Xavfsizlik maydoni autentifikatsiya, avtorizatsiya, kriptografiya va xavfsizlik bilan bog'liq boshqa vazifalar uchun interfeyslar, ob'ektlar va boshqa dasturlash elementlarini o'z ichiga oladi. Grafik quyi tizimi monitorlar, printerlar va boshqa displey qurilmalarida grafiklarni ko'rsatish uchun funksionallikni ta'minlaydi. Koristuvach interfeysi oynalar va koristuvach elementlarini yaratish uchun funksionallikni ta'minlaydi.

Multimedia komponenti video, audio va kiritish qurilmalari bilan ishlash vositalarini taqdim etadi. Shell interfeysi funktsiyalari dasturlarga operatsion tizim qobig'i tomonidan taqdim etilgan funktsiyalarga kirish imkonini beradi. Merezhevi xizmatlari Windows-da maksimal darajada kirishni ta'minlaydi.

Komponentlar

WinAPI ishga tushirilganda, siz ettita toifaga bo'lingan Windows API-ning asosiy imkoniyatlaridan foydalanasiz. Keling, ularning hisobotining terisini ko'rib chiqaylik.

Asosiy xizmatlar Windows tizimidagi asosiy tizim resurslariga kirishni ta'minlaydi. Ilovalar: fayl tizimi, periferik qurilmalar, jarayonlar, tizim registriga va yadrolar tizimiga kirish. Bu funksiyalar 16-bitli tizimlar uchun kernel.exe, krnl286.exe yoki krnl386.exe va 32-bitli tizimlar uchun kernel32.dll va advapi32.dll fayllarida saqlanadi.

Grafik interfeys monitorlar, printerlar va boshqa periferik qurilmalarda ko'rsatish uchun resurslarga kirishni ta'minlaydi. U 16 bitli tizimlarda gdi.exe faylida va 32 bitli tizimlarda gdi32.dll faylida saqlanadi.

Foydalanuvchi interfeysi interfeysi asosiy elementlarning ko'rinishi bilan tavsiflanadi, masalan, tugmalar va aylantirish, klaviatura va sichqonchalar haqidagi ma'lumotlar, shuningdek, ular bilan bog'liq funktsiyalar. Bu funksiyalar 16 bitli tizimlarda user.exe faylida, 32 bitli tizimlarda user32.dll comctl32.dll faylida saqlanadi. XP versiyasidan boshlab boshqaruv elementlari comctl32.dll da guruhlangan.

Maxfiy dialoglar - fayllarni ochish va saqlash, ranglar va shriftlarni tanlash uchun ma'lumotlarni ko'rsatish. Fayl 16 bitli tizimlarda comdlg.dll va 32 bitli tizimlarda comdlg32.dll.

Windows Shell - bu WinAPI komponenti bo'lib, dasturlarga operatsion tizim qobig'i tomonidan taqdim etilgan funktsiyalarga kirish imkonini beradi.

Tarmoq xizmatlari operatsion tizimning maksimal imkoniyatlaridan foydalanishni ta'minlaydi. Uning subkomponentlariga NetBIOS, Winsock, RPC kiradi. Eski versiyalarda NetDDE mavjud.

Versiyalar

Win16, Win32 va Win32s standart komponentlar to'plami bo'lib, ular amaliy dasturlarga Windows oilasining turli operatsion tizimlarining funktsiyalarini bajarishga imkon beradi.

Win16 vorisi Win32 1993 yilda Windows oilasining 32 bitli mahsulotlarida, masalan, Windows NT, 2000, 95da taqdim etilgan. Ushbu dasturiy interfeys uchta dasturiy kutubxonani amalga oshiradi: Kernel32.dll, User32.dll va GDI32.dll2. Xuddi shu Win32 funksiyalari barcha Windows mahsulotlarida mavjud va mahsulotga qarab, bu funksiyalarning qo‘shilishi xizmat bilan bog‘liq muammolarga olib kelishi mumkin.

Win32 ning imkoniyatlariga dasturlar, jarayonni boshqarish, kompyuter fayllari, printerlar, serverlar va aloqa portlari o'rtasidagi aloqa kiradi.

Spetsifikatsiya

WinAPI - bu Windows operatsion tizimi uchun dasturlash interfeysi uchun mavhum spetsifikatsiya. Funktsiyalar, ulanishlar, tuzilmalar, ma'lumotlar turlari, makrolar, konstantalar va boshqa dasturlash elementlari deklaratsiyasidan iborat. WinAPI sarlavha tomonidan tasvirlangan va Windows C sarlavhalarida joylashgan WinAPI funktsiyasining rasmiy amalga oshirilishi dinamik kutubxonalarda (DLL) joylashgan: masalan, tizimda kernel32.dll, user32.dll, gdi32.dll va shell32.dll. katalog. Windows API-ning uchinchi tomon ilovalari mavjud: eng muhimi, Wine loyihasi va ReactOS loyihasi.

Windows API dinamik ob'ektdir. OSning har bir yangi versiyasi va yangi yangilash paketlari bilan funktsiyalar soni asta-sekin o'sib bormoqda. Server versiyalari va operatsion tizimning ish stoli versiyalari o'rtasida ham muhim farqlar mavjud. Ushbu funktsiyalar rasmiy ravishda hujjatlashtirilmagan.

Pelles C

Pelles C - bu dasturiy ta'minotsiz dastur va eng tezkor C kompilyatori va C tilida dasturlash uchun integratsiyalashgan ishlab chiqish mexanizmi (IDE) 32-bit Windows (x86) va 64-bit Windows (x64) ni qo'llab-quvvatlaydi. C99 va C11 standartlarini amalga oshiradi. Pelles tarkibiga resurs muharriri, bitmap tasviri, piktogramma, kursor muharriri va o'n oltita dump muharriri kiradi. Shved sotuvchisi Pelle Orinius tomonidan ochib berilgan. Kompilyatorning nomi uning muallifi nomini oladi. SDK bilan birga dasturchi yaratilgan dasturni qo'shimcha o'rnatmasdan darhol chop etishi mumkin.

Maqsadli arxitektura

Windows API dasturlarini yaratish uchun siz Microsoft kengaytmalarini yoqishingiz kerak. Uning orqasida yoqimsiz hid bor, shu sababli kompilyator xato haqida xabarni ko'radi, go'yo bu buzilgan tuzilishga ega C WinAPI ilovasi: halokatli xato #1014: #error: "Maqsadli arxitektura yo'q". Microsoft kengaytmasini yoqish uchun loyiha parametrlariga o'ting va "Tuzuvchi" yorlig'ini tanlang. Ushbu yorliqda "Microsoft kengaytmalarini o'chirish" opsiyasi faollashtirilgan.

MSDN

Bu Windows-ni o'rnatish uchun markaziy portal. Bu turli xil Microsoft vositalaridan dasturlarni ishlab chiqish bilan bog'liq ajoyib materiallar to'plami. Ish stoli ilovalarini ishlab chiqish hujjatlari va Windows API ro'yxati bilan to'liq ma'lumotlar bazasi.

WinAPI C da Zastosuvannya DLL

Kengaytirilgan elementlar kutubxonasi qatorlar, oyna ko'rsatkichlari, asboblar paneli va yorliqlar kabi operatsion tizimning ilg'or funktsiyalariga kirishni ta'minlaydi. Ushbu buyruqlar commctrl.dll kutubxonasida 16 bitli tizimlarda va comctl32.dllda joylashgan va mijoz interfeysi bilan guruhlangan.

DLL bu Windows dasturlari uchun bir nechta kodlar va protseduralarni saqlash uchun ishlatiladigan dinamik kutubxona fayl formatidir. DLL fayllari shunday yaratilganki, bir qator dasturlar o'z ma'lumotlariga bir zumda kirishlari va shu bilan xotirani tejashlari mumkin edi. Foydalanuvchilarga bir nechta dasturlarda kodni o'zgartirmasdan tahrirlash imkonini beradi. DLL kutubxonalari statik, vikorist MSIL Disassembler yoki Lib 3.00 uchun DLL ga aylantirilishi mumkin.

Winapi Yak INTERFAS Windows Proponovs of Flood Forms, Yaki ularning belgilarini saqlashga imkon beradi, bu shunchaki grafik ilnterphys mahkumlariga fayllarni Nizorivniye Haydovchilarning sud jarayoni uchun kiritish ekanligi aniq. Nastyv.

WinAPI bilan dasturlashni boshlashdan oldin, Windows-da kod uchun o'rta zaminni o'rnatishingiz kerak. Garchi u Linux distribyutsiyasi bo'lmasa-da, qo'shimchalarni yaratish uchun o'rnatilgan kompilyatorga ega emas. Keling, kodni kompilyatsiya qilishning quyidagi variantlarini ko'rib chiqaylik:


Windows uchun ishlab chiquvchilar to'plami mavjud bo'lib, u ishlab chiquvchilarga Wikimedia API va tegishli texnologiyalar bilan dasturiy ta'minot yaratish imkonini beruvchi hujjatlar va vositalarni taqdim etadi.

Windows API - operatsion tizim funktsiyalari to'plami

API qisqartmasi ko'plab yangi dasturchilar uchun noaniq va chalkash ko'rinadi. Aslida, amaliy dasturlash interfeysi (API) shunchaki qo'shimcha sotuvchilar tomonidan ishlatilishi mumkin bo'lgan tayyor funktsiyalar to'plamidir. Rasmiy ma'noda bu kontseptsiya ilgari ko'pincha kichik dasturlar kutubxonasi deb ataladigan narsaga tengdir. Biroq, shuni yodda tutingki, API ostida bunday kutubxonalarning maxsus toifasi mavjud.

Ishlab chiqish jarayonida oxirgi foydalanuvchi uchun muayyan dasturni amalga oshirish uchun zarur bo'lgan o'ziga xos ichki funktsiyalar to'plami shakllantiriladi, bu MyApplication API deb ataladi. Biroq, ko'pincha bu funktsiyalardan boshqa dasturlarni, shu jumladan boshqa dasturlarni yaratishda samarali foydalanish mumkinligi aniqlangan. Mualliflar o'z mahsulotlarini sotish strategiyasidan kelib chiqib, qanday yo'l bilan ovqatlanishni tanlaydilar: nima uchun ular tashqi mijozlar uchun qaysi to'plamga kirishga ruxsat berishadi? Agar tasdiqlansa, dasturiy ta'minot to'plamining ijobiy xarakteristikasi sifatida tavsifi quyidagi iborani o'z ichiga oladi: "To'plam API funktsiyalarining to'liq to'plamini o'z ichiga oladi" (yoki qo'shimcha pul uchun).

Shunday qilib, ko'pincha API ostida bitta dasturning bir qismi bo'lgan, ammo boshqa dasturlarda foydalanish uchun mavjud bo'lgan funktsiyalar to'plami mavjud. Misol uchun, Excel oxirgi foydalanuvchi interfeysiga qo'shimcha ravishda, masalan, VB yordamida yaratilgan dasturlar bilan kirish mumkin bo'lgan Excel API funktsiyalari to'plamiga ega.

Ko'rinishidan, Windows API - bu operatsion tizimning bir qismi bo'lgan va bir vaqtning o'zida boshqa har qanday dastur, shu jumladan VB yordamida yozilgan funktsiyalar to'plami. Ushbu reja tizim BIOS/DOSni bekor qilish to'plamiga to'liq o'xshaydi, bu aslida DOS API.

Windows API funksionalligining afzalligi, bir tomondan, DOS-ga qaraganda ancha kengroq bo'lsa, ikkinchi tomondan, u sobiq OTdagi dasturlarda mavjud bo'lgan kompyuter resurslarini bevosita boshqarish uchun ko'plab funktsiyalarni o'z ichiga olmaydi. Bundan tashqari, Windows API ga ulanish qo'shimcha protsessual parametrlarga asoslanadi va DOS funksiyasiga Interrupt deb nomlangan maxsus protsessor mashinasi buyrug'i orqali kirish mumkin.

VB dasturchilar uchun eng zarur Win API

Nima bo'lishidan qat'iy nazar, VB hech qanday turli funktsiyalarga ega emas, ko'proq yoki kamroq jiddiy rivojlanish jarayonida ularning imkoniyatlari ko'pincha zarur vazifalarni bajarish uchun etarli emasligi aniqlandi. Bu holda, yangi boshlanuvchilar dasturchilar tez-tez VB-da skimp boshlaydi va vositalari o'zgartirish haqida o'ylash, ularning kompyuter xarajatlar katta majmui bor va ularni tez kiritish kerak, deb gumon emas.

Win API bilan tanishganingizda, ma'lum bo'ladiki, VB-ning juda ko'p qo'llaniladigan funktsiyalari mavjud bo'lib, ular muayyan tizim protseduralari uchun ishlab chiqilgandan boshqa narsa emas, lekin faqat ushbu tilning sintaksisi bo'yicha amalga oshiriladi. Tez APIga bo'lgan ehtiyojga asoslanib, mavjud variantlar:

  1. Odatda VB funktsiyalari shaklida amalga oshiriladigan API funktsiyalari. Vaqt kam emas, bu holda API turg'unligiga o'tish kerak bo'lishi mumkin, bu sizga unumdorlikni tezda oshirishga imkon beradi (o'tkaziladigan parametrlarda keraksiz o'zgarishlarning yo'qligi bundan mustasno).
  2. Yaratilgan VB funktsiyalari faqat API funktsiyalarining bir qismi sifatida amalga oshiriladi. Mana oddiyroq variant. Masalan, CreateDirectory API funksiyasi VB MkDir operatoriga nisbatan katta imkoniyatlarga ega.
  3. VB tilining joriy versiyasida o'xshashi bo'lmagan ko'p sonli API funktsiyalari mavjud. Masalan, VB yordamida katalogni o'chirish mumkin emas - buning uchun DeleteDirectory funksiyasidan foydalanish kerak.

Shuni ham ta'kidlash kerakki, ba'zi API funktsiyalariga (ularning ba'zilari Win API-da hatto ahamiyatsiz) VB dasturlaridan bir qator til interfeyslari orqali kirish mumkin emas, masalan, xotira manzillari bilan ishlash qobiliyati yo'qligi sababli. Biroq, bir qator hollarda, noan'anaviy dasturlash usullari yordam berishi mumkin (xuddi shu manzillar bo'lsa).

Muallifning o'ziga xos g'oyasi shundaki, versiyani VB tomonidan ishlatiladigan funktsiyalar versiyasiga kengaytirish o'rniga, quyida eng keng tarqalgan API funktsiyalarining yaxshi tavsifi beriladi. Shu bilan birga, men ishlab chiquvchilarni kengaytirilgan funktsiyalarga ega bo'lgan xususiyat uchun yangi versiyaning paydo bo'lishini kutmasdan, balki original Win API zaxirasini hisobga olishlarini iltimos qilmoqchiman - bu sizning imkoniyatlaringiz aniq ekanligi aniq. Ehtiyoj 1991 yil í̈ VB 1.0 versiyasida amalga oshirilishi mumkin edi.

Yak vivchati Win API

Win32 API funktsiyalari soni taxminan 10 mingga baholanganini eslash unchalik oson emas (Microsoft kabi aniq raqamni hech kim bilmaydi).

VB ombori (4-6 versiyalari) Win API - WIN32API.TXT tavsifi bilan faylni o'z ichiga oladi (uni amalga oshirish bo'yicha hisobot keyinroq e'lon qilinadi). Avvalo, ushbu yordam yordamida siz ushbu va boshqa funksiya va parametrlarning ma'nosi haqidagi ma'lumotlarni quyidagi mnemonik nomlardan tashqari ko'rishingiz mumkin va boshqacha aytganda, bu faylning funktsiyasi bir xil emas. Hozirgi vaqtda (omad bo'lsa), VB 3.0 da Win16 API funktsiyalarini tavsiflovchi maxsus kontseptsiyani tasdiqlovchi fayllar mavjud edi. v.4.0 da ushbu qimmatli ma'lumot allaqachon qo'lda interfeys orqali mavjud.

Win32 API haqida qo'shimcha ma'lumotni oldingi Platforma dasturiy ta'minotini ishlab chiqish to'plamida topish mumkin, u VB 5.0, 6.0 Enterprise Edition va Office 2000 Developer Edition bilan birga MSDN Library CD-larida ham mavjud. Biroq, u erda kerakli ma'lumotlarni topish va unga kirish oson emas. U erdagi barcha tavsiflar butunlay C tomonidan qilinganligini eslatib o'tmasdan.

VB muhitlarida API dasturlash bo'yicha dunyoning eng tanish tanishuvi taniqli amerikalik mutaxassis Daniel Applemanning kitobidir. Den Applemanning Windows API bo'yicha Visual Basic dasturchi qo'llanmasining ushbu seriyasi (Win16, Win32, VB ning yuzlab turli versiyalari uchun) 1993 yildan beri doimiy ravishda VB dasturchilari uchun eng yaxshi sotuvchiga aylandi. 1997 yilda nashr etilgan Den Applemanning VB 5.0 dasturchining Win32 API uchun qo'llanmasi kitobini muallifga AQShdan kichik bir viloyat shaharchasidagi birinchi kitob do'koni haqida bilgan do'sti olib kelgan.

1500 dan ortiq sahifadan iborat ushbu kitob VB-da API dasturlashning ilg'or usullari, shuningdek, 900 dan ortiq funksiyalarning tavsifini o'z ichiga oladi. CDda kitobning to'liq matni va barcha dasturiy ta'minot ilovalari, shuningdek, ikkinchi versiyaga chiqmagan bir qator qo'shimcha bo'limlar mavjud. 1999 yilda Den Appleman Den Applemanning Win32 API jumboq kitobi va Visual Basic dasturchilari uchun o'quv qo'llanmasini chiqardi, unda yana 7600 ta funksiyaning umumiy ko'rinishi (hisobot taxtasi bo'lmasa ham) mavjud.

Win API va Dynamic Link Library (DLL)

Dinamik DLL kutubxonalari sifatida Win API ilovalari to'plami. Keyinchalik Win API omboriga kiritilgan kutubxonalarni qo'llashda VB o'rtasida DLL-larni o'rnatish texnologiyasi haqida gapiramiz. Biroq, DLL haqida gapirganda, juda ko'p hurmat qozonish kerak.

Bunday holda, DLL ostida biz kerakli protseduralarga - kichik dasturlarga yoki funktsiyalarga to'g'ridan-to'g'ri konvertatsiya qilishni ta'minlaydigan dual dinamik kutubxonalarning an'anaviy versiyasini hurmat qilishimiz mumkin (taxminan VB loyihasining o'rtasida protseduralarni bosish kutilgandek). . Bunday kutubxonalar boshqa vositalar yordamida yaratilishi mumkin: VC++, Delphi, Fortran va VB (7.0 versiyasida paydo bo'lishiga qarab) - qolganlari ActiveX DLLsiz ishlashi mumkin, ularga kirish OLE Automation interfeysi orqali sozlangan.

Dinamik kutubxona fayllari kengaytmani o'z ichiga olishi mumkin.DLL, lekin bu shart emas (Win16 uchun kengaytma.EXE ko'pincha tiqilib qolgan); Tashqi qurilmalar drayverlari qo'shimcha DRV ostida keltirilgan.

Yuqorida aytib o'tganimizdek, Windows API funktsiyalari va fayllari tizim katalogida saqlanishi uchun ularning aniq sonini aniqlash muhim ahamiyatga ega. Ushbu reja operatsion tizim yadrosiga qadar bo'lgan kutubxona omborini va asosiy qo'shimcha funktsiyalarga ega asosiy kutubxonalarni ko'rishni afzal ko'radi.

Va endi men baxtliman.

Iltimos, 1. DL e'lonining to'g'ri formatlanishiga rioya qiling L-protseduralar

Dasturning DLL protseduralarigacha bo'lgan ierarxiyasi "asosiy" Visual Basic protseduralari bilan bir xil ko'rinadi, masalan:

DllName-ga qo'ng'iroq qiling ([argumentlar ro'yxati])

Biroq, tashqi DLL funksiyalaridan (jumladan, Win API-dan) foydalanish uchun ular dastur tomonidan Declare bayonoti yordamida chaqirilishi kerak, bu quyidagicha ko'rinadi:

Quyi protsedura nomini e'lon qilish Lib _ "Kutubxona nomi" _ [([Argumentlar ro'yxati])]

Funksiya nomini e'lon qilish _ Lib "Kutubxona nomi" _ [([Argumentlar ro'yxati])]

Bu yerda, kvadrat ustunlarda operatorning zarur elementlari ko'rsatilgan, o'zgaruvchan so'zlar kursiv bilan, kalit so'zlar esa kursiv bilan ko'rsatilgan. Murakkab tizim operator sintaksisining yaxshi tavsifini ta'minlash uchun ishlab chiqilgan, bu esa ba'zi fikrlarni ahamiyatsiz qiladi.

Tashqi funktsiyalarning aksariyati modulning Umumiy deklaratsiyalar bo'limida joylashgan. Agar siz uni forma moduliga joylashtirsangiz, Private kalit so'zini ko'rsatishingiz kerak (bu faqat modulning o'rtasida mavjud bo'ladi) - bu forma modulining barcha protseduralari uchun bir xil.

Win32 API ilovalari to'plami funksiyalar bilan cheklangan (Win16 API-da juda ko'p pastki dasturlar mavjud edi). Bu, ayniqsa, ko'pincha operatsiyani yakunlash kodini qaytaradigan Long tipidagi funktsiyalar uchun to'g'ri keladi.

Declare operatori allaqachon DOS uchun MS Basic-da paydo bo'lgan va loyihaga ichki protseduralarni etkazish uchun ishlatilgan. Bu Visual Basic-ga kerak emas, chunki ichki protseduralar deklaratsiyasi avtomatik ravishda ularning Sub va Funktsiya tavsiflarini tavsiflaydi. Basic/DOS-dan moslashtirilgan yangi tavsifda protsedura joylashgan kutubxona faylining nomi ko'rsatilishi kerak. Wip API kutubxonalari Windows tizimi katalogida joylashgan bo'lib, faqat fayl nomi talab qilinadi. Agar siz DLL ustida ishlayotgan bo'lsangiz, ishonch hosil qilish uchun ushbu faylga yangi yo'l yozishingiz kerak bo'ladi.

Declare operatorining tavsifi juda ko'p joy egallaydi va kod oynasi yaqinidagi bir qatorga to'g'ri kelmaydi. Shuning uchun biz dasturlarni yozishda har qanday turdagi qatorlarni uzatish sxemasiga e'tibor berishni tavsiya qilamiz, masalan:

Funktsiyani e'lon qiling GetTempPath _ Lib “kernel32” taxallus ​​“GetTempPathA” _ (ByVal nBufferLength As Long, _ ByVal lpBuffer String sifatida)

Va bu erda turli qatorlar tavsifining barcha asosiy elementlari tasvirlangan va o'qish yaxshi.

Iltimos, 2. DLL funksiyalari bilan ishlashda ayniqsa hurmatli bo'ling

Win API va turli DLL funktsiyalaridan foydalanish VB ning funktsional imkoniyatlarini sezilarli darajada kengaytiradi va ko'pincha dastur unumdorligini oshirishga imkon beradi. Biroq, narxni to'lash uchun narx, ayniqsa, ishlab chiqish jarayonida robotli dasturlarning ishonchliligining pasayishi hisoblanadi.

VB oraliq dasturining eng muhim afzalliklaridan biri bu dasturni ishlab chiqish jarayonining ishonchliligidir: tarjimon ramkasi ostida ishlaydigan dastur kodini Windows va VB robotini buzish nazariy jihatdan imkonsizdir. Dasturchi chaqirilayotgan funktsiyaga parametrlarni o'tkazishning to'g'riligiga juda ehtiyot bo'lmasligi mumkin - bunday xatolar kodni tarjima qilish jarayonida yoki uni bajarish paytida tarjimonning o'zi tomonidan osongina aniqlanadi. Eng yomon stsenariyda, ma'no, qaerda va nima sodir bo'lganligi nuqtai nazaridan, ishlov berish rejimida shunchaki uzilish bo'ladi.

Windows API yoki boshqa DLL kutubxonalarining to'g'ridan-to'g'ri funktsiyalaridan foydalanish ma'lumotlarni uzatish va VB o'rtasidan tashqaridagi kodga birlashtirish jarayonini nazorat qiladi. Shuning uchun tashqi funksiyalardagi murosa VB va operatsion tizimning ishlamay qolishiga olib kelishi mumkin. Bu, ayniqsa, imtiyozlarning mavjudligi mutlaqo tabiiy bo'lsa, dasturni ishlab chiqish bosqichida juda muhimdir. Shunday qilib, bazaviy tizim funktsiyalarining keng doirasi tufayli dasturchi ularni amalga oshirishning to'g'riligi uchun javobgarlikni o'z zimmasiga oladi.

Muammo turli dasturlarning protseduralar o'rtasida parametrlarni o'tkazishning turli usullariga ega ekanligi bilan yanada murakkablashadi. (Aniqrog'i, turli xil uzatish usullari muhokama qilinadi, chunki ko'pchiligimiz bir qator usullarni qo'llab-quvvatlay olamiz.) Win API C/C++ da amalga oshirilgan va biz ushbu tizimda qabul qilingan Are Excluded kabi parametrlarni uzatish haqida gapirishimiz kerak. standart VB variantidan.

Shu munosabat bilan shuni ta'kidlash kerakki, API funktsiyalarining VB analoglarining paydo bo'lishi qolganlarini VB sintaksisiga moslashtirish va ma'lumotlar almashinuvini boshqarishning shunga o'xshash mexanizmini amalga oshirish bilan oqlanadi. Biz, shuningdek, dasturlarni yakuniy ishlab chiqish bosqichida kompilyatsiya qilingan modulni qurishda Native Code (mashina kodi) o'rniga P-kodni kompilyatsiya qilish variantini tanlash yaxshidir. Dastlab, dastur tarjimon nazorati ostida ishlaydi - mashina kodini ishlatishdan ko'ra, lekin operatsion tizimga qarash va mumkin bo'lgan xatolarni aniqlash uchun qo'lda rejimni ta'minlash orqali.

Porada 3. Dan Applemandan VB o'rta dasturida ishonchli API dasturlash uchun o'nta tavsiyalar

API ning turli funktsiyalari protseduralarni kengaytirishning oddiy bo'lmagan usullaridan foydalangan holda (VBga nisbatan) ehtiyotkorlik bilan dasturlashni talab qiladi. Biz asta-sekin bu oziq-ovqatdan o'zimizni och qolamiz. Va endi biz Den Applemanning ushbu mavzu bo'yicha munozaralarining qisqacha mazmunini (birinchi versiya 1993 yilda paydo bo'lgan) ba'zi qo'shimcha sharhlarimiz bilan taqdim etamiz.

1. ByVal haqida eslang. Funktsiyalardan oldin API va DLL amalga oshirilganda yuzaga keladigan eng keng tarqalgan muammo ByVal kalit so'zining noto'g'ri lug'atida yotadi: ular uni qo'yishni unutishadi yoki oxir-oqibat, kerak bo'lmaganda qo'yishadi.

Ushbu misollar parametrlarni uzatish uchun ByVal operatorining kiritilishini ko'rsatadi

Parametr turi Z ByVal ByVal holda
Butun son Stack 16 bitli sig'imga ega Stack 16 bitli butun sonning 32 bitli manzillarini joylashtirishi mumkin
Uzoq Stack 32 bitli sig'imga ega Stack 32 bitli butun sonning 32 bitli manzillarini sig'dira oladi
String Ketma-ketlik C da qo'llaniladigan formatga aylantiriladi (oxirgi null bayt berilgan). Yangi qatorning 32-bitli manzillari stekga joylashtirilgan Stek qatorning VB deskriptorini o'z ichiga oladi. (Bunday identifikatorlar hech qachon Windows API-ning o'zi tomonidan tan olinmaydi va faqat VB uchun maxsus o'rnatilgan DLL-larda tan olinadi.)

Bu erda shuni ta'kidlash joizki, har qanday dasturlash tizimida, shu jumladan VBda parametrlarning uzatilishi ikkita asosiy bosqich bilan belgilanadi: yuborish (ByRef) yoki qiymat (ByVal). Birinchi variant birja manzilini oladi (bu variant VBda almashish uchun ishlatiladi), ikkinchisi uning qiymatini oladi. Yaroqlilik printsipi shundan iboratki, qo'shimcha xabardan so'ng qo'ng'iroq qiluvchi dastur o'tgan parametrning o'zgartirilgan qiymatiga qaytarilishi ta'minlanadi.

Boshlash uchun quyidagi dasturlardan foydalangan holda tajriba o'tkazing:

Dim v Butun son sifatida v = 2 MyProc(v) MsgBox “v = “ & v Sub MyProc (v Integer) v = v + 1 End Sub-ga qo'ng'iroq qiling

Ushbu ilovani ishga tushirgandan so'ng, siz 3 ga teng o'zgaruvchining qiymatlari haqida ma'lumotni ko'rasiz. O'ng tomonda, bu holda, v o'zgaruvchining manzillari bosilgan dastur tomonidan jismoniy yaratilgan, MyProc kichik dasturiga o'tkaziladi. . Endi protsedura tavsifini o'zgartiring

Sub MyProc (ByVal v butun son sifatida)

Natijada, testni o'tkazganingizda, siz v = 2 ni olib tashlaysiz, bu o'zgaruvchining chiqish qiymati protseduraga o'tganligini bildiradi - unda bajariladigan amallarning natijasi chaqiruvchi dasturga qaytarilmaydi. Qiymatlarni uzatish rejimini Qo'ng'iroq operatori yordamida ham quyidagi tarzda o'zgartirish mumkin:

Sub MyProc (v As Integer) ... MyProc ((v)) '(v) ga qo'ng'iroq qiling - qo'llar uzatish rejimini ko'rsatadi _ qiymatlar ortida.

Biroq, ichki VB-protseduralarga kengaytirilganda, Call bayonotida ByVal kalit so'zidan foydalanish bostiriladi - buning o'rniga dumaloq qo'llar bloklanadi. Mana tushuntirish.

Klassik versiyada (C, Fortran, Paskal) ByRef va ByVal rejimlarining ahamiyati ma'lumotlar almashinuvi stekiga nima joylashtirilganiga - almashinuv manzillari yoki qiymatlariga bog'liq. Basic-da, dasturiy ta'minot emulyatsiyasining ByVal versiyasi tarixan ishlatilgan - stek har doim manzillarni o'z ichiga oladi, vaqt o'zgarishi yaratilgan qiymatlarni o'tkazish hollari bundan mustasno. Ikki variantni (Klassik va Asosiy) farqlash uchun ByVal rejimini tavsiflashning turli usullari mavjud. VB-da ByVal rejimining emulyatsiyasi dasturlarning ishonchliligini ta'minlashi juda muhim: konvertatsiya shaklini aralashtirib, dastur chertgan dasturni aylantirish (yoki aylantirilmaydi) qiymatini to'g'irlashdan mahrum qilish xavfini tug'diradi. o'zgartirish. "Klassik" versiyada bunday chalkashlik yakuniy protsedura bir soat ichida halokatli o'limga olib kelishi mumkin (masalan, vikoristning xotira manzili o'rniga o'zgaruvchan qiymatlar mavjud bo'lsa, masalan, nolga teng. ).

DLL funktsiyalari "klassik" tamoyillarga muvofiq amalga oshiriladi va shuning uchun har bir argument bilan ma'lumotlar almashinuvining aniq tavsifini talab qiladi. Buning o'zi E'lon qilish tavsifi (aniqrog'i, uzatiladigan argumentlar ro'yxati) orqali e'lon qilish funktsiyasi sifatida xizmat qilishi mumkin. Ko'pincha, parametrlarni Windows API funktsiyasi yoki DLL ga o'tkazish ByVal kalit so'zi yordamida belgilanadi. Bundan tashqari, uni e'lon qilish operatorida yoki to'g'ridan-to'g'ri funktsiyani chaqirganda ko'rsatish mumkin.

Noto'g'ri parametrlarni uzatish merosini uzatish oson. Agar siz yaroqsiz manzilni tanlasangiz, GPF (Umumiy himoya xatosi) bildirishnomasini ko'rasiz. Funktsiya to'g'ri manzildan qochib ketadigan qiymatlarni olganligi sababli, API funktsiyasi chet el hududiga (masalan, Windows yadrosiga) kiradi va har xil halokatli oqibatlarga olib keladi.

2. O'tkazilayotgan parametrlar turini o'zgartiring. O'tkazilgan parametrlarning to'g'ri soni va turi ham bir xil darajada muhimdir. Declare-da e'lon qilingan argumentlar API funktsiyasi parametrlariga mos kelishi kerak. Parametrlarni o'tkazish bilan bog'liq eng katta muammo NULL va nollar qatori o'rtasidagi farq bilan bog'liq - bitta va bir xil bo'lgan xotira izi.

3. Aylanayotgan qiymat turini tekshiring.

VB funktsiya tomonidan aylantiriladigan qiymatlar turlarining xilma-xilligini o'rnatishga toqat qiladi va ba'zi raqamli qiymatlar stek orqali emas, balki registrlar orqali aylantiriladi. Quyidagi qoidalar API funktsiyasi tomonidan qaytariladigan to'g'ri qiymatlarni aniqlashga yordam beradi:

  • Qiymatlarni aylantirmaydigan DLL funktsiyasi ("C" dagi bekorga o'xshash) VB Sub kabi o'chirib qo'yilishi mumkin.
  • Qiymatni (Integer yoki Long) aylantiruvchi API funksiyasi Sub yoki ma'lum turdagi qiymatlarni aylantiruvchi funksiya sifatida belgilanishi mumkin.
  • Ushbu API funktsiyasi suzuvchi nuqta raqamlarini aylantirmaydi, lekin DLL-lar bu turdagi ma'lumotlarni aylantirishi mumkin.

4. Har qanday konstruktsiyadan katta ehtiyotkorlik bilan foydalaning. Ko'pgina Windows API funktsiyalari har xil turdagi parametrlarni qabul qilish va ularni As Any konstruktsiyasiga asoslangan holda ishlatish qobiliyatiga ega (turni talqin qilish o'tkazilgan boshqa parametrlarning ma'nosiga bog'liq).

Yaxshi echimlar bir xil funktsiyalarni almashadigan ikkita yoki undan ko'p o'rtasida bir nechta taxallus (taxallus) funktsiyalariga ega bo'lishi mumkin va parametrlar har bir tavsif qo'shiq turida ko'rsatilgan.

5. Qatorlarni ishga tushirishni unutmang. Win API parametr sifatida uzatiladigan qator buferlaridan ma'lumotlarni yig'ish orqali ma'lumotni aylantiruvchi oddiy funksiyaga ega. Dasturingizda siz hamma narsani to'g'ri bajarishingiz mumkin: ByVal haqida unutmang, funktsiyaga parametrlarni to'g'ri o'tkazing. Ammo Windows ko'rilgan saqlash maydoni qanchalik katta ekanligiga ishonolmaydi. Qatorning o'lchami unga joylashtirilishi mumkin bo'lgan barcha ma'lumotlarni joylashtirish uchun etarli bo'lishi kerak. Kerakli o'lchamdagi buferni zaxiralash uchun javobgarlik VB dasturchisi zimmasiga tushadi.

Shuni esda tutingki, 32-bitli Windows-da, turli qatorlar bilan, milliy tizim sozlamalariga qarab, Unicode (ikki baytli kodlash) dan ANSI (bir baytli kodlash) ga va orqaga aylantirish mumkin. Shuning uchun, buferlarni zahiraga olish uchun odatdagilar o'rniga bayt massivlaridan foydalanish xavfsizroqdir. (Bu haqdagi hisobot quyida muhokama qilinadi.)

Ko'pgina Win API funktsiyalari maksimal blok hajmini o'zingiz belgilashga imkon beradi. Masalan, blokning o'lchamini ko'rsatish uchun boshqa API funksiyasini chaqirishingiz kerak. Masalan, GetWindowTextLength sizga GetWindowText funksiyasi tarkibidagi oynaning sarlavhasini joylashtirish uchun zarur bo'lgan qator hajmini aniqlash imkonini beradi. Shu sababli Windows chegaradan tashqariga chiqmasligingizga kafolat beradi.

6. Vikorize Option Explicit ikkala tilda ham.

7. Parametrlarning qiymatlarini va aylantirilayotgan qiymatlarni diqqat bilan tekshiring. VB turlarni tekshirish imkoniyatiga ega. Bu shuni anglatadiki, agar siz VB funktsiyasiga noto'g'ri parametrni o'tkazishga harakat qilsangiz, eng yomoni VB dan xato xabarini rad etishingiz mumkin. Afsuski, bu mexanizm Windows API funksiyasiga yangilanganda ishlamaydi.

Windows 9x ko'pgina API funktsiyalari uchun parametrlarni tekshirish uchun murakkab tizimga ega. Shuning uchun, ushbu ma'lumotlarda kechirimning mavjudligi halokatli kompensatsiyani anglatmaydi, ammo bunga nima sabab bo'lganini aniqlash unchalik oson emas.

Bu erda sutning ushbu turini yaxshilashning bir qancha usullarini topishingiz mumkin:

  • API funksiyasining teri javobini tekshirish uchun terini sozlash rejimini yoki Debug.Printni tekshiring. Har bir narsa normal chegaralarda ekanligiga va funksiya to'g'ri bajarilganligiga ishonch hosil qilish uchun ushbu bosish natijalarini ko'rib chiqing;
  • Vikorist - CodeView va Windows-ning moslashtirilgan versiyasi (Windows SDK-dan) kabi Windows-ga asoslangan dasturchi. Ushbu funktsiyalar parametrlarning o'zgarishini aniqlashi va eng muhimi, qaysi API funksiyasini o'zgartirish kerakligini aniqlashi mumkin;
  • Parametrlarning turlarini va ularning qiymatlarining maqbulligini tekshirish uchun uchinchi tomon kompaniyalarining qo'shimcha xususiyatlarini tekshiring. Bunday usullar nafaqat parametr o'zgarishlarini topibgina qolmay, balki VB kodiga o'zgartirish kiritilgan joyni ham aytib berishi mumkin.

Bundan tashqari, API funktsiyasining natijasini diqqat bilan tekshirish kerak.

8. VB va Windows dagi raqamlar bir xil emasligini unutmang. Avval eslaylikki, VB-dagi “Integer” atamasi 16-bitli sonni, Win 32 hujjatlarida esa 32-bitli sonni bildiradi. Boshqacha qilib aytganda, VB-dagi butun sonlar (Integer va Long) belgisiz qiymatlar emas (bir raqam belgi sifatida, ikkinchisi raqamning mantissi sifatida ishlatiladi), Windows-da - hatto noma'lum raqamlar ham qo'llaniladi. Agar siz qo'shimcha arifmetik amallar yordamida parametr hosil qilsangiz (masalan, baza va ofsetni qo'shimcha almashtirish yordamida manzilni hisoblash) bu holatni hisobga olish kerak. Qaysi standart VB arifmetik funktsiyalari mos kelmaydi. Nima uchun bu vaziyatdan qo'rqasiz, keling, bu haqda gaplashaylik.

9. Funksiya nomlari bilan ehtiyot bo‘ling. Win16-da, barcha Win32 API funktsiyalarining nomlari kichik va katta harflarning aniq o'zgarishiga sezgir (Win16-da bunday yo'q edi). Agar siz katta yozuvchi o'rniga kichik yozuvchini qo'ysangiz, kerakli funksiya topilmaydi. Shuningdek, qator parametrlarini oʻrnatish uchun funksiyalardagi toʻgʻri A yoki W qoʻshimchasiga amal qiling. (Bu haqda xabar bering - quyida div.)

10. Ishingiz natijalarini iloji boricha tez-tez saqlang. Noto'g'ri DLL va Win API skriptlari bilan bog'liq nosozliklar VB o'rta ta'minoti va, ehtimol, butun operatsion tizimning ishdan chiqishiga olib kelishi mumkin. Iltimos, sinovdan oldin kodingiz saqlanganligiga e'tibor bering. Eng oddiy narsa, VB muhitida loyihani boshlashdan oldin loyihaga modullarni avtomatik yozish rejimini o'rnatishdir.

Avvalgisini o'qib chiqqandan so'ng, Win API funksiyasi o'ng tomondan o'chirilganligi sizni hayratda qoldirishi mumkin. Aytgancha, bu to'g'ri, lekin faqat VB o'zi ta'minlaydigan xavfsiz dasturlash bo'yicha. Biroq, engil turg'unlik va ma'lum bo'lishi mumkin bo'lgan tuzoqlar bo'lsa, bu xavf minimaldir. Bundan tashqari, Win API-ning turg'unligini engish ko'pincha imkonsizdir - bu jiddiy rivojlanishda kerak bo'ladi.

Bundan oldin, biz ilgari DLL-larning keng toifasi uchun "suv ostidagi" toshlar haqida o'yladik. Win API bilan hamma narsa ancha sodda, chunki bu funktsiyalarni amalga oshirish shakli aniq birlashtirilgan. Onaning hurmatini e'tiborga olish kerak bo'lgan asosiy fikrlar:

  1. Win32 API funksiyalari funksiyalar yoki Funktsiya tipidagi protseduralardir (Win16 API-da ko'plab pastki dasturlar mavjud edi). Barcha funksiyalar Long turiga ega, shuning uchun ularning tavsiflari ushbu shaklda yoziladi: Funktsiya nomini e'lon qilish ... As Long ‘funktsiya turi _ aniq shaklda ko'rsatilgan.

    Declare Function name& 'funktsiya turi _ qo'shimcha qo'shimcha bilan ko'rsatilgan

    API funktsiyasiga o'tkazish quyidagicha ko'rinadi:

Natija& = ApiName& ([ Argumentlar ro'yxati]
  1. Aylanadigan eng muhim funktsiya operatsiyani yakunlash kodidir. Bundan tashqari, nolga teng bo'lmagan qiymat oddiy bajarilishni anglatadi, nol qiymati esa bajarilishni anglatadi. Yana bir bor (yoki ilgari emas), siz GetLastError funksiyasidan foydalanib, o'zgartirishning mohiyatini aniqlab olishingiz mumkin. Ushbu funktsiyaning tavsifi quyidagicha ko'rinadi: Funktsiyani e'lon qilish GetLastError & Lib "kernel32" ()

    UVAGA! VB o'rtasida ishlaganda, aniqlangan kodning qiymatini o'chirish uchun LastDLLError Err ob'ektidan foydalangan ma'qul, chunki VB GetLastError funktsiyasini API yangilanishlari va dasturlarning davom etishi o'rtasida qayta o'rnatadi.

    Siz API32.TXT faylida ERROR_ qo'shimchasi bilan boshlanadigan nomlar bilan yozilgan qo'shimcha konstantalar yordamida GelLastError ni yaratuvchi kodni sharhlashingiz mumkin.

    Hujumlarning eng keng tarqalgan turlari quyidagi kodlardir:

    • ERROR_INVALID_HANDLE = 6& - noto'g'ri tutqich
    • ERROR_CALL_NOT_IMPLEMENTED = 120& - Windows 9x funksiyalariga qo'ng'iroq qilish faqat Windows NT uchun mavjud
    • ERROR_INVALID_PARAMETER = 87& - parametr qiymati noto‘g‘ri

    Biroq, berilgan parametrning qiymatlarini aylantirish uchun juda ko'p funktsiyalar mavjud (masalan, OpenFile fayl tavsifining qiymatlarini aylantiradi). Bunday holda, qiymat boshqa maxsus Qaytish va qiymatlariga tayinlanadi, ko'pincha 0 -1.

  2. Win32 API-da ma'lumotlarning eng oddiy turlarini uzatish uchun qat'iy belgilangan usullar mavjud. a) ByVal...As Long

    Argumentlarni o'tkazishning kamida 80% Long turi bilan amalga oshiriladi. Argumentni qayta ko'rib chiqing Birinchidan ByVal kalit so'zi bilan birga keladi va bu, boshqa narsalar qatori, ma'lumotlarni bir tomonlama uzatish - VB dasturlaridan API funktsiyasiga bog'langanligini anglatadi.

    B) ByVal...String sifatida

    Ushbu turdagi uzatish ham tez-tez va bir xil dalil bilan sodir bo'ladi Birinchidan ByVal tiqilib qoladi. API funksiyasi chaqirilganda, satr manzillari stekga yoziladi, bu ikki tomonlama ma'lumot almashish imkonini beradi. Qatorlarda ishlashda ba'zi muammolarni hal qilish kerak.

    Birinchidan, satrlar uchun xotira zahirasini chaqiruvchi dastur amalga oshiradi, shuning uchun agar API funksiyasi satrlarni saqlasa, uni chaqirishdan oldin kerakli o'lchamdagi qatorni yaratish kerak bo'ladi. Masalan, GetWindowsDirectory funktsiyasi Windows katalogiga yo'lni aylantiradi, bu 144 dan ortiq belgini egallashi shart emas. Shubhasiz, ushbu funktsiyani amalga oshirish quyidagicha ko'rinishi mumkin:

    WinPath$ = Space$(144) ' _ 144 belgidan iborat zahiralangan qator Natija& = GetWindowsDirectory& (WinTath$, 144) _ ' buferni to'ldirish ' Natija& - nomidagi belgilarning haqiqiy soni _ katalog WinPath$ = Left$(WinPath, Result&)

    Yana bir muammo shundaki, API funksiyasi API funksiyasiga aylantirilganda chiqish qatori uning ichki displeyida qayta yaratiladi va funksiyadan chiqqanda ham xuddi shunday sodir bo‘ladi. Xuddi Win16 ning dastlabki kunlarida bu operatsiya nol baytni qo'shishdan kamroq vaqtni oladi, masalan, qator, keyin Win32 paydo bo'lishi bilan ikki baytli Unicode kodlash ANSI ga o'zgartirildi va bir vaqtning o'zida erishilgan. (Bu haqda “VBda qator oʻzgarishlari bilan robotlarning xususiyatlari” maqolasida, Computer Press 10'99 va 01'2000-da xabar qilingan). Faqatgina ahamiyatlisi shundaki, ByVal... String konstruktsiyasi yordamida simvolik ma'lumotlar qatorlarini almashish mumkin.

    B) ...Har qanday kabi

    Bu shuni anglatadiki, xotira bufer manzilining qiymati stekga joylashtiriladi, masalan, API funktsiyasi nima bilan shug'ullanishi o'rniga talqin boshqa argumentlarning ma'nosidan mustaqildir. Biroq, As Any faqat Declare operatorida ishlatilishi mumkin - ma'lum bir funktsiya qo'llanilganda, argumentga ma'lum bir qiymat berilishi mumkin.

    D) ... UserDefinedType sifatida

    Bunday tuzilma ko'pincha boshqa tuzilma uchun ma'lumot almashish zarurati tug'ilganda (huquqbuzar tomonning va'dasi) tiqilib qoladi. Aslida, bu dizayn As Any uzatish shaklini o'ziga xos tarzda amalga oshirishning oddiy turi bo'lib, har bir funktsiya o'zgarmas tuzilishga ega.

    Ma'lumotlar strukturasining shakli ma'lum bir API funktsiyasi bilan belgilanadi va ularni to'g'ri tavsiflash va bir xil dastur bilan zaxiralash dasturning mas'uliyati hisoblanadi. Bu dizayn Birinchidan vikorist holda ByVal so'zlari, keyin jo'natilgandan keyin o'tkazish ushbu qutiga qo'shiladi - almashinuv manzili stekga yoziladi.

API funksiyasiga o'ting

Bu fayllar bilan ishlashning ikkita asosiy funksiyasi - lopen va lread misolida tasvirlangan, ular quyidagicha tavsiflanadi:

Funktsiyani lopen Lib "kernel32" _ Alias ​​"_lopen" (_ ByVal lpFileName String sifatida, _ ByVal wReadWrite As Long) Funktsiyani lread Lib "kernel32" _ Alias ​​"_lread" (_ ByVal hFile As Long, lpBuff _ ByVal wBytes As Long) As Long

VBda ularning analoglari - ba'zan aniqroq - Open va Get operatorlari (Binary rejim uchun). Bo'sh funktsiyada Alias ​​kalit so'zidan foydalanish bizni juda hayratda qoldirdi - bu xuddi shu muammo, agar usiz qilolmasangiz. Kutubxonadagi bu funksiya nomlari VB tomonidan ruxsat etilmaydigan stul ostidagi belgi bilan boshlanadi (C filmi uchun odatiy uslub).

Faylni ochish jarayoni quyidagicha ko'rinishi mumkin:

Const INVALID_HANDLE_VALUE = -1 ' noto'g'ri _ qiymat tavsifi lpFileName$ = "D:\calc.bas" ' fayl nomi wReadWrite& = 2 ' o'qish-yozish rejimi hFile& = lopen(lpFileName$, wReadWrite&) _ IN_ALV'D keyin faylni tuzatish ' tuzatish kodini belgilang CodeError& = Err.LastDllError 'CodeError& = GetLastDllError _ ' bu konstruksiya ishlamaydi End If

Bu erda ikkita fikrni ta'kidlashimiz kerak:

  • Funktsiyaning qiymati sifatida biz fayl tavsifining qiymatini aniqlaymiz. Qiymat -1 qiymatini tasdiqlaydi;
  • Bunday holda, GetLastError funksiyasiga o'tish shart emas - xatoning ko'rsatilgan qiymatini olish uchun biz Err ob'ektiga o'tdik (bunday vaziyatning ehtimoli haqida ko'proq gaplashdik).

Keyin fayl o'rniga siz o'qishingiz mumkin, lekin bu dastur uning tuzilishini tanib olish uchun mas'ul ekanligini ham bildiradi (bir nechta ikkita fayl bilan ishlashda bo'lgani kabi). Bunday holda, lread funksiyasining tavsifi quyidagicha ko'rinishi mumkin:

Dim MyVar As Single wBytes = lread (hFile&, MyVar, Len(MyVar) ' nutq raqamini o'qish, 4 bayt ' wBytes - haqiqatda o'qilgan ma'lumotlar soni, '-1 - paritet... MyStruct x As Single i Integer sifatida yozing. Yakuniy turi Dim MyVar MyStruct sifatida wBytes = lread (hFile&, MyVar, Len(MyVar)) ' o'qish ma'lumotlar strukturasi, 6 bayt

Yana bir bor hurmat ko'rsating: funktsiyaning boshqa argumenti jo'natuvchilarga va qiymatlarga qaytishga o'tadi.

MyVar As String MyVar = Space$(10) ' 10 ta belgi uchun joy zaxiralang wBytes = lread (hFile&, ByVal MyVar, Len(MyVar)) ' o'qiladigan belgilar qatori, 10 ta belgi

Bu erda siz ilgari kiritilgan dumbaning ahamiyatini ko'rishingiz mumkin - qatorni o'zgartirish, albatta, ByVal kalit so'zi bilan birga keladi.

Massivdagi fayl o'rniga o'qish (oddiylik uchun biz bitta baytli massivdan foydalanamiz) quyidagicha kompilyatsiya qilinadi:

Dim MyArray(1 dan 10 gacha) As byte wBytes = lread (hFile&, MyArray(1), _ Len(MyArray(1))* 10) ‘ massivdan 10 ta elementni o‘qish

Argument sifatida massivning birinchi elementini ko'rsatib, massiv uchun ajratilgan xotira maydoni boshining manzilini o'tkazamiz. Shubhasiz, siz ushbu usul yordamida massivning istalgan qismini saqlashingiz mumkin:

WBytes = lread (hFile&, MyArray(4), _ Len(MyArray(1))* 5) massiv elementlarini 4-dan 8-gacha oʻqish

Porada 5. Transfer uchun Vickory taxallus Sozlamalar Har qanday

Bu erda, oldingi dumbaga asoslanib, biz Den Appleman uchun to'rtinchisining mohiyatini ochib beramiz.

lread funksiyasi bilan ishlashda shuni yodda tutish kerakki, undan oldin oddiy o‘zgaruvchi ishga tushirilganda ByVal kalit so‘zidan foydalanish zarur (aks holda noqonuniy operatsiya haqidagi ma’lumotlar yo‘qolmaydi). Xavfsiz tomonda bo'lish uchun siz faqat umumiy o'zgarishlar bilan ishlash uchun ushbu funktsiyaning qo'shimcha maxsus tavsifini yaratishingiz mumkin:

Funktsiyani e'lon qiling lreadString Lib “kernel32” _ Alias ​​​​“_lread” (_ ByVal hFile As Long, ByVal lpBuffer String sifatida, _ ByVal wBytes As Long)

Ushbu tavsif bilan ishlaganda, chop etishda ByValni ko'rsatish shart emas:

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

Aftidan, Declare operatorining sintaksisi massiv uchun shunday maxsus tavsifni yaratishga imkon beradi:

Funktsiyani lreadString Lib "kernel32" taxallus "_lread" (_ ByVal hFile As Long, lpBuffer() Bayt sifatida, _ ByVal wBytes As Long) uzunligini e'lon qiling

Hayvonni himoya qilish

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

muqarrar ravishda dastur tomonidan o'limga olib keladi.

Bu Visual Basic qatoridagi o'zgarishlarni qayta ishlashning o'ziga xos xususiyatlari haqidagi munozaraning davomi: VB ikki baytli Unicode kodlashdan foydalanadi, Win API - bir baytli ANSI (va C da qabul qilingan format bilan - oxirida nol bayt bilan). Ko'rinib turibdiki, qator o'zgarishlarini argument sifatida o'zgartirganda, Unicode-dan ANSI-ga o'tkazish API funktsiyasini (aniqrog'i, DLL funktsiyasi) chaqirganda avtomatik ravishda amalga oshiriladi va aylantirish aylantirilganda amalga oshiriladi.

Bu erda xulosa oddiy: siz o'zgaruvchan Strings yordamida ramziy ma'lumotlarni almashishingiz mumkin, ammo ulardan etarlicha ikki tomonlama ma'lumot almashish uchun foydalana olmaysiz (VB ning 16-bitli versiyalari bilan ishlashda bo'lgani kabi). Bir o'lchovli bayt massividan foydalanish yaxshidir.

Ko'rinib turibdiki, String turi strukturaning tuzilishini tavsiflash uchun ishlatilishi mumkin. Ushbu xotira bilan bog'lanish quyidagicha:

  • Win API-ni ishlab chiqish uchun quyidagi konstruktsiyadan foydalanish mutlaqo mumkin emas: MyStruct x As Single s As String yozing.

    O'zgartirish tartibida qator deskriptori dastur ko'rinishidagi barcha meroslar bilan birga uzatiladi.

  • Ruxsat etilgan ikkilanish satrining struktura elementi sifatida mumkin: MyStruct x As Single s As String*8 ‘ qatori qattiq ikki barobarga yozing.

Bunday holda, kodni qayta yaratishni unutmang.

Va hurmat saqlanib qoladi: bir vaqtning o'zida API funksiyasiga yangilanganda qator o'zgarishlarini (ham qat'iy, ham o'zgaruvchan) birlashtirish mumkin emas. Aks holda, "noqonuniy operatsiya" ning paydo bo'lishi kafolatlanadi.

Agar kutubxonangizga DLL funksiyasini yozishingiz kerak bo'lsa, siz yomon ahvolda ekanligingiz aniq. Agar aralash dasturlash texnologiyasi - bitta dasturni amalga oshirish uchun ikki yoki undan ortiq dasturlarning kombinatsiyasidan foydalansangiz, ehtiyoj muqarrar ravishda paydo bo'ladi.

Bu aralash dasturlash keng qamrovli hisobotga erishish uchun amalga oshirishning asosiy maqsadi ekanligi bilan bog'liq holda muhimdir. Darhaqiqat, til tili (aniqrog'i, tilga asoslangan dasturlash tizimi) o'zining kuchli va zaif tomonlariga ega, shuning uchun turli vazifalarni bajarish uchun turli vositalarning afzalliklaridan foydalanish butunlay mantiqiydir. Masalan, VB - kompyuter interfeysini yaratish uchun, C - tizim resurslariga samarali kirish uchun, Fortran - raqamli algoritmlarni amalga oshirish uchun.

Muallifning g'oyasi quyidagicha: dasturlashda jiddiy ishtirok etishni ishlab chiquvchi ikkita vositadan foydalangan holda ta'kidlaydi. Shubhasiz, zamonaviy onglarda ikkita tizimda mustaqil ekspert bo'lish juda qiyin, bu "asosiy va qo'shimcha til" sxemasini mantiqiyroq qiladi. Bu erda g'oya shundan iboratki, "qo'shimcha" tilni (bir qator oddiy protseduralar bilan yozilgan) bilimga etkazish "asosiy" tilning samaradorligini sezilarli darajada oshirishi mumkin. VB ni bilish qo'shimcha foyda sifatida endi professional dasturchi uchun amaliy talab bo'lishi muhim. Gapirishdan oldin, bir necha soatlik DOS-da, har qanday dasturchi uchun Basic-ni ko'rib chiqaylik, Assembler asoslarini bilish juda muhim bo'lar edi.

Demak, bu boshqacha, ammo guruh robotlarining fikriga ko'ra, teri dasturchisi o'zining maxsus ishi bilan shug'ullanganida, turli tillardagi protsessual interfeysning o'ziga xos xususiyatlari haqidagi bayonotlar loyihaning barcha ishtirokchilarining aybidir. Tushunishga bog'liq bo'lgan interfeysdan tashqari, boshqa usullarni o'rnatish imkonini beruvchi, dasturlash usullarini protseduralarga kengaytiruvchi, interfeysni moslashtirishga imkon beruvchi juda ko'p dasturlash tizimlari (jumladan, VB) mavjudligini bilaman. Boshqa tillar.

Protseduralararo interfeysdan foydalanganda quyidagi mumkin bo'lgan tuzoqlardan xabardor bo'ling:

  • Turli tillar identifikatorlarni yozish qoidalari haqida sizni qiziqtirishi mumkin. Masalan, protsedura nomining VBda yashiringan taxallus belgisi ko'pincha ishlatiladi. Ushbu muammoni Declare operatoridagi Alias ​​kalit so'zidan foydalanish bilan osongina tushuntirish mumkin (2.3 uchun ajoyib misol).
  • Siz stekga uzatiladigan argumentlarni yozish ketma-ketligini aniqlashingiz mumkin. Masalan, DOS soatlarida (to'g'risini aytsam, Windows o'rtasida qanday ko'rinishini bilmayman), ro'yxat oxiridan argumentlarni, boshqa tillarda (Fortran, Paskal, Basic) - dan. boshlanishi.
  • Parametrlarni uzatishning turli tamoyillari - ko'rsatmalar yoki ma'nolar uchun - tushuntirilgan.
  • O'rinbosarlarni saqlashning qat'iy tamoyillari. Masalan, C tilida (Fortran va Paskal tillarida bo'lgani kabi) satr oxiri uning oxirida nol bayt bilan ko'rsatilgan, Basicda esa oxiri satr deskriptorida aniq yoziladi. Shubhasiz, turli xil belgilar kodlarini o'zgartirish qobiliyatini esga olish kerak.
  • Boy dunyo massivlarini o'tkazayotganda, boy dunyo tuzilmalarini bir dunyoga o'zgartirishning turli xil variantlari mavjudligini unutmang (birinchi indeksdan boshlab yoki qolganlaridan boshlab, yuzta ikki o'lchovli massivlar - "satrlarda" yoki "ustunlarda" jo'jalar").

Shunga asoslanib, quyidagi tavsiyalarni shakllantirish mumkin:

  • Argumentlarni DLL funktsiyasiga o'tkazish usulini qayta ko'rib chiqish orqali eng oddiy narsalarni tekshiring. Win API uchun qabul qilingan standartlar butunlay mos keladi.
  • Har safar oddiy askarlarning massasini o'tkazmang.
  • Oddiy oddiy va boy massivlarni o'tkazishni hurmat bilan vikorist.
  • Argumentlarni chaqirilgan va orqaga qaytariladigan protseduraga o'tkazish mexanizmining funksionalligini diqqat bilan tekshirib ko'ring. Ma'lumotlarni tekshirish uchun maxsus test yozing. Teri argumentini uzatishning to'g'riligini diqqat bilan tekshiring. Misol uchun, agar sizda ko'p argumentli protsedura bo'lsa, avval bitta argument bilan variant uchun teri parametrini, keyin esa butun ro'yxat uchun o'tishning to'g'riligini tekshiring.

Agar DLL funktsiyasi allaqachon yozilgan bo'lsa, masalan, Fortran-da, lekin kiritish interfeysi yangi VB standartiga mos kelmasa, u nima qiladi? Bu erda siz ikkita sana berishingiz mumkin. Birinchidan: test DLL funktsiyasini yozing va uning yordami bilan VB dasturlari uchun kerakli funksionallikni tanlash uchun sinov va xato usulidan foydalanishga harakat qiling. Boshqasi: Fortranda VB va DLL funktsiyasi o'rtasida oddiy interfeysni ombordagi oddiy ma'lumotlar tuzilmalarini o'zgartirish bilan ta'minlaydigan adapter protsedurasini yozing (masalan, qatorli massivdan katta bayt massivini o'zgartirish).

Otzhe: vykorist DLL funktsiyalari. Bundan tashqari, shirinlikni saqlang.

ComputerPress 9" 2000

Ushbu maqola C++ da dasturlashni yangi boshlagan va WinAPI dan foydalanishga majbur bo'lganlar uchun mo'ljallangan.
Men o'yindan oldinga borishni xohlayman:
Men o'zimni C++ yoki WinAPI gurusi sifatida ko'rsatmayman.
Men endigina boshlayapman va bu yerda WinAPI funksiyalari va mexanizmlaridan foydalanishni osonlashtiradigan bir qator ilovalarni kiritmoqchiman.

Ushbu maqolada siz sinflar yaratish va ular uchun turli operatorlarni o'tkazish imkoniyatiga ega bo'lish uchun C++ bilan allaqachon tanish bo'lgansiz va siz o'z mexanizmlaringizni sinfga "sevgansiz" deb o'ylayman.

Konsolning yaratilishi va vikoristani

Win32 dasturlarini yaxshilash uchun yoki shunchaki o'rtada hamma narsa qanday ko'rinishini hayratda qoldirish uchun men har doim konsolni tirnayman.
Konsol emas, balki GUI ilovasini yaratayotganingiz uchun konsol ulanmaydi. Internetga bosish uchun siz ushbu kodni topishingiz mumkin

Agar (AllocConsole())
{



std::ios::sync_with_stdio();
}
Aniqlik uchun Raja uni funktsiyaga o'radi. Masalan:
void CreateConsole()
{
agar (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();
}

Konsol faqat displey rejimida ishlaydi va konsol dasturlaridagi kabi ishlaydi. Ma'lumotni avvalgidek kiriting - cout/wcout.
Ushbu kod samarali bo'lishi uchun loyihaga quyidagi fayllarni kiritish kerak:
#o'z ichiga oladi
#o'z ichiga #o'z ichiga oladi
va global nomlar maydonida std nom maydonini yoqing:
std nom maydonidan foydalanish;
Albatta, agar siz hech narsa qilishni xohlamasangiz, undagi barcha ob'ektlarga std:: qo'shing.

Ko'rsatish va arifmlar uchun ob'ektlarni qisqartirish. operatsiya

Siz yaratganingizdan va "nihoyat" ni kiritganingizdan so'ng, avval konsolga istalgan qiymatlarni chiqarishingiz kerak.
Masalan:
GetClientRect qo'shimcha funktsiyasidan foydalanib, siz oynaning mijoz maydonining o'lchamini aniqlaysiz, bu erda parametr ushbu ob'ektni ma'lumotlar bilan to'ldirish uchun RECT tuzilmasi ob'ektining manziliga uzatiladi. Agar siz qo'lga kiritilgan mijoz maydoni hajmini bilishingiz kerak bo'lsa, uni allaqachon ulangan konsolga kiritishingiz mumkin.

Kout<

Ale ishi juda tez (ayniqsa, siz tez-tez shunday ishlashingiz kerak bo'lganligi sababli) oson emas.
Bu erda tinchlik bizga yordam beradi.
RECT tuzilmasidan ochiq tarzda yiqilib tushadigan sinf yarating va chiqish bayonotining maqsadini o'zgartiring<< так, как вам угодно.
Masalan:

Yangi sinf: umumiy RECT
{
ommaviy:
do'st ostream va operator<<(ostream &strm,newrect &rect)
{
strm<<"Prtint RECT object:\n";
strm<qaytish strm;
}
};

Endi ob'ektni cout/wcout yordamida yozing:

Kout<

Va o'zingiz ko'rishingiz mumkinki, hamma narsa sizga kerak bo'lgan tarzda mavjud.
Bundan tashqari, kerakli operatorlar bilan ishlashingiz mumkin.
Misol uchun, agar siz tuzilmalarni o'zgartirishingiz yoki belgilashingiz kerak bo'lsa (masalan, RECT yoki POINT) - operator==() va operator=() ni butunlay o'zgartiring.
Operatorni kamroq amalga oshirishni istasangiz< что бы быстро сравнивать размеры окна и т.д. перегрузите operator<().
Shunday qilib, siz har qanday tuzilmalar bilan ham ishlashingiz mumkin va birinchi navbatda, RECT tuzilmasining asosiy ob'ekti bilan ishlaydigan barcha funktsiyalar u bilan yaxshi ishlaydi deb o'ylayman.
Shuningdek, men bu go'zallikning barchasini ulangan alohida faylga qo'yishni va kerak bo'lganda tahrirlashni tavsiya qilaman.

Sizning sinfingiz

Boshqalar haqida bilmayman, lekin men butunlay yashilman, men terining funktsiyasi yoki kitobning teri bo'limi / bo'limi uchun yangi loyiha yaratishga qaror qildim, shunda hamma narsa tartibda edi va uni aylantirish mumkin edi. orqaga qayting va uni istalgan vaqtda xotirada yangilang' Bu zarur daqiqalar.
WinAPI-da oddiy oyna yaratish uchun siz sinf tuzilmasini to'ldirishingiz, uni ro'yxatdan o'tkazishingiz va arzimas oyna protsedurasini yozishingiz kerak, uchinchi yoki to'rtinchi loyihadan keyin men hali ham C++ da yozayotganimni angladim.
Natijada, men oddiy sinfdan hamma narsani oldim. Oyna dastagi, oyna nomi, sinf nomi, oyna protsedurasi manzillari, oyna sinfi (WNDCLASS) hammasi xususiy sinf bo'limida saqlanadi.
Ularni olish uchun siz oddiy "Get" usulini tavsiflashingiz kerak, masalan:
HWND GetHWND()
LPCTSTR GetClsName() va boshqalar.
Deraza sinfini yangilash va ro'yxatdan o'tkazish, oynaning o'zini yaratish va uni ko'rsatish dizayner tomonidan amalga oshiriladi.
Ishlarni osonlashtirish uchun siz konstruktorni qayta rejalashtirishingiz va oyna sinfining tugallanishi va ro'yxatga olinishini sinf uchun shaxsiy funktsiyaga o'rashingiz va uni har bir konstruktordan chaqirishingiz mumkin. Orqaga aylantirishning afzalligi shundaki, ba'zida butunlay oddiy oyna yaratish kerak bo'ladi va men ikkita parametrga ega bo'lgan konstruktorni bosing - oyna nomi va dasturning orqa tomoni.
Aks holda, standart oyna protsedurasi va boshqa uslublar bilan emas, balki maxsus o'lchamli oyna yaratish kerak emas - men bog'langan parametrlar bilan konstruktorni bosing.
Ushbu sinf to'g'ridan-to'g'ri kiritilgan faylda kamroq qiymatlarga ega, u IDE ning o'z ichiga papkasida joylashgan.
Ushbu sinf uchun shablon:
sinf BaseWindow
{
WNDCLASSEX_wcex;
TCHAR_sinf nomi;
TCHAR_oyna nomi;
HWND_hwnd;
bool _WindowCreation();
ommaviy:
BaseWindow(LPCTSTR oyna nomi, HINSTANCE hInstance, DWORD uslubi, UINT x, UINT y, UINT balandligi, UINT kengligi);
BaseWindow(LPCTSTR oyna nomi, HINSTANCE hInstance);
const HWND GetHWND()const(HWNDni qaytarish;)
LPCTSTR GetWndName()const(_windowNameni qaytarish;)
};

Bunday darsni o'ylab, yozganingizdan so'ng, siz hayotingizni osonlashtirasiz va bir vaqtning o'zida bir xil narsani yozishning boshlanishini o'zlashtirish va charxlash uchun bir soatdan ko'proq vaqt sarflaysiz. Tim ko'proq, men buni yanada chiroyli hurmat qilaman - bunday sinfni o'zingiz yaratishingiz va uni ehtiyojlaringizga ko'ra to'ldirishingiz.

P.S.

Ta'riflangan hamma narsa quyidagilarga to'g'ri keladi:
Platforma - Windows 7 32 bit
IDE - Visual Studio 2010
Ehtimol, kimdir kulgi va istehzoni chaqirishni xohlaydi, lekin oxir-oqibat, biz hammamiz o'zimizni yangi kelganlar / stajyorlar / yoshlar deb o'yladik.
Xabaringizdan oldin ehtiyotkor bo'lishingizni so'rayman. Konstruktiv tanqid, albatta, uchib ketadi. Operatsion tizimlar (OT)