Би windows api функцуудын тайлбарыг хаанаас үзэж болох вэ? Windows API гэж юу вэ. MSDN дахь функцын прототипүүдийн тодорхойлолт

FindWindow
GetWindow
GetWindowText
SetWindowText
IsWindow
MoveWindow
IsWindowVisible
EnableWindow
IsWindowEnabled
WindowFromPoint
ShowWindow
Цонх хаах
SetWindowPos
GetClassLong
SetClassLong
GetWindowLong
SetWindowLong
GetDesktopWindow
GetParent

FindWindow функц

функц FindWindow(ангиллынНэр,ЦонхныНэр: PChar) : HWND;
Уг функц нь хүсэлтийг хангасан цонхны тодорхойлогчийг буцаана (хэрэв тийм цонх олдохгүй бол 0).

Ангийн нэр Системийн БҮХ цонхнуудаас хайхад ашигладаг ангийн нэр. Цонхны нэрЦонхны гарчиг

Параметрүүдийн аль нэг нь тэгтэй тэнцүү байж болно, дараа нь хайлтыг өөр параметр ашиглан гүйцэтгэнэ.
Жишээ:

GetWindow функц

функц GetWindow(Wnd: HWND; Param) : HWND
Уг функц нь хүсэлтийг хангасан цонхны тодорхойлогчийг буцаана.

Wnd Анхны цонхны бариул Парам Дараах тогтмол утгуудын аль нэгийг авна. gw_Эзэмшигч Өвөг дээдсийн цонхны бариулыг буцаана (хэрэв өвөг байхгүй бол 0). gwHWNDFЭхлээд Эхний цонхонд бариулыг буцаана (Wnd-тэй холбоотой). gw_HWNDДараа нь Дараагийн цонх руу бариулыг буцаана (цонхнууд дахин давтагдахгүй, өөрөөр хэлбэл та функцийн Wnd параметрийг өөрчлөөгүй бол бариулыг дахин буцааж өгөхгүй) gw_Хүүхэд Эхний хүүхэд цонх руу бариулыг буцаана.

Жишээ:

GetWindowText функц

функц GetWindowText(hWnd: HWND; lpString: PChar; nMaxCount: Бүхэл тоо): Бүхэл тоо;
Функц нь цонхны текстийг буцаана. Маягтын хувьд энэ нь гарчиг, товчлуурын хувьд товчлуур дээрх шошго байх болно.

hWnd Текстийг нь авахыг хүссэн цонхны тодорхойлогч. lpString Үр дүнг байршуулах хувьсагч nMaxCount

Текстийн хамгийн урт урт, хэрэв текст урт байвал таслагдана.


Жишээ:

IsWindow функц

функц IsWindow(hWnd: HWND): BOOL;Өгөгдсөн бариултай цонх байвал True, үгүй ​​бол худал буцаана.

Hwnd Хүссэн цонхны тодорхойлогч

MoveWindow функц

MoveWindow(hWnd: HWND; X, Y, nWidth, nHeight: Integer; bRepaint: BOOL): BOOL;Цонхыг шинэ байрлал руу шилжүүлнэ.

hWnd Цонхны бариулыг зөөж байна. X, Y, nWidth, nHeight Үүний дагуу: шинэ координат X,Y; шинэ өргөн, өндөр. b Дахин будах Цонхыг дахин зурах эсэхийг илтгэх логик утга.

IsWindowVisible функц

функц IsWindowVisible(hWnd: HWND): BOOL;
Өгөгдсөн цонх харагдаж байвал Үнэнийг буцаана.

hWndЦонхны тодорхойлогч.

EnableWindow функц

функц EnableWindow(hWnd: HWND; bEnable: BOOL): BOOL;
Цонхны бэлэн байдлыг тохируулна (хэрэв хулгана, гар гэх мэт үйл явдалд хариу өгөхгүй бол цонх ажиллахгүй). Бүрэлдэхүүн хэсгүүдийн Enabled шинж чанарын Delphi дахь аналог. Хэрэв бүх зүйл амжилттай болсон бол EnableWindow Үнэнийг, үгүй ​​бол Худал буцаана.

hWndЦонхны тодорхойлогч. bEnable Цонх боломжтой эсэхийг илтгэх логик утга.


Жишээ:

IsWindowEnabled функц

функц IsWindowEnabled(hWnd: HWND): BOOL;
Өгөгдсөн цонхны буцаалт: Хэрэв цонх байгаа бол үнэн, үгүй ​​бол худал.

hWndЦонхны тодорхойлогч.

WindowFromPoint функц

WindowFromPoint(Цэг: TPoint): HWND;
Дэлгэцийн өгөгдсөн цэг дээр байрлах цонхны бариулыг буцаана.

Оноо Дэлгэцийн цэгийн координатын төрөл TPoint(төрлийн тодорхойлолтыг доороос үзнэ үү)

Чиг үүрэг

төрөл TPoint = Бичлэг x: Longint; у: Longint; Төгсгөл;

ShowWindow функц

функц ShowWindow(hWnd: HWND; nCmdShow: Бүхэл тоо): BOOL;Цонхыг харуулах эсвэл нуух.

hWnd Хүссэн цонхны тодорхойлогч nCmdShow Цонхтой юу хийхийг тодорхойлдог тогтмол: SW_HIDE SW_SHOWNORMAL SW_NORMAL SW_SHOW БАГАЖУУЛСАН SW_SHOW MAXIMIZED SW_MAXIMIZE SW_SHOWNOACTIVATE SW_SHOW SW_MINIMIZE SW_SHOWMINNOACTIVE SW_SHOWNA SW_RESTORE SW_SHOWDEFAULT SW_MAX


Жишээ:

CloseWindow функц

функц CloseWindow(hWnd: HWND): BOOL; stdcall;
Цонхыг хаадаг.

hWnd Хаагдах цонхны бариул.

SetWindowPos

функц SetWindowPos(hWnd: HWND; hWndInsertAfter: HWND; X, Y, cx, cy: Integer; uFlags: UINT): BOOL; stdcall;
Цонхыг шинэ байрлалд тохируулна

hWndцонхны тохируулагч hWndInsertAfter Жагсаалтын өмнө байгаа цонхны тодорхойлогч Z-захиалгацонх оруулах болно hWnd, эсвэл дараах тогтмолуудын аль нэг нь: HWND_BOTTOM Цонхыг Z-Order жагсаалтын доод талд байрлуул HWND_TOP Цонхыг Z-Order жагсаалтын дээд талд байрлуул X, Y, cx, cy

Үүний дагуу шинэ давхрага. , vert. цонхны байрлал ( X, Y), түүнчлэн шинэ өргөн
ба өндөр ( cx, cy)

uFlags Нэг буюу хэд хэдэн (тусгаарлагдсан ЭСВЭЛ) дараах тогтмолууд: SWP_NOSIZE Зөөж авсны дараа цонхны хэмжээг бүү өөрчил ( cx, cyүл тоомсорлодог) SWP_NOZORDER Z-Order жагсаалт дахь цонхны байрлалыг өөрчилж болохгүй SWP_SHOWWINDOW Хөдлөсний дараа цонхыг харагдуулна SWP_HIDEWINDOW Зөөж авсны дараа цонхыг нуу SWP_NOACTIVATE Хөдлөсний дараа цонхонд анхаарлаа төвлөрүүлж болохгүй SWP_NOMOVE Цонхыг бүү хөдөлгө (үл тоосон X, Y)

GetClassLong функц

функц GetClassLong(hWnd: HWND; nIndex: Integer): Бүхэл тоо;
Энэ функц нь бичлэгийн тодорхой талбараас авсан 32 битийн бүхэл тоог буцаана TWndClassExзаасан цонх.

hWndЦонхны бариул nИндекс Юу буцааж өгөхийг байнга тодорхойлдог. Дараах зүйлсийн аль нэг нь байх ёстой: GCL_MENUNAME Зарим програмтай холбоотой нөөц файлд тодорхойлсон ангийн цэсийн нэрийг агуулсан мөр рүү заагчийг буцаана. GCL_HBRBACKGROUND Ангитай холбоотой дэвсгэр сойз руу бариулыг (HBRUSH) буцаана GCL_HCURSOR Ангитай холбоотой курсор руу бариулыг (HCURSOR) буцаана GCL_HICON Ангитай холбоотой дүрсэнд бариулыг (HICON) буцаана GCL_HMODULE Ангийг бүртгэсэн процессын (HMODULE) бариулыг буцаана. GCL_CBWNDEXTRA ЭНЭ ЦОНХНЫ нэмэлт өгөгдөл хадгалахад зориулагдсан санах ойн хэмжээг (байтаар) буцаана. Энэ санах ойг хэрхэн ашиглах тухай тайлбарыг функцийн тайлбараас үзнэ үү GCL_CBCLSEXTRA ӨГӨГДСЭН АНГИЙГ нэмэлт хадгалахад зориулагдсан санах ойн хэмжээг (байтаар) буцаана GCL_WNDPROC Ангитай холбоотой цонхны процедурын хаягийг буцаана. GCL_STYLE Ангийн хэв маягийг буцаана (тодорхой хэв маяг байгаа эсэхийг битийн үйлдлээр шалгана Тэгээдгэх мэт тогтмолуудыг ашиглах cs_XXX) GCL_HICONSM

тэмдэглэл: функц нь заагчийг буцаах тохиолдолд төрөл casting шаардлагатай (Бүтэн тоо ->

SetClassLong функц

функц SetClassLong(hWnd: HWND; nIndex: Integer; dwNewLong: Longint): Бүхэл тоо;Хослох функц. Шаардлагатай талбарт тохирох утгыг тохируулна.
Функц нь талбарын хуучин утгыг буцаадаг бөгөөд ингэснээр дараа нь засч залруулах эсвэл ямар нэг зүйл буруу болвол тэгийг буцаана.

hWndЦонхны бариул nИндекс Тогтмолуудын нэг GCL_XXXфункцээс. Энэ талбарын утгаас хамааран шаардлагатай талбар өөрчлөгдөнө.

тэмдэглэл Заагчбичих Бүхэл тоо.

GetWindowLong функц

функц GetWindowLong(hWnd: HWND; nIndex: Бүхэл тоо): Longint;Цонхны талаарх мэдээллийг 32 битийн бүхэл тоогоор буцаана.

hWndЦонхны бариул nИндекс Юу буцааж өгөхийг байнга тодорхойлдог. Энэ нь дараахь зүйлсийн нэг байх ёстой.
GWL_WNDPROC Энэ цонхтой холбоотой цонхны процедурын хаягийг буцаана. Үүссэн хаягийг (тохирох төрлийн дамжуулалтын дараа) функцэд ашиглаж болно CallWindowProc. Энэ утгыг ихэвчлэн тэд одоо байгаа цонхны процедурыг өөрийнхтэй солихыг хүсвэл ашигладаг бөгөөд цонхны үйл ажиллагааг алдахгүйн тулд ихэвчлэн ашигладаг. CallWindowProc. GWL_HINSTANCE Цонхыг функцээр үүсгэсэн үед заасан програмын бариулыг буцаана CreateWindowEx. GWL_HWNDPARENT Эх цонхны бариулыг (HWND) буцаана GWL_STYLE Цонхны хэв маягийг буцаана. Тодорхой загварын утгыг битийн үйлдлийг ашиглан олно Тэгээдболон тогтмолууд WS_XXX GWL_EXSTYLE Өргөтгөсөн цонхны хэв маягийг буцаана. Тодорхой загварын утгыг битийн үйлдлийг ашиглан олно Тэгээдболон тогтмолууд WS_EX_XXX GWL_USERDATA Цонхтой холбоотой 32 битийн бүхэл тоог буцаана (энэ нь CreateWindow эсвэл CreateWindowEx дуудлагын сүүлчийн параметр юм) GWL_ID CreateWindow эсвэл CreateWindowEx-ийг дуудах үед хүүхдийн цонхны hMenu параметрээр заасан цонхны ID-г (энэ нь цонхны бариултай ямар ч хамаагүй!) буцаана.

тэмдэглэл: функц нь заагчийг буцаах тохиолдолд төрөл casting шаардлагатай (Бүтэн тоо -> Заагч). Та үүнийг дараах байдлаар хийж болно.

SetWindowLong функц

функц SetWindowLong(hWnd: HWND; nIndex: Бүхэл тоо; dwNewLong: Longint): Longint;
Функцтэй хослуулсан. Тодорхой цонхны шинж чанаруудыг өөрчилдөг.
Хэрэв дуудлага амжилттай бол функц нь өмчийн хуучин утгыг буцаана, эс бөгөөс тэг болно.

hWndЦонхны бариул nИндекс Ямар шинж чанарыг өөрчлөхийг тодорхойлдог тогтмол. Тогтмолуудын нэг байх ёстой GWL_XXXфункцийн тайлбараас dwNewLong Тогтмолоор тодорхойлогдсон өмчийн шинэ утга nИндекс

тэмдэглэл: заагч талбаруудыг тохируулахдаа cast төрөл шаардлагатай Заагчбичих Бүхэл тоо.

GetDesktopWindow функц

функц GetDesktopWindow: HWND
Уг функц нь Ширээний цонхонд бариулыг буцаана. Параметр алга.

GetParent

функц GetParent(hWnd: HWND): HWND;
Цонхны эх цонхны бариулыг буцаана hWnd.

hWndЦонхны бариул

C WinAPI нь үйлдлийн системд байдаг Microsoft-ын програмчлалын интерфейсийн (API) үндсэн багц юм.Эхний хувилбарыг Win32 API гэж нэрлэдэг.

Оршил

C WinAPI нь Windows програмуудыг үүсгэхэд ашигладаг програмчлалын интерфейс юм. Эхлэхийн тулд шинэхэн хэрэглэгч өмнө нь Платформ SDK гэгддэг Windows SDK-г татаж авах ёстой.

Толгой файлууд, номын сан, дээж, баримт бичиг, програмуудыг боловсруулахад ашигладаг хэрэгслүүдийг агуулна. C болон C++ програмчлалын хэлэнд зориулсан API. Энэ нь компанийн үйлдлийн систем дээр програм үүсгэх хамгийн шууд арга юм.

C WinAPI-г хэд хэдэн хэсэгт хувааж болно:

    үндсэн үйлчилгээ;

    аюулгүй байдал;

  • Хэрэглэгчийн интерфэйс;

    мультимедиа;

    Windows бүрхүүл;

    сүлжээний үйлчилгээ.

Үндсэн үйлчилгээ нь үндсэн нөөцөд хандах боломжийг олгодог. Үүнд C WinAPI функцууд, файлын системүүд, төхөөрөмжүүд, процессууд, урсгалууд, бүртгэл, алдаатай ажиллах зэрэг орно. Аюулгүй байдлын хэсэг нь баталгаажуулалт, зөвшөөрөл, криптограф болон бусад аюулгүй байдалтай холбоотой ажлуудад зориулсан интерфейс, объект болон бусад програмчлалын элементүүдээр хангадаг. График дэд систем нь монитор, принтер болон бусад гаралтын төхөөрөмжид график агуулгыг гаргах функцээр хангадаг. Хэрэглэгчийн интерфэйс нь цонх, удирдлага үүсгэх функцээр хангадаг.

Мультимедиа бүрэлдэхүүн хэсэг нь видео, аудио, оролтын төхөөрөмжтэй ажиллах хэрэгслүүдээр хангадаг. Бүрхүүлийн интерфейсийн функцууд нь үйлдлийн системийн бүрхүүлээс өгсөн функцүүдэд хандах боломжийг програмуудад олгодог. Сүлжээний үйлчилгээ нь Windows-ийн сүлжээний чадамжид хандах боломжийг олгодог.

Бүрэлдэхүүн хэсгүүд

WinAPI C-г үүсгэхдээ Windows API-ийн үндсэн боломжуудыг анхаарч үзэх хэрэгтэй бөгөөд үүнийг долоон ангилалд хувааж болно. Тэд тус бүрийг илүү нарийвчлан авч үзье.

Зайлшгүй үйлчилгээнүүд нь Windows дээр байдаг системийн үндсэн нөөцөд хандах боломжийг олгодог. Жишээ нь: файлын систем, дагалдах төхөөрөмж, процесс, бүртгэлийн хандалт, онцгой байдлын удирдлагын систем. Эдгээр функцууд нь 16 битийн системүүдийн хувьд kernel.exe, krnl286.exe, эсвэл krnl386.exe, 32 битийн системүүдийн хувьд kernel32.dll болон advapi32.dll файлд хадгалагддаг.

GUI нь монитор, принтер болон бусад захын төхөөрөмж дээр харуулах нөөцөд хандах боломжийг олгодог. 16 битийн систем дээр gdi.exe, 32 битийн систем дээр gdi32.dll дээр хадгалагдана.

Хэрэглэгчийн интерфэйс нь товчлуур, гүйлгэх самбар зэрэг үндсэн элементүүдийг харах, хянах, гар, хулганы мэдээлэл авах, холбогдох функцуудыг хариуцдаг. Эдгээр функцууд нь 16 битийн систем дээр user.exe, 32 битийн систем дээр user32.dll comctl32.dll дээр хадгалагддаг. XP-ээс эхлэн хяналтуудыг comctl32.dll болгон бүлэглэсэн.

Ерөнхий харилцах цонхнууд - файл нээх, хадгалах, өнгө, фонт сонгох мэдээллийг харуулах. 16 битийн систем дээрх comdlg.dll, 32 битийн систем дээрх comdlg32.dll файлаас олдсон.

Windows Shell нь WinAPI-ийн бүрэлдэхүүн хэсэг бөгөөд програмууд нь үйлдлийн системийн бүрхүүлээс өгсөн функцэд хандах боломжийг олгодог.

Сүлжээний үйлчилгээ нь үйлдлийн системийн янз бүрийн сүлжээний боломжуудад хандах боломжийг олгодог. Түүний дэд бүрэлдэхүүн хэсгүүдэд NetBIOS, Winsock, RPC орно. Хуучин хувилбаруудад - NetDDE.

Хувилбарууд

Win16, Win32, Win32s нь хэрэглээний программ хангамжид Windows-ийн гэр бүлийн янз бүрийн үйлдлийн системийн функцуудыг ашиглах боломжийг олгодог бүрэлдэхүүн хэсгүүдийн стандарт багц юм.

Win16-ийн залгамжлагч Win32 нь 1993 онд Windows NT, 2000, 95 зэрэг 32 битийн Windows гэр бүлийн бүтээгдэхүүнүүдэд танилцуулагдсан. Энэхүү програмчлалын интерфейсийг Kernel32.dll, User32.dll болон GDI32.dll2 гэсэн гурван программ хангамжийн сангууд хэрэгжүүлдэг. Ижил Win32 функцууд нь Windows-ийн бүх бүтээгдэхүүнд байдаг бөгөөд тухайн бүтээгдэхүүнээс хамааран тодорхой функцуудыг ашигласнаар үйлчилгээний алдаа гарч болзошгүй.

Win32 боломжууд нь программ хоорондын харилцаа холбоо, процессын удирдлага, компьютерийн сүлжээ, файл, принтер, сервер, холбооны портуудыг багтаадаг.

Тодорхойлолт

C WinAPI нь Windows үйлдлийн системд зориулсан хийсвэр програмчлалын интерфейсийн тодорхойлолт юм. Функц, нэгдэл, бүтэц, өгөгдлийн төрөл, макро, тогтмол болон бусад програмчлалын элементүүдийн мэдэгдлээс бүрдэнэ. WinAPI-г мастер тайлбарласан бөгөөд Windows C-ийн толгой хэсэгт байдаг.WinAPI функцүүдийн албан ёсны хэрэгжилтийг динамик холбоосын сангаас (DLL) олж болно: жишээлбэл, kernel32.dll, user32.dll, gdi32.dll эсвэл shell32.dll. системийн лавлах. Windows API-ийн гуравдагч этгээдийн хэрэгжүүлэлтүүд байдаг: ялангуяа Wine төсөл болон ReactOS төсөл.

Windows API нь динамик объект юм. Үйлдлийн системийн шинэ хувилбар болон шинэ үйлчилгээний багц бүрээр функцүүдийн тоо байнга нэмэгдэж байна. Үйлдлийн системийн сервер болон ширээний хувилбаруудын хооронд бас чухал ялгаа бий. Зарим функцийг албан ёсоор баримтжуулаагүй болно.

Пеллес С

Pelles C нь үнэ төлбөргүй програм бөгөөд C програмчлалын хэлний хамгийн шилдэг C хөрвүүлэгч, нэгдсэн хөгжүүлэлтийн орчин (IDE) юм.32 битийн Windows (x86) болон 64 битийн Windows (x64)-ийг дэмждэг. C99 болон C11 стандартыг хоёуланг нь хэрэгжүүлдэг. Pelles C нь нөөцийн засварлагч, битмап, дүрс, курсор засварлагч, зургаан өнцөгт дамп засварлагчтай. Үүнийг Шведийн хөгжүүлэгч Пелле Ориниус боловсруулсан. Хөрвүүлэгчийг зохиогчийнхоо нэрээр нэрлэсэн. SDK-ийн хамт ирдэг тул програмист нэмэлт суулгалгүйгээр шууд програм үүсгэж эхлэх боломжтой.

Зорилтот архитектурын алдаа

Windows API програмуудыг үүсгэхийн тулд та Microsoft өргөтгөлүүдийг идэвхжүүлэх ёстой. Тэдгээр нь анхдагчаар идэвхгүй болсон бөгөөд хөрвүүлэгч дараах алдааны мессежийг гаргахад хүргэдэг бөгөөд энэ нь эвдэрсэн C WinAPI-ийн жишээ юм: аюултай алдаа #1014: #алдаа: "Зорилтот архитектур байхгүй" Майкрософт өргөтгөлүүдийг идэвхжүүлэхийн тулд төслийн тохиргоо руу очоод "Хөрвүүлэгч" табыг сонгоно уу. Энэ таб дээр "Microsoft өргөтгөлүүдийг идэвхжүүлэх" нүдийг идэвхжүүлнэ үү.

MSDN

Windows хөгжүүлэлтийн төв портал юм. Энэ бол Майкрософт хэрэгслийг ашиглан програм боловсруулахтай холбоотой асар том материалын цуглуулга юм. Энэ бол ширээний програм хөгжүүлэх баримт бичиг, Windows API-ийн жагсаалтын хамт хамгийн өргөн хүрээтэй мэдээллийн сан юм.

WinAPI C дээр DLL ашиглах

Нийтлэг хяналтын номын сан нь төлөвийн мөр, явцын мөр, хэрэгслийн мөр, таб зэрэг үйлдлийн системийн дэвшилтэт функцүүдэд хандах боломжийг олгодог. Эдгээр командууд нь 16 битийн систем болон comctl32.dll дээрх commctrl.dll-ээс олддог бөгөөд хэрэглэгчийн интерфэйсээр бүлэглэгддэг.

DLL нь Windows програмын олон код, процедурыг хадгалахад ашигладаг динамик холбоосын номын сангийн файлын формат юм. DLL файлууд нь олон программууд өөрсдийн мэдээллийг нэгэн зэрэг ашиглах боломжтой байхаар бүтээгдсэн бөгөөд энэ нь санах ойг хэмнэхэд тусалдаг. Хэрэглэгч хэд хэдэн програмын кодчилолыг өөрчлөхгүйгээр нэг дор засварлах боломжийг олгоно. DLL файлуудыг MSIL Disassembler эсвэл Lib 3.00-д зориулсан DLL ашиглан статик сан руу хөрвүүлж болно.

WinAPI нь Windows-д зориулсан хэрэглээний програмчлалын интерфейсийн хувьд энгийн файл боловсруулахаас эхлээд доод түвшний төхөөрөмжийн драйверуудыг програмчлах график интерфэйсийг бий болгох хүртэл өөрийн программыг бий болгох боломжийг олгодог олон хүчирхэг функцуудыг санал болгодог.

Та WinAPI дээр программчилж эхлэхээсээ өмнө Windows дээр өөрийн кодын орчинг тохируулах хэрэгтэй. Энэ нь Линукс түгээлт биш тул програм үүсгэхэд зориулагдсан хөрвүүлэгчгүй. Кодыг эмхэтгэхийн тулд дараах сонголтуудыг анхаарч үзээрэй.


Windows-д зориулсан хөгжүүлэлтийн иж бүрдэл нь хөгжүүлэгчдэд API болон холбогдох технологийг ашиглан програм хангамж үүсгэх боломжийг олгох баримт бичиг, хэрэгслээр хангадаг.

API гэсэн үгийн товчлол нь Application Programming Interface (API) нь зүгээр л програм хөгжүүлэгчид ашиглаж болох бэлэн функцүүдийн багц юм. Ерөнхийдөө энэ ойлголт нь өмнө нь дэд програмын номын сан гэж нэрлэгддэг зүйлтэй дүйцэхүйц юм. Гэсэн хэдий ч ихэнхдээ API нь ийм номын сангийн зарим тусгай ангиллыг хэлдэг.

Эцсийн хэрэглэгчдэд зориулсан бараг бүх нарийн төвөгтэй програмыг (MyApplication) боловсруулах явцад MyApplication API гэж нэрлэгддэг энэ програмыг хэрэгжүүлэхэд ашигладаг тодорхой дотоод функцүүдийн багц үүсдэг. Эдгээр функцийг бусад программистууд, түүний дотор бусад программуудыг бий болгоход үр дүнтэй ашиглаж болох нь ихэвчлэн тохиолддог. Энэ тохиолдолд зохиогчид бүтээгдэхүүнээ сурталчлах стратеги дээр үндэслэн асуултыг шийдэх ёстой - тэд гадны хэрэглэгчдэд энэ багцад хандах хандалтыг нээх үү, үгүй ​​юу? Хэрэв хариулт эерэг байвал програм хангамжийн багцын тайлбар дээр түүний давуу тал болох "багц нь API функцүүдийн нээлттэй багцыг агуулдаг" гэсэн хэллэг гарч ирнэ.

Тиймээс API нь ихэвчлэн нэг програмын хэсэг болох функцүүдийн багцыг хэлдэг боловч бусад програмуудад ашиглах боломжтой байдаг. Жишээлбэл, Excel нь эцсийн хэрэглэгчийн интерфэйсээс гадна Excel-ийн API функцуудтай бөгөөд ялангуяа VB ашиглан програм үүсгэх үед ашиглах боломжтой.

Үүний дагуу Windows API нь үйлдлийн системийн нэг хэсэг бөгөөд бусад ямар ч програм ашиглах боломжтой функцүүдийн багц юм. Үүнтэй холбогдуулан BIOS/DOS системийн тасалдлын багцтай зүйрлэсэн зүйрлэл нь үнэндээ DOS API юм.

Үүний ялгаа нь Windows API-ийн функцүүдийн найрлага нь нэг талаас DOS-тэй харьцуулахад хамаагүй өргөн, нөгөө талаас өмнөх үед программистуудын ашиглаж байсан компьютерийн нөөцийг шууд удирдах олон хэрэгслийг агуулаагүй явдал юм. OS. Нэмж дурдахад, Windows API руу залгах нь энгийн процедурын дуудлагуудыг ашиглан хийгддэг бөгөөд DOS функцууд руу залгах нь Interrupt хэмээх тусгай процессорын заавраар хийгддэг.

Win16 API болон Win32 API

Windows 3.x-ээс Windows 95-д шилжсэнээр 16 битийн үйлдлийн системийн архитектураас 32 бит рүү шилжсэнийг та бүхэн мэдэж байгаа. Үүний зэрэгцээ 16 битийн Windows API (Win16 API) нь 32 битийн шинэ хувилбараар (Win32 API) солигдсон. Энэ тохиолдолд та Windows 9x болон Windows NT гэр бүлүүдийн хувьд Win32 API багц нь цөөн хэдэн үл хамаарах зүйл гэдгийг санах хэрэгтэй.

Win API-тай танилцахдаа та олон суулгасан функцууд нь холбогдох системийн процедурыг дуудахаас өөр зүйл биш бөгөөд зөвхөн тухайн хэлний синтакс хэлбэрээр хэрэгждэг болохыг олж мэдэх болно. Үүнийг харгалзан API ашиглах хэрэгцээг дараах сонголтуудаар тодорхойлно.

API функцууд нь бүхэлдээ суурилагдсан функц хэлбэрээр хэрэгждэг. Гэсэн хэдий ч заримдаа энэ тохиолдолд API ашиглахад шилжих нь ашигтай байдаг, учир нь энэ нь заримдаа гүйцэтгэлийг мэдэгдэхүйц сайжруулж чаддаг (ялангуяа дамжуулагдсан параметрүүдийг шаардлагагүй хувиргалтгүйгээс).

Баригдсан функцууд нь зөвхөн тохирох API функцийн тусгай тохиолдлыг хэрэгжүүлдэг. Энэ бол нэлээд түгээмэл сонголт юм.

Маш олон тооны API функцууд нь хөрвүүлэгчийн одоогийн хувилбарт огт аналоггүй байдаг. Жишээлбэл, та VB ашиглан лавлахыг устгах боломжгүй - үүний тулд DeleteDirectory функцийг ашиглах хэрэгтэй.

Зарим API функцийг (тэдгээрийн Win API-д эзлэх хувь маш бага) хэлний хэд хэдэн хязгаарлалт, жишээлбэл санах ойн хаягтай ажиллах боломжгүй зэргээс шалтгаалан програмаас дуудах боломжгүй гэдгийг онцлон тэмдэглэх нь зүйтэй. Гэхдээ зарим тохиолдолд энгийн бус програмчлалын аргууд тусалж чадна (ялангуяа ижил хаягтай тохиолдолд).

Win APIТэгээдДинамик холбоосын сан (DLL)

Win API багц нь динамик DLL хэлбэрээр хэрэгждэг.

Энэ тохиолдолд DLL гэж бид хоёртын динамик номын сангийн уламжлалт хувилбарыг хэлдэг бөгөөд энэ нь програмуудыг шаардлагатай процедурууд - дэд програмууд эсвэл функцуудад шууд хандах боломжийг олгодог (төслийн хүрээнд процедурыг дуудах үед тохиолддогтой адил). Ийм сангуудыг VC++, Delphi, Fortran, Assembler гэх мэт өөр өөр хэрэгслүүд ашиглан үүсгэж болно.

Динамик номын сангийн файлууд ихэвчлэн .DLL өргөтгөлтэй байдаг ч энэ нь шаардлагагүй. Win16-ийн хувьд .EXE өргөтгөлийг ихэвчлэн ашигладаг байсан бөгөөд гадаад төхөөрөмжийн драйверуудыг .DRV ашиглан томилдог.

Windows API функцүүдийн яг тоо, тэдгээрийг агуулсан файлуудыг тодорхойлоход хэцүү байдаг (гэхдээ тэдгээр нь бүгд системийн лавлахад байрладаг). Үүнтэй холбогдуулан үйлдлийн системийн цөмийг бүрдүүлдэг номын сангуудын бүрэлдэхүүн, үндсэн нэмэлт функц бүхий үндсэн сангуудыг тодруулах нь зүйтэй.

Windows 95/98 үйлдлийн системийн цөмийн Win32 API сангууд:

KERNEL32.DLL: санах ой, даалгавар болон бусад системийн нөөцийг удирдах доод түвшний функцууд;

USER32.DLL: Энэ нь голчлон хэрэглэгчийн интерфэйсийн хяналтын функцүүд байрладаг;

GDI32.DLL: График төхөөрөмжийн интерфэйсийн номын сан - гадаад төхөөрөмж рүү гаргах төрөл бүрийн функцууд;

COMDLG32.DLL: Ерөнхий зориулалтын харилцах цонхыг ашиглахтай холбоотой функцууд.

Өргөтгөх функц бүхий үндсэн сангууд:

COMCTL32.DLL: Модны жагсаалт болон баялаг текст зэрэг Windows-ийн нэмэлт хяналтын багц;

MAPI32.DLL: имэйлтэй ажиллах функцууд;

NETAPI32.DLL: хяналт ба сүлжээний функцууд;

ODBC32.DLL: Энэ номын сангийн функцууд нь ODBC протоколоор дамжуулан янз бүрийн мэдээллийн сантай ажиллахад шаардлагатай;

WINMM.DLL: Системийн медиа хандалтын үйлдлүүд.

Энэ нийтлэлийг надтай адил C++ програмчлалд анхлан суралцаж байгаа, санамсаргүй эсвэл хүслээр WinAPI сурахаар шийдсэн хүмүүст зориулав.
Би танд нэн даруй анхааруулахыг хүсч байна:
Би өөрийгөө C++ эсвэл WinAPI багш гэж хэлэхгүй.
Би дөнгөж сурч байгаа бөгөөд WinAPI-ийн функц, механизмыг сурахад илүү хялбар болгох зарим жишээ, зөвлөмжийг энд өгөхийг хүсч байна.

Энэ нийтлэлд та аль хэдийн C++ хэл дээр анги үүсгэх, янз бүрийн операторуудыг хэт ачаалах чадвартай болсон, мөн анги доторх зарим механизмаа аль хэдийн “нуусан” гэж бодож байна.

Консол үүсгэх, ашиглах

Win32 програмыг дибаг хийх эсвэл дотор нь энэ бүхэн хэрхэн өрнөж байгааг харахын тулд би үргэлж консол ашигладаг.
Та консолын програм биш GUI програм үүсгэж байгаа тул консол холбогдоогүй байна. Үүнийг дуудахын тулд энэ кодыг интернетийн гүнээс олжээ

Хэрэв (AllocConsole())
{



std ::ios :: stdio_тэй синхрончлох();
}
Тохиромжтой болгохын тулд би үүнийг функцээр боож өгөхийг зөвлөж байна. Жишээлбэл:
CreateConsole () хүчингүй
{
хэрэв (AllocConsole())
{
int hCrt = _open_osfhandle((урт)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 :: stdio_тэй синхрончлох();
}

Дуудагдсан консол нь зөвхөн гаралтын горимд ажилладаг бөгөөд консолын програмуудтай адил ажилладаг. Мэдээллийг ердийн байдлаар гарга - cout/wcout.
Энэ кодыг ажиллуулахын тулд та дараах файлуудыг төсөлд оруулах ёстой.
#оруулна
#include #include
мөн дэлхийн нэрийн талбарт std нэрийн орон зайг оруулна уу:
namespace std ашиглах;
Мэдээжийн хэрэг, хэрэв та үүнийг хийхийг хүсэхгүй байгаа бол std::-г дотор нь байгаа бүх нэгжид нэмнэ үү.

Гаралт болон арифмын хувьд объектуудын өв залгамжлал. үйл ажиллагаа

"Цонх"-ыг өөрсдөө үүсгэж, судлахдаа би үргэлж консол дээр тодорхой утгыг гаргах шаардлагатай болдог.
Жишээлбэл:
Та GetClientRect функцийг ашиглан цонхны үйлчлүүлэгчийн талбайн хэмжээг авах бөгөөд RECT бүтцийн объектын хаягийг энэ объектыг өгөгдлөөр дүүргэхийн тулд параметр болгон дамжуулдаг. Хэрэв та хүлээн авсан үйлчлүүлэгчийн талбайн хэмжээг мэдэх шаардлагатай бол үүнийг аль хэдийн холбогдсон консол дээр харуулах боломжтой

Коут<

Гэхдээ үүнийг хийх болгондоо (ялангуяа ийм зүйл хийх шаардлагатай бол) маш тохиромжгүй байдаг.
Энд өв залгамжлал бидэнд туслах болно.
RECT бүтцээс нээлттэй удамшдаг класс үүсгээд гаралтын операторыг хэт ачаална<< так, как вам угодно.
Жишээлбэл:

Шинэ анги: нийтийн RECT
{
олон нийтэд:
найз ostream & оператор<<(ostream &strm,newrect &rect)
{
strm<<"Prtint RECT object:\n";
strm<буцах strm;
}
};

Одоо зүгээр л cout/wcout ашиглан объектыг гаргана:

Коут<

Мөн бүх зүйл таны хүссэнээр танд тохиромжтой хэлбэрээр харагдах болно.
Та өөрт хэрэгтэй ямар ч оператортой ижил зүйлийг хийж болно.
Жишээлбэл, хэрэв та бүтцийг харьцуулах эсвэл хуваарилах шаардлагатай бол (жишээлбэл, RECT эсвэл POINT), хэт ачаалах оператор==() болон оператор=() тус тус сонгоно.
Хэрэв та бага операторыг хэрэгжүүлэхийг хүсвэл< что бы быстро сравнивать размеры окна и т.д. перегрузите operator<().
Та үүнийг бараг ямар ч бүтцээр хийж чадна гэж би бодож байна, хамгийн чухал зүйл бол ердийн RECT бүтцийн объекттой ажилладаг бүх функцууд нь түүний өв залгамжлагчтай адилхан ажиллах болно.
Мөн би энэ бүх гоо сайхныг тусдаа хавсаргасан файлд хийж, шаардлагатай бол ашиглахыг зөвлөж байна.

Танай анги

Бусдын талаар мэдэхгүй ч би бүрэн ногоон болсон тул судалж үзсэн функц бүрдээ эсвэл номын бүлэг/дэд бүлэг бүрт шинэ төсөл зохиохоор шийдсэн бөгөөд ингэснээр бүх зүйл тавиур дээр байх болно. Хэзээ ч буцаж ирж, шаардлагатай зүйлсийн талаар миний санах ойг сэргээж чадна.
WinAPI дээр хамгийн энгийн цонхыг үүсгэхийн тулд та ангийн бүтцийг бөглөж, бүртгүүлж, жижиг цонхны процедурыг бичих хэрэгтэй, гурав, дөрөв дэх төслийн дараа би C++ дээр бичиж байснаа санаж байна.
Эцэст нь би бүх зүйлийг энгийн ангид нуусан. Цонхны бариул, түүний нэр, ангийн нэр, цонхны процедурын хаяг, цонхны анги (WNDCLASS) бүгд ангийн хувийн хэсэгт нуугдсан байдаг.
Тэдгээрийг олж авахын тулд энгийн Get аргуудыг тайлбарлахад хангалттай, жишээлбэл:
HWND GetHWND()
LPCTSTR GetClsName() гэх мэт.
Цонхны анги дүүргэх, бүртгэх, цонхыг өөрөө үүсгэх, харуулах зэрэг нь бүтээгч дээр хийгддэг.
Тохиромжтой болгохын тулд та бүтээгчийг хэт ачаалж, цонхны ангиллын бөглөх, бүртгэлийг тусдаа хувийн ангийн функцэд нууж, түүнийг бүтээгч бүрд дуудаж болно. Хэт ачааллын тав тухтай байдал нь заримдаа би маш энгийн цонх үүсгэх шаардлагатай болдог бөгөөд би цонхны нэр болон програмын зөвлөмж гэсэн хоёр параметр бүхий бүтээгчийг дууддаг.
Бусад тохиолдолд би анхдагч цонхны горимоор биш, тусгай хэмжээтэй цонх үүсгэх шаардлагатай болдог бөгөөд бусад тодорхой хэв маягтай байдаг - би дагалдах параметрүүдтэй хамт бүтээгчийг дууддаг.
Би энэ классыг IDE-ийн оруулах хавтсанд байрлах тусдаа оруулах файлд тодорхойлсон.
Энэ ангийн загвар:
анги BaseWindow
{
WNDCLASSEX_wcex;
TCHAR_ангийн нэр;
TCHAR_цонхны нэр;
HWND_hwnd;
bool _WindowCreation();
олон нийтэд:
BaseWindow(LPCTSTR цонхны нэр, HINSTANCE hInstance, DWORD загвар, UINT x, UINT y, UINT өндөр, UINT өргөн);
BaseWindow(LPCTSTR цонхны нэр, HINSTANCE hInstance);
const HWND GetHWND()const(HWND буцаана;)
LPCTSTR GetWndName()const(_windowName буцаана;)
};

Ийм хичээлийг сайтар тунгаан бодож, бичсэний дараа та амьдралаа хөнгөвчлөх бөгөөд нэг зүйлийг байнга бичихээс илүү суралцаж, ур чадвараа сайжруулахад илүү их цаг зарцуулах болно. Түүгээр ч барахгүй ийм ангиудыг өөрөө бий болгож, шаардлагатай үед нэмж оруулах нь их хэрэгтэй гэж бодож байна.

P.S.

Тодорхойлсон бүх зүйл нь үнэн юм:
Платформ - Windows 7 32 бит
IDE - Visual Studio 2010
Магадгүй эдгээр зөвлөмжүүд нь зарим хүмүүсийн инээдэм, инээдэмийг төрүүлж магадгүй ч бид бүгд нэгэн цагт ямар нэгэн зүйлд анхлан суралцагч/дадлагажигч/ багачууд байсан.
Энэ бичлэгийг зөвөөр хүлээн авна уу. Бүтээлч шүүмжлэлийг мэдээж сайшаана.

Хариуцлага

WinAPI өнгөрсөн зүйл болж байгаа юм шиг санагдаж байна. Удаан хугацааны туршид олон тооны хөндлөн платформ хүрээнүүд байсан; Windows нь зөвхөн ширээний компьютер дээр байдаггүй бөгөөд Microsoft өөрөө энэ мангасыг ашигладаг програмуудыг дэлгүүртээ хүлээн авдаггүй. Үүнээс гадна WinAPI ашиглан цонхыг хэрхэн бүтээх талаар зөвхөн энд төдийгүй Интернет даяар сургуулийн өмнөх насны болон түүнээс дээш насныханд зориулсан олон мянган нийтлэл байдаг. Энэ бүх үйл явц атомуудад хуваагдахаа больсон, харин субатомын хэсгүүдэд хуваагддаг. Юу илүү энгийн бөгөөд ойлгомжтой байж болох вэ? Тэгээд би энд байна ...

Гэхдээ бүх зүйл санагдсан шиг энгийн биш юм.

Яагаад одоо WinAPI-ийн талаар?

Нэгэн удаа, нэг тоглоомыг маш сайн тоглоомоор судалж байхдаа: Энэ бол сайн эмульс юм шиг санагдаж байна, гэхдээ дибаг хийгчид гарны товчлууруудаар шилжих гэх мэт энгийн зүйл байдаггүй. ямар ч ердийн дибаг хийгчид.

Би юу яриад байгаа юм бэ? Мөн энд нэг хэсэг код байна:

Case WM_KEYDOWN: MessageBox(hwndDlg,"Үх!","Би үхлээ!",MB_YESNO|MB_ICONINFORMATION); завсарлага;
Тиймээс зохиогчид гарны дэмжлэгийг нэмэхийг хүссэн боловч Windows дахь харилцах цонхны архитектурын гүн гүнзгий бодит байдал нь ийм санаачлагыг ноцтойгоор дарж орхив. Эмулятор болон дибаггер ашигласан хэн нэгэн энэ мессежийг харж байсан уу?
Юу болов?

Хариулт нь: та үүнийг хийж чадахгүй!

WinAPI-ийн талаархи анхны асуулт руу буцахдаа: маш олон алдартай, тийм ч алдартай биш төслүүд одоогоор үүнийг ашигласаар байна. Цэвэр API ашиглахаас илүү олон зүйлийг хийх боломжгүй (энд та дээд түвшний хэл, ассемблер хэлийг харьцуулах гэх мэт аналогийг эцэс төгсгөлгүй өгч болно, гэхдээ энэ нь одоо биш юм). Тэгээд хэн мэдэх вэ? Тэд зүгээр л ашигладаг, тэгээд л болоо.

Асуудлын талаар

Харилцах цонхнууд нь GUI-тэй ажиллахад хялбар болгохын зэрэгцээ биднийг өөрсдөө ямар нэг зүйл хийх боломжийг хаадаг. Жишээлбэл, цонхны процедурт ирж буй WM_KEYDOWN/WM_KEYUP мессежүүд нь DefDlgProc-ийн гүнд "иддэг" бөгөөд эдгээр нь: Tab навигаци, Esc боловсруулах, Enter товчлуурууд гэх мэт. Нэмж дурдахад, харилцах цонхыг гараар үүсгэх шаардлагагүй: нөөцийн засварлагч дээр товчлуурууд, жагсаалтуудыг зурах нь илүү хялбар бөгөөд WinMain дээр CreateDialog/DialogBox руу залгахад бэлэн боллоо.

Ийм жижиг бэрхшээлийг даван туулахад хялбар байдаг. Дор хаяж хоёр бүрэн хууль ёсны арга зам байдаг:

  1. RegisterClassEx-ээр дамжуулан өөрийн ангийг үүсгэж, анги боловсруулах процедурын WM_KEYDOWN-г барьж, түүнийг харилцах цонх боловсруулах процедур руу дахин чиглүүлээрэй. Тийм тийм! Та өөрийн ангитай харилцах цонх үүсгэж болох ба VS-ийн суулгасан засварлагч нь харилцах цонхонд ангийн нэрийг зааж өгөх боломжийг олгодог. Гэхдээ хэн үүнийг мэддэг, ашигладаг вэ?
    Сул тал нь ойлгомжтой: Та дахин нэг анги бүртгүүлэх, дахин 1 CALLBACK процедуртай байх шаардлагатай бөгөөд үүний мөн чанар нь зөвхөн хоёр мессеж дамжуулах явдал юм. Түүнээс гадна бид мэдэхгүй ХаанаТэднийг цац, тэгвэл та таягтай хашаа барих хэрэгтэй болно.
  2. Суурилуулсан хурдасгуур механизмыг ашигла. Мөн бид харилцах цонхны процедурын кодыг өөрчлөх шаардлагагүй! За, сэлгэхийн тулд нэг мөр нэмж болно, гэхдээ доороос илүү ихийг хэлнэ үү.

Хичээл?

Би ингэж хэлэхээс айхгүй байна Бүгд WinAPI-ээр дамжуулан цонх үүсгэх заавар нь ийм энгийн кодоор эхэлдэг бөгөөд үүнийг "мессеж боловсруулах гогцоо" гэж илэрхийлдэг (би цонхны анги болон бусад холболтыг бэлтгэх дэлгэрэнгүй мэдээллийг орхих болно):

Харин (GetMessage(&msg, nullptr, 0, 0)) ( TranslateMessage(&msg); DispatchMessage(&msg); )
Энд үнэхээр энгийн:

  1. GetMessage() нь дарааллаас дараагийн мессежийг авах ба гол мөч: Дараалал хоосон байвал хэлхээг блоклодог.
  2. WM_KEYDOWN/WM_KEYUP-аас TranslateMessage() нь WM_CHAR/WM_SYSCHAR мессежийг үүсгэдэг (хэрэв хэн нэгэн өөрийн текст засварлагчийг хийхийг хүсвэл тэдгээр нь хэрэгтэй болно).
  3. DispatchMessage() нь цонхны процедурт мессеж илгээдэг (хэрэв байгаа бол).
Энэ кодыг ашиглахад аюултай, яагаад гэдгийг эндээс эхэлье. Зүүлт тайлбарыг анхаарна уу:
Буцах утга нь тэг, тэг эсвэл -1 байж болох тул дараах кодоос зайлсхий.
байхад (GetMessage(lpMsg, hWnd, 0, 0)) ...
Доорх нь зөв гогцооны жишээ юм.

Win32 програмын VS загваруудад яг ийм зүйл бичигдсэн байдаг гэдгийг хэлэх нь зүйтэй болов уу буруумөчлөг. Мөн энэ нь маш харамсалтай юм. Эцсийн эцэст цөөхөн хүн зохиогчид өөрсдөө юу хийснийг судлах болно, учир нь энэ нь априори зөв юм. Мөн буруу код нь барьж авахад маш хэцүү алдаатай хамт олширдог.

Энэхүү кодын фрагментийн дараа, дүрмээр бол хурдасгуурын тухай түүх гарч, хэд хэдэн шинэ мөр нэмэгддэг (MSDN дээрх тэмдэглэгээг харгалзан би зөв мөчлөгийг нэн даруй бичихийг санал болгож байна):

HACCEL hAccel = Load Accelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; байхад (bRet = GetMessage(&msg, nullptr, 0, 0)) (хэрэв (-1 == bRet) завсарлага; хэрэв (!TranslateAccelerator(msg.hwnd, hAccel, &msg))) ( TranslateMessage(&msg); DispatchMessage(&msg) ;))
Энэ бол миний хамгийн олон удаа харсан сонголт юм. Тэгээд тэр ( та-дам) дахиад буруу байна!

Нэгдүгээрт, юу өөрчлөгдсөн тухай (дараа нь энэ кодтой холбоотой асуудлын талаар):

Эхний мөрөнд түлхүүрүүдийн хүснэгтийг нөөцөөс ачаалж байгаа бөгөөд дарахад WM_COMMAND мессеж харгалзах тушаалын id-тэй үүсгэгдэнэ.

Үнэн хэрэгтээ TranslateAccelerator үүнийг хийдэг: хэрвээ энэ жагсаалтад байгаа WM_KEYDOWN болон түлхүүр кодыг харвал (дахин гол цэг) WM_COMMAND (MAKEWPARAM(id, 1)) мессежийг үүсгэж, холбогдох мессеж рүү илгээнэ. эхний аргумент дээр заасан цонхны бариул , боловсруулах журам.

Сүүлийн өгүүлбэрээс харахад өмнөх кодтой холбоотой асуудал юу байсан нь тодорхой болсон гэж бодож байна.
Тайлбарлая: GetMessage нь "цонх" төрлийн БҮХ объектуудад (үүнд хүүхдүүд орно: товчлуурууд, жагсаалтууд гэх мэт) мессежийг барьж авдаг бөгөөд TranslateAccelerator нь үүсгэсэн WM_COMMAND-г хааш нь илгээх вэ? Зөв: товчлуур/жагсаалт руу буцах гэх мэт. Гэхдээ бид WM_COMMAND-г процедуртаа боловсруулдаг бөгөөд энэ нь бид үүнийг хүлээн авах сонирхолтой гэсэн үг юм.

Бидний үүсгэсэн цонхонд TranslateAccelerator дуудагдах ёстой нь ойлгомжтой.

HWND hMainWnd = Цонх үүсгэх(...); HACCEL hAccel = Load Accelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; байхад (bRet = GetMessage(&msg, nullptr, 0, 0)) (хэрэв (-1 == bRet) завсарлага; хэрэв (!TranslateAccelerator(hMainWnd, hAccel, &msg))) ( TranslateMessage(&msg); DispatchMessage(&msg); ) )
Одоо бүх зүйл сайхан, гайхалтай харагдаж байна: бид бүх зүйлийг нарийвчлан шинжилж үзсэн бөгөөд бүх зүйл төгс ажиллах ёстой.

Бас дахин үгүй. :-) Бид яг нэг цонхтой бол энэ нь зөв ажиллах болно - бидний. Загваргүй шинэ цонх (харилцах цонх) гарч ирмэгц тэнд дарагдсан бүх товчлуурууд WM_COMMAND руу хөрвүүлээд хаашаа илгээгдэх вэ? Мөн дахин зөв: манай үндсэн цонхонд.

