передо мной стоит такая задача. сделать невозможным закрытие/сворачивание/максимизирование любого окна из управляемого кода.
Системное меню окон я поборол ровно как и Alt+F4. Получилось задисэйблить кнопку "Х", но не мин/макс. с мин/макс у меня проблемы. Я решил сделать так, чтоб когда пользователь нажимает на эти кнопки ничего не происходило. Для этого я хочу использовать функцию SetWindowLong с параметром GWL_WNDPROC. Как сказано в мсдне эта функция в комбинации с этим аргументом:
Sets a new address for the window procedure.
Т.е. я устанавливаю новый адрес процедуры окна и в новой процедуре проверяю пришедшее сообщение — если оно не мин и не макс вызываем старую процедуру, а если мин или макс — ничего не делаем.
Данный код пытается заменить оконную функцию блокнота. Но ничего не происходит. Если попытаться заменить оконную процедуру текущего процесса — все работает как надо.
Я так понимаю, нужно подключиться к чужому процессу и в нем менять оконную функцию.
Для этого нужно (поправьте меня если я в чем-то не прав):
1. Выделить память в чужом процессе для моей функции, которая будет заменять оконную функцию.
2. скопировать ее в это пространство.
3. создать удаленный поток (CreateRemoteThread) указав ему адрес этой же функции.
Если так, то у меня еще несколько вопросов:
а) как должна выглядеть функция, которую я собираюсь копировать в чужой процесс (которая будет менять оконную функцию)? я так понимаю, она не может быть написана на с#?
б) скопировать в чужой процесс придется не только эту функцию, но также и новую оконную функцию?
Re: SetWindowLong GWL_WNDPROC для другого процесса
Здравствуйте, VisitorS, Вы писали:
VS>Добрый день,
VS>передо мной стоит такая задача. сделать невозможным закрытие/сворачивание/максимизирование любого окна из управляемого кода.
MSDN:
Calling SetWindowLongPtr with the GWLP_WNDPROC index creates a subclass of the window class used to create the window. An application can subclass a system class, but should not subclass a window class created by another process.
Здравствуйте, VisitorS, Вы писали:
d.4>>Стать частью любого другого процесса Вам помогут хуки. Почитайте тут: http://www.rsdn.ru/summary/292.xml
VS>Мои попытки установить хук на WH_CALLWNDPROC блокнота были обречены на провал. Что я делаю не так?
VS>
VS>Хук устанавливается нормально, но, как только приходит сообщение, блокнот (в данном примере) сразу сообщает о внутренней ошибке.
мне кажется проблема в том, что адрес, который передается в SetWindowsHookEx актуален только в твоем процессе. поэтому когда хук возбуждается, тебя забрасывает на хрен-знает-какое-место-где-никого-нет.
решение, которое мне видится — загрузить DLL в адресное пространство процесса notepad-а и сделать так, чтобы она установила хук в контексте этого процесса [первая мысль, может не правильная, создать именованный memory-mapping file, положить туда координаты процесса за которым нужно смотреть и ждать загрузки в него, оценивая обстановку в DLL_PROCESS_ATTACH]
p.s. просто мысли вслух, ногами не бить
Re[6]: SetWindowLong GWL_WNDPROC для другого процесса
Здравствуйте, StDenis, Вы писали:
SD>мне кажется проблема в том, что адрес, который передается в SetWindowsHookEx актуален только в твоем процессе. поэтому когда хук возбуждается, тебя забрасывает на хрен-знает-какое-место-где-никого-нет.
Да, так и есть. В коде, который я написал выше, используется GetModuleHandle(NULL) — эта функция возвращает hinstance моего C#-exeшника. Для того, чтоб получить hinstance моей длл — UnmanagedHooks.dll — нужно GetModuleHandle(NULL) заменить на GetModuleHandle("UnmanagedHooks.dll").
Взвращаемся к теме поста. оконная функуия меняется без проблем, но только когда приходит определенное сообщение (например WH_MOUSE). Да и не хотелось бы, чтоб на сообщение WH_MOUSE висел постоянно дополнительный hookproc. нужно сделать что-то вроде такого:
т.е. чтоб ChangeWndProc исполнилась только один раз. Хук устанавливается без ошибок. PostMessage помещает сообщение в очередь (проверил на примере других сообщений с очевидным результатом их обработки). Но не вызывается ChangeWndProc. Такая же история и с PostThreadMessage.
"Вручную" (когда мышь над процессом threadId) все работает как надо. Вручную, это когда вызывается только этот код, а PostMessage вы делаете сами с помощью мыши: