Взаимодействие процессов (приложений) на WinApi
Сейчас в интернетах можно встретить много Hello World’ов на WinApi, но когда новичок спрашивает как в этот Hello World добавить пару нужных функций — закидывают тухлыми яблоками и тут же отправляют в пресловутый и могучий MSDN.
В этой статье от новичка новичкам я расскажу, как построить два простых приложения которые будут взаимодействовать друг с другом — одно будет принимать на вход параметры геометрической прогрессии и передавать её второму, второе же приложение будет рассчитывать n-ый член прогрессии, записывать его в файл и передавать ответ первому приложению.

Итак, поехали (Гагарин).
С тем что нам нужно мы уже определились во введении, разрабатывать мы будем в Visual Studio 2008, так как она единственная лежала на сервере университета.
Создаем проект пустой проект Application A, а в нем создадим обертку для упрощенния создания окна (эта обертка понадобится и в другом проекте, а так же может понадобится Вам в будущем).
Хоть статья и для начинающих — на описании процесса создания окна мы останавливаться не будем, так как этой информации в интернете предостаточно.
Далее нам нужно в файл ресурсов добавить диалоговое окно:
Выглядеть это должно примерно так:
Приступим к кодингу.
Интересные и интересующие моменты рассмотрим отдельно
Тут мы объявляем структуру данных которую мы посылаем и необходимые структуры:
Далее идет проверка — запущено ли второе приложение, если нет то программа запускает его.
Далее упаковываем данные в нашу структуру
Правильно заполняем структуру передаваемых данных и отправляем её другому приложению:
Вот и все — не каких проверок на то заполнены ли поля и заполнены ли они корректно мы делать не будем в этой статье.
А теперь приступим к приложению B. Первые два файла — kWnd.h и kWnd.cpp остаются неизменными. Само приложение мы будем строить уже не на базе диалогового окна, а на базе чистого хардкора.
Вооот, этот длинный файл и делает всю сложную работу — принимает сообщение, вычисляет(в многопоточном режиме(не удивляетесь, это было одним из пунктов задания)), записывает, отправляет назад.
Здесь из интересных моментов стоит отметить прием данных в событии:
Далее к принятым данным можно достучаться например так:
Остальные приемы этого файла нам не интересны и скучны, далее там следует подсчет прогрессии и отправка тем же методом первому процессу.
И вот что у нас получилось:
Я очень надеюсь что моя статья была кому либо полезна и очень извиняюсь перед теми кому она не понравилась. Жду комментариев к коду (говнокоду).
Структура оконного приложения
Оконные приложения строятся по принципам событийно-управляемого программирования (event-driven programming) — стиля программирования, при котором поведение компонента системы определяется набором возможных внешних событий и ответных реакций компонента на них. Такими компонентами в Windows являются окна.
Задача любого оконного приложения — создать главное окно и сообщить Windows функцию обработки событий для этого окна. Все самое интересное для приложения будет происходить именно в функции обработки событий главного окна.
В Windows программа пассивна. После запуска она ждет, когда ей уделит внимание операционная система. Операционная система делает это посылкой сообщений. Сообщения могут быть разного типа, они функционируют в системе достаточно хаотично, и приложение не знает, какого типа сообщение придет следующим. Логика построения Windows-приложения должна обеспечивать корректную и предсказуемую работу при поступлении сообщений любого типа.
Классическое оконное приложение, как правило, состоит по крайней мере из двух функций:
Стартовая функция WinMain
Эта функция использует последовательность вызовов API и при завершении возвращает операционной системе целое число.
Аргументы функции:
В структуре стартовой функции Windows можно выделить следующие операции, образующие «скелет» программы:
Регистрация класса окна
Регистрация класса окна осуществляется функцией
Члены структуры
style — устанавливает стиль(и) класса. Этот член структуры может быть любой комбинацией стилей класса.
| Имя | Значение | Описание |
| CS_VREDRAW | 0x01 | Вертикальная перерисовка: осуществлять перерисовку окна при перемещении или изменении высоты окна. |
| CS_HREDRAW | 0x02 | Горизонтальная перерисовка: осуществлять перерисовку окна при перемещении или изменении ширины окна. |
| CS_KEYCVTWINDOW | 0x04 | В окне будет выполняться преобразование виртуальных клавиш. |
| CS_DBLCLKS | 0x08 | Окну будут посылаться сообщения о двойном щелчке кнопки мыши. |
| CS_OWNDC | 0x20 | Каждому экземпляру окна присваивается собственный контекст изображения. |
| CS_CLASSDC | 0x40 | Классу окна присваивается собственный контекст изображения,который можно разделить между копиями. |
| CS_PARENTDC | 0x80 | Классу окна передается контекст изображения родительского окна. |
| CS_NOKEYCVT | 0x100 | Отключается преобразование виртуальных клавиш. |
| CS_NOCLOSE | 0x200 | Незакрываемое окно: в системном меню блокируется выбор пункта закрытия окна. |
| CS_SAVEBITS | 0x800 | Часть изображения на экране, закрытая окном, сохраняется. |
| CS_BYTEALIGNCLIENT | 0x1000 | Выравнивание клиентской области окна: использование границы по байту по оси x. |
| CS_BYTEALIGNWINDOW | 0x2000 | Выравнивание окна: bспользование границы по байту по оси x. |
| CS_PUBLICCLASS CS_GLOBALCLASS | 0x4000 | Определяется глобальный класс окон. |
lpfnWndProc — указатель на оконную процедуру.
cbClsExtra — устанавливает число дополнительных байт, которые размещаются вслед за структурой класса окна. Система инициализирует эти байты нулями, в большинстве случаев равен 0.
cbWndExtra — устанавливает число дополнительных байтов, которые размещаются вслед за экземпляром окна. Система инициализирует байты нулями.
hInstance — дескриптор экземпляра, который содержит оконную процедуру для класса.
hIcon — дескриптор значка класса, дескриптор ресурса значка. Если этот член структуры — NULL, система предоставляет заданный по умолчанию значок.
hCursor — дескриптор курсора класса, дескриптор ресурса курсора. Если этот член структуры — NULL, приложение устанавливает форму курсора всякий раз, когда мышь перемещается в окно прикладной программы.
Создание окна
Создание окна осуществляется функцией
Прототип функции находится в файле библиотеки user32.dll.
Возвращаемое значение – дескриптор создаваемого окна. В случае невозможности создать окно возвращается NULL.
Аргументы функции :
lpClassName – указывает на строку с ‘\0’ в конце, которая определяет имя класса окна. Имя класса может быть зарегистрированным функцией RegisterClass или любым из предопределенных имен класса элементов управления.
lpWindowName — указывает на строку с ‘\0’ в конце, которая определяет имя окна.
dwStyle — определяет стиль создаваемого окна.
| Имя | Значение | Описание |
| WS_BORDER | 0x00800000 | Окно имеет тонкую границу в виде линии. |
| WS_CAPTION | 0x00C00000 | Окно имеет строку заголовка. |
| WS_CHILD | 0x40000000 | Окно является дочерним. |
| WS_DISABLED | 0x08000000 | Окно является изначально неактивным. |
| WS_GROUP | 0x00020000 | Окно группирует другие управляющие элементы. |
| WS_HSCROLL | 0x00100000 | Окно содержит горизонтальную полосу прокрутки. |
| WS_MAXIMIZE | 0x01000000 | Исходный размер окна – во весь экран. |
| WS_MINIMIZE | 0x20000000 | Исходно окно свернуто. |
| WS_OVERLAPPED | 0x00000000 | Окно может быть перекрыто другими окнами. |
| WS_POPUP | 0x80000000 | Всплывающее окно. |
| WS_SYSMENU | 0x00080000 | Окно имеет системное меню в строке заголовка. |
| WS_VISIBLE | 0x10000000 | Окно изначально видимое. |
| WS_VSCROLL | 0x00200000 | Окно имеет вертикальную полосу прокрутки. |
у – определяет координату верхней стороны окна относительно верхней стороны экрана. Измеряется в единицах измерения устройства, чаще всего в точках (pt). Для дочернего окна определяет координату верхней стороны относительно начальной координаты родительского окна.
nHeight – определяет высоту окна в единицах измерения устройства.
hWndParent – дескриптор родительского окна.
hInstance — идентифицирует экземпляр модуля, который будет связан с окном.
lpParam — указывает на значение, переданное окну при создании.
Отображение и перерисовка окна
Отображение окна осуществляется функцией
Прототип функции находится в файле библиотеки user32.dll.
Возвращаемое значение: 1 – успешное отображение окна, 0 – ошибка.
Аргументы функции :
hWnd – дескриптор отображаемого окна.
nCmdShow – константа, определяющая, как будет отображаться окно согласно таблице.
Перерисовка окна осуществляется функцией
Прототип функции находится в файле библиотеки user32.dll.
Возвращаемое значение: 1 – успешная перерисовка окна, 0 – ошибка.
Аргумент функции hWnd – дескриптор окна.
Цикл обработки сообщений
Для получения сообщения из очереди используется функция:
Аргументы функции :
lpMsg — указатель на структуру сообщения.
Структура POINT имеет вид
hWnd — дескриптор окна, очередь для которого просматривается.
wMsgFilterMin — нижняя граница фильтра идентификаторов сообщений.
wMsgFilterMax — верхняя граница фильтра идентификаторов сообщений.
передает аргумент — структуру msg обратно в Windows для преобразования какого-либо сообщения с клавиатуры. Возвращает ненулевое значение в случае успешной расшифровки сообщения, 0 – ошибка.
передает аргумент — структуру msg обратно в Windows. Windows отправляет сообщение для его обработки соответствующей оконной процедуре — таким образом, Windows вызывает соответствующую оконную функцию, указанную при регистрации класса окна.
Пример стартовой функции, создающей и выводящей окно размером 500х300 точек:
Примечание : Для корректной сборки приложения используется многобайтовая кодировка.
Оконная функция — обработка сообщений окна
Оконная функция предназначена для обработки сообщений окна. Функция обработки сообщений окна организована по принципу ветвления, состоящего из последовательной проверки типа сообщения. При совпадении типа сообщения, переданного в структуре Message с соответствующей веткой, осуществляется его обработка. Минимальный вид оконной функции представлен ниже.
Вызов функции DefWindowProc() обрабатывает по умолчанию все сообщения, которые не обрабатывает оконная процедура.
Функция PostQuitMessage() сообщает Windows, что данный поток запрашивает завершение. Аргументом является целочисленное значение, которое функция вернет операционной системе.
Результат выполнения программы, выводящей окно:
Комментариев к записи: 13
Расшифровка типа HWND
В Visual studio 2008 HWND раскрывается в
#define DECLARE_HANDLE(name) struct name##__ < int unused; >; typedef struct name##__ *name
Помогите понять что это такое )
Для чего служит первый параметр (HWND hWnd) в функции WndProc?
// функция обработки сообщений LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM.