Энэ үе шатанд би энэ мухардмал нөхцөл байдлыг шийдвэрлэхийн тулд таяг ашиглахгүй байхыг санал болгож байна, гэхдээ хичээл дээр аль хэдийн ховор тохиолддог (эсвэл бараг хэзээ ч олдоогүй) зүйлсийг авч үзэхийг санал болгож байна.

IsDialogMessage

Энэ функцийн нэрнээс харахад өгөгдсөн мессеж нь харилцан ярианд хамаарах эсэхийг тодорхой шалтгааны улмаас тодорхойлдог гэж та бодож магадгүй юм. Гэхдээ эхлээд бид яагаад үүнийг мэдэх хэрэгтэй байна вэ? Хоёрдугаарт, энэ мэдээллээр бид юу хийх ёстой вэ?

Үнэн хэрэгтээ энэ нь нэрнээс нь арай илүү зүйлийг хийдэг. Тухайлбал:

  • Tab/Shift+Tab/дээш/доош/баруун/зүүн товчлууруудыг ашиглан хүүхдийн удирдлагад шилжинэ. Дээрээс нь бас нэг зүйл, гэхдээ энэ нь бидэнд хангалттай
  • ESC дарснаар WM_COMMAND (IDCANCEL) үүсгэнэ.
  • Enter товчийг дарснаар WM_COMMAND(IDOK) буюу одоогийн товчлуур дээр дарснаар анхдагчаар үүсгэнэ
  • Өгөгдмөл товчлууруудыг сэлгэдэг (ийм товчлууруудын хүрээ нь бусдаас арай илүү гэрэлтдэг)
  • За, хэрэглэгчдэд харилцан яриатай ажиллахад хялбар болгодог бусад олон зүйлүүд
