Re[10]: Я в шоке GetMessage()
От: Andrew S Россия http://alchemy-lab.com
Дата: 13.09.05 06:11
Оценка: +1 :)
V>Относительно статьи. Я, конечно, может и ошибаюсь, но она меня не совсем устраивает. Я писал конечно длл компоненты для 1с на си шарпе, но на другой фирме. А здесь это сделать нелегко. У нас около 30 филиалов разбросаных по Украине. и устанавливать на кждом по .NET Framework не сахар . Кроме того, есть калькуляторы, у которых установлено Вынь 98. А всего этих компьютеров насчитывается около 150 штук!

Нда, что делает с человеком занятие 1с. При чем тут Net? Там был показан способ создания Com сервера для 1c. С тем же успехом это можно сделать и на ATL.

V>Неужто придется выбирать вариант "удалять гланды через анус"?


V>Вот еще одна статья: http://www.codeguru.com/Cpp/W-P/system/keyboard/article.php/c5699/ . Вот только мне не виртся, что получив HANDLE окна я не могу достучаться до WM_CHAR этого окна и получить код символа. В вышописанной статье путь конечно супер гиморный. Может посоветуете билиотеки какие?


Все, что надо делать, я уже написал. Внимательно прочитайте написаное, ипользуйте поиск по форуму. Тема сабклассинга окна в чужом приложении тут обсуждалась, и даже были примеры кода. Но еще раз — на мой взгляд, хуки вам не нужны. Все, что нужно — написать inproc com сервер, который будет загружаться при открытии нужной вам формы. Вы же ведь можете при ее открытии выполнять скрипт?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[11]: Я в шоке GetMessage()
От: Votblin  
Дата: 13.09.05 06:45
Оценка:
Ну создам я очередную компоненту, что тогда делать то? Как перехватить?
Re[12]: Я в шоке GetMessage()
От: Andrew S Россия http://alchemy-lab.com
Дата: 13.09.05 06:48
Оценка:
V>Ну создам я очередную компоненту, что тогда делать то? Как перехватить?

Применить сабклассирование. Находите нужное окно, сабклассируете его, и в своей WNDPROC обрабатываете нужные сообщения.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[13]: Я в шоке GetMessage()
От: Votblin  
Дата: 13.09.05 06:49
Оценка:
Здравствуйте, Andrew S, Вы писали:

V>>Ну создам я очередную компоненту, что тогда делать то? Как перехватить?


AS>Применить сабклассирование. Находите нужное окно, сабклассируете его, и в своей WNDPROC обрабатываете нужные сообщения.


ОК, Andrew S. Спасибо. Вы супер. сейчас попробую. Эхх...
Re[11]: Я в шоке GetMessage()
От: Ovl Россия  
Дата: 13.09.05 07:43
Оценка:
Здравствуйте, Andrew S, Вы писали:

V>>Относительно статьи. Я, конечно, может и ошибаюсь, но она меня не совсем устраивает. Я писал конечно длл компоненты для 1с на си шарпе, но на другой фирме. А здесь это сделать нелегко. У нас около 30 филиалов разбросаных по Украине. и устанавливать на кждом по .NET Framework не сахар . Кроме того, есть калькуляторы, у которых установлено Вынь 98. А всего этих компьютеров насчитывается около 150 штук!


AS>Нда, что делает с человеком занятие 1с. При чем тут Net? Там был показан способ создания Com сервера для 1c. С тем же успехом это можно сделать и на ATL.


а com на 98-ой есть? или патчитить калькуляторы?
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re[10]: Я в шоке GetMessage()
От: Ovl Россия  
Дата: 13.09.05 07:54
Оценка:
Здравствуйте, Votblin, Вы писали:

V>И насколько я понял из описания необходимо создавать dll.


V>Неужто все так запущено?


да, dll. потому что она хорошо подходит для этой цели — её можно загрузить в процесс, и она содержит только функции
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re[12]: Я в шоке GetMessage()
От: Andrew S Россия http://alchemy-lab.com
Дата: 13.09.05 07:56
Оценка:
AS>>Нда, что делает с человеком занятие 1с. При чем тут Net? Там был показан способ создания Com сервера для 1c. С тем же успехом это можно сделать и на ATL.

Ovl>а com на 98-ой есть? или патчитить калькуляторы?


Странный вопрос. Com есть на 95-х. 1с же активно использует ActiveX\Com объекты, насколько я помню по своему давнему опыту общения с этим сабпродуктом.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[10]: Я в шоке GetMessage()
От: Ovl Россия  
Дата: 13.09.05 08:48
Оценка: 3 (1) +1
Здравствуйте, Votblin, Вы писали:

V>Спасибо за ответ. Но чтот я и та ки сяк пытался поюзать этот хук. Ничего не выходит.


