Имеются 2 независимых приложения с почти идентичным кодом. В одном из них генерируем сообщение (нажав на мышку) и вместе с сообщением высылается указатель на структуру.
Вопрос: как можно выслать сообщение из одного приложения, а перехватить другим без появления синего экрана.
Что уже пробовал:
//Высылаемая структура, есть глобальный объект структуры - ball
struct ballXY
{
bool state;
int azaz;
};
ballXY ball = {false, 666};
// а так же message для нашей структуры
const UINT ball_msg = RegisterWindowMessage((LPCWSTR)("ball"));
Функция CALLBACK
выглядит как-то так:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == ball_msg)
{
ball = *(ballXY*)lParam;
return 0;
}
switch (message)
{
case WM_PAINT:
//рисуем тут
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_LBUTTONDOWN:
if (!ball.state)
ball.state = true;
break;
case WM_TIMER:
if (ball.state) {
SendMessage(HWND_BROADCAST, ball_msg, NULL, (LPARAM)&ball);
ball.state = false;
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
Итог: запустив 2 приложения, я нажал на правую кнопку мыши в одном - закрашился эксплорер, часть программ закрылась.
Для межпроцессорной пересылки данных Windows API предоставляет два простых способа:
Именованные каналы. Хоть я и советовал этот способ в комментариях к вопросу, но он сопряжён с одной неустранимой трудностью. Кто закроет канал, если передающее приложение рухнет? Так как канал общий, то никто — будет утечка глобальных ресурсов.
Посылка оконного сообщения WM_COPYDATA
. Это сообщение — одно из немногих, которые обрабатываются оконной подсистемой на особых правах, а потому указанный в нём блок байт будет заботливо скопирован в адресное пространство получателя.
При таком подходе код будет выглядеть так:
отправление сообщения:
struct BallXY
{
bool state;
int azaz;
};
// =================
void sendBallState(BallXY& ball, HWND hParent)
{
// Перебираем все окна-получатели и рассылаем им обновлённые данные
HWND hDestWnd = NULL;
bool continueIteration = true;
while(continueIteration)
{
hDestWnd = FindWindowEx(
/* hwndParent */ NULL,
/* hwndChildAfter */ hDestWnd,
/* lpszClass */ TEXT("оконный_класс_получателя"),
/* lpszWindow */ NULL);
if(hDestinationWnd)
{
COPYDATASTRUCT cds;
cds.dwData = 0; // Любой идентификатор; передаётся получателю как есть
cds.cbData = sizeof(ball);
cds.lpData = &ball;
SendMessage(hDestWnd, WM_COPYDATA, (WPARAM)hParent, (LPARAM)&cds);
}
else
continueIteration = false;
}
}
оконная процедура:
static void onCopyData(HWND hWnd, HWND hSourceWnd, PCOPYDATASTRUCT cds)
{
UNREFERENCED_PARAMETER(hWnd);
// Проверяем по размеру данных, что они хотя бы примерно похожи на наши
if(cds->cbData == sizeof(BallXY))
{
// Проверяем, что отправитель — подконтрольное нам окно
TCHAR sourceClassName[256]; // Длина гарантирована MSDN
GetClassName(hSourceWnd, sourceClassName, sizeof(sourceClassName));
if(lstrcmp(sourceClassName, TEXT("оконный_класс_отправителя")) == 0)
{
// Безопасно преобразуем типы, избегая неопределённого поведения
memcpy(&ball, cds->lpData, sizeof(ball));
}
}
static void onTimerTick(HWND hWnd, UINT uTimerId)
{
UNREFERENCED_PARAMETER(uTimerId);
if(ball.state)
{
sendBallState(ball, hWnd);
ball.state = false;
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// Забываем про развесистые switch-case и пользуемся вместо этого удобными
// message crackers из windowsx.h
switch(message)
{
HANDLE_MSG(hWnd, WM_COPYDATA, onCopyData);
HANDLE_MSG(hWnd, WM_TIMER, onTimerTick);
// ...
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Интересует не столько решение, сколько причина по которой программа выводит неверный результат
Visual Studio 2010 на попытку создать свойство у класса пишет:
Есть кнопка в ob_panelui - on_pB_Switch_clicked и элемент в mainwindow