Энэ нь бидэнд юу өгөх вэ? Нэгдүгээрт, бид цонхны доторх навигацийн талаар бодох шаардлагагүй. Тэд ямар ч байсан бидний төлөө бүхнийг хийх болно. Дашрамд хэлэхэд, табын навигацыг манай үндсэн цонхонд WS_EX_CONTROLPARENT хэв маягийг нэмснээр хийж болно, гэхдээ энэ нь болхи, тийм ч ажиллагаагүй юм.

Хоёрдугаарт, энэ нь жагсаалтад орсон бусад бүх зүйл дээр бидний амьдралыг хөнгөвчлөх болно (мөн үүнээс ч илүү).

Ерөнхийдөө энэ нь ажлыг хангахын тулд Windows-ийн гүнд хаа нэгтээ ашиглагддаг модаль харилцах цонхнууд, ба программистуудад үүнийг загваргүй харилцах цонхонд дуудах зорилгоор өгдөг. Гэсэн хэдий ч бид үүнийг хаана ч ашиглаж болно:

IsDialogMessage функц нь загваргүй харилцах цонхнуудад зориулагдсан хэдий ч та үүнийг удирдлага агуулсан дурын цонхонд ашиглаж болох бөгөөд энэ нь цонхонд харилцах цонхонд ашигладагтай ижил гарын сонголтыг өгөх боломжийг олгоно.
Тэдгээр. Хэрэв бид гогцоог дараах байдлаар зохион бүтээвэл:

HWND hMainWnd = Цонх үүсгэх(...); HACCEL hAccel = Load Accelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; байхад (bRet = GetMessage(&msg, nullptr, 0, 0)) (хэрэв (-1 == bRet) тасарвал; хэрэв (!TranslateAccelerator(hMainWnd, hAccel, &msg))) (хэрэв (!IsDialogMessage(hMainWnd, &msg))) ( TranslateMessage(&msg); DispatchMessage(&msg); ) ) )
Дараа нь манай цонх үндсэн Windows харилцах цонх шиг навигацитай болно. Гэхдээ одоо бидэнд хоёр сул тал байна:

  1. Энэ код нь зөвхөн сайн ажиллах болно нэг (модаль бус) цонхтой;
  2. Харилцах цонхны навигацийн бүх давуу талыг хүлээн авсны дараа бид WM_KEYDOWN/WM_KEYUP мессеж хэлбэрээр дур булаам зүйлээс салсан (зөвхөн цонхонд зориулагдсан, хүүхдийн удирдлагын хувьд биш);
Энэ үе шатанд ерөнхийдөө бүх хичээлүүд дуусч, асуултууд эхэлдэг: Winapi стандарт харилцах цонхонд гарны үйл явдлыг хэрхэн зохицуулах вэ?
Энэ бол Google дээрх анхны холбоос, гэхдээ надад итгээрэй: тэдний олон мянган байдаг. Санал болгож буй шийдлүүдийн талаар (хамгийн сайн нь RegisterHotKey болон дэд ангилахаас өмнө дээр бичсэн өөрийн харилцах анги үүсгэх явдал юм. Хаа нэгтээ би "хамгийн сайн" арга замыг харсан: Windows Hooks ашиглах).