Пытаюсь понять какое значение хранит первый параметр HWND hWnd в функции WndProc. В Windows в.
Почему переменная HWND hwnd объявлена дважды?
Один раз в функции WinMain: int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance.
Найти HWND окна, зная HWND окна, породившего его
Здравствуйте! Имеется основное окно «А». Это окно создаёт новое недочернее окно «Б». Необходимо.
typedef HANDLE HWND
Если интересно узнать больше о DDE что будет полезно для лучшего понимания можно почитать данную инфу по ссылке ниже:
Если интересно узнать больше о DDE что будет полезно для лучшего понимания можно почитать данную инфу по ссылке ниже:
Вот короткий вариант того что нужно
typedef HANDLE HWND

Возврат объекта шаблонного типа от типа Type из специализации шаблона метода от того же типа
Доброго времени суток, пишу класс содержащий несколько std::set от разных типов, нужно сделать.

Как взять дескриптор окна через его имя?
HWND
Доброго времени суток, извините за такой тупой вопрос, но. объявляю функцию void draw(HWND.
IN HWND hWnd
Здравствуйте. Каково назначение IN в объявлении IN HWND hWnd? В чём разница между HWND hWnd и IN.

Почему так странно объявлен тип HWND? Может кто прокомментировать эти строки: //winnt.h #define.
hwnd c что это
Мы с Вами в этом шаге каснемся работы с окнами в Windows. У каждого окна есть уникальный идентификатор HWND. Этот идентификатор указывает на окно. Окна в Windows можно представить в виде дерева с корнем в DeskTop. Это легко увидеть запустив SPY (см. «Шаг 47 — Как пользоваться SPY»).
Итак, как и у любого дерева, у дерева окон есть корень. Получить указатель на него можно функцией GetDesktopWindow(), которая вернет HWND корня в виде рабочего стола. Ага начало есть. Дальше как у того богатыря на картинке. Налево, направо или куда. От текущего HWND можно получить HWND либо ребенка, вот так GetWindow(hwnd, GW_CHILD), либо соседа вот так GetWindow(hwnd, GW_HWNDNEXT). И так далее. Дерево господа и алгоритм его обхода. Имея HWND можно получить заголовок окна GetWindowText. Ну пора. Вот код получения имен окон первого уровня. А вот результат работы у меня
Вообще могу подсказать HWND — это handle-обработка DDE — Dynamic Data Exchange Management Library (библиотека управления динамическим обменом данных) она содержится в директиве Ddeml.h из этого следует — typedef HANDLE HSZ. Если интересно узнать больше о DDE что будет полезно для лучшего понимания можно почитать данную инфу по ссылке ниже:http://citforum.ru/programming/32less/les21.shtml
В WinAPI такие идентификаторы реализованы в виде указателей неизвестно на что. Чтобы указатели на разные вещи не имели один и тот же тип (вроде void *) и не слишком запутывались между собой, в приведённом макросе для каждого отдельного типа хэндлов создаётся своя структура, указателем на которую и является хэндл.
Хорошо, ЕДИНСТВЕННАЯ причина, которую я спрашиваю, состоит в том, что я прочитал, что HWND является указателем, указатели изменяют исходное значение вместо создания дубликата, который хранится в этой ячейке памяти.
Но на самом деле он не действует как указатель, поэтому я говорю это, потому что, если бы у меня был оператор switch, Пример:
Но не следует забывать, что вы — новый программист на C ++ для Win32. Просто, найдя адрес памяти, затем захватывая содержимое внутри. Если адрес памяти не меняется и т. Д.
Я действительно не знаю, вы не возражаете против разработки? Благодарю.
Решение
Это, вероятно, не самый качественный ответ; предложения по улучшению приветствуются.
Вы правы, предполагая, что значение HWND никогда не изменяется, пока окно, на которое указывает HWND, остается живым.
Я предполагаю, что вы написали такой код:
и интересно, почему это не работает, но меняется
Это не собственность HWND. Ничего о сбое кода не происходит, потому что значение HWND изменилось. На самом деле, это не имеет ничего общего с Windows, и все, что связано с C.
Причина, по которой код не работает, заключается в том, что переменная button создается каждый раз, когда wndproc() функция называется. Видите, оконная процедура вызывается много раз, по одному разу для каждого сообщения, которое окно когда-либо получает во время выполнения вашей программы. Каждый раз вы получаете совершенно новый button переменная, и значение, которое button переменная в предыдущих вызовах теряется. Указатель все еще там, но он не хранится ни в одной переменной или в любом другом месте памяти! Окно не было разрушено. Вы просто не можете добраться до него обычными способами.
Что за static действительно, говорит C, что вы хотите, чтобы переменная оставалась без изменений при каждом вызове функции Так что теперь каждый вызов вашей оконной процедуры имеет одинаковый button и это значение указателя больше не теряется.
Это быстрое решение, и оно не очень хорошо масштабируется для очень больших проектов. В этих случаях структуры, содержащие дескрипторы окна, (возможно) глобальные переменные или использование GWLP_USERDATA или другой cbWndExtra байты лучше. Я думаю, что лучший вопрос заключается в том, почему это быстрое исправление продолжает предлагаться в качестве решения подобных проблем других людей здесь, в Переполнении стека (или, по крайней мере, почему это быстрое исправление не объясняется), но это то, о чем мы должны подумать, как сообщество.
Просто помните, что по умолчанию в большинстве языков (не только C и C ++!) Локальные переменные функции существуют только на время каждого отдельного вызова функции.
Другие решения
В коде, о котором идет речь, отсутствует много контекста (так что здесь просто догадайтесь вслепую), но если код находится в отдельной функции и переменной hButton является локальной переменной в этой функции, то вы должны помнить, что локальные переменные выходят из области видимости, когда функция, в которой они находятся, возвращает, и в следующий раз, когда вызывается функция, переменная является совершенно новой, уникальной для этого вызова и только этот звонок.
Также стоит отметить, что нестатические локальные переменные не инициализируются автоматически. Если вы явно не инициализируете такую переменную, ее значение будет неопределенный и использование его любым способом (кроме как для его инициализации) приводит к неопределенное поведение.
Управление состоянием приложения
Оконная процедура — это просто функция, которая вызывается для каждого сообщения, поэтому она по сути не имеет состояния. Поэтому необходим способ отслеживания состояния приложения от одного вызова функции к следующему.
Самый простой подход — просто поместить все в глобальные переменные. Это хорошо подходит для небольших программ, и многие из примеров пакета SDK используют этот подход. Однако в большой программе она приводит к распространению глобальных переменных. Кроме того, у вас может быть несколько окон, каждая из которых имеет собственную процедуру окна. Отслеживание того, какое окно должно иметь доступ, какие переменные становятся запутанными и подвержены ошибкам.
Функция CreateWindowEx предоставляет способ передачи любой структуры данных в окно. При вызове этой функции в оконную процедуру отправляются следующие два сообщения:
Эти сообщения отправляются в указанном порядке. (Они не являются единственными двумя сообщениями, отправленными во время CreateWindowEx, но мы можем игнорировать другие для этого обсуждения.)
Сообщение WM _ Нккреате и WM _ CREATE отправляются до того, как окно станет видимым. Это делает их хорошим местом для инициализации пользовательского интерфейса, например, для определения первоначального макета окна.
Давайте посмотрим, как использовать этот параметр для передачи данных приложения в окно. Сначала определите класс или структуру, которые содержат сведения о состоянии.
Элемент лпкреатепарамс структуры CREATESTRUCT является исходным указателем void, указанным в CreateWindowEx. Получите указатель на собственную структуру данных путем приведения лпкреатепарамс.
Затем вызовите функцию сетвиндовлонгптр и передайте указатель в структуру данных.
Цель последнего вызова функции — сохранить указатель статеинфо в данных экземпляра для окна. После этого вы всегда можете вернуть указатель из окна, вызвав жетвиндовлонгптр:
Теперь можно написать процедуру окна следующим образом.
Object-Orientedный подход
Этот подход можно расширить. Мы уже определили структуру данных для хранения сведений о состоянии окна. Имеет смысл предоставить эту структуру данных с помощью функций-членов (методов), которые работают с данными. Это естественно ведет к проектированию, где структура (или класс) отвечает за все операции в окне. Затем процедура окна станет частью класса.
Другими словами, мы хотели бы проделать следующее:
Единственная проблема заключается в том, как подключить MyWindow::WindowProc метод. Функция registerClass ждет, что процедура окна является указателем на функцию. Нельзя передать указатель на функцию-член (не статическую) в этом контексте. Однако можно передать указатель на статическую функцию-член, а затем делегировать ее функции-члену. Ниже приведен шаблон класса, демонстрирующий этот подход:
BaseWindow Класс является абстрактным базовым классом, от которого наследуются определенные классы окон. Например, ниже приведено объявление простого класса, производного от BaseWindow :
Чтобы создать окно, вызовите BaseWindow::Create :
BaseWindow::HandleMessage Для реализации процедуры окна используется чистый виртуальный метод. Например, следующая реализация эквивалентна процедуре окна, показанной в начале модуля 1.
многие из существующих Windows платформ программирования, таких как Microsoft Foundation Classes (MFC) и библиотека atl, используют подходы, похожие на показанные здесь. Конечно, полностью обобщенная платформа, такая как MFC, сложнее, чем этот сравнительно простой пример.









