vserd
Silver Member | Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Вот код на Delphi. Я думаю что в Билдере тоже сработает. У меня он работает именно с потоками. unit FunctionWrapper; interface {Обработка обратных вызовов OC Windows методами классов.} {http://mazurkin.virtualave.net/papers/11callback/} {Можно использовать при создании потоков, таймеров, окон и др. случаях. !!! Метод или функция должны быть объявлены как StdCall, иначе не будет работать. !!! } function CreateFunctionWrapper(Obj: TObject; Method: Pointer): Pointer; procedure DeleteFunctionWrapper(Wrapper: Pointer); {пример использования: type TMyClass = class Private FWindows : TStringList; FHandler : Pointer; function EnumWindowsCallback(Wnd: THandle; Param: Cardinal): LongBool; StdCall; public procedure Refresh; constructor Create; Destructor Destroy; override; end; constructor TMyClass.Create begin ...... // Создаем wrapper для метода обратного вызова FHandler := CreateFunctionWrapper(Self, @TMyClass.EnumWindowsCallback); ..... end; Destructor TMyClass.Destroy; begin ..... DeleteFunctionWrapper(FHandler); .... end; function TMyClass.EnumWindowsCallback(Wnd: THandle; Param: Cardinal): LongBool; var WindowName : array [0..1023] of Char; begin // Получаем имя окна GetWindowText(Wnd, @WindowName[0], SizeOf(WindowName)); // Добавляем имя окна в коллекцию if WindowName <> '' then FWindows.Add(WindowName); // Продолжаем перечисление Result := True; end; procedure TMyClass.Refresh; begin // Очистка контейнера FWindows.Clear; // Перечисляем окна EnumWindows(FHandler, 0); // Сортируем названия FWindows.Sort; end; } {Функция обратного вызова, оформленная в виде метода класса имеет полный доступ ко всем членам класса. При этом второй параметр функции не задействован и мы можем использовать его для своих нужд} implementation uses Windows; function CreateFunctionWrapper(Obj: TObject; Method: Pointer): Pointer; begin // Allocate the callback block Result := VirtualAlloc(nil, 128, MEM_RESERVE OR MEM_COMMIT, PAGE_EXECUTE_READWRITE); // Check allocated block Assert(Result <> nil, '{9FA7DAE8-0FA4-4223-8230-8CA14DAAF451}'); // Compose the callback block asm mov EAX, Obj mov ECX, Result mov word ptr [ECX+0], $6858 // pop EAX mov dword ptr [ECX+2], EAX // push _Self_ mov word ptr [ECX+6], $E950 // push EAX mov EAX, Method sub EAX, ECX sub EAX, 12 mov dword ptr [ECX+8], EAX // jmp Object.Method end; end; //////////////////////////////////////////////////////////////////////////////// // Delete the wrapper //////////////////////////////////////////////////////////////////////////////// procedure DeleteFunctionWrapper(Wrapper: Pointer); begin VirtualFree(Wrapper, 0, MEM_RELEASE); end; end. |