V>МОжет подскажете все таки?


посмотрел я посты — действительно, хук + сабклассинг более верно.
делается это примерно так.

нам потребуется dll c двумя процедурами. одна из них будет хук-процедурой, вторая — новой оконной процедурой.
то есть интерфейс такой


// hookDll.h

// экспортируется из длл
void DLL_EXPORT SetHook( HMODULE currentModule );
void DLL_EXPORT ClearHook( HMODULE currentModule );
LRESULT CALLBACK DLL_EXPORT CBTProc(int nCode, WPARAM wParam, LPARAM lParam);


про тело можно позже поговорить.
можно поставить так ( это уже исходник приложения, то есть exe-шника)

// appUsingHook.cpp

typedef void ( *STARTHOOKPROC )();

void ApplicationSetHook() {
    HMODULE dll = LoadLibrary("hookDll.dll");
    if ( dll != INVALID_HANDLE_VALUE ) {
        STARTHOOKPROC proc = (STARTHOOKPROC) GetProcAddress( dll, "SetHook" );
        if ( proc != NULL ) {
            proc( dll );
        }
        FreeLibrary( dll );
    }
}    

void ApplicationClearHook() {
    HMODULE dll = LoadLibrary("hookDll.dll");
    if ( dll != INVALID_HANDLE_VALUE ) {
        STARTHOOKPROC proc = (STARTHOOKPROC) GetProcAddress( dll, "ClearHook" );
        if ( proc != NULL ) {
            proc( dll );
        }
        FreeLibrary( dll );
    }
}


здесь удобно, что все функции, выставляющие хук находятся внутри самой dll, и таким образом получают премущество в виде shared memory section. образно говоря, внутри dll можно сделать память, которая будет общей для этой dll, даже если она была загружена в другой процесс.

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


//hookDll.cpp
HHOOK hook;

WNDPROC oldProc = NULL;
void SubclassWindow( HWND hwnd );
LRESULT CALLBACK NewWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);


void DLL_EXPORT SetHook( HMODULE currentModule ) {
    hook = SetWindowsHookEx( WH_CBT, CBTProc, currentModule, 0 );
}

void DLL_EXPORT ClearHook() {
    UnhookWindowsHookEx( hook );
}

LRESULT CALLBACK DLL_EXPORT CBTProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if ( nCode < 0 )
        return CallNextHookEx( hook, nCode, wParam, lParam );
    
    switch ( nCode ) {
        case HCBT_CREATEWND: {
            if ( lp->lpszClass != 0 && stricmp(lp->lpszClass, "WindowClassName") == 0 ) {
                SubсlassWindow( (HWND) wParam );
            }
            break; }
    }
    return CallNextHookEx( hook, nCode, wParam, lParam ); }
}

void SubclassWindow( HWND hwnd ) {
    if ( oldProc == NULL ) {
        oldProc = SetClassLongPtr( hwnd, GCLP_WNDPROC, NewWndProc );
    }
}

LRESULT CALLBACK NewWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch ( msg ) {
        case WM_KEYDOWN {
            ::MessageBox( hwnd, "You pressed key", "KEY", MB_OK );
        }
    }
    return oldProc( hwnd, msg, wParam, lParam );
}


момент — CallNextHookEx() получает хендл хука, который был установлен. а если я устанавливаю его в одном процессе, например, в своем, а он потом вызывается другой, например из калькулятора:
1) в адресное пространство калькулятора загружается hookDll.dll
2) там ищется функция CBTProc
3) вызывается оная.

и внутри неё нам нужно вызвать следующий хук ( они там в очереди все стоят ). но SetWindowsHookEx я вызывал в другом процессе, значит и хендл хука в другом процессе. вот тут-то и пригодятся shared memory section. они позволяют сказать линкеру, что вот эта область память будет доступна для всех длл, неважно где и когда они загрузились.
конкретно, в эту область нам надо поместить HHOOK hook. в результате получается


//hookDll.cpp
#pragma data_seg( .shared ) 
HHOOK hook = NULL;
#pragma data_seg() 
#pragma comment(linker, /section:.shared,RWS )

WNDPROC oldProc = NULL;
void SubclassWindow( HWND hwnd );
LRESULT CALLBACK NewWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);



зы.. все это, неоднократно обсуждалось на форуме
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re[13]: Я в шоке GetMessage()
От: Ovl Россия  
Дата: 13.09.05 08:54
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>>>Нда, что делает с человеком занятие 1с. При чем тут Net? Там был показан способ создания Com сервера для 1c. С тем же успехом это можно сделать и на ATL.


Ovl>>а com на 98-ой есть? или патчитить калькуляторы?


