Hinstance c что это

от admin

Как получить HINSTANCE модуля в котором находится код?

Как в MS Visual C++ получить HINSTANCE модуля (exe или dll) в котором находится текущая функция?

Я согласен, что вариант с __ImageBase можно использовать в определенных случаях, но хотел упомянуть о двух других стандартных методах.

Чаще всего необходимо получить HINSTANCE основной программы (EXE). Для этого проще всего использовать GetModuleHandle(NULL).

Другая типичная ситуация, что мы написали DLL с callback функцией и ее кто-то вызывает. В этом случае у нас обычно есть параменры переданные вазывающим нас модулем. С помощью GetModuleHandleEx с параметром GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS можно получит HMODULE по адесу переменной, а HINSTANCE DLL это и есть HMODULE .

Есть конечно много других способов. Но решающим является в каком контексте мы находимся.

Мне лично, в свое время, дало многое для общего поминания программка которую я включил в этот ответ. Она показывает, что огромное виртуальное пространства процесса зазбито на блоки и каждый блок принадлежит своему модулю. Имея начала модуля можно поличить о нем всю информацию. Я полагаю, что GetModuleHandleEx работает примерн так.

Введение в Win32 API

Win32 API (далее WinAPI) – это набор функций (API – Application Programming Interface), работающих под управлением ОС Windows. Они содержатся в библиотеке windows.h .

С помощью WinAPI можно создавать различные оконные процедуры, диалоговые окна, программы и даже игры. Эта, скажем так, библиотека является базовой в освоении программирования Windows Forms, MFC, потому что эти интерфейсы являются надстройками этой библиотеки. Освоив её, Вы без труда будете создавать формы, и понимать, как это происходит.

Не будем внедряться в теорию. Начнём с того, как создать этот проект в MVS, а в конце статьи будет разобран простой пример.

Итак. Сначала открываем Visual Studio, затем, нажимаем на вкладку «Файл», далее «Создать проект»:

Безымянный

Затем, в раскрывающемся списке Visual C++ выбираем пункт Win32, там и будет «Проект Win32». Щелкаем по нему: Вводим название проекта, указываем путь и нажимаем «ОК». Далее будет написано: «Добро пожаловать в мастер приложения Win32». Нажимаем далее. По-умолчанию у надписи «Пустой проект» галочка отсутствует. Нам нужно её поставить и убедиться, что у нас «Тип Приложения» — Приложение Windows. Если всё верно, нажимаем – «Готово».

2.

У нас должен быть пустой проект такого вида:

3

Ну а теперь начнём писать простую программу, которая традиционно будет выводить на экран надпись: «Привет, Мир. ».

Естественно, к проекту нужно добавить файл типа «имя».cpp. Кликаем по «Файлы исходного кода» правой кнопкой мыши, в раскрывающемся списке выбираем вкладку – «Добавить», далее «Создать элемент…». В результате у нас должно появиться такое окно:

4

Выбираем «Файл С++», вводим имя, нажимаем «Добавить». Затем открываем этот файл и вставляем в него такой код (подробности далее):

Результат должен быть таким:

5

Теперь остановимся поподробнее на коде программы.

В первой строке мы подключаем заголовочный файл windows.h . В нём содержатся все необходимые «апишные» функции. Здесь всё понятно.

В 4-7 строках у нас описание функции int WINAPI WinMain() .

Квалификатор WINAPI, нужен для функции WinMain всегда. Просто запомните это. WinMain – название функции. Она имеет четыре параметра. Первый из них – HINSTANCE hInstance (строка 4). hInstance является дескриптором экземпляра окна (это некий код оконной процедуры, идентификатор, по которой ОС будет отличать её от остальных окон). Через него можно обращаться к окну в процессе работы в других функциях (об этом позже), что-либо менять в параметрах окна. HINSTANCE является одним из многочисленных типов данных определенных в WinAPI, таким же как int, например. А запись HINSTANCE hInstance говорит нам о том, что мы создаём новую переменную типа HINSTANCE с названием hInstance.

