Допустим, Вы хотите создать подкласс от экземпляра окна, порожденного другим процессом. Это, как Вы помните, позволит изменять поведение окна Все, что от Вас для этого требуется, — вызвать функцию SetWindowLongPtr, чтобы заменить адрес оконной процедуры в блоке памяти, принадлежащем окну, новым — указывающим на Вашу функцию WndProc. В документации Platform SDK утверждастся, что приложение
не может создать подкласс окна другого процесса Это не совсем верно Проблема создания подкласса окна из другого процесса па самом деле сводится к преодолению границ адресного пространства
Вызывая SetWindowLongPtr для создания подкласса окна (как показано ниже), Вы говорите системе, что все сообщения окну, на которое указывает hwnd, следует направлять не обычной оконной процедуре, а функции MySubclassProc
SetWindowLongPtr(hwnd, GWLP_WNDPROC, MySubclassProc);
Иными словами, когда системе надо передать сообщение процедуре WndProc указанного окна, она находит ее адрес и вызывает напрямую В нашем примере система видит, что с окном сопоставлен адрес функции MySubclassProc, и поэтому вызывает именно ее, а нс исходную оконную процедуру
Проблема с созданием подкласса окна, принадлежащего другому процессу, состоит в том, что процедура подкласса находится в чужом адресном пространстве Упрощенная схема приема сообщений оконной процедурой представлена па рис 22.1 Процесс А создает окно На адресное пространство этого процесса проецируется файл User32.dlI Эта проекция User32.dll О1вечает за прием и диспетчеризацию сообщений (синхронных и асинхронных), направляемых любому из окон, созданных потоками процесса А Обнаружив кякое-то сообщение, она определяет адрес процедуры WndProc окна и вызывает ее, передавая описатель окна, сообщение и параметры wParam и lParam Когда WndProc обработает сообщение, Uscr32 dll вернется в начало цикла и будет ждать следующее оконное сообщение
Рис. 22-1. Поток процесса В пытается создать подкласс окна, сформированного потоком процесса А
Теперь допустим, что процесс В хочет создать подкласс окна, порожденного одним из потоков процесса А Сначала код процесса В должен определить описатель этого окна, что можно сделать самыми рязными способами В примере на рис 22-1 поток процесса В просто вызывает FindWindow, затем — SetWtndowLongPtr, пытаясь изменить адрес процедуры WndProc окна Обратитевниманис пытаясь Этот вызов не дает ничего, кроме NULL Функция SetWindowLongPtr просто проверяет, не хочет