AS>Странный вопрос. Com есть на 95-х. 1с же активно использует ActiveX\Com объекты, насколько я помню по своему давнему опыту общения с этим сабпродуктом.


вопрос не странный. просто я не знаю когда именно появился ком, не думал, что это было до появления 98.
однако в msdn:


HRESULT CoInitialize(
LPVOID pvReserved
);


Windows NT/2000/XP: Requires Windows NT 3.1 or later.

Windows 95/98: Requires Windows 95 or later.

Header: Declared in objbase.h.

Library: Use ole32.lib.


а вот насчет activeX — интуиция мне подсказывает, что наличие activeX коррелирует с наличием IE4.0
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re[14]: Я в шоке GetMessage()
От: Andrew S Россия http://alchemy-lab.com
Дата: 13.09.05 08:58
Оценка:
Ovl>а вот насчет activeX — интуиция мне подсказывает, что наличие activeX коррелирует с наличием IE4.0

Интуиция вас обманывает. Для начала неплохо разобраться, что такое ActiveX
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[11]: Я в шоке GetMessage()
От: Ovl Россия  
Дата: 13.09.05 08:59
Оценка:
поправка

// appUsingHook.cpp

typedef void ( *STARTHOOKPROC )( HMODULE );

void ApplicationSetHook() {

...
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re[11]: Я в шоке GetMessage()
От: Andrew S Россия http://alchemy-lab.com
Дата: 13.09.05 09:00
Оценка:
Ovl>посмотрел я посты — действительно, хук + сабклассинг более верно.

Я думаю, не нужен там хук. 1c позволяет писать под себя плагины.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[12]: Я в шоке GetMessage()
От: Ovl Россия  
Дата: 13.09.05 09:03
Оценка:
Здравствуйте, Andrew S, Вы писали:

Ovl>>посмотрел я посты — действительно, хук + сабклассинг более верно.


AS>Я думаю, не нужен там хук. 1c позволяет писать под себя плагины.


тем проще. однако я из кода не видно, что написание хука труднее.

в любом случае — это один из альтернативных вариантов. не пригодится ему — пригодится другому..
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re[15]: Я в шоке GetMessage()
От: Ovl Россия  
Дата: 13.09.05 09:04
Оценка:
Здравствуйте, Andrew S, Вы писали:

Ovl>>а вот насчет activeX — интуиция мне подсказывает, что наличие activeX коррелирует с наличием IE4.0


AS>Интуиция вас обманывает. Для начала неплохо разобраться, что такое ActiveX


да, неплохо бы...

хотя мне бы программировать научится — и то удачно
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re[11]: Я в шоке GetMessage()
От: Votblin  
Дата: 13.09.05 10:29
Оценка:
Супер! Ovl, Спасибо за науку. Не забуду мать родную! оченб поучительно.
Re[11]: Я в шоке GetMessage()
От: Votblin  
Дата: 13.09.05 11:12
Оценка:
А что это за зверь такой DLL_EXPORT ? Где обитает?
Re[12]: Я в шоке GetMessage()
От: Ovl Россия  
Дата: 13.09.05 11:20
Оценка:
Здравствуйте, Votblin, Вы писали:

V>А что это за зверь такой DLL_EXPORT ? Где обитает?



#define DLL_EXPORT __declspec( dllexport )


и ещё нуно добавить в проект файл hookDll.def

LIBRARY HOOKDLL.DLL
EXPORTS
SetHook @1
ClearHook @2
CBTProc @3


проверить правильность dll можно с помощью утилитки depends.
она должна показать, что из dll экспортируется три функции с этими именами
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re[13]: Я в шоке GetMessage()
От: Votblin  
Дата: 13.09.05 11:23
Оценка:
ОК, а как родить lp ?

в

if ( lp->lpszClass != 0 && stricmp(lp->lpszClass, "WindowClassName") == 0 )
Re[14]: Я в шоке GetMessage()
От: Ovl Россия  
Дата: 13.09.05 11:26
Оценка:
Здравствуйте, Votblin, Вы писали:

V>ОК, а как родить lp ?


V>в


V> if ( lp->lpszClass != 0 && stricmp(lp->lpszClass, "WindowClassName") == 0 )


забыл
        case HCBT_CREATEWND: {
            LPCREATESTRUCT lp = (LPCREATESTRUCT) lParam;
            if ( lp->lpszClass != 0 && stricmp(lp->lpszClass, "WindowClassName") == 0 ) {


и соответственно вместо "WindowClassName" будет имя класса окна, поведение которого ты хочешь изменить
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re[15]: Я в шоке GetMessage()
От: Votblin  
Дата: 13.09.05 11:34
Оценка:
Все конечно здорово, вот только не понятно что находится в

SubсlassWindow( (HWND) wParam );

Наверно у Вас эта длл магическим образом скомпилировалась...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.