О типах данным мы поговорим позже, поэтому переходим к следующему параметру: HINSTANCE hPrevInstance (строка 5). Как написано в комментариях, в Win32 он не используется, так как он создан для 3.x разрядной системы, из предыдущего понятно, что это дескриптор экземпляра окна. Далее у нас переменная типа LPSTR (строка 6) с именем lpCmdLine . Она используется в том случае, если мы запускаем окно через командную строку с прописью параметров. Очень экзотический способ, поэтому мы не будем на нём задерживаться.

И последний параметр: целочисленный, определяет способ показа окна. Нужен для функции ShowWindow , которая будет описана позже. Например, с помощью него мы можем развернуть окно на весь экран, сделать его определённой высоты, прозрачным или поверх остальных.

Переходим к функции MessageBox() (строка 10). Она имеет четыре параметра и нужна для вывода сообщений о ошибках, например. В данном случае мы использовали её для вывода сообщения. В общем виде описание функции выглядит следующим образом:

В нашем случае, первому параметру присвоен ноль. Всё потому, что у нас нет родительских окон (оно не запущено какой-нибудь программой).

Далее у нас идут две переменные типа LPCTSTR : lpText и lpCaption . Первая сообщает информацию, которая будет выведена в окне в текстовом виде. Вторая сообщает, что будет написано в тексте заголовка к окну. Это аналог char *str , но всё же нет. Для того, чтобы текст выводился корректно, нужно перед строкой поставить букву L (UNICODE строка).

Ну и последний тип данных – UINT – 32-х битное целое без знака. То есть аналог unsigned int . Этому параметру можно передавать некоторые значения (о них тоже позже), за счёт чего можно менять вид кнопки. В нашем случае – это MB_OK — означает, что окно создаёт кнопку с надписью «ОК» и соответствующим действием при её нажатии (закрытием приложения).

В строке 11 мы возвращаем значение функции, так как она имеет не тип void .

Таким образом, общее представление о WinAPI теперь есть. Продолжение в следующих разделах.

Windows Programming/Handles and Data Types

One of the first things that is going to strike many first-time programmers of the Win32 API is that there are tons and tons of old data types to deal with. Sometimes, just keeping all the correct data types in order can be more difficult than writing a nice program. This page will talk a little bit about some of the data types that a programmer will come in contact with.

Contents

Hungarian Notation [ edit | edit source ]

First, let’s make a quick note about the naming convention used for some data types, and some variables. The Win32 API uses the so-called «Hungarian Notation» for naming variables. Hungarian Notation requires that a variable be prefixed with an abbreviation of its data type, so that when you are reading the code, you know exactly what type of variable it is. The reason this practice is done in the Win32 API is because there are many different data types, making it difficult to keep them all straight. Also, there are a number of different data types that are essentially defined the same way, and therefore some compilers will not pick up on errors when they are used incorrectly. As we discuss each data type, we will also note the common prefixes for that data type.

Putting the letter «P» in front of a data type, or «p» in front of a variable usually indicates that the variable is a pointer. The letters «LP» or the prefix «lp» stands for «Long Pointer», which is exactly the same as a regular pointer on 32 bit machines. LP data objects are simply legacy objects that were carried over from Windows 3.1 or earlier, when pointers and long pointers needed to be differentiated. On modern 32-bit systems, these prefixes can be used interchangeably.

LPVOID [ edit | edit source ]

LPVOID data types are defined as being a «pointer to a void object». This may seem strange to some people, but the ANSI-C standard allows for generic pointers to be defined as «void*» types. This means that LPVOID pointers can be used to point to any type of object, without creating a compiler error. However, the burden is on the programmer to keep track of what type of object is being pointed to.

Also, some Win32 API functions may have arguments labeled as «LPVOID lpReserved». These reserved data members should never be used in your program, because they either depend on functionality that hasn’t yet been implemented by Microsoft, or else they are only used in certain applications. If you see a function with an «LPVOID lpReserved» argument, you must always pass a NULL value for that parameter — some functions will fail if you do not do so.

LPVOID objects frequently do not have prefixes, although it is relatively common to prefix an LPVOID variable with the letter «p», as it is a pointer.

DWORD, WORD, BYTE [ edit | edit source ]

These data types are defined to be a specific length, regardless of the target platform. There is a certain amount of additional complexity in the header files to achieve this, but the result is code that is very well standardized, and very portable to different hardware platforms and different compilers.

DWORDs (Double WORDs), the most commonly occurring of these data types, are defined always to be unsigned 32-bit quantities. On any machine, be it 16, 32, or 64 bits, a DWORD is always 32 bits long. Because of this strict definition, DWORDS are very common and popular on 32-bit machines, but are less common on 16-bit and 64-bit machines.

WORDs (Single WORDs) are defined strictly as unsigned 16-bit values, regardless of what machine you are programming on. BYTEs are defined strictly as being unsigned 8-bit values. QWORDs (Quad WORDs), although rare, are defined as being unsigned 64-bit quantities. Putting a «P» in front of any of these identifiers indicates that the variable is a pointer. putting two «P»s in front indicates it’s a pointer to a pointer. These variables may be unprefixed, or they may use any of the prefixes common with DWORDs. Because of the differences in compilers, the definition of these data types may be different, but typically these definitions are used:

Notice that these definitions are not the same in all compilers. It is a known issue that the GNU GCC compiler uses the long and short specifiers differently from the Microsoft C Compiler. For this reason, the windows header files typically will use conditional declarations for these data types, depending on the compiler being used. In this way, code can be more portable.

As usual, we can define pointers to these types as:

DWORD variables are typically prefixed with «dw». Likewise, we have the following prefixes:

Data Type Prefix
BYTE «b»
WORD «w»
DWORD «dw»
QWORD «qw»

LONG, INT, SHORT, CHAR [ edit | edit source ]

These types are not defined to a specific length. It is left to the host machine to determine exactly how many bits each of these types has.

Types LONG notation LONG variables are typically prefixed with an «l» (lower-case L). UINT notation UINT variables are typically prefixed with an «i» or a «ui» to indicate that it is an integer, and that it is unsigned. CHAR, UCHAR notation These variables are usually prefixed with a «c» or a «uc» respectively.

If the size of the variable doesn’t matter, you can use some of these integer types. However, if you want to exactly specify the size of a variable, so that it has a certain number of bits, use the BYTE, WORD, DWORD, or QWORD identifiers, because their lengths are platform-independent and never change.

STR, LPSTR [ edit | edit source ]

STR data types are string data types, with storage already allocated. This data type is less common than the LPSTR. STR data types are used when the string is supposed to be treated as an immediate array, and not as a simple character pointer. The variable name prefix for a STR data type is «sz» because it’s a zero-terminated string (ends with a null character).

Most programmers will not define a variable as a STR, opting instead to define it as a character array, because defining it as an array allows the size of the array to be set explicitly. Also, creating a large string on the stack can cause greatly undesirable stack-overflow problems.

LPSTR stands for «Long Pointer to a STR», and is essentially defined as such:

LPSTR can be used exactly like other string objects, except that LPSTR is explicitly defined as being ASCII, not unicode, and this definition will hold on all platforms. LPSTR variables will usually be prefixed with the letters «lpsz» to denote a «Long Pointer to a String that is Zero-terminated». The «sz» part of the prefix is important, because some strings in the Windows world (especially when talking about the DDK) are not zero-terminated. LPSTR data types, and variables prefixed with the «lpsz» prefix can all be used seamlessly with the standard library <string.h> functions.

TCHAR [ edit | edit source ]

TCHAR data types, as will be explained in the section on Unicode, are generic character data types. TCHAR can hold either standard 1-byte ASCII characters, or wide 2-byte Unicode characters. Because this data type is defined by a macro and is not set in stone, only character data should be used with this type. TCHAR is defined in a manner similar to the following (although it may be different for different compilers):

TSTR, LPTSTR [ edit | edit source ]

Strings of TCHARs are typically referred to as TSTR data types. More commonly, they are defined as LPTSTR types as such:

These strings can be either UNICODE or ASCII, depending on the status of the UNICODE macro. LPTSTR data types are long pointers to generic strings, and may contain either ASCII strings or Unicode strings, depending on the environment being used. LPTSTR data types are also prefixed with the letters «lpsz».

HANDLE [ edit | edit source ]