Хичээл, хариултанд байхгүй зүйлийн талаар ярих цаг болжээ.

Дүрмээр бол (дүрмээр бол хэн нэгэн илүү ихийг хүсч байвал та ангиа харилцах цонхонд бүртгүүлж, ийм байдлаар ажиллах боломжтой. Хэрэв хэн нэгэн үүнийг сонирхож байвал би үүнийг нийтлэлд нэмж болно) тэд хүссэн үедээ WM_KEYDOWN-ийг хүсдэг. цонхон дээрх сонгосон удирдлагаас үл хамааран функцийг гүйцэтгэх товчлуур дээр товших процесс - i.e. Энэ бүх тодорхой харилцан ярианы зарим ерөнхий функц. Хэрэв тийм бол WinAPI-ийн бидэнд санал болгож буй баялаг боломжуудыг яагаад ашиглаж болохгүй гэж? TranslateAccelerator.

Хаа сайгүй хэрэглэдэг яг нэгхурдасгуурын хүснэгт, зөвхөн үндсэн цонхонд зориулагдсан. За, үнэхээр: нэг GetMessage-loop цикл байгаа нь нэг хүснэгт байна гэсэн үг. Тэд өөр хаашаа явах ёстой вэ?

Үнэн хэрэгтээ GetMessage-гогцоонууд байж болно үүрлэсэн. PostQuitMessage-ийн тайлбарыг дахин харцгаая:

PostQuitMessage функц нь WM_QUIT мессежийг хэлхээний мессежийн дараалалд байршуулж, тэр даруй буцаж ирдэг; уг функц нь систем нь ирээдүйд ямар нэгэн цагт урсгалыг зогсоохыг хүсч байгааг харуулж байна.
Мөн GetMessage:
Хэрэв функц нь WM_QUIT мессежийг татаж авбал буцах утга нь тэг болно.
Тиймээс, хэрэв бид PostQuitMessage-г цонхны процедурт дуудвал GetMessage-гогцоо гарах болно. Энэ нь юу гэсэн үг вэ?

Бид чадна хүн бүр модаль бус Манай програмын цонхнууд ижил төстэй гогцоо үүсгэдэг. Энэ тохиолдолд DialogBoxParam нь бидэнд тохиромжгүй, учир нь Энэ нь өөрийн мөчлөгийг эргэдэг бөгөөд бид үүнд нөлөөлж чадахгүй. Гэсэн хэдий ч, хэрэв бид CreateDialogBoxParam-ээр харилцах цонх эсвэл CreateWindow-ээр дамжуулан цонх үүсгэвэл өөр давталт эргүүлэх боломжтой. Үүний зэрэгцээ, in хүн бүрИйм цонх болон харилцах цонхонд бид PostQuitMessage руу залгах ёстой:

HWND hMainWnd = Цонх үүсгэх(...); HACCEL hAccel = Load Accelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; байхад (bRet = GetMessage(&msg, nullptr, 0, 0)) (хэрэв (-1 == bRet) тасарвал; хэрэв (!TranslateAccelerator(hMainWnd, hAccel, &msg))) (хэрэв (!IsDialogMessage(hMainWnd, &msg))) ( TranslateMessage(&msg); DispatchMessage(&msg); ) ) ) // .... LRESULT CALLBACK WndProc(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam) ( switch(umsg) ( case WM_MYMESSAGE: (HWDlog) үүсгэх: (HWDlog) hЖишээ нь, MAKEINTRESOURCE(IDD_MYDIALOG), hwnd, MyDialogBoxProc); HACCEL hAccel = Ачаалал хурдасгагчид(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR_FOR_MY_DIALOG)); BOOL bRet = 0, fStatEnW боломжтой (Эх боломжтой) hwnd, FALSE); // эх цонхыг идэвхгүй болгох, харилцах цонх нь модаль байх үед (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) завсарлага; хэрэв (!TranslateAccelerator(hDlg, hAccel, &msg))) ( хэрэв (!IsDialogMessage(hDlg)) , &msg)) ( TranslateMessage(&msg); DispatchMessage(&msg); ) ) ) EnableWindow(hwnd, fSavedEnabledState); // эх цонхыг идэвхжүүлнэ. Харилцах цонх хаагдсан; ) ) ) INT_PTR CALLBACK MyDlgProc(HWND WRAMPA, hwnd, wparam, LPARAM lparam) ( switch(umsg) ( case WM_CLOSE: ( // EndDialog(hwnd, 0); --ТИЙГЭЭД БАЙХГҮЙ! // EndDialog нь ЗӨВХӨН DialogBox(Param) DestroyWindow(hwnd)-аар үүсгэсэн Modal Dialogs-д хүчинтэй; завсарлага; ) тохиолдол WM_DESTROY: ( PostQuitMessage(0); завсарлага; ) // .... ) 0 буцаана; )
Анхаарна уу: одоо манай програмын шинэ цонх бүрт боловсруулалтад нэмж оруулах боломжтой эзэмшдэгхурдасгуурын хүснэгт. WM_QUIT нь GetMessage-г харилцах цонхны давталтаас салгаж авах бөгөөд гаднах давталт нь үүнийг харахгүй. Яагаад ийм зүйл болж байна вэ?

Гаднах гогцоо нь өөрөө эргэдэг бидний процедур гэж нэрлэгддэг DispatchMessage руу залгахад "зогссон" нь баримт юм. дотоод засал GetMessage давталт нь ижил DispatchMessage-тэй. Сонгодог үүрлэсэн дуудлага (энэ тохиолдолд DispatchMessage). Тиймээс гаднах давталт нь WM_QUIT-г хүлээн авахгүй бөгөөд энэ үе шатанд дуусахгүй. Бүх зүйл жигд ажиллах болно.

Гэхдээ энэ нь бас сул талуудтай:
Ийм давталт бүр мессежийг боловсруулах болно зөвхөн "таны" цонхонд зориулагдсан. Энд байгаа бусад хүмүүсийн талаар бид мэдэхгүй. Энэ нь хэрэв хаа нэгтээ өөр цикл гарч ирвэл бусад бүх цонхнууд TranslateAccelerator/IsDialogMessage хосын мессежийн шаардлагатай боловсруулалтыг хүлээн авахгүй гэсэн үг юм.

За, эдгээр бүх сэтгэгдлийг анхаарч үзэх, эцэст нь манай програмын бүх цонхны бүх мессежийг зөв боловсруулах цаг болжээ. Доор бид нэг сэдвийн хэргийг авч үзэж байгааг тэмдэглэхийг хүсч байна. Учир нь Утас бүр өөрийн гэсэн мессежийн дараалалтай байдаг бөгөөд дараа нь хэлхээ болгонд та өөрийн бүтцийг бий болгох хэрэгтэй болно. Энэ нь кодын маш өчүүхэн өөрчлөлтөөр хийгддэг.

