Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / подмена оконной процедуры - крах приложения / 8 сообщений из 8, страница 1 из 1
27.05.2014, 10:00
    #38652790
iMerlin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подмена оконной процедуры - крах приложения
Здравствуйте, помогите, пожалуйста, что то никак не могу ухватить что не так сделал.
Есть задача: научить приложение VBA (Access) реагировать на сообщение пользователя (управление внешней программой).
Для этого была сделана DLL, подменяющая оконную процедуру и долженствующая вызвать некоторую функцию при приходе сообщения UserMsg.

DLL имеет три используемые в данном случе функции: NewDialogProc, SetNewProc и int Init.
Init (просто для сведения привел - там вроде все правильно работает) регистрирует UserMsg.
SetNewProc - подменяет оконную процедуру.
NewDialogProc - новая процедура. Ее цель - обеспечить отдельную обработку UserMsg.

При отладке на простеньком MFC приложении обнаружился вылет через долю секунды после запуска.
При пошаговом исполнении оказалось, что происходит переполнение стека и через 10-15 обработанных сообщений стек рушится.

Думаю, я что-то очевидно не так сделал, но сам не могу сообразить что. Подскажите плс, куда копать?

PS: на данном этапе выполнения условие Msg==UserMsg не выполняется, то есть фактически в NewDialogProc выполняется только строка "return OldFunct(hWnd,Msg,wParam,lParam);".


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
typedef void (*pf_vii)(int,int);
typedef LRESULT (*pf_lhulw)(HWND,UINT,LPARAM,WPARAM);
pf_lhulw OldFunct;
pf_vii NewFunct;
HWND hWndMain;
UINT UserMsg;
HANDLE hEvent;


DWORD NewDialogProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
{
	if(Msg==UserMsg)
	{
		NewFunct((DWORD)wParam, (DWORD)lParam);
		return TRUE;
	}
	else
	{
		return OldFunct(hWnd,Msg,wParam,lParam);
	}
}



void WINAPI SetNewProc(HWND hWnd, pf_vii funct)
{
	if(OldFunct)return;
	OldFunct=(pf_lhulw)SetWindowLong(hWnd,-4,(DWORD)&NewDialogProc);
	hWndMain=hWnd;
	NewFunct=funct;
}


int Init()
{


	UserMsg=RegisterWindowMessage("4DBB78B9-0C23-412e-951A-2F1735567521_wm");
	if(!UserMsg){MessageBox(NULL,"Can't register message","System error",MB_ICONERROR | MB_OK);return 0;}

	SetLastError(0);
	hEvent=CreateEvent(NULL,1,0,"4DBB78B9-0C23-412e-951A-2F1735567521_ld");
	if(!hEvent){MessageBox(NULL,"Can't create event","System error",MB_ICONERROR | MB_OK);return 0;}
	if(GetLastError()==ERROR_ALREADY_EXISTS){MessageBox(NULL,"Already runned...","User error",MB_ICONERROR | MB_OK);return -1;}
	
	return 0;
}
...
Рейтинг: 0 / 0
27.05.2014, 10:16
    #38652807
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подмена оконной процедуры - крах приложения
Не надо свою очередь делать. Читай про хуки http://www.rsdn.ru/article/baseserv/winhooks.xml
...
Рейтинг: 0 / 0
27.05.2014, 10:53
    #38652858
iMerlin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подмена оконной процедуры - крах приложения
Спасибо, но думаю хуками сложней и не удобно. Мне надо в своем процессе просто сделать предобработчик событий и все. Хуки, как мне думается, скорее для слежения за чужим процессом.
...
Рейтинг: 0 / 0
27.05.2014, 11:42
    #38652974
iMerlin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подмена оконной процедуры - крах приложения
Все, всем спасибо, вопрос закрыт: упустил описание CALLBACK в оконных процедурах.
...
Рейтинг: 0 / 0
27.05.2014, 14:44
    #38653354
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подмена оконной процедуры - крах приложения
iMerlin,

Код: plaintext
1.
UserMsg=RegisterWindowMessage("4DBB78B9-0C23-412e-951A-2F1735567521_wm");



Регистрировать сообщение вовсе не обязательно. Это нужно ТОЛЬКО тогда, когда
сообщение посылается между окнами разных приложений. В таком случае регистрация
сообщения гарантирует, что идентификатор сообщения будет один и тот же в этих
приложениях.
...
Рейтинг: 0 / 0
27.05.2014, 14:52
    #38653370
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подмена оконной процедуры - крах приложения
iMerlin
Код: plaintext
1.
DWORD NewDialogProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)



Сигнатура этой функции должна быть такой:

LRESULT (CALLBACK* WNDPROC) (HWND, UINT, WPARAM, LPARAM);

DWORD и LRESULT не всегда одно и то же.
Про CALLBACK ты уже заметил.
...
Рейтинг: 0 / 0
28.05.2014, 20:07
    #38655008
iMerlin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подмена оконной процедуры - крах приложения
MasterZiviMerlin,

Регистрировать сообщение вовсе не обязательно. Это нужно ТОЛЬКО тогда, когда
сообщение посылается между окнами разных приложений. В таком случае регистрация
сообщения гарантирует, что идентификатор сообщения будет один и тот же в этих
приложениях.

Конечно. Внешняя программа и будет это сообщение отсылать - я указывал вначале, что основная задача управлять проектом с помощью внешней программы.

MasterZivDWORD и LRESULT не всегда одно и то же.


Хм... А мне казалось - одно и тоже, по крайней мере на 32-х битах. Ну да ладно, это я тоже поправил.
Сама передача сообщений работает на ура - я сделал маленький тестовый сервер MFC Dialog based, все отлично.
Но возникла другая проблема, сегодня весь день голову ломал:
При запуске этой лабуды в vba опять же крах.
Стал разбираться. При отладке видно, что SetWindowLong с параметром -4 (GWL_WNDPROC) возвращает не адрес оконной процедуры а какуюто белиберду, при попытке обращения к которой естественно идет исключение.
Поменял на +4 (DWL_DLGPROC), стал тестировать - что то странное. На тестовом сервере (который на обычном диалоге) отрабатывает так же как и с параметром -4. На диалоге vba опять грохается, но просмотр стека дает цепочку неидентифицируемых процедур.
В связи с этим два вопроса: кто нибудь имеет опыт подмены диалоговой процедуры в vba?
Объясните пожалуйста, как получилось, что при подмене адреса хоть GWL_WNDPROC, хоть DWL_DLGPROC для "нормального" диалогового окна все проходит правильно. Что, одна процедура вызывает другую что ли?

PS: технология подмены позаимствована из статьи http://www.vbnet.ru/articles/showarticle.aspx?id=76 , там вроде GWL_WNDPROC используется.
...
Рейтинг: 0 / 0
04.06.2014, 11:27
    #38661128
iMerlin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подмена оконной процедуры - крах приложения
Провел исследования: под Spy++ проверил hWnd главного окна - все в порядке, совпадает с тем что дает Application.hWndAccessApp

Беру GetClassName, GetWindowText - все правильно, все совпадает.

Делаю ?hex(GetWindowLong(Application.hWndAccessApp,-4)) - возвращает FFFF0161, spy++ показывает 0x300bb46a
Вот это и рушит все попытки сабклассинга. Почему возвращается ошибочное значение?6258
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / подмена оконной процедуры - крах приложения / 8 сообщений из 8, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]