HANDLE data types are some of the most important data objects in Win32 programming, and also some of the hardest for new programmers to understand. Inside the kernel, Windows maintains a table of all the different objects that the kernel is responsible for. Windows, buttons, icons, mouse pointers, menus, and so on, all get an entry in the table, and each entry is assigned a unique address known as a HANDLE. If you want to pick a particular entry out of that table, you need to give Windows the HANDLE value, and Windows will return the corresponding table entry.

HANDLEs are defined as void pointers (void*). They are used as unique identifiers to each Windows object in our program such as a button, a window an icon, etc. Specifically their definition follows: typedef PVOID HANDLE; and typedef void *PVOID; In other words HANDLE = void*.

HANDLEs are generally prefixed with an «h». Handles are unsigned integers that Windows uses internally to keep track of objects in memory. Windows moves objects like memory blocks in memory to make room, if the object is moved in memory, the handles table is updated.

Below are a few special handles that are worth discussing:

HWND [ edit | edit source ]

HWND data types are «Handles to a Window», and are used to keep track of the various objects that appear on the screen. To communicate with a particular window, you need to have a copy of the window’s handle. HWND variables are usually prefixed with the letters «hwnd», just so the programmer knows they are important.

Canonically, main windows are defined as:

Child windows are defined as:

and Dialog Box handles are defined as:

Although you are free to name these variables whatever you want in your own program, readability and compatibility suffer when an idiosyncratic naming scheme is chosen — or worse, no scheme at all.

HINSTANCE [ edit | edit source ]

HINSTANCE variables are handles to a program instance. Each program gets a single instance variable, and this is important so that the kernel can communicate with the program. If you want to create a new window, for instance, you need to pass your program’s HINSTANCE variable to the kernel, so that the kernel knows what program instance the new window belongs to. If you want to communicate with another program, it is frequently very useful to have a copy of that program’s instance handle. HINSTANCE variables are usually prefixed with an «h», and furthermore, since there is frequently only one HINSTANCE variable in a program, it is canonical to declare that variable as such:

It is usually a benefit to make this HINSTANCE variable a global value, so that all your functions can access it when needed.

HMENU [ edit | edit source ]

If your program has a drop-down menu available (as most visual Windows programs do), that menu will have an HMENU handle associated with it. To display the menu, or to alter its contents, you need to have access to this HMENU handle. HMENU handles are frequently prefixed with simply an «h».

Читать:
Сколько форм может содержать проект

WPARAM, LPARAM [ edit | edit source ]

In the earlier days of Microsoft Windows, parameters were passed to a window in one of two formats: WORD-length (16-bit) parameters, and LONG-length (32-bit) parameters. These parameter types were defined as being WPARAM (16-bit) and LPARAM (32-bit). However, in modern 32-bit systems, WPARAM and LPARAM are both 32 bits long. The names however have not changed, for legacy reasons.

WPARAM and LPARAM variables are generic function parameters, and are frequently type-cast to other data types including pointers and DWORDs.

Лекция по курсу ОС и СП №8

Познакомиться с набором библиотек WinAPI. Получить первичные сведения о функциях WinAPI и их применением в различных ситуациях.

Теоретическая часть лекции.

Windows API (англ. application programming interfaces) — общее наименование целого набора базовых функций интерфейсов программирования приложений операционных систем семейств Microsoft Windows корпорации «Майкрософт» и совместимой с ними свободной бесплатной операционной системы ReactOS. Является самым прямым способом взаимодействия приложений с Windows и ReactOS. Для создания программ, использующих Windows API, «Майкрософт» выпускает комплект разработчика программного обеспечения, который называется Platform SDK, и содержит документацию, набор библиотек, утилит и других инструментальных средств для разработки.

Windows API спроектирован для использования в языке Си для написания прикладных программ, предназначенных для работы под управлением операционной системы MS Windows. Работа через Windows API — это наиболее близкий к операционной системе способ взаимодействия с ней из прикладных программ. Более низкий уровень доступа, необходимый только для драйверов устройств, в текущих версиях Windows предоставляется через Windows Driver Model.

Windows API представляет собой множество функций, структур данных и числовых констант, следующих соглашениям языка Си. Все языки программирования, способные вызывать такие функции и оперировать такими типами данных в программах, исполняемых в среде Windows, могут пользоваться этим API. В частности, это языки C++, Pascal, Visual Basic и многие другие.