Бид үүнийг сайхан хийдэг

Учир нь Асуудлыг зөв томъёолох нь шийдлийн тал хувь нь тул та эхлээд энэ асуудлыг зөв тавих хэрэгтэй.

Нэгдүгээрт, энэ нь зөвхөн логик байх болно идэвхтэйцонх мессеж хүлээн авдаг. Тэдгээр. Идэвхгүй цонхны хувьд бид хурдасгуурыг дамжуулахгүй бөгөөд IsDialogMessage руу мессеж дамжуулахгүй.

Хоёрдугаарт, хэрэв хурдасгуурын хүснэгтийг цонхонд заагаагүй бол цацах зүйл байхгүй, бид зүгээр л IsDialogMessage руу мессеж илгээх болно.

Цонхны тодорхойлогчийг хурдасгуурын хүснэгтийн тодорхойлогчтой харьцуулах энгийн std::map бүтээцгээе. Үүн шиг:

Std :: газрын зураг l_mAccelTable;
Цонхыг үүсгэх үед бид дуртай хүснэгтэд тодорхойлогчтой шинэ цонхнуудыг нэмэх болно (эсвэл ийм боловсруулалт шаардлагагүй бол тэг).

BOOL AddAccelerators(HWND hWnd, HACCEL hAcceler) ( if (IsWindow(hWnd)) ( l_mAccelTable[ hWnd ] = hAccel; буцах ҮНЭН; ) буцаах FALSE; ) BOOL AddAccelerators(HWND hWnd, HACCEL hAcceler)(HWND hWnd, LPCcellerATS) буцаана. ( hInstance, accel)); ) BOOL AddAccelerators(HWND hWnd, int accel) ( буцаана AddAccelerators(hWnd, MAKEINTRESOURCE(accel)); ) BOOL AddAccelerators(HWND hWnd) ( буцаана AddAccelerators(hWnd, HACCEL));
За, цонхыг хаасны дараа устгана уу. Үүн шиг:

Хүчингүй DelAccel(HWND hWnd) ( std::map :: давтагч намайг = l_mAccelTable.find(hWnd); if (me != l_mAccelTable.end()) ( if (me->секунд) ( DestroyAcceleratorTable(me->second); ) l_mAccelTable.erase(me); ) )
Одоо бид шинэ харилцах цонх/цонх үүсгэх үед AddAccelerators (hNewDialog, IDR_MY_ACCEL_TABLE) дуудна уу. Хэрхэн хаах вэ: DelAccel(hNewDialog).

Бидэнд шаардлагатай тодорхойлогч бүхий цонхнуудын жагсаалт байна. Мессеж боловсруулах гол гогцоог бага зэрэг өөрчилье:

// ... HWND hMainWnd = Цонх үүсгэх(...); AddAccelerators(hMainWnd, IDR_ACCELERATOR); BOOL bRet = 0; байхад (bRet = GetMessage(&msg, nullptr, 0, 0)) (хэрэв (-1 == bRet) завсарлага; хэрэв (!HandleAccelArray(GetActiveWindow(), msg)) ( TranslateMessage(&msg); DispatchMessage(&msg); ) ) // ...
Хамаагүй дээр! HandleAccelArray-д юу байгаа ба яагаад GetActiveWindow() байгаа вэ?

Бяцхан онол:

Идэвхтэй цонхонд бариулыг буцаах хоёр функц байдаг: GetForegroundWindow болон GetActiveWindow. Эхний болон хоёр дахь ялгааг хоёр дахь тайлбарт маш тодорхой тайлбарласан болно.

Буцах утга нь дуудаж буй хэлхээний мессежийн дараалалд хавсаргасан идэвхтэй цонхны бариул юм. Үгүй бол буцах утга нь NULL байна.
Хэрэв эхнийх нь системийн аль ч цонхонд бариулыг буцааж өгөх юм бол сүүлийнх нь зөвхөн буцаж ирнэ Энэ нь манай хэлхээний мессежийн дарааллыг ашигладаг. Учир нь Бид зөвхөн утасныхаа цонхнуудыг (тиймээс бидний мессежийн дараалалд орох цонхнуудыг) сонирхож байгаа тул бид сүүлийнхийг нь авах болно.

Тиймээс HandleAccelArray нь идэвхтэй цонхонд шилжүүлсэн тодорхойлогчийн дагуу манай газрын зураг дээрх яг энэ цонхыг хайж, хэрэв байгаа бол TranslateAccelerator руу энэ мессежийг илгээж, дараа нь (эхний цонх хараагүй бол) баруун талд) IsDialogMessage руу оруулна уу. Хэрэв сүүлийнх нь мессежийг боловсруулаагүй бол бид стандарт TranslateMessage/DispatchMessage процедурыг давахын тулд FALSE гэж буцаана.

Ийм харагдаж байна:

BOOL HandleAccelWindow(std::map ::const_iterator mh, MSG & msg) ( const HWND & hWnd = mh->first; const HACCEL & hAccel = mh->секунд; хэрэв (!TranslateAccelerator(hWnd, hAccel, &msg))) (Орчуулагч.-д зориулагдаагүй //cceler. Хэрэв (!IsDialogMessage(hWnd, &msg)) ( // тэгэхээр, анхдагч зүйл нь ХУДАЛ буцаана; ) ) ) // за, мессеж орчуулагдсан. Дараагийн мессежийг ҮНЭН гэж буцаахын тулд мессежийн давталт гэж хэлээрэй; ) BOOL HandleAccelArray (HWND hActive, MSG & msg) (хэрэв (!hActive) FALSE буцаавал; // идэвхтэй цонх байхгүй. Хийх зүйл алга. std::map ::const_iterator mh = l_mAccelTable.find(hActive); if (mh != l_mAccelTable.end()) ( // Ойлголоо! Идэвхтэй цонхны буцах хэсэгт энэ мессежийг орчуулж үзээрэй HandleAccelWindow(mh, msg); ) FALSE буцаана; )
Одоо хүүхэд цонх бүр өөрийн дуртай хурдасгуурын хүснэгтийг нэмж, шаардлагатай кодоор WM_COMMAND-г тайван барьж, боловсруулах эрхтэй.

WM_COMMAND зохицуулагчийн кодын өөр нэг мөр яах вэ?

TranslateAccelerator дээрх тайлбар нь:
Энэ функцийн илгээдэг мессежийг цэс эсвэл удирдлагаар илгээсэн мессежээс ялгахын тулд WM_COMMAND эсвэл WM_SYSCOMMAND мессежийн wParam параметрийн өндөр эрэмбийн үг нь 1 утгыг агуулна.
Ер нь WM_COMMAND боловсруулах код нь дараах байдлаар харагдана.

Switch(HIWORD(wParam)) ( BN_CLICKED: // товч/цэсээс тушаал (шилж(LOWORD(wParam))) ( IDC_BUTTON1: DoButton1Stuff(); завсарлага; IDC_BUTTON2: DoButton2Stuff(); завсарлага; // ... ) завсарлага;))
Одоо та дараах байдлаар бичиж болно.

Switch(HIWORD(wParam)) ( 1-р тохиолдол: // хурдасгуурын тохиолдол BN_CLICKED: // товчлуурууд/цэсүүдээс тушаал ( switch(LOWORD(wParam))) ( тохиолдол IDC_BUTTON1: DoButton1Stuff(); завсарлага; тохиолдол IDC_BUTTON2: DoButton2Stuff(); завсарлага ; // ... ) завсарлага; ))
Тэгээд одоо, ижил fceux руу буцаж, нэмэх ганцхан мөрТовчлуурын командуудыг боловсруулах код руу оруулснаар бид хүссэн зүйлээ авдаг: дибаглагчийг гараас удирдана. Гол мессежийн давталтын эргэн тойронд жижиг боодол, шаардлагатай тохирох VK_KEY => IDC_DEBUGGER_BUTTON хурдасгуурын шинэ хүснэгт нэмэхэд хангалттай.

P.S .: Цөөхөн хүн мэддэг, гэхдээ та хурдасгуурын ширээгээ өөрөө үүсгэж, одоо үүнийг шууд хэрэглэж болно.

P.P.S.: Учир нь DialogBox/DialogBoxParam нь өөрийн гогцоог эргүүлж, дараа нь тэдгээрээр дамжуулан харилцах цонхыг дуудах үед хурдасгуур ажиллахгүй бөгөөд бидний давталт (эсвэл гогцоонууд) "сул" байх болно.

P.P.P.S.: HandleAccelWindow руу залгасны дараа l_mAccelTable газрын зураг өөрчлөгдөж магадгүй. TranslateAccelerator эсвэл IsDialogMessage нь DispatchMessage-г дууддаг бөгөөд тэнд бид зохицуулагчдаа AddAccelerators эсвэл DelAccel-тэй таарч магадгүй! Тиймээс энэ функцийн дараа түүнд хүрэхгүй байх нь дээр.

Та кодыг мэдрэх болно. MS VS 2017 стандарт загвараас үүсгэсэн кодыг үндэс болгон авсан.

Шошго: шошго нэмэх