Основни услуги на Windows и API функции. Windows api - набор от функции на операционната система. Защо за WinAPI наведнъж?

Хайде! Хайде! Днес най-накрая отново отваряме прозореца на Windows. Сбогом, горката конзола!

Дотогава трябва да сте запознати със синтаксиса на C++, да разбирате как да използвате цикли и цикли и да разбирате как функциите работят добре. Ако сте били хванати в морска битка, можете да вземете под внимание какво сте заловили.

Ugorsk регистрационен формуляр

Целият код, който се използва от WinAPI, е написан на украински език. Добра идея е да напишете добре кода.

Чия буква от кочана трябва да се постави преди името на промяната. Всички думи в имената на важни функции започват с голяма буква.

Ос на префиксите:

b – промяна на типа bool.
l - промяна на типа дълго цяло число.
w – дума (дума) – 16 бита. Име на краткия тип без знак.
dw – двойна дума (поддума) – 32 бита. Zminna тип unsigned long.
sz - ред, който завършва с нула (низ, завършващ нула). Просто прост ред, който последователно използвахме.
p или lp – показалец. lp (като дълъг указател) – тези индикатори са пренесени от миналото. В същото време lp i p означават същото.
h – описание (тип дръжка).

Например, оста се нарича така:

void * pData;

Този формуляр за влизане е защитен с авторски права от Microsoft. Има много хора, които критикуват този метод за именуване на променливи. Но подобни изказвания (особено за кодирането) са жизненоважни за големите компании.

Нека ви напомня, че постоянните идентификатори се основават на големите букви: WM_DESTROY. WM_DESTOY - стойност 2, константата се дефинира чрез define.

Освен това winAPI има много преназначени типове. Оста на тази страница е http://msdn.microsoft.com/en-us/library/aa383751(VS.85).aspx, можете да намерите описания на всички видове Windows (на английски).

И още една реч, която не разбрахме. Душовете често получават NULL стойности. Моля, обърнете внимание, че това е просто 0 и подписващите, на които е присвоена стойността NULL (нула), не посочват споделена памет.

Windows API (WinAPI)

Всички програми на Windows използват специален интерфейс за програмиране WinAPI. Наборът от функции и структури в Movi C прави вашата програма да работи добре в Windows.

Windows API има големи възможности за работа с операционната система. Може да се каже – без граници.

Не можем да разгледаме само сто от възможностите на WinAPI. Точно сега искам да взема повече материали, но това ще отнеме много часове и след като изтеглим WinAPI в блатата, ще стигнем до DirectX в няколко скали Описание на WinAPI, ще вземем два урока (включително този). , Те ще разгледат само рамката на програмата.

Програмата за Windows, точно както програмата за DOS, има основната функция. Тук тази функция се нарича WinMain.

Функция WinMain

Програмата за Windows се състои от следните части (всичко се съхранява в WinMain):

Създаване и регистрация на прозореца на класа. Не се бъркайте с C++ класове. WinAPI е написан на C, има много класове в това, което ни е познато като обща дума.
Създаване на прозореца на програмата.
Основният цикъл, в който се формират знанията.
Обработката се отчита в крайната процедура. Процедурата на прозореца е основна функция.
Ос и няколко точки са в основата на Windows програмите. Разширявайки този нов урок, ще подредим всичко в детайли. Ако се изгубите в описанието на програмите, върнете се към тези точки.

Сега нека подредим всичко:

WinAPI: WNDCLASS структура

Първо трябва да създадем и запазим структурната промяна WNDCLASS и след това да регистрираме крайния клас въз основа на нея.

Оста изглежда като тази структура:

моят c++ код typedef struct ( UINT стил; // стил на прозорец WNDPROC lpfnWndProc; // индикатор за процедурата на прозореца int cbClsExtra; // допълнителни байтове след класа. Първо зададено на 0 int cbWndExtra; // допълнителни байтове след екземпляра на прозореца. Първо зададено на 0 / програмна програма: предава се от параметъра за изглед в WinMain hIcon; // икона на програмата HCURSOR hBrush;

Структурата WNDCLASS в хранилището на WinAPI дефинира основните правомощия на прозореца, който се създава: икони, изглед на курсора на мишката, менюто на прозореца, коя добавка ще бъде в прозореца...

След като запазите тази структура, можете да регистрирате последния клас на тази база. Това не е същият клас като C++. Сега можете да запомните, че това е шаблонът, който сте регистрирали в системата, и сега можете да създадете нов шаблон въз основа на този шаблон. И всички тези дни ще бъдат управлявани от властите, както научихте от структурната промяна на WNDCLASS.

WinAPI: функция CreateWindow

След регистриране на новия клас, на негова база се създават основните програми (продължихме към друга точка). Опитайте тази допълнителна функция CreateWindow. Може да има обиден прототип:

моят c++ код HWND CreateWindow(LPCTSTR lpClassName // име на клас LPCTSTR lpWindowName // име на прозорец (показва се в заглавието) DWORD dwStyle // стил на прозорец int x // хоризонтална координата от левия край на екрана int y // вертикална координата wow edge screen int nWidth, // ширина на прозореца int nHeight, // височина на прозореца HWND hWndParent, // прозорецът на бащата HMENU hMenu, // описание на менюто HINSTANCE hInstance, // екземпляр на програма LPVOID lpParam // параметърът за първи път е зададен на NULL);

Тъй като на класа на прозореца (структура WNDCLASS) са дадени основните правомощия на прозореца, тогава тук са специфичните параметри на прозореца на кожата: размер на прозореца, координати...

Тази функция завърта прозореца за описание. За допълнително описание можете да отидете до прозореца, който е подобен на идентификатор.

Моля, имайте предвид, че тук има много нови типове. Всъщност цялата воня е стара, просто преименувана. Например: HWND не е преназначаване към типа HANDLE, което по свой начин е преназначаване на PVOID, което също е преназначаване на void*. Истината е заровена толкова дълбоко! В края на краищата, типът HWND не е знак за празнота.

Прозорецът се състои от много части. Всъщност във всяка програма ще видите: заглавието на прозореца, системното меню (щракнете върху иконата на програмата в горната лява част на прозореца), три системни бутона за работа с прозореца: свети, цял екран и близо. Също така, практически винаги в допълнение има меню. Оста на останалата определено няма да е в нас. И, разбира се, по-голямата част от прозореца е заета от т.нар. клиентска зона, в която клиентът работи.

Това е по-добре от прозоречния режим. Ако продължим да практикуваме с DiectX дълго време, няма да използваме режима на цял екран.

Обработка на съобщения

Основното предимство на всички разширени програми под Windows е обработката на актуализации.

Например, когато потребител натисне клавиш на клавиатурата, се генерира известие, че е натиснат клавиш. След това ще трябва да отидете на програмата, която е била активна, когато сте натиснали клавиша.

Тук имаме събитие - натиснат е клавиш.

Действията могат да бъдат: преместване на курсора на мишката, промяна на фокуса на програмите, натискане на клавишите на клавиатурата, затваряне на прозореца. Доста е богато. Дуже! За секунда в операционната система могат да бъдат създадени десетки съобщения.

Така че, ако има някакъв отговор, операционната система генерира известие: при натискане на клавиша се променят координатите на курсора на мишката и се отваря нов прозорец.

Информацията може да се създава както от операционната система, така и от различни програми.

Структурата и външният вид на предстоящата поръчка:

моят c++ код typedef struct tagMSG ( HWND hwnd; // прозорецът, който показва съобщението UINT за известие; // код за известяване WPARAM wParam; // параметър LPARAM lParam; // параметър DWORD време; // час, когато е издадено известието POINT pt; // координира курсора на мишката) MSG;

Моля, обърнете внимание на факта, че структурите се преназначават с помощта на typedefs.

За да създадете тази структура, можете бързо да използвате следния код:

моят c++ код msg.messgae == 2; // това са два реда еквивалентни фрагменти msg.message == WM_DESTROY; // константа WM_DESTROY стари две

Ето полето, в което се намира кодът за известяване (името на известието е равно на константата WM_DESTROY. WM - в Windows Message (подсистема на Windows). WM_DESTROY - това е известието, което се генерира при затваряне на прозореца (унищожаване - запазване) ).

Кодовете са посочени зад допълнителни константи и префикса WM_: WM_CLOSE, WM_CREATE и други.

Структурата на MSG има тип HWND - Window Handle (дръжка на прозорец и описание на прозорец). Това е нещо, което описва света. Цената е за ID символ (име на прозорец).

Запомнете тази дума - дръжка (опишете, дескриптор). В Windows това е много често срещана тема. Освен това всички типове Windows, които започват с H, са описания: описание на икона, описание на шрифта, описание на екземпляр на програма. Доколкото си спомням, те са около тридесет.

Всички взаимодействия между приложенията в Windows се осъществяват с помощта на тези описания на прозорци (HWND).

Има още един важен дескриптор - дескрипторът на програмата (HINSTANCE - първият параметър на WinMain) - това е уникален идентификатор на програмата, тъй като всяка операционна система не може да смеси две различни програми. Това е приблизително като баркод. Ще го разгледаме по-късно.

Незабавно, когато извършите каквото и да е действие, се създава и запомня известие: задава се прозорец с описание, където можете да отмените известието, задава се идентификаторът на известието, запазват се параметрите, запазва се часът (текущият) на поръчката Намерете координатите на курсора на мишката (виж структурата).

След това известие преминете към следващото известие на операционната система. Когато става въпрос за нашата информация, тя ще бъде изпратена до необходимия прозорец (Windows знае как да изпрати информация за кожата на специалистите). Ако сте запознати с програмите, ще трябва да бъдете информирани за тях. Трудно е да стигнеш до дъното, става скучно.

Удивително е, че в този момент, когато потребителят е извършил някакво действие (съобщението е показано и е генерирано съобщение) и в този момент, когато програмата е реагирала на това действие (съобщението е генерирано от програмата), има много на информация. Дори ако използвате Windows, можете също да получите много информация от програми. Първият може да има около стотици, другият може да има поне около няколко.

Прозоречна процедура - WndProc

Продължаваме от момента, в който информацията е изразходвана до края на програмата. Просто е много време и започва да се руши. За обработка, моля, имайте предвид, че програмата за кожата има специална функция - процедура на прозорец. Нарича се WndProc (от Window Procedure). Прозорецът на процедурата за разширяване се изпълнява в основния програмен цикъл и се завършва по време на всяка итерация на цикъла.

Информация (под формата на структурни промени MSG) се прилага към тази функция под формата на параметри: описание на прозореца, идентификатор на известие и два параметъра. Моля, обърнете внимание, че полетата time и pt не се предават на процедурата на прозореца. Тото, да ти кажа, вече е „розибран“.

В средата на процедурата на прозореца превключвателят се деинсталира, което включва проверка на идентификатора на известието. Оста е пример за проста прозоречна процедура (тя е напълно работеща):

моят c++ код// не си губете времето с HRESULT и __stdcall. Ще ги разгледаме по-късно. ) // компилаторът решава да информира )

Оставам – основният цикъл. Вин е още по-прост. Всяка итерация на цикъла се проверява от програмата. Веднага щом имате информация, вие сте привлечени от нея. След това цикълът ще бъде подканен да щракне върху процедурата на прозореца, за да обработи информацията.

Оста е в разгара си и всичко е за днес. Вече е ясно, че програма под WinAPI е много по-подобна на програма под DOS. Както вече писах, в следващия урок ще разгледаме кода на програмата, която работи.

Имам право да създам нов проект. В прозореца Нов проект изберете шаблон – Win32Project (предварително сме избрали Win32 Console Application). В един от предстоящите прозорци не задавайте флага за празен проект и IDE ще генерира подготвените програми.

Ако разгледате внимателно кода във файла project_name.cpp, ще видите всички неща, които обсъдихме: структурната промяна на MSG, попълването на структурата WNDCLASS, създаването на прозорец от функцията CreateWindow, основния програмен цикъл . Освен това на файла е присвоена функцията WndProc. Трябва да обработите редица информация в кутиите за превключване: WM_COMMAND, WM_PAINT, WM_DESTROY. Намерете всичко във файла.

В допълнение към това, което видяхме, програмата съдържа много допълнителен код. При следващото издание ще разгледаме кода на програмата, така че всичко да бъде проверено. Ще бъде много по-просто и по-интелигентно от това, което генерира IDE.

Опровержение

Бих си помислил, че WinAPI ще излезе точно в съседство. Отдавна е ясно, че има голям брой крос-платформени рамки, Windows не е само на настолни компютри, а самият Microsoft в своя магазин не се колебае да добави добавки, които биха оправдали това чудовище. Има хиляди статии за това как да създавате в WinAPI, не само тук, но и в целия Интернет, наброяващи хиляди, както в предучилищна възраст, така и извън нея. Целият процес на дисекция вече не се основава на атоми, а на субатомни частици. Какво може да бъде по-просто и по-интелигентно? И ето ме...

Но не всичко е толкова просто, колкото изглежда.

Защо за WinAPI сега?

Един ден, докато бях изтощен от същото хубаво нещо, си помислих: какво, по дяволите, е това, а в редактора няма толкова прост език като навигация през бутоните на клавиатурата, както е във всеки нормален редактор.

за какво говоря И кода на оста:

Case WM_KEYDOWN: MessageBox(hwndDlg,"Умри!","Мъртъв съм!",MB_YESNO|MB_ICONINFORMATION);
По този начин авторите искаха да добавят поддръжка към клавиатурата, но реалността на архитектурата на диалоговите прозорци в Windows жестоко наказваше такова самоугаждане. Всеки, който е използвал емулатор или контролер, би ли искал да знае това?
Какъв е проблема?

Отговорът е следният: не можете да работите така!

И, като се върнем назад, към източника на WinAPI: има твърде много популярни и не толкова много проекти, за да продължим да използваме този в момента, защото Накратко, не можете да правите много речи за чист API (тук можете безкрайно да рисувате аналогии с изравняването на висококачествен език и асемблер, но не изобщо). Защо не? Просто використ и това е.

За проблема

Диалоговите прозорци са по-лесни за работа от GUI, като в същото време ни дават възможност да правим нещата сами. Например информацията WM_KEYDOWN/WM_KEYUP, която се намира в процедурата на прозореца, се намира в подсекциите на DefDlgProc, включително думи като: навигация с раздели, обработка на Esc, клавиши Enter и др. Освен това не е необходимо да създавате диалогови прозорци ръчно: просто добавете бутони, списъци, редактор на ресурси, щракнете върху WinMain CreateDialog/DialogBox и сте готови.

Лесно е да заобиколите такива други тайни. И най-малко два напълно законни начина:

  1. Създайте свой собствен клас чрез RegisterClassEx и добавете WM_KEYDOWN към процедурата за обработка на класа и го пренасочете към самата процедура за обработка на диалог. Горе-долу! Можете да създавате диалози със свой собствен клас и да използвате VS редактора, който ви позволява да зададете име за класа за диалога. Някой знае ли за това и се самообслужва?
    Очевидният недостатък: Необходимо е да се регистрира още един клас, така че има още 1 CALLBACK процедура, чиято същност ще се загуби при излъчването на залога. Освен това не знаем кудиТе ще бъдат престъпени и в крайна сметка ще бъдат тормозени от полицията.
  2. Vikoristovat изпълнението на ускорителния механизъм. И никога няма да се налага да променяме кода на диалоговата процедура! Е, защо не добавите един ред към превключвателя / кутията, но цената е по-ниска.

уроци?

Не ме е страх да го кажа МустакУроците за създаване на прозорци чрез WinAPI започват с такъв прост код, показващ как се отчита цикълът на обработка (ще пропусна подробностите за подготовката на класа на прозореца и други връзки):

Докато (GetMessage(&msg, nullptr, 0, 0)) ( TranslateMessage(&msg); DispatchMessage(&msg); )
Тук всичко е много просто:

  1. GetMessage() крещи дяволското съобщение и ключов момент: блокира потока, защото е празен
  2. TranslateMessage() с WM_KEYDOWN/WM_KEYUP формира известие WM_CHAR/WM_SYSCHAR (това е необходимо, ако искате да създадете свой собствен текстов редактор).
  3. DispatchMessage() изпраща известието до процедурата на прозореца (както е).
Ясно е, че не е безопасно да се използва този код и ето защо. Върнете уважение към виното:
Следователно върнатата стойност може да бъде различна от нула, нула или -1, избягвайте код като този:
докато (GetMessage(lpMsg, hWnd, 0, 0)) ...
Насочвам дупето по-надолу в правилния цикъл.

Варто каза, че VS шаблоните за Win32 имат същите допълнения към правописа грешноцикъл. И наистина е лудост. Въпреки че малко хора се задълбочават в това, което самите автори са съставили, това е априори правилно. И неправилният код се умножава с грешки, което е много трудно да се хване.

След този фрагмент от код, като правило, има дискусия за ускорителите и се добавят няколко нови реда (по отношение на MSDN, препоръчвам ви да напишете правилния цикъл):

HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) break; if (!TranslateAccelerator(msg.hwnd, hAccel, &msg)) ( TranslateMessage(&msg); DispatchMes ; ) )
Най-често предпочитам този вариант. печеля ( та-дам) Znovu греши!

Ще говоря за тези, които са се променили (и след това за проблемите с този код):

В първия ред от ресурси е избрана таблица с ключове и когато щракнете върху някой от форматите, ще се покаже известието WM_COMMAND със съответния идентификатор на командата.

Това прави TranslateAccelerator: как да извлечете WM_KEYDOWN и кода на ключа, който е в този списък, след което (отново ключовата точка) форматирате съобщението WM_COMMAND (MAKEWPARAM(id, 1)) и го изпратите до типовете Един ден за прозореца манипулатор, посочен в първия аргумент, процедури за обработка.

С останалата фраза, предполагам, стана ясно какъв е проблема с предишния код.
Нека обясня: GetMessage е избрано за ВСИЧКИ обекти от типа „прозорец“ (включително деца: бутони, списъци и т.н.) и TranslateAccelerator ще изпрати генерираната WM_COMMAND къде? Точно така: тогава обратно към бутона/списъка. Добавяме WM_COMMAND към нашата процедура, което означава, че трябва да я премахнем от нея.

Оказва се, че TranslateAccelerator трябва да се използва за нашия създаден прозорец:

HWND hMainWnd = Създаване на прозорец(...); HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) break; if (!TranslateAccelerator(hMainWnd, hAccel, &msg)) ( TranslateMessage(&msg); DispatchMess )
И сега всичко е добре и прекрасно: подредихме всичко в детайли и всичко работи перфектно.

Пак знам. :-) Нека да го правим както трябва, щом имаме само едно – нашето. Веднага щом се появи немодален нов прозорец (диалог), всички клавиши, които ще бъдат натиснати в новия прозорец, се превеждат в WM_COMMAND и се изпращат къде? И нека го кажа правилно: главоболието ни е лошо.

На този етап ви съветвам да не блокирате полицията от най-глухата ситуация, а по-скоро да погледнете речите, които вече са по-ранни (или може да не са изяснени) в уроци.

IsDialogMessage

Въз основа на името на тази функция може да си помислите, че означава: да сте наясно с всеки диалог. Але, първо, какво знаеш? С други думи, каква е стойността на тази информация?

Наистина си струва да платите малко повече, стърчи от името. И на себе си:

  • Можете да навигирате през дъщерните контроли с помощта на бутоните Tab/Shift+Tab/Нагоре/Надолу/Надясно/Наляво. Плюс още нещо, това ни е достатъчно
  • След натискане на ESC се формира WM_COMMAND(IDCANCEL)
  • След натискане на Enter се формира WM_COMMAND(IDOK) или след натискане на бутона на реда
  • Сменя бутоните зад връзките (рамката на такива бутони е малко по-ярка от другите)
  • Е, и още повече различни неща, които улесняват робота на кореспондента с диалог
Какво ни дава? Първо, не е нужно да мислим за навигация в средата на прозореца. Трябва да пестим всичко толкова много. Преди да говорите, навигацията с раздели може да бъде постигната чрез добавяне на стила WS_EX_CONTROLPARENT към основния ни прозорец, но той не е много полезен и не толкова функционален.

По друг начин можем да улесним живота зад решетките на точките, изброени в списъка (и още няколко).

Vzagali, вие използвате тук в горната част на Windows за сигурност на роботи модални диалогови прозорци, а на програмистите се дава възможност да щракнат върху тях за немодални диалогови прозорци. Въпреки това можем да използваме това за добра мярка:

Освен това диалоговата функция на функцията се използва за моделиране на диалогови прозорци, можете да я използвате с всеки прозорец, така че знаците да се настройват в прозорците, за да се гарантира, че самата клавиатура е избрана, така че Налична в диалоговия прозорец.
Tobto. Сега нека форматираме цикъла по следния начин:

HWND hMainWnd = Създаване на прозорец(...); HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) прекъсване; if (!TranslateAccelerator(hMainWnd, hAccel, &msg)) ( if (!IsDialogMessage(hMainWnd) TranslateMessage(&msg) ; DispatchMessage(&msg);
Тогава най-накрая ще използваме навигация, точно както в други диалогови прозорци на Windows. Но сега сме отвлечени от два недостатъка:

  1. Този код също ще бъде използван само любезно с един (немодален) прозорец;
  2. След като отнехме всички предимства на диалоговата навигация, трябва да добавим WM_KEYDOWN/WM_KEYUP към изгледа (само за самия прозорец, а не за дъщерни контроли);
И на този етап всички уроци приключват и храната започва: Как да обработвам събития от клавиатурата в стандартен диалогов прозорец на winapi?
Това е първото нещо, публикувано в Google или в Интернет: хиляди от тях. За предложеното решение (най-вече е необходимо да създадете свой собствен клас диалози, за които писах по-горе, преди подкласиране и RegisterHotKey. Тук ще науча „най-краткия“ от методите: vikorize Windows Hooks).

Дойде време да поговорим за това какво липсва в уроците и видеоклиповете.

Като правило (като правило! Ако някой иска повече, можете да регистрирате класа си за диалози и да работите така. И ако не ви интересува, мога да добавя тази статия) WM_KEYDOWN, ако искате да обработите натиска, натиснете клавиша да изберете функцията независимо от необходимия контрол в офиса - т.е. Това е жизненоважна функция за този конкретен диалог. И ако това е така, тогава защо не представим бързо богатите възможности, на които самият WinAPI ни учи: TranslateAccelerator.

Чрез vikoryst точно единтаблица с ускорители и дори главния прозорец. Е, честно казано: има само един цикъл на GetMessage и има само една таблица. Къде трябва да отидат?

Всъщност циклите на GetMessage могат да бъдат вноски. Нека се възхитим още веднъж на описанието на PostQuitMessage:

Функции PostQuitMessage публикува съобщение WM_QUIT в опашката за съобщения на нишката и се връща незабавно;
Получавам съобщение:
Ако функцията е да актуализира съобщението WM_QUIT, върнатата стойност е нула.
По този начин се получава излизане от цикъла GetMessage, както наричаме PostQuitMessage в процедурата на прозореца. Какво означава това?

Можем за кожен немодален Това е прозорецът за нашата програма за създаване на собствен цикъл, подобен на мощност. Ако DialogBoxParam е подходящ за нас, т.к За нас е невъзможно да завъртим собствения си цикъл на влага. Ако обаче създадете диалогов прозорец чрез CreateDialogBoxParam или прозорец чрез CreateWindow, можете да стартирате друг цикъл. Когато става въпрос за коженЗа този вид диалог ние сме длъжни да щракнем PostQuitMessage:

HWND hMainWnd = Създаване на прозорец(...); HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) прекъсване; if (!TranslateAccelerator(hMainWnd, hAccel, &msg)) ( if (!IsDialogMessage(hMainWnd) TranslateMessage(&msg) ; DispatchMessage(&msg); ) ) // .... hInstance, MAKEINTRESOURCE(IDD_MYDIALOG), hwnd, MyDialogBoxProc), HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR_FOR_MY_DIALOG)); wnd, FALSE);// деактивиране на родителския прозорец, тъй като диалоговият прозорец е модален, докато (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) прекъсване; if (!TranslateAccelerator(hDlg, hAccel) , &msg)) ( if (!IsDia , &msg)) ( TranslateMessage(&msg); DispatchMessage(&msg); ) ) ) EnableWindow(hwnd, fSavedEnabledState); // Разрешаване на родителски прозорец. wparam, LPARAM lparam) (switch(umsg) (case WM_CLOSE: (// EndDialog(hwnd, 0)); - НЕ ПРАВЕТЕ ТОВА! // EndDialog е правилен само за модифициране на диалогови прозорци, създадени с DialogBox(Param) DestroyWindow(hwnd) ; break; ) case WM_DESTROY: ( PostQuitMessage(0); break; ) // .... ) return 0; )
Възвърнете уважението: сега за новия прозорец на кожата в нашата програма, който можем да добавим преди обработката Vlasnuускорителна маса. WM_QUIT премахва GetMessage от диалоговия цикъл и външният цикъл не се изпълнява. защо си толкова развълнуван

Вдясно е, че текущият цикъл „се изправя“ върху щракването на DispatchMessage, което се щраква върху нашата процедура, как да включим силата му вътрешниЦикълът GetMessage със самото това DispatchMessage. Класически wiki прикачени файлове (в DispatchMessage). Следователно външният цикъл не отменя WM_QUIT и завършва на този етап. Всичко върви гладко.

Е, тук има някои недостатъци:
Кожата е наясно с този цикъл само за „вашия“ прозорец. Не знаем за другите тук. Това означава, че ако тук се появи друг цикъл, тогава всички те ще трябва да обработят своите съобщения с помощта на двойката TranslateAccelerator/IsDialogMessage.

Е, дойде моментът да върнем всичките си почитания и да напишем и вземем решение за правилната обработка на всичко, за да ви информираме за всички резултати от нашата програма. Искам да уважа, че наградата за един поток е по-ниска. защото Ако кожният поток позволява структурата му да стане осъзната, тогава кожният поток ще трябва да създаде своите структури. Да се ​​страхуват дори от тривиални промени в кода.

Робимо е красив

защото Ако правилното задаване на задача е половината от решението, тогава първо трябва да задам правилно задачата.

Първо, логично би било само по-активенСега получавам известия. Tobto. За неактивен прозорец ние не превеждаме ускорителя и не изпращаме известия до IsDialogMessage.

По друг начин, ако таблицата на ускорителя не е зададена за прозореца, тогава няма какво да се превежда, само известие в IsDialogMessage.

Нека създадем проста std::map, която ще картографира дескриптора на прозореца в дескриптора на ускорителната таблица. Оста е така:

Std::map l_mAccelTable;
И в света на създадените прозорци ще продължим да добавяме нов прозорец с дескриптор към любимата ви таблица (или нула, тъй като такава обработка не се изисква).

BOOL AddAccelerators(HWND hWnd, HACCEL hAccel) ( if (IsWindow(hWnd)) ( l_mAccelTable[ hWnd ] = hAccel; return TRUE; ) return FALSE; ) BOOL AddAccelerators(HWNDhW LoadAccelerators( hInstance, accel));) BOOL AddAccelerators( HWND hWnd, int accel)
И след като затворите прозореца, си тръгнете. Оста е така:

Void DelAccel(HWND hWnd) ( std::map ::iterator me = l_mAccelTable.find(hWnd); if (me != l_mAccelTable.end()) ( if (me->second) ( DestroyAcceleratorTable(me->second); ) l_mAccelTable.erase(me); ) )
Сега, когато създаваме нов диалог/прозорец, щракнете върху AddAccelerators(hNewDialog, IDR_MY_ACCEL_TABLE). Как да затворите: DelAccel(hNewDialog).

Имаме списък с необходимите дескриптори. Ето как променяме нашия основен цикъл на обработка:

// ... HWND hMainWnd = CreateWindow(...); AddAccelerators(hMainWnd, IDR_ACCELERATOR); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) прекъсване; if (!HandleAccelArray(GetActiveWindow(), msg)) ( TranslateMessage(&msg); DispatchMessage ) // .. .
Много по-добре! Какво има с HandleAccelArray и какво следва с GetActiveWindow()?

Малко теория:

Има две функции, които завъртат манипулатора на активния прозорец GetForegroundWindow и GetActiveWindow. Значението на първото над другото е напълно описано в описанието на другото:

Върнатата стойност е манипулаторът на активния прозорец, прикрепен към опашката от съобщения на извикващата нишка. В противен случай върнатата стойност е NULL.
Ако първо завъртите дескриптора на който и да е прозорец в системата, тогава само останалите как використите разказват нашия поток. защото Ще продължим да живеем само в нашия поток (а също и тези, които ще бъдат похабени до наши дни), тогава ще останем.

Така че оста HandleAccelArray, която се предава от дескриптора на активния прозорец, е най-видима в нашата карта и тъй като е там, тя изпраща съобщение до излъчването на TranslateAccelerator и след това (като че ли първото не е необходимо nogo ) в IsDialogMessage. Ако съобщението все още не е изпратено, задайте FALSE, за да преминете през стандартната процедура TranslateMessage/DispatchMessage.

Изглежда така:

BOOL HandleAccelWindow(std::map ::const_iterator mh, MSG & msg) ( const HWND & hWnd = mh->first; const HACCEL & hAccel = mh->second; if (!TranslateAccelerator(hWnd, hAccel, &msg)) ( // съобщението не е за превод Опитайте то с IsDialogMessage if (!IsDialogMessage(hWnd, &msg)) ( // така че нещата по подразбиране връщат FALSE; ) ) // добре, съобщението е преведено (HWND hActive, MSG & msg) ( if (!hActive) връща FALSE; / / няма активен прозорец. Нищо за правене std::map ::const_iterator mh = l_mAccelTable.find(hActive); if (mh != l_mAccelTable.end()) ( // Разбрах! Опитайте се да преведете това съобщение за активния прозорец return HandleAccelWindow(mh, msg); ) return FALSE; )
Сега всяко дете има право да добави любимата си ускорителна таблица и спокойно да хване и въведе WM_COMMAND с необходимия код.

Какво друго има за един ред в кода WM_COMMAND?

Описание в TranslateAccelerator, за да кажете:
За да стане ясно, че функцията за изпращане със съобщения означава меню или контроли, силно ефективната дума с wParam параметър WM_COMMAND или WM_SYSCOMMAND съобщение съдържа стойност 1.
Кодът за обработка на WM_COMMAND изглежда така:

Switch(HIWORD(wParam)) ( case BN_CLICKED: // Команда от бутони/менюта ( switch(LOWORD(wParam))) ( case IDC_BUTTON1: DoButton1Stuff(); break; case IDC_BUTTON2: DoButton2Stuff ) break; ) )
Сега можете да го напишете така:

Switch(HIWORD(wParam)) ( case 1: // ускорител case BN_CLICKED // Команда от бутони/менюта ( switch(LOWORD(wParam))) ( case IDC_BUTTON1: DoButton1Stuff(); break; case IDC_BUT // ... ) прекъсване;))
И сега, обръщайки се към същия fceux, добавяйки само един редВ кода за обработка на команди за бутони премахваме следното: използвайте дебъгера от клавиатурата. Достатъчно е да добавите малка обвивка близо до цикъла на главата и нова таблица с ускорители с подчинени VK_KEY => IDC_DEBUGGER_BUTTON.

PS: Малко хора знаят дали е възможно да създадете своя собствена таблица за ускоряване и сега да я замразите директно.

P.P.S.: Защото DialogBox/DialogBoxParam завъртат цикъла на захранване, след което, когато диалогът се извика през тях, ускорителите не работят и нашият цикъл (или цикли) е „неактивен“.

P.P.P.S.: След щракване върху HandleAccelWindow картите l_mAccelTable могат да се променят, т.к. TranslateAccelerator или IsDialogMessage щракнете върху DispatchMessage и там можете да се присъедините към AddAccelerators или DelAccel в нашите процесори! Затова е по-добре да не пренебрегвате тези функции.

Можете да въведете кода. Той се основава на кода, генериран от стандартния MS VS 2017 шаблон.

Тагове: Добавете тагове

C WinAPI е основният набор от програмни интерфейси на Microsoft (API), налични в операционните системи. Една ранна версия се нарича Win32 API.

Въведете

WinAPI е интерфейс за програмиране на приложения, който се използва за създаване на Windows програми. Като начало разработчикът трябва да използва Windows SDK, известен преди като Platform SDK.

Обединете заглавни файлове, библиотеки, изображения, документация и инструменти, използвани за разработване на програми. API за езиково програмиране на C и C++. Това е най-прекият начин за създаване на добавки в операционната система на една компания.

С WinAPI можете да го разделите на няколко области:

    основни услуги;

    безопасност;

  • Koristuvalnytsky интерфейс;

    мултимедия;

    обвивка на Windows;

    Мережеви услуги.

Основните услуги ще осигурят достъп до основни ресурси. Те включват функции на WinAPI, файлови системи, устройства, процеси, нишки, регистър и обработка на грешки. Зоната за сигурност съдържа интерфейси, обекти и други програмни елементи за удостоверяване, оторизация, криптография и други задачи, свързани със сигурността. Графичната подсистема осигурява функционалност за показване на графики на монитори, принтери и други дисплейни устройства. Интерфейсът на художника ще предостави функционалност за създаване на прозорци и елементи на художника.

Мултимедийният компонент предоставя инструменти за работа с видео, аудио и входни устройства. Функциите на интерфейса на обвивката позволяват на програмите да получат достъп до функциите, предоставени от обвивката на операционната система. Мрежовите услуги осигуряват достъп до максималната възможна степен в Windows.

Компоненти

С активиран WinAPI ще имате достъп до основните възможности на Windows API, които могат да бъдат организирани в седем категории. Нека да разгледаме кожата на техния доклад.

Основните услуги осигуряват достъп до основните системни ресурси в Windows. Приложения: файлова система, периферни устройства, процеси, достъп до системния регистър и система от ядра. Тези функции се съхраняват във файловете kernel.exe, krnl286.exe или krnl386.exe за 16-битови системи и kernel32.dll и advapi32.dll за 32-битови системи.

Графичният интерфейс ще осигурява достъп до ресурси за показване на монитори, принтери и друго периферно оборудване. Той се съхранява във файла gdi.exe на 16-битови системи и gdi32.dll на 32-битови системи.

Интерфейсът на потребителския интерфейс се характеризира с появата на основни елементи, като бутони и превъртане, информация за клавиатурата и мишките, както и функции, свързани с тях. Тези функции се съхраняват във файла user.exe на 16-битови системи и user32.dll comctl32.dll на 32-битови системи. Започвайки с версията на XP, контролите са групирани в comctl32.dll.

Тайни диалози - Показване на данни за отваряне и запазване на файлове, избор на цветове и шрифтове. Файлът е comdlg.dll на 16-битови системи и comdlg32.dll на 32-битови системи.

Windows Shell е WinAPI компонент, който позволява на програмите да получат достъп до функциите, предоставени от обвивката на операционната система.

Мрежовите услуги осигуряват достъп до максималните възможности на операционната система. Неговите подкомпоненти включват NetBIOS, Winsock, RPC. По-старите версии имат NetDDE.

Версии

Win16, Win32 и Win32s са стандартни набори от компоненти, които позволяват на приложния софтуер да изпълнява функциите на различни операционни системи от семейството Windows.

Win32, наследникът на Win16, беше представен през 1993 г. в 32-битови продукти от семейството на Windows, като Windows NT, 2000, 95. Този софтуерен интерфейс реализира три софтуерни библиотеки: Kernel32.dll, User32.dll и GDI32.dll2. Същите функции на Win32 са налични във всички продукти на Windows и в зависимост от продукта добавянето на тези функции може да причини проблеми с обслужването.

Възможностите на Win32 включват комуникация между програми, контрол на процеси, компютърни файлове, принтери, сървъри и комуникационни портове.

Спецификация

WinAPI е абстрактна спецификация за програмен интерфейс за операционната система Windows. Състои се от декларации на функции, връзки, структури, типове данни, макроси, константи и други програмни елементи. WinAPI се описва от заглавката и се намира в заглавките на Windows C. Официалната реализация на функцията WinAPI се намира в динамични библиотеки (DLL): например kernel32.dll, user32.dll, gdi32.dll и shell32.dll в системата указател. Има реализации на Windows API от трети страни: най-вече проекта Wine и проекта ReactOS.

Windows API е динамичен обект. Броят на функциите постепенно нараства с всяка нова версия на операционната система и нови пакети за актуализация. Съществуват и важни разлики между сървърните версии и настолните версии на операционната система. Тези функции не са официално документирани.

Пелес К

Pelles C е програма без софтуер и най-бързият C компилатор и интегриран двигател за разработка (IDE) за програмиране на език C Поддържа 32-битов Windows (x86) и 64-битов Windows (x64). Изпълнява стандартите C99 и C11. Pelles може да включва редактор на ресурси, растерно изображение, икона, редактор на курсори и редактор на шестнадесет дъмпа. Разкрито от шведския търговец на дребно Pelle Orinius. Името на съставителя носи името на неговия автор. Включен с SDK, програмистът може незабавно да отпечата създадената програма без допълнителна инсталация.

Целенасочена архитектура

За да създадете Windows API програми, трябва да активирате разширенията на Microsoft. Зад него има воня, във връзка с която компилаторът вижда съобщение за грешката, сякаш е C WinAPI приложение с нарушена структура: фатална грешка #1014: #error: „Няма целева архитектура.“ За да активирате разширението на Microsoft, отидете на параметрите на проекта и изберете раздела „Компилатор“. В този раздел е активирана опцията „Деактивиране на разширенията на Microsoft“.

MSDN

Това е централният портал за инсталиране на Windows. Това е страхотна колекция от материали, свързани с разработването на програми от различни инструменти на Microsoft. Изчерпателна база данни с документация от разработката на десктоп приложения и списък на Windows API.

Използване на DLL в WinAPI C

Библиотеката от разширени елементи ще осигури достъп до разширени функции на операционната система, като редове, индикатори на прозорци, ленти с инструменти и раздели. Тези команди се намират в библиотеката commctrl.dll в 16-битови системи и comctl32.dll и са групирани с клиентския интерфейс.

DLL е файлов формат на динамична библиотека, който се използва за запазване на няколко кода и процедури за програми на Windows. DLL файловете са създадени по такъв начин, че редица програми да имат незабавен достъп до тяхната информация, като по този начин пестят памет. Позволява на потребителите да редактират код в множество програми, без да ги променят. DLL библиотеките могат да бъдат преобразувани в статични, vikorist MSIL Disassembler или DLL за Lib 3.00.

WinAPI, като интерфейс за програмиране на приложения за Windows, предлага прости функции, които ви позволяват да създавате свои собствени програми, от проста обработка на файлове до графичен интерфейс за програмиране на драйвери на устройства от ниско ниво.

Преди да започнете да програмирате с WinAPI, трябва да настроите средно положение за кода в Windows. Въпреки че не е дистрибуция на Linux, тя няма вграден компилатор за създаване на добавки. Нека да разгледаме следните опции за компилиране на код:


Наличен е комплект за разработчици за Windows, който предоставя документация и инструменти, които позволяват на разработчиците да създават софтуер с Wikimedia API и свързани технологии.

Windows API - набор от функции на операционната система

Съкращението на API изглежда неясно и объркващо за много начинаещи програмисти. Всъщност интерфейсът за програмиране на приложения (API) е просто готов набор от функции, които могат да се използват от доставчици на добавки. Във формален смисъл тази концепция е еквивалентна на това, което преди това често се наричаше библиотека от подпрограми. Все пак, имайте предвид, че под API има специална категория такива библиотеки.

По време на процеса на разработка за крайния потребител се формира набор от специфични вътрешни функции, които са необходими за изпълнението на определена програма, което се нарича MyApplication API. Въпреки това, често се открива, че тези функции могат да бъдат ефективно използвани за създаване на други програми, включително други програми. По какъв начин авторите, въз основа на стратегията за продажба на своя продукт, избират храненето: защо позволяват достъп до кой комплект за външни клиенти? Ако бъде потвърдено, описанието на софтуерния пакет като положителна характеристика включва фразата: „Пакетът включва изчерпателен набор от API функции“ (или срещу допълнителни пари).

По този начин най-често под API има набор от функции, които са част от една програма, но които са достъпни за използване в други програми. Например Excel, в допълнение към интерфейса за крайния потребител, има набор от Excel API функции, които могат да бъдат достъпни, например, с програми, създадени с помощта на VB.

Очевидно Windows API е набор от функции, който е част от самата операционна система и в същото време е достъпен за всяка друга програма, включително написана с помощта на VB. Този план е напълно аналогичен на набора от системни настройки на BIOS/DOS, който всъщност е DOS API.

Предимството на функционалността на Windows API, от една страна, е много по-широко от това на DOS, от друга страна, не включва много функции за директен контрол на компютърните ресурси, достъпни за програмите на бившата ОС. Освен това връзката с Windows API се основава на допълнителни процедурни параметри, а DOS функцията се осъществява чрез специална процесорна машинна команда, наречена Interrupt.

Най-необходимият Win API за VB програмисти

Независимо от това, че VB няма разнообразни функции, в процеса на повече или по-малко сериозно развитие се разкрива, че техните възможности често не са достатъчни за изпълнение на необходимите задачи. В този случай начинаещите програмисти често започват да пестят VB и мислят за промяна на инструмента, без да подозират, че компютърът им има голям набор от разходи и трябва да ги въведе бързо.

Когато се запознаете с Win API, се оказва, че има много използвани VB функции, които не са нищо повече от разширени до специфични системни процедури, но само имплементирани в същия синтаксис като дадения език. Въз основа на необходимостта от бърз API, наличните опции са:

  1. API функции, които обикновено се изпълняват под формата на VB функции. Времето обаче не е по-малко, в който случай може да се наложи да преминете към стагнация на API, така че да ви позволи бързо да увеличите производителността (с изключение на липсата на ненужни промени в параметрите, които се прехвърлят).
  2. Създадените VB функции се реализират само в резултат на външни API функции. Ето един по-прост вариант. Например функцията CreateDirectory API има по-големи възможности в сравнение с оператора VB MkDir.
  3. Има голям брой API функции, които нямат аналози в текущата версия на езика VB. Например, не е възможно да изтриете директория с помощта на VB - за това трябва да използвате функцията DeleteDirectory.

Трябва също така да се отбележи, че някои API функции (някои от тях в Win API са дори незначителни) не могат да бъдат достъпни от VB програми през редица езикови интерфейси, например поради липсата на възможност за работа с адреси на паметта. Въпреки това, в редица случаи нетривиалните техники за програмиране могат да помогнат (в случай на едни и същи адреси).

Специалната идея на автора е, че вместо да разширява версията до версията на функциите, използвани от VB, следното ще даде добро описание на най-често срещаните API функции. В същото време бих искал да моля разработчиците да не чакат появата на нова версия за функция с разширени функции, а по-скоро да вземат предвид запасите от оригиналния Win API - напълно ясно е, че възможностите, които вие необходимост може да бъде приложен още във версия í VB 1.0 издание 1991 г.

Как да vivchati Win API

Не е толкова лесно да запомните, че броят на функциите на Win32 API се оценява на около 10 хиляди (никой не знае точната цифра, като Microsoft).

Складът на VB (версии 4-6) включва файл с описание на Win API - WIN32API.TXT (отчет за внедряването му ще бъде обявен по-късно). Ale, в Persher, с yogo, може да се откаже от Vidomosti за признаването на същите параметри за vicoristovani mnemoni izmen, а от друга страна - perepass на функциите на файла tsomo далеч не е изчезнал. В днешно време (за късмет) VB 3.0 имаше специални файлове за доказване на концепцията, описващи функциите на Win16 API. Във v.4.0 тази ценна информация вече е достъпна чрез ръчния интерфейс.

Допълнителна информация за Win32 API може да бъде намерена в предишния комплект за разработка на платформен софтуер, който също е достъпен на CD-тата с библиотека на MSDN, включени в VB 5.0, 6.0 Enterprise Edition и Office 2000 Developer Edition. Въпреки това намирането на необходимата информация там и достъпът до нея не е никак лесно. Без дори да споменаваме, че всички описания там са направени изцяло от C.

Най-познатото в света въведение в API програмирането във VB среди е книгата на известния американски експерт Даниел Епълман. Тази поредица от Ръководство на Visual Basic програмиста на Dan Appleman за Windows API (за Win16, Win32, стотици различни версии на VB) от 1993 г. насам постоянно се превръща в бестселър за програмистите на VB. Книгата Dan Appleman's VB 5.0 Programmer's Guide to the Win32 API, публикувана през 1997 г., беше донесена на автора от САЩ от приятел, който знаеше за първата книжарница в малък провинциален град.

Тази книга, с над 1500 страници, включва описание на усъвършенстваните техники за програмиране на API във VB, както и повече от 900 функции. Компактдискът ще съдържа пълния текст на книгата и всички софтуерни приложения, както и редица допълнителни раздели, които не са достигнали до втората версия. През 1999 г. Dan Appleman издаде нова книга, Win32 API Puzzle Book and Tutorial for Visual Basic Programmers на Dan Appleman, която включва прегледи на други 7600 функции (макар и не табла за отчети).

Win API и библиотека за динамични връзки (DLL)

Набор от реализации на Win API като динамични DLL библиотеки. След това всъщност ще говорим за технологията за инсталиране на DLL в средата на VB в приложението на библиотеки, които са включени в Win API склада. Въпреки това, когато говорим за DLL файлове, е необходимо да спечелим много уважение.

В този случай под DLL можем да спазваме традиционната версия на двойни динамични библиотеки, което осигурява директно преобразуване към необходимите процедури - подпрограми или функции (приблизително същото, което се очаква при извикване на процедури в средата на VB проект ). Такива библиотеки могат да бъдат създадени с помощта на други инструменти: VC++, Delphi, Fortran и VB (който се появява във версия 7.0) - останалите могат да работят само с помощта на ActiveX DLL, които могат да бъдат достъпни чрез лицето на Internet OLE Automation.

Файловете на динамичната библиотека може да съдържат разширението.DLL, но това не е непременно така (за Win16 разширението.EXE често оставаше); Драйверите на външни устройства са изброени под допълнителния DRV.

Както вече споменахме, важно е да се определи точният брой функции и файлове на Windows API, така че да могат да се съхраняват в системния каталог. Този план би по-добре да вижда библиотечен склад, който достига до ядрото на операционната система, и основните библиотеки с ключови допълнителни функции.

И сега съм щастлив.

Моля, 1. Следвайте правилното форматиране на DL съобщението L-процедури

Йерархията на програмата до процедурите на DLL изглежда по същия начин като до „първичните“ процедури на Visual Basic, например:

Извикване на DllName ([списък с аргументи])

Въпреки това, за да използвате външни DLL функции (включително Win API), те трябва да бъдат извикани от програмата с помощта на оператора Declare, който изглежда така:

Декларирайте име на подпроцедура Lib _ „Име на библиотека“ _ [([Списък с аргументи])]

Декларирайте функция Име на функция _ Lib „Име на библиотека“ _ [([Списък с аргументи])]

Тук, при квадратните рамена, са посочени необходимите елементи на оператора, редуващите се думи са показани в курсив, а ключовите думи са показани в курсив. Усъвършенстваната система е проектирана да осигури добро описание на синтаксиса на оператора, което прави някои точки по-малко значими.

Повечето от външните функции се намират в секцията Общи декларации на модула. Ако го поставите в модул на формуляр, трябва да посочите ключовата дума Private (това ще бъде достъпно само в средата на модула) - това е същото за всички процедури на модула на формуляр.

Наборът от реализации на Win32 API е ограничен до функции (API на Win16 имаше много подпрограми). Това важи особено за функциите от тип Long, които най-често връщат кода за завършване на операция.

Операторът Declare се появи в MS Basic вече за DOS и беше използван за съобщаване на вътрешни процедури на проекта. Visual Basic не се нуждае от това, тъй като декларациите на вътрешните процедури автоматично описват техните описания на под и функции. Адаптирано от Basic/DOS, новото описание трябва да посочва името на библиотечния файл, където се намира процедурата. Библиотеките на Wip API се намират в системната директория на Windows; всичко, което е необходимо, е име на файл. Ако работите върху DLL, ще трябва да напишете нов път към този файл, за да сте сигурни.

Описанието на оператора Declare заема много място и не се побира в един ред близо до прозореца на кода. Затова препоръчваме, когато пишете програми, да обърнете внимание на всеки тип схема за прехвърляне на редове, например:

Декларирайте функцията GetTempPath _ Lib “kernel32” Псевдоним ​​​​“GetTempPathA” _ (ByVal nBufferLength As Long, _ ByVal lpBuffer As String) As Long

И тук са описани всички основни елементи от описанието на различните редове и е добре да се прочетат.

Моля 2. Бъдете особено уважителни, когато работите с DLL функции

Използването на Win API и различни DLL функции значително разширява функционалните възможности на VB и най-често ви позволява да увеличите производителността на програмата. Въпреки това цената, която трябва да се плати за цената, е намаляването на надеждността на роботизираните програми, особено по време на процеса на разработка.

Едно от най-важните предимства на VB мидълуера е надеждността на процеса на разработка на програмата: работейки под рамката на интерпретатора, теоретично е невъзможно програмният код да разбие робота на Windows и VB. Програмистът може да не е много внимателен относно правилността на предаването на параметри към извиканата функция - такива грешки лесно ще бъдат открити от самия интерпретатор, или по време на процеса на превод на кода, или по време на неговото изпълнение. В най-лошия случай просто ще има прекъсване на режима на обработка, както смисъл, така и къде и какво се е случило.

Използването на директни функции на Windows API или други DLL библиотеки поема такъв контрол върху прехвърлянето на данни и процеса на конкатенация към код извън средата на VB. Следователно, компромис във външни функции може да доведе до повреда както на VB, така и на операционната система. Това е особено важно на етапа на разработване на програмата, ако наличието на ползи е напълно естествено. По този начин, поради широкия набор от функции на базовата система, програмистът поема отговорност за коректността на тяхното изпълнение.

Проблемът допълнително се усложнява от факта, че различните програми имат различни начини за предаване на параметри между процедурите. (По-точно, различните методи на предаване са предмет на обсъждане, тъй като много от нас могат да поддържат редица методи.) Win API е внедрен в C/C++ и трябва да говорим за предаване на параметри, приети в тази система, тъй като в са класифицирани като основен VB вариант.

Във връзка с това трябва да се отбележи, че появата на VB аналози на API функции е оправдано от адаптирането на останалите към VB синтаксиса и прилагането на подобен механизъм за контрол на обмена на данни. Ние също така оценяваме, че на етапа на окончателното разработване на програми, когато се изгражда модул, който се компилира, е по-добре да изберете опцията за компилиране P-код вместо Native Code (машинен код). Първоначално програмата работи под контрола на интерпретатор - вместо да използва машинен код, но за предпочитане чрез разглеждане на операционната система и осигуряване на ръчен режим за идентифициране на възможни грешки.

Porada 3. Десет препоръки от Dan Appleman за надеждно програмиране на API във VB мидълуера

Различните функции на API изискват по-внимателно програмиране с използването на някои не толкова основни методи за мащабиране на процедурите (срещу VB). Постепенно гладуваме от тази храна. А сега ще представим резюме на дискусиите на Дан Епълман по тази тема (първата версия се появи през 1993 г.) с някои от нашите допълнителни коментари.

1. Спомнете си за ByVal.Най-честият проблем, който възниква, когато API и DLL се внедряват преди функции, се крие в неправилния речник на ключовата дума ByVal: те или забравят да я поставят, или в крайна сметка я поставят, когато няма нужда от нея.

Тези примери показват въвеждането на оператора ByVal за прехвърляне на параметри

Тип параметър Z ByVal Без ByVal
Цяло число Стекът има 16-битов капацитет Стекът може да побере 32-битови адреси на 16-битово цяло число
Дълги Стекът има 32-битов капацитет Стекът може да побере 32-битови адреси на 32-битово цяло число
низ Последователността се преобразува във формата, който се използва в C (предвид крайния нулев байт). 32-битовите адреси на новия ред се поставят в стека Стекът съдържа VB дескриптора на реда. (Такива дескриптори никога не се разпознават от самия Windows API и се разпознават само в DLL, реализирани специално за VB.)

Тук си струва да споменем, че прехвърлянето на параметри във всяка система за програмиране, включително VB, се определя от две основни стъпки: изпращане (ByRef) или стойност (ByVal). Първата опция получава адреса на обмена (тази опция се използва във VB за обмен), другата получава неговата стойност. Принципът на валидност се състои в това, че след допълнително съобщение се гарантира, че програмата, която извиква, се връща към променената стойност на предадения параметър.

За да започнете, направете експеримент, като използвате следните програми:

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

След като стартира дупето на Viconnya, vikamama, стойностите на ZINSYAM ZMINENE, RIVNE 3. Отдясно, в датския випад, адресите на Zmínino V, физически плитки проекции, Viclikaє, се предават на danas. Сега променете описанието на процедурата на

Sub MyProc (ByVal v Като цяло число)

В резултат на това, когато стартирате теста, премахвате v = 2, което означава, че изходната стойност на променливата се предава на процедурата - резултатът от операциите, които се изпълняват върху нея, не се връща на програмата, която извиква. Режимът на предаване на стойността може да бъде променен и с помощта на Call operator, както следва:

Sub MyProc (v Като цяло число) ... Извикване на MyProc ((v)) '(v) - рамената показват режима на предаване _ зад стойностите.

Въпреки това, когато се разширява до вътрешни VB-процедури, използването на ключовата дума ByVal в оператора Call се потиска - вместо това кръглите рамена се блокират. Ето едно обяснение.

В класическата версия (C, Fortran, Pascal) важността на режимите ByRef и ByVal зависи от това какво се поставя в стека за обмен на данни - адресите или стойностите за обмен. В Basic версията ByVal на софтуерната емулация исторически се използва - стекът винаги съдържа адреси, освен когато се предават стойностите, за които се създава промяна на времето. За да разграничите две опции (класически и основен), има различни начини за описание на режима ByVal. Наложително е BYVAL в режима VB във vb, забравяйки групата от горните знаци: преобладаващата форма на звяра, програмата на личея, викликата, обърнете (abo не се обръща) виленията на Змининов . В „класическата“ версия такова объркване може да доведе до фатална смърт в рамките на часа от процедурата за финализиране (например, ако вместо адреса на паметта на потребителя има променливи стойности, равни, да речем, на нула ).

Функциите на DLL се изпълняват според „класическите“ принципи и следователно изискват ясно описание на това как се обменят данни с всеки аргумент. Самото това може да служи като функция за деклариране чрез описанието на Declare (по-точно, списъкът с аргументи, които се предават). Най-често предаването на параметри към Windows API функция или DLL се определя с помощта на ключовата дума ByVal. Освен това може да се посочи или в оператора Declare, или директно при извикване на функцията.

Наследството от неправилно прехвърляне на параметри е лесно за прехвърляне. Ако изберете очевидно невалиден адрес, ще видите известие за GPF (Обща грешка в защитата). Тъй като функцията извлича стойности, които избягват валиден адрес, API функцията влиза в чужда област (например в ядрото на Windows) с всякакви катастрофални последици, които произтичат.

2. Променете типа на параметрите, които се прехвърлят.Също толкова важен е правилният брой и тип на параметрите, които се предават. Необходимо е аргументите, декларирани в Declare, да съответстват на параметрите на API функцията. Най-големият проблем с подаването на параметри е свързан с разликата между NULL и ред нули - следата на паметта, която е една и съща.

3. Проверете вида на ротираната стойност.

VB е толерантен към настройването на разнообразието от типове стойности, които се въртят от функцията, а някои числови стойности се въртят през регистри, а не през стека. Следните правила ще ви помогнат да определите правилните стойности, които се връщат от API функцията:

  • DLL функция, която не върти стойности (аналогично на void в 'C'), може да бъде заглушена като VB Sub.
  • API функция, която върти стойност (цяло число или дълга), може да бъде обозначена или като Sub или като функция, която върти стойности от конкретен тип.
  • Тази API функция не върти числа с плаваща запетая, но DLL могат да въртят този тип данни.

4. С голямо внимание използвайте конструкцията As Any.Много API функции на Windows имат способността да приемат параметри от различни типове и да ги използват въз основа на конструкцията As Any (интерпретацията на типа зависи от значението на другите параметри, които се предават).

Добрите решения могат да имат няколко псевдонима (Alias) функции и две или повече от тях споделят едни и същи функции и всяко описание има параметър и тип на изпяване.

5. Не забравяйте да инициализирате редовете. Win API има проста функция, която върти информация чрез събиране на данни от буфери на редове, които се предават като параметър. Във вашата програма можете да направите всичко правилно: не забравяйте за ByVal, предайте параметрите на функцията правилно. Но Windows не може да повярва колко голям е размерът на видимото място за съхранение. Размерът на реда трябва да е достатъчен, за да побере всички данни, които могат да бъдат поставени в него. Отговорността за запазване на буфер с необходимия размер е на VB програмиста.

Моля, обърнете внимание, че в 32-битов Windows с различни редове е възможно да се конвертира от Unicode (двубайтово кодиране) в ANSI (еднобайтово кодиране) и обратно, в зависимост от националните системни настройки. Следователно, за резервиране на буфери често е по-безопасно да се използват байтови масиви вместо обикновени. (Доклад за това ще бъде обсъден по-долу.)

Повечето функции на Win API ви позволяват сами да зададете максималния размер на блока. Например, трябва да извикате друга API функция, за да посочите размера на блока. Например GetWindowTextLength ви позволява да определите размера на реда, необходим за поставяне на заглавието на прозореца, съдържащ се от функцията GetWindowText. Поради тази причина Windows гарантира, че няма да отидете отвъд границата.

6. Опция Vikorize Explicit и на двата езика.

7. Внимателно проверете стойностите на параметрите и стойностите, които се въртят. VB има потенциала да проверява типове. Това означава, че ако се опитате да предадете неправилен параметър на VB функция, най-лошото, което може да се случи, е да отхвърлите съобщението за грешка от VB. За съжаление, този механизъм не работи, когато се надстрои до функция на Windows API.

Windows 9x има усъвършенствана система за проверка на параметри за повечето API функции. Следователно наличието на помилване в тези данни не означава фатално обезщетение, но не е толкова просто да се определи какво го е причинило.

Тук можете да намерите няколко начина за подобряване на този вид мляко:

  • Проверете режима за настройка на кожата или Debug.Print, за да проверите реакцията на кожата на API функцията. Прегледайте резултатите от тези кликвания, за да сте сигурни, че всичко е в нормални граници и функцията е изпълнена правилно;
  • Vikorist базиран на Windows разработчик като CodeView и персонализирана версия на Windows (от Windows SDK). Тези функции могат да открият модификацията на параметрите и най-важното да определят коя API функция трябва да бъде модифицирана;
  • Проверете допълнителните функции на трети страни, за да проверите типовете параметри и приемливостта на техните стойности. Такива методи могат не само да намерят промени в параметрите, но и да кажат на VB кода къде е направена промяната.

Освен това е необходимо внимателно да проверите резултата от API функцията.

8. Запомнете, че числата във VB и Windows не са еднакви.Нека първо си припомним, че терминът „Цяло число“ във VB означава 16-битово число, докато в документацията на Win 32 означава 32-битово число. По друг начин, целите числа (Integer и Long) във VB не са стойности без знак (едната цифра се използва като знак, другата като мантиса на число), в Windows - дори се използват неизвестни числа. Тази ситуация трябва да се вземе предвид, ако формирате параметър с помощта на допълнителни аритметични операции (например изчисляване на адрес с помощта на допълнително заместване на база и отместване). За кои стандартни VB аритметични функции не са подходящи. Защо се страхувате от тази ситуация, нека поговорим за това.

9. Внимавайте с имената на функциите.В Win16 имената на всички API функции на Win32 са чувствителни към точния вариант на второстепенните и главните букви (Win16 нямаше това). Ако поставяте малък писател на мястото на голям, тогава необходимата функция няма да бъде намерена. Също така следвайте правилния суфикс A или W във функциите, за да зададете параметри на реда. (Докладвайте за това – div. по-долу.)

10. Запазвайте резултатите от работата си възможно най-често.Неизправностите, свързани с неправилни DLL и Win API скриптове, могат да доведат до срив на VB мидълуера и евентуално на цялата операционна система. Моля, обърнете внимание, за да се уверите, че вашият код е запазен преди тестовото изпълнение. Най-простото нещо е да зададете режим за автоматично писане на модули към проекта, преди да стартирате проекта във VB средата.

След като прочетете предишния, може да бъдете поразени от факта, че функцията Win API е премахната отдясно. Между другото, това е вярно, но само в съответствие с безопасното програмиране, което самата VB предоставя. Въпреки това, в случай на лек застой и известни възможни клопки, този риск е минимален. Освен това често е просто невъзможно да се справим със стагнацията на Win API - той все още ще е необходим в случай на сериозно развитие.

Преди това по-рано мислехме за „подводните“ камъни за широк клас DLL файлове. С Win API всичко е много по-просто, тъй като формата на изпълнение на тези функции е ясно унифицирана. Ето основните моменти, които трябва да вземете предвид уважението на майката:

  1. Функциите на Win32 API са функции или процедури от типа Function (Win16 API имаше много подпрограми). Всички функции са от тип Long, така че техните описания са написани в следната форма: Деклариране на името на функцията ... Като Long ‘функционален тип _ е посочен в изричната форма

    Деклариране на име на функция& 'тип на функция _ се обозначава с допълнителен суфикс

    Преобразуването към API функцията изглежда така:

Резултат& = ApiName& ([ Списък с аргументи]
  1. Най-важната функция, която се завърта, е кодът за завършване на операцията. Освен това ненулева стойност означава нормално завършване, докато нулева стойност означава изпълнение. Още веднъж (или не преди), можете да изясните естеството на изменението, като използвате функцията GetLastError. Описанието на тази функция изглежда така: Declare Function GetLastError& Lib “kernel32” ()

    УВАГА!При робота в средното лице VB за ryannate на валидните кодове на помилването, силата на vicoristovati е мощна Lastdlleror Op'kta Err, bb іnodi vene на функцията GetlasterRor в индустриалния на MIZh към API vicuno viconun, викунките на викуномите на оградите.

    Можете да интерпретирате кода, който генерира GelLastError, като използвате допълнителни константи, записани във файла API32.TXT, с имена, започващи със суфикса ERROR_.

    Най-често срещаните видове атаки са следните кодове:

    • ERROR_INVALID_HANDLE = 6& - неправилен манипулатор
    • ERROR_CALL_NOT_IMPLEMENTED = 120& - повикване за функции на Windows 9x, налични само за Windows NT
    • ERROR_INVALID_PARAMETER = 87& - неправилна стойност на параметъра

    Има обаче много функции за завъртане на стойностите на даден параметър (например OpenFile завърта стойностите на описание на файл). В този случай стойността се присвоява на някои други специални Return& стойности, най-често 0 -1.

  2. Win32 API има строго фиксирани методи за прехвърляне на най-простите типове данни. а) ByVal...As Long

    Най-малко 80% от предаването на аргументи се извършва с типа Long. Преразгледайте аргумента преди всичкое придружен от ключовата дума ByVal и това освен всичко друго означава, че е свързан еднопосочен трансфер на данни - от VB програми към API функция.

    B) ByVal...As String

    Този тип предаване също има тенденция да се случва често и със същия аргумент преди всичко ByVal се забива. Когато се извика API функция, адресите на редовете се записват в стека, което позволява двупосочен обмен на данни. Когато работите в редове, е необходимо да се погрижите за някои проблеми.

    Първо, резервирането на памет за редове се извършва от програмата, която извиква, така че ако API функцията ще съхранява редове, е необходимо да създадете ред с необходимия размер, преди да го извикате. Например функцията GetWindowsDirectory завърта пътя до директорията на Windows, която не е задължително да заема повече от 144 знака. Очевидно изпълнението на тази функция може да изглежда така:

    WinPath$ = Space$(144) ' резервен ред в _ 144 символа Result& = GetWindowsDirectory& (WinTath$, 144) _ 'buffer filling' Result& - действителен брой знаци в името _ директория WinPath$ = Left$(WinPath, Result&)

    Друг проблем се крие във факта, че когато API функция се преобразува в API функция, изходният ред се пресъздава на вътрешния й дисплей, а при излизане от функцията – по същия начин. Точно както в ранните дни на Win16 тази операция отнемаше по-малко от добавянето на нулев байт, например ред, тогава с появата на Win32, трансформацията на двубайтовото Unicode кодиране в ANSI и за същото време беше постигнати. (Това беше съобщено в статията „Характеристики на роботи с промени на редове във VB“, Computer Press 10'99 и 01'2000). Важно е само, че с помощта на конструкцията ByVal... Като String е възможно да се обменят редове от символни данни.

    B) ... Както всеки

    Това означава, че стойността на адреса на буфера на паметта ще бъде поставена в стека, тълкуването вместо това, което API функцията ще обработва, например, е независимо от значението на други аргументи. Въпреки това, As Any може да се използва само в оператора Declare - когато се приложи конкретна функция, на аргумента може да бъде присвоена конкретна стойност.

    D) ... Като UserDefinedType

    Такава структура също често се забива, когато е необходимо да се обменят данни (обещанието на нарушилата се страна) в името на друга структура. Всъщност този дизайн е прост тип специфична реализация на формата за предаване As Any, просто всяка функция има фиксирана структура.

    Формата на структурата на данните се определя от конкретна функция на API и е отговорност на програмата да ги опише правилно и резервира със същата програма. Това е дизайнът преди всичковикорист бездумите ByVal, тогава трансферът след изпращане се добавя към това поле - адресът за обмен се записва в стека.

Докоснете се до API функцията

Това е илюстрирано с примера на две основни функции за работа с файлове - lopen и lread, които са описани по следния начин:

Декларирайте функция lopen Lib "kernel32" _ Псевдоним ​​"_lopen" (_ ByVal lpFileName As String, _ ByVal wReadWrite As Long) Декларирайте функция lread Lib "kernel32" _ Псевдоним ​​"_lread" (_ ByVal hFile As Long, lpBuff _ ByVal wBytes As Long) Колкото дълго

Във VB техните аналози - понякога по-точни - са операторите Open и Get (за двоичен режим). Много сме впечатлени от използването на ключовата дума Alias ​​в празната функция - това е същият проблем, ако не можете без него. Имената на тези функции в библиотеката започват със символ под стол (типичен стил за филм C), което не е разрешено от VB.

Операцията за отваряне на файл може да изглежда така:

Const INVALID_HANDLE_VALUE = -1 ' невалидно _ описание на стойността lpFileName$ = “D:\calc.bas” ' име на файл wReadWrite& = 2 ' режим на четене и запис hFile& = lopen(lpFileName$, wReadWrite&) _ ' valued = INVALID_HANDLE _VALUE Тогава _ ' коригирайте файла ' посочете кода за корекция CodeError& = Err.LastDllError 'CodeError& = GetLastError _ ' тази конструкция не работи Край Ако

Тук трябва да подчертаем два момента:

  • Като стойност на функцията определяме стойността на описанието на файла. Стойността потвърждава стойността -1;
  • В този случай не е необходимо да отидете до функцията GetLastError - за да извлечем посочената стойност на грешката, отидохме до обекта Err (говорихме повече за възможността за такава ситуация).

След това можете да прочетете вместо файла, но също така предава, че програмата е отговорна за разпознаването на неговата структура (както е в случая при работа с множество двойни файлове). В този случай конфигурацията за функцията lread може да изглежда така:

Dim MyVar As Single wBytes = lread (hFile&, MyVar, Len(MyVar) ' четене на номера на речта, 4 байта ' wBytes - брой действително прочетени данни, '-1 - паритет... Тип MyStruct x As Single i Като цяло число End Type Dim MyVar As MyStruct wBytes = lread (hFile&, MyVar, Len(MyVar)) ' структура от данни за четене, 6 байта

Още веднъж покажете уважение: другият аргумент на функцията се предава на подателите и на връщането към стойностите.

Dim MyVar As String MyVar = Space$(10) ' резервиране на място за 10 знака wBytes = lread (hFile&, ByVal MyVar, Len(MyVar)) ' прочитане на символен низ, 10 знака

Тук можете да видите важността на въведената по-рано дупка - промяната на реда е задължително придружена от ключовата дума ByVal.

Четенето вместо файл в масив (за простота ще използваме еднобайтов масив) се компилира по следния начин:

Dim MyArray(1 To 10) As Byte wBytes = lread (hFile&, MyArray(1), _ Len(MyArray(1))* 10) ‘ прочете 10 елемента от масива

Посочвайки първия елемент от масива като аргумент, ние предаваме адреса на главата на областта на паметта, запазена за масива. Очевидно можете да съхранявате всеки фрагмент от масив, като използвате този метод:

WBytes = lread (hFile&, MyArray(4), _ Len(MyArray(1))* 5) четене на елементи от масив от 4-ти до 8-ми

Porada 5. Vickory Псевдоним за прехвърлянеНастройки като всеки

Тук, на базата на предния задник, разкриваме същността на четвъртия заради Дан Епълман.

Когато работите с функцията lread, е важно да запомните, че когато стартирате обикновена променлива преди нея, е необходимо да използвате ключовата дума ByVal (в противен случай информацията за незаконната операция няма да бъде загубена). За по-голяма сигурност можете да създадете допълнително специално описание на тази функция за работа само с общи промени:

Декларирайте функцията lreadString Lib “kernel32” _ Alias ​​​​​​“_lread” (_ ByVal hFile As Long, ByVal lpBuffer As String, _ ByVal wBytes As Long) As Long

Когато работите с това описание, вече не е необходимо да посочвате ByVal при печат:

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

Изглежда, че синтаксисът на оператора Declare ви позволява да създадете такова специално описание за масив:

Декларирайте функцията lreadString Lib “kernel32” Псевдоним “_lread” (_ ByVal hFile As Long, lpBuffer() As Byte, _ ByVal wBytes As Long) As Long

Защитете животното

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

неизбежно води до фатално изпълнение от програмата.

Това е продължение на дискусията за особеностите на обработката на промените в редове Visual Basic: VB използва двубайтово Unicode кодиране, Win API - еднобайтов ANSI (и с формат, приет в C - с нулев байт в края). Очевидно е, че при промяна на промените на реда като аргумент, преобразуването от Unicode в ANSI винаги се извършва автоматично, когато извикате API функция (по-точно DLL функция) и преобразуването се обръща при завъртане.

Изводът тук е прост: можете да обменяте символни данни с помощта на променливи низове, но те не могат да се използват за обмен на достатъчно двойна информация (какъвто беше случаят при работа с 16-битови версии на VB). По-добре е да използвате едномерен байтов масив.

Очевидно типът String може да се използва за описание на структурата на структурата. Връзката с тази памет е следната:

  • Категорично не е възможно да се използва следната конструкция за разработката на Win API: Type MyStruct x As Single s As String

    В реда на смяната дескрипторът на реда се предава заедно с всички наследства във външния вид на програмата.

  • Възможно е като структурен елемент на ред с фиксирано удвояване: Тип MyStruct x As Single s As String*8 ‘ ред с фиксирано удвояване Краен тип

В този случай не забравяйте да създадете отново кода.

И уважението остава: не е възможно да се консолидира масивът от промени в редовете (както фиксирани, така и променливи), когато се надстрои до API функцията едновременно. В противен случай появата на „незаконна операция“ ще бъде гарантирана.

Съвсем ясно е, че сте в лоша ситуация, ако трябва да напишете DLL функция във вашата библиотека. Необходимостта неминуемо ще се появи, ако използвате смесена технология за програмиране - комбинация от две или повече програми за изпълнение на една програма.

Важно е във връзка с факта, че смесеното програмиране е основната цел за внедряване за постигане на цялостен отчет. Наистина, езиковият език (по-точно системата за програмиране, базирана на езика) има своите силни и слаби страни, така че е напълно логично да се използват предимствата на различни инструменти за постигане на различни задачи. Например VB – за създаване на компютърен интерфейс, C – за ефективен достъп до системните ресурси, Fortran – за реализиране на числени алгоритми.

Идеята на автора е следната: сериозното участие в програмирането се подчертава от разработчика с помощта на два инструмента. Очевидно в съвременните умове е много трудно да бъдеш независим експерт в две системи, което прави схемата „основен и допълнителен език“ по-логична. Идеята тук е, че пренасянето на знанията на „допълнителния“ език (написан на няколко прости процедури) може значително да подобри ефективността на „основния“ език. Важно е познаването на VB, като допълнителна полза, сега да е практическо изискване за професионален програмист. Преди да говорим, само за няколко часа DOS, за всеки програмист, нека да разгледаме Basic, би било изключително важно да знае основите на Assembler.

Така че е различно, но в съзнанието на груповите роботи, когато програмистът на кожата се занимава със собствена специфична работа, твърденията за особеностите на процедурния интерфейс на различни езици са по вина на всички участници в проекта. Знам, че има много системи за програмиране (включително VB), в допълнение към интерфейса, който трябва да бъде обяснен, е възможно да се установят други методи, разширявайки методите за обработка до процедури, които ви позволяват да адаптирате интерфейса към други езици .

Когато използвате междупроцедурния интерфейс, имайте предвид следните възможни клопки:

  • Различни езици може да представляват интерес за вас относно правилата за писане на идентификатори. Например, често се използва псевдонимът на името на процедурата, който е скрит във VB. Този проблем може лесно да се обясни с използването на ключовата дума Alias ​​в оператора Declare (отличен пример за 2.3).
  • Можете да определите последователността на писане на аргументи, които се предават на стека. Например, в часовете на DOS (честно казано, не знам как изглежда в средата на Windows), записвайки аргументи от края на списъка, други езици (Fortran, Pascal, Basic) – от начало.
  • Обясняват се различни принципи на прехвърляне на параметри - за инструкции или значения.
  • Строги принципи за запазване на редовия състав. Например в C (както във Fortran и Pascal), последният ред от ред се обозначава с нулев байт в края му, а в Basic последната минута се записва изрично в дескриптора на реда. Очевидно е необходимо да се помни възможността за промяна на различни кодове на символи.
  • Когато прехвърляте масиви от богат свят, не забравяйте, че има различни опции за трансформиране на структури от богат свят в един свят (започвайки от първия индекс или от останалите, сто двуизмерни масива - „в редове“ или „в редове“ на малките птички“).

Въз основа на това могат да се формулират следните препоръки:

  • Проверете най-простите неща, като преразгледате начина, по който аргументите се предават на DLL функция. Стандартите, приети за Win API, са напълно последователни.
  • Всеки път не прехвърляйте маси от обикновени войници.
  • С уважение vikorist прехвърлянето на прости обикновени и богати масиви.
  • Не забравяйте внимателно да проверите функционалността на механизма за предаване на аргументи към процедурата, която се извиква и обратно. Напишете специален тест, за да проверите данните. Внимателно проверете правилността на прехвърлянето на аргумента на кожата. Например, ако имате процедура с много аргументи, първо проверете правилността на предаване на параметъра на кожата за опцията с един аргумент, а след това за целия списък.

Какво прави, ако DLL функцията вече е написана, например, на Fortran, но интерфейсът за въвеждане не пасва добре на новия VB стандарт? Тук можете да посочите две дати. Първо: напишете тестова DLL функция и с нейна помощ опитайте да използвате метода проба и грешка, за да изберете необходимата функционалност за VB програми. Друго: напишете процедура за адаптер във Fortran, която ще осигури прост интерфейс между VB и DLL функция с трансформация на прости структури от данни в склад (например трансформация на голям масив от байтове от масив от редове).

Otzhe: vykorist DLL функции. Освен това запазете сладостта.

КомпютърПрес 9"2000

Тази статия е адресирана до онези, които са нови в програмирането на C++ и са били принудени да използват WinAPI.
Искам да изпреваря това:
Не се правя на C++ или WinAPI гуру.
Тъкмо започвам и искам да представя няколко приложения тук, които ще улеснят използването на функциите и механизмите на WinAPI.

В тази статия предполагам, че вече сте се запознали с C++, за да можете да създавате класове и да прехвърляте различни оператори за тях и че вече сте „обикнали“ вашите механизми в клас.

Създаването и използването на конзолата

За да подобря Win32 програмите или просто да се учудя как изглежда всичко там в средата, винаги ще надраскам конзолата.
Тъй като създавате GUI приложение, а не конзолно, конзолата няма да се свърже. За да кликнете в интернет, можете да намерите този код

Ако (AllocConsole())
{



std::ios::sync_with_stdio();
}
За по-голяма яснота Раджа го обгръща във функция. Например:
void CreateConsole()
{
ако (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();
}

Конзолата работи само в режим на показване и работи по същия начин, както в конзолните програми. Въведете информацията както преди - cout/wcout.
За да бъде ефективен този код, е необходимо да включите следните файлове в проекта:
#включи
#включва #включва
и активирайте пространството от имена std в глобалното пространство от имена:
използване на пространство от имена std;
Разбира се, ако не искате да правите нищо, просто добавете std:: към всички обекти, които са в него.

Уреждане на обекти за показване и аритми. операция

След като създадете и въведете „накрая“, първо трябва да изведете всички стойности към конзолата.
Например:
Вие определяте размера на клиентската област на прозореца, като използвате допълнителната функция GetClientRect, където параметърът се предава на адреса на обекта на структурата RECT, за да запълни този обект с данни. Ако трябва да знаете размера на заснетата клиентска област, можете просто да го въведете във вече свързаната конзола.

Коут<

Але работата толкова бързо (особено след като често трябва да работите така) не е лесна.
Тук спокойствието ни идва на помощ.
Създайте клас, който открито се свива от RECT структура и пренасочете изходния израз<< так, как вам угодно.
Например:

Клас newrect:публичен RECT
{
публичен:
приятел ostream& оператор<<(ostream &strm,newrect &rect)
{
strm<<"Prtint RECT object:\n";
strm<връщане strm;
}
};

Сега просто отпечатайте обекта с помощта на cout/wcout:

Коут<

И можете сами да видите, че всичко е там, както ви трябва.
Можете също така да работите с всички оператори, от които се нуждаете.
Например, ако трябва да промените или присвоите структури (например RECT или POINT) - променете напълно operator==() и operator=().
Ако искате да внедрите оператора по-малко< что бы быстро сравнивать размеры окна и т.д. перегрузите operator<().
Така че можете да работите, предполагам, дори с всякакви структури и най-вече, че всички функции, които работят с първичния обект на структурата RECT, ще работят също толкова добре с него.
Също така препоръчвам да поставите цялата тази красота в отделен файл, който е свързан, и да го редактирате, ако е необходимо.

Твоят клас

Не знам за другите, но аз съм напълно зелен, реших да създам нов проект за функцията на кожата или за раздела / подраздела на книгата, така че всичко да е наред и да е възможно да се обърне наоколо и го опреснявайте във всеки един момент и в паметта' Това са необходими моменти.
Тъй като в WinAPI, за да създадете прост прозорец, трябва да попълните структурата на класа, да я регистрирате и да напишете тривиална прозоречна процедура, след третия или четвъртия проект разбрах, че все още пиша на C++.
В резултат на това грабнах всичко от обикновен клас. Манипулатор на прозорец, име на прозорец, име на клас, адреси на прозоречни процедури, клас на прозорец (WNDCLASS) се съхраняват в раздела за частни класове.
За да ги извлечете, трябва да опишете прост метод „Вземи“, например:
HWND GetHWND()
LPCTSTR GetClsName() и т.н.
Обновяването и регистрацията на класа прозорец, създаването на самия прозорец и неговото показване се извършват от дизайнера.
За простота можете да пренасрочите конструктора и да обвиете завършването и регистрацията на класа прозорец в частна функция за класа и да я извикате от всеки от конструкторите. Предимството на обръщането се крие в това, че понякога е необходимо да се създаде напълно прост прозорец и аз щраквам върху конструктора с два параметъра - името на прозореца и задната част на програмата.
Иначе не е необходимо да се създава прозорец със специални размери, нито с прозоречната процедура по подразбиране и какъвто и да е друг стил - щракам върху конструктора със съответните параметри.
Този клас има по-малко стойности във файла, който е директно включен, който е в папката за включване на IDE.
Шаблон за този клас:
клас BaseWindow
{
WNDCLASSEX_wcex;
TCHAR_className;
TCHAR_име на прозорец;
HWND_hwnd;
bool _WindowCreation();
публичен:
BaseWindow(LPCTSTR windowName,HINSTANCE hInstance,DWORD стил,UINT x,UINT y,UINT височина,UINT ширина);
BaseWindow(LPCTSTR windowName,HINSTANCE hInstance);
const HWND GetHWND()const(връщане на HWND;)
LPCTSTR GetWndName()const(return _windowName;)
};

След като сте обмислили и написали такъв клас, вие ще улесните живота си и ще прекарате повече от час, за да овладеете и изострите началото на писането на едно и също нещо наведнъж. Тим повече, уважавам това още по-красиво - сам да създадеш такъв клас и да го допълваш според нуждите си.

P.S.

Всичко описано е вярно за:
Платформа - Windows 7 32 bit
IDE - Visual Studio 2010
Може би някой би искал да извика смях и ирония, но в крайна сметка всички се мислехме за новодошли/стажанти/младши.
Моля ви да сте скрупульозни преди публикацията си. Градивната критика, разбира се, отлита. Операционни системи (ОС)