Для облегчения программирования под Windows, в компании Microsoft и сторонними разработчиками было предпринято множество попыток создать библиотеки и среды программирования, частично или полностью скрывающие от программиста особенности Windows API, и предоставляющие ту или иную часть его возможностей в более удобном виде. В частности, сама Microsoft в разное время предлагала библиотеки Active Template Library (ATL)/Windows Template Library (WTL), Microsoft Foundation Classes (MFC), .Net/WinForms/WPF. Компания Borland (ныне Embarcadero, её преемник в части средств разработки) предлагала OWL и VCL. Есть кроссплатформенные библиотеки, такие как Qt, Tk и многие другие. Весомая часть этих библиотек сконцентрирована на облегчении программирования графического интерфейса пользователя.

Для облегчения переноса на другие платформы программ, написанных с опорой на Windows API, сделана библиотека Wine.

• Win16 — первая версия WinAPI для 16-разрядных версий Windows. Изначально назывался Windows API, позднее был ретроспективно переименован в Win16 для отличия от Win32. Описан в стандарте ECMA-234.

• Win32 — 32-разрядный API для современных версий Windows. Самая популярная

ныне версия. Базовые функции реализованы в динамически подключаемых

библиотеках kernel32.dll и advapi32.dll ; базовые модули графического интерфейса

пользователя — в user32.dll и gdi32.dll . Win32 появился вместе с Windows NT и затем был

перенесён в несколько ограниченном виде в системы серии Windows 9x. В современных версиях Windows, происходящих от Windows NT, работу Win32 GUI обеспечивают два модуля: csrss.exe (процесс исполнения клиент-сервер), работающий в пользовательском режиме, и win32k.sys в режиме ядра. Работу же системы обеспечивает ядро — ntoskrnl.exe .

подмножество Win32, устанавливаемое на семейство 16-разрядных

систем Windows 3.x и реализующее ограниченный набор функций Win32 для этих систем.

64-разрядная версия Win32, содержащая дополнительные

функции Windows на платформах x86-64 и IA-64.

Несколько слов об API, Win32, DLL

API (Application Programming Interface — интерфейс прикладных программ) — это множество функций, организованных, обычно, в виде DLL. Функции API позволяют организовать интерфейс между прикладной программой и средой, в которой работает эта программа. Вызов функций API позволяет программе получать доступ к ресурсам среды и управлять ее работой. Как правило, API задает стандарт взаимодействия среды и прикладной программы.

Win32 — это название интерфейса, ориентированного на 32-х разрядные приложения и реализованного на таких известных платформах как Windows 95, Windows 98, Windows NT, Windows CE. Функции, составляющие этот интерфейс, позволяют прикладной программе получать доступ к ресурсам операционной системы и управлять ее работой. Более ранние версии Windows используют интерфейс, известный как Win16. Конечно, не все функции, составляющие интерфейс Win32, реализованы в полной мере на всех платформах, так что вызов одной и той же функции под NT приведет к определенному результату, а под Windows 95 работает как вызов заглушки. Любое из приложений, работающее в среде Windows, прямо или косвенно вызывает функции, входящие в Win32 API.

Функции, составляющие Win32 интерфейс, организованы в виде нескольких динамически подключаемых библиотек (DLL) и исполняемых файлов. Говоря о Win32 API, следует в первую очередь упомянуть три основные библиотеки:

1. Kernel32.dll. Эта библиотека предназначена для работы с объектами ядра операционной системы и ее функции позволяют управлять памятью и другими системными ресурсами.

2. User32.dll. Здесь сосредоточены функции для управления окнами — основным видом объектов операционной системы. Обработка сообщений, работа с меню, таймерами, все это выполняют функции этой DLL.

3. GDI32.dll. Эта библиотека, обеспечивающая графический интерфейс операционной системы (Graphics Device Interface). Функции управления выводом на экран дисплея, управления выводом принтера, функции для работы со шрифтами — все они входят

в состав этой библиотеки.

Заметьте, Win API функции находятся не только в этих библиотеках. С другой стороны API функции не обязательно входят в состав Win32 интерфейса. Например, MAPI интерфейс (Messaging Application Programming Interface) составляют функции, предназначенные для обработки сообщений электронной почты, TAPI (Telephone API) — функции работы с телефонными

сообщениями. MAPI, TAPI, также как и Win32 это некоторый набор функций, задающий определенный стандарт взаимодействия

Как мы уже говорили, функции, образующие API, обычно, организованы в виде DLL — динамически подключаемых библиотеках. Одно из достоинств DLL состоит в том, что, сколько бы приложений (процессов) не работало с функциями одной и той же DLL, код DLL существует в единственном экземпляре.

Win32 API (далее WinAPI) – это набор функций (API – Application Programming Interface), работающих под управлением ОС Windows. Они содержатся в библиотеке windows.h .

С помощью WinAPI можно создавать различные оконные процедуры, диалоговые окна, программы и даже игры. Эта, скажем так, библиотека является базовой в освоении программирования Windows Forms , MFC, потому что эти интерфейсы являются надстройками этой библиотеки. Освоив её, Вы без труда будете создавать формы, и понимать, как это происходит.

Не будем внедряться в теорию. Начнём с того, как создать этот проект в MVS, а в конце статьи будет разобран простой пример.

Итак. Сначала открываем Visual Studio, затем, нажимаем на вкладку «Файл», далее «Создать проект»:

Затем, в раскрывающемся списке Visual C++ выбираем пункт Win32, там и будет «Проект Win32». Щелкаем по нему:

Вводим название проекта, указываем путь и нажимаем «ОК». Далее будет написано: «Добро пожаловать в мастер приложения Win32». Нажимаем далее. По-умолчанию у надписи «Пустой проект» галочка отсутствует. Нам нужно её поставить и убедиться, что у нас «Тип Приложения» — Приложение Windows. Если всё верно, нажимаем – «Готово».

У нас должен быть пустой проект такого вида:

Ну а теперь начнём писать простую программу, которая традиционно будет выводить на экран надпись: «Привет, Мир. ».

Естественно, к проекту нужно добавить файл типа «имя».cpp. Кликаем по «Файлы исходного кода» правой кнопкой мыши, в раскрывающемся списке выбираем вкладку – «Добавить», далее «Создать элемент…». В результате у нас должно появиться такое окно:

Выбираем «Файл С++», вводим имя, нажимаем «Добавить». Затем открываем этот файл и вставляем в него такой код (подробности далее):

1 #include <windows.h> // заголовочный файл, содержащий функции API

3 // Основная функция — аналог int main() в консольном приложении:

4 int WINAPI WinMain(HINSTANCE hInstance, // дескриптор экземпляра приложения

HINSTANCE hPrevInstance, // в Win32 не используется

LPSTR lpCmdLine, // нужен для запуска окна в режиме командной строки

int nCmdShow) // режим отображения окна

9 // Функция вывода окна с кнопкой «ОК» на экран (о параметрах позже)

10 MessageBox(NULL, L»Привет, мир. «, L»Оконная процедура», MB_OK);

11 return NULL; // возвращаем значение функции

Результат должен быть таким:

Теперь остановимся поподробнее на коде программы.

В первой строке мы подключаем заголовочный файл windows.h . В нём содержатся все необходимые «апишные» функции. Здесь всё понятно.

В 4-7 строках у нас описание функции int WINAPI WinMain() .

Квалификатор WINAPI, нужен для функции WinMain всегда. Просто запомните это. WinMain

– название функции. Она имеет четыре параметра. Первый из них – HINSTANCE hInstance (строка 4). hInstance является дескриптором экземпляра окна (это некий код оконной процедуры, идентификатор, по которой ОС будет отличать её от остальных окон). Через него можно обращаться к окну в процессе работы в других функциях (об этом позже), что-либо менять в параметрах окна. HINSTANCE является одним из многочисленных типов данных определенных в WinAPI, таким же как int, например. А запись HINSTANCE hInstance говорит нам о том, что мы создаём новую переменную типа HINSTANCE с названием hInstance.

О типах данным мы поговорим позже, поэтому переходим к следующему параметру: HINSTANCE hPrevInstance (строка 5). Как написано в комментариях, в Win32 он не используется, так как он создан для 3.x разрядной системы, из предыдущего понятно, что это дескриптор экземпляра окна. Далее у нас переменная типа LPSTR (строка 6) с именем lpCmdLine . Она используется в том случае, если мы запускаем окно через командную строку с прописью параметров. Очень экзотический способ, поэтому мы не будем на нём задерживаться.

И последний параметр: целочисленный, определяет способ показа окна. Нужен для функции ShowWindow , которая будет описана позже. Например, с помощью него мы можем развернуть окно на весь экран, сделать его определённой высоты, прозрачным или поверх остальных.

Переходим к функции MessageBox() (строка 10). Она имеет четыре параметра и нужна для вывода сообщений о ошибках, например. В данном случае мы использовали её для вывода сообщения. В общем виде описание функции выглядит следующим образом:

1 int MessageBox(HWND hWnd, // дескриптор родительского окна

LPCTSTR lpText, // указатель на строку с сообщением

LPCTSTR lpCaption, // указатель на строку с текстом заголовка

UINT uType);// флаги для отображения кнопок, стиля пиктограммы и прочее

В нашем случае, первому параметру присвоен ноль. Всё потому, что у нас нет родительских окон (оно не запущено какой-нибудь программой).

Далее у нас идут две переменные типа LPCTSTR : lpText и lpCaption . Первая сообщает информацию, которая будет выведена в окне в текстовом виде. Вторая сообщает, что будет написано в тексте заголовка к окну. Это аналог char *str , но всё же нет. Для того, чтобы текст выводился корректно, нужно перед строкой поставить букву L (UNICODE строка).

Ну и последний тип данных – UINT – 32-х битное целое без знака. То есть аналог unsigned int . Этому параметру можно передавать некоторые значения (о них тоже позже), за счёт чего можно менять вид кнопки. В нашем случае – это MB_OK — означает, что окно создаёт кнопку с надписью «ОК» и соответствующим действием при её нажатии (закрытием приложения).

В строке 11 мы возвращаем значение функции, так как она имеет не тип void .

Типы данных в Win32 API

В WINAPI определено множество типов данных, так же, как и в C/С++ ( int , char , float и т.д.). Учить их определения не обязательно. Достаточно помнить, что они существуют, а когда они появятся или потребуются где-нибудь в программе, посмотреть их определения. В дальнейшем мы будем использовать их все. Условно их можно разделить на несколько видов: основные, дескрипторные, строковые и вспомогательные.

С основными типами данных трудностей возникнуть не должно. Если всё же возникнут, то нужно заглянуть сюда http://cppstudio.com/post/271/ .

BOOL – этот тип данных аналогичен bool . Он также имеет два значения – 0 или 1. Только при использовании WINAPI принято использовать вместо 0 спецификатор NULL . О нём ниже.

BYTE – байт, ну или восьмибитное беззнаковое целое число. Аналог – unsigned char . DWORD — 32-битное беззнаковое целое. Аналоги: unsigned long int , UINT .

INT – 32-битное целое. Аналог – long int .

LONG – 32-битное целое – аналог всё также long int .

NULL – нулевой указатель. Вот его объявление:

UINT – 32-битное беззнаковое целое. Аналоги: unsigned long int , DWORD .

Дескрипторные типы данных

Про дескрипторные типы немного рассказывалось на вводном уроке в WINAPI. Дескриптор, как говорилось ранее, — это идентификатор какого-либо объекта. Для разных типов объектов существуют разные дескрипторы. Дескриптор объекта можно описать так:

Есть также дескрипторы кисти, курсора мыши, шрифта и т.д. С их помощью мы можем при инициализации или в процессе работы приложения поменять какие-нибудь настройки, чего, например, мы не могли сделать в консольном приложении. Используются они в описательных функциях, управляющих типа: CreateProcess(), ShowWindow() и т.д. или как возвращаемое значение некоторых функций :

1 // получает дескриптор для устройства ввода или вывода:

2 HANDLE h = GetStdHandle(DWORD nStdHandle);

В этой функции мы получили дескриптор считывания потоков std_in и std_out. И можем, например, его использовать в каком-нибудь условии.

Не будем вдаваться в физику создания дескрипторов. Разве что, при необходимости или для большего понимания процессов.

Примечание: для удобства в WINAPI предусмотрены сокращения для типов данных. Первая буква H – означает, что это дескриптор, от слова handle.

HANDLE – дескриптор объекта.

HBITMAP – дескриптор растрового изображения. От фразы handle bitmap.

HBRUSH – дескриптор кисти. От фразы handle brush.

HCURSOR – дескриптор курсора. От фразы handle cursor.

HDC – дескриптор контекста устройства. От фразы handle device context.

HFONT – дескриптор шрифта. От фразы handle font.

HICONS – дескриптор криптограммы. От фразы handle icons.

HINSTANCE – дескриптор экземпляра приложения. От фразы handle instance. HMENU – дескриптор меню. От фразы handle menu.

HPEN – дескриптор пера. От фразы handle pen.

HWND – дескриптор окна. От фразы handle window.

Строковые типы данных

Для начала начнём, с того, какие кодировки существуют в Windows ОС.

Есть два вида кодировок символов: ANSI и UNICODE. Однобайтные символы относятся к ANSI, двухбайтные — к кодировке UNICODE. Мы можем с лёгкостью подключить UNICODE кодировку в свойствах проекта. И тогда в коде создать переменную типа char можно будет так:

1 // создаём строку из 10 элементов: 2 wchar_t str[10];

Если же мы хотим использовать кодировку ANSI, то мы традиционно напишем:

1 // тоже создаём строку из 10 элементов:

В WINAPI, в зависимости от того, подключён юникод или нет, используются два вида строк UNICODE-ные или TCHAR-ные. Ниже описаны строковые типы данных.

Всё также для удобства, первые две буквы LP – от фразы long pointer сигнализируют о том, что это указатель.

LPCSTR – указатель на константную строку, заканчивающуюся нуль-терминатором. От фразы long pointer constant string.

LPCTSTR – указатель на константную строку, без UNICODE. От фразы long pointer constant TCHAR string. Это надстройка функции LPCSTR.

LPCWSTR – указатель на константную UNICODE строку. От фразы фразы long pointer constant wide character string. Это надстройка функции LPCSTR.

LPSTR – указатель на строку, заканчивающуюся нуль-терминатором. От фразы long pointer

LPTSTR – указатель на строку, без UNICODE. От фразы long pointer TCHAR string. Это надстройка функции LPSTR.

LPWSTR – указатель на UNICODE строку. От фразы long pointer wide character string. Это надстройка функции LPSTR.

TCHAR – символьный тип — аналог char и wchar_t.

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

1 LRESULT CALLBACK ИмяФункции(HWND hWnd, UINT uMSg,

2 WPARAM wParam, LPARAM lParam);

Работа с данной функцией будет в следующих разделах.

LPARAM – тип для описания lParam (long parameter). Используются вместе с wparam в некоторых функциях.

LRESULT – значение, возвращаемое оконной процедурой имеет тип long .

WPARAM – тип для описания wParam (word parameter). Используются вместе с lParam в некоторых функциях.

На этом типы данных не закончены.

Создание полноценной оконной процедуры в Win32 API (Часть 1)

В разделе по WINAPI мы разобрали программу, которая выводит окно с сообщением. Кроме того, после нажатия «ОК» окно закрывалось. И это всё, что она могла. Нетрудно догадаться, что при помощи Win32 API можно реализовывать более информативные окна. Поговорим о создании настоящей оконной процедуры.

Обобщённый алгоритм создания оконной процедуры в WINAPI:

1. Создать две функции: WinMain() – основная функция с параметрами, оговоренными

в первой статье – аналог main в консоли, и функцию обрабатывающую процессы (название своё, пусть будет традиционно – WndProc() ), потоки сообщений к/от ОС Windows.

2. Создать дескриптор окошка hMainWnd и зарегистрировать класс окошка WNDCLASSEX (то есть указать характеристики окна, которое будем создавать). Должен содержаться

3. Создать оболочку нашего окна. Должна содержаться в WinMain.

4. Создать циклы для обработки сообщений. Содержатся в функции WndProc.

5. Создать функцию для вывода окна ShowWindow и другие вспомогательные.

Теперь будет трудновато, потому что сейчас появятся различные функции с кучей параметров, классы, которые следует знать, понимать, ну и некоторые другие премудрости языков С и С++.

Похожие статьи