Форум: "Основная";
Текущий архив: 2004.02.10;
Скачать: [xml.tar.bz2];
ВнизCallback для метода класса. Реально? Найти похожие ветки
← →
dmk (2004-02-01 17:04) [0]Поискал информацию по конференциям на эту тему.
Кто-то говорит можно, кто-то говорит нельзя.
Встречал "хакерские" способы, но они исключительно
для Си. Для Delphi все говорят - невозможно!
Это действительно так?
← →
Юрий Федоров (2004-02-01 17:07) [1]глупости
все реально
← →
Saracin (2004-02-01 17:15) [2]Как ты думаешь что такое Event ??? :)
и кто его вызывает :)
Дело в том что работа любой колбек функции это просто вызов функции по указателю, ранее передоному обекту.
например obj1 и obj2. Семантика такая: Когда obj1 закончить заниматься фитгней пни obj2 вызвав его функцию pni_menia;
Реализация:
type
TCallBackFunction = function (I: Integer): Integer;
TObj1 = class
public
FCallBack: TCallBackFunction;
procedure do_fignu;
end
TObj2 = class
function pni_menia(I: Integer):Integer;
end;
procedure TObj1.do_fignu;
begin
...
FCallBack(10);
end;
begin
...
obj1.FcallBack := obj2.pni_menia;
obj1.do_fignu;
end.
Примерно так, Делфи не стоит 100% правельность проверить не могу, но суть такая :)
С Уважением Saracin.
← →
Vuk (2004-02-01 17:33) [3]to dmk:
Все зависит от того, что Вы имеете в виду под callback. Если просто event, то это, я думаю особых проблем не вызывает. Если же имеется в виду передача метода в качестве функции обратного вызова для WinAPI, то здесь не так все просто - для методов объектов важен не только адрес кода, но и адрес экземпляра. К тому же первым параметром метода всегда передается указатель на экземпляр (для методов класса - сслка на класс). То есть если функуия обратного вызова не поддерживает передачу дополнительных параметров, предоставляемых приложением, напрямую передавать адрес метода для этих целей не стоит.
Но путь решения проблемы есть и этот путь используется в VCL. Если внимательно присмотреться к модулю Classes, то можно обнаружить там методы MakeObjectInstance и FreeObjectInstance. Они используются как раз для того, чтобы позволить методу WndProc работать в качестве оконной процедуры (типичный callback). Работа функции MakeObjectInstance заключается в том, что она выделяет небольшой блок памяти и пишет туда код, который при выполнении обеспечивает вызов метода WndProc конкретного экземпляра. При этом адрес экземпляра пишется непосредственно в этот блок памяти. Результатом работы функции является адрес этого блока памяти. Он же и служит адресом, который теперь может использоваться в качестве адреса функции обратного вызова.
to Saracin:
>TCallBackFunction = function (I: Integer): Integer;
Надо бы of object дописать...
← →
dmk (2004-02-01 17:38) [4]2 Saracin © (01.02.04 17:15) [2]
Как раз такая конструкция и не работает на Delphi.
Объявляю
Type TEnumProc = Function(Wnd:HWND; Data:Pointer): bool of object;
в классе EnumProc: TEnumProc;
В итоге результат я присвоить не могу.
Вот сама функция
Function TImageForm.FEnumProc:TEnumProc;
var
WinStyle,
ExStyle : Cardinal;
PStruct: TRepaintStruct;
Function AcceptStyle(WindowStyle, ExWindowStyle:Cardinal): boolean;
var
r1, r2, r3: boolean;
begin
r1 := ((ExWindowStyle and WS_EX_TOPMOST) <> 0) and
((ExWindowStyle and WS_EX_TOOLWINDOW) <> 0) and
((WindowStyle and WS_VISIBLE) <> 0);
r2 := ((ExWindowStyle and WS_EX_TOPMOST) <> 0) and
((WindowStyle and WS_VISIBLE) <> 0);
r3 := ((ExWindowStyle and WS_EX_TOOLWINDOW) <> 0) and
((WindowStyle and WS_VISIBLE) <> 0);
Result := r1 or r2 or r3;
end;
begin
Result := True;
PStruct := TRepaintStruct(Data^);
WinStyle := GetWindowLong(WindowHandle, GWL_STYLE);
ExStyle := GetWindowLong(WindowHandle, GWL_EXSTYLE);
If AcceptStyle(WinStyle, ExStyle) then
begin
With PStruct do
Self.RepaintTopFormIntersect(iX, iY, iPrevX, iPrevY, dX, dY, WindowHandle);
end;
end;
← →
vuk (2004-02-01 17:42) [5]to dmk:
Где Вы пытаетесь использовать эту процедуру как callback?
← →
dmk (2004-02-01 17:44) [6]2 Vuk
Под callback я понимаю stdcall.
Мне надо просто перечислить окна.
EnumWindows(@EnumProc, Integer(@FRepaintStruct));
Я конечно передавал данные через второй параметр,
но в связи с некоторыми особенностями класса
это неправильно, данные передаются устаревшие.
В случае с методом класса все будет Ок.
← →
vuk (2004-02-01 17:52) [7]to dmk:
В этом случае можно поступить проще. Этот callback позволяет передавать дополнительные параметры, и поэтому нужно только вручную написать функцию-переходник примерно такого вида:
function EnumWindowsCallback(Wnd: HWnd; Data: Pointer): boolean;
begin
if Data <> nil then
Result := TSomeClass(Data).SomeMethod(...)
else
Result := ...;
end;
Теперь можно вызывать EnumWindows:
EnumWindows(@EnumWindowsCallback, SomeClassInstance);
← →
vuk (2004-02-01 17:53) [8]>EnumWindows(@EnumWindowsCallback, SomeClassInstance);
естественно
integer(SomeClassInstance)
← →
Anatoly Podgoretsky (2004-02-01 17:56) [9]Type
Вот это ты напрасно придумал
TEnumProc = Function(Wnd:HWND; Data:Pointer): bool of object;
← →
Saracin (2004-02-01 17:58) [10]to vuk
со всем согласен :) заставили меня даже Delphi поставить. :)
to dmk
если добавить of object; то все работает , теперь проверил :)
← →
dmk (2004-02-01 17:59) [11]Да. Я так и делал до этого.
Все работает относительно "нормально", но дело в том, что мой класс использует еще один класс TTread. И в момент перечисления окон, экземпляр класса может сменится и тогда данные от другого экземпляра попадают в только что активизировавшийся.
Поэтому я и хотел, чтобы у каждого экземпляра был свой stdcall.
Придется наверно логику работы менять.
← →
dmk (2004-02-01 18:00) [12]2 Anatoly Podgoretsky © (01.02.04 17:56) [9]
Я и без него пробовал. Компилятору не нравится.
← →
Юрий Зотов (2004-02-01 18:08) [13]> dmk © (01.02.04 17:44) [6]
> Под callback я понимаю stdcall.
Что совершенно неверно. Stdcall - это просто одно из соглашений о вызове и к термину Callback не имеет никакого отношения.
> Мне надо просто перечислить окна.
> EnumWindows(@EnumProc, Integer(@FRepaintStruct));
При вызове метода класса ему, помимо явно перечисленных в его объявлении параметров, передается еще один параметр - тот самый Self. А при вызове обычной процедуры/функции никаких дополнительных параметров, конечно же, не передается - вот чем она отличается от методов класса.
Естественно, EnumWindows ни о каких там классах не имеет ни малейшего понятия и поэтому будет вызывать EnumProc, как обычную функцию. Значит EnumProc и должна быть именно обычной функцией (причем как раз с stdcall) - а вот внутри нее Вы уже можете вызывать что угодно. Например, вместо RepaintStruct передавайте ссылку на экземпляр Вашего класса и по ней (приведя тип к нужному) вызывайте любой его метод.
← →
dmk (2004-02-01 18:14) [14]>Что совершенно неверно. Stdcall - это просто одно из соглашений
>о вызове и к термину Callback не имеет никакого отношения.
Это я в Си конференциях подхватил. Там наверное тоже на понимают этого термина как и я. Кстати, что это за термин?
← →
default (2004-02-01 18:27) [15]ф-ции обратного вызова, те которые вызывает ОС
← →
Anatoly Podgoretsky (2004-02-01 18:27) [16]Callback в терминологии Дельфи, это процедурная переменная, все события класса являются Callback функция, которые вызываются через переменную, естественно ее можно передавать в любую функцию как параметр. Для виндоус Callback функции не могут быть классами, любого языка программирования.
← →
Юрий Зотов (2004-02-01 18:33) [17]> dmk © (01.02.04 18:14) [14]
Соглашения о вызове - это правила, устанавливающие способ передачи параметров (через регистры, через стек, комбинированный), порядок следования параметров в стеке (первый вверху или последний вверху) и то, на чьей стороне (вызывающей или вызываемой) должно восстанавливаться состояние стека после завершения работы вызванной функции. По этому поводу см. Calling conventions в справке Delphi - там все расписано подробно.
Callback - это термин, означающий, что при вызове какой-то функции (в Вашем случае - EnumWindows) ей передается адрес так называемой функции обратного вызова (callback-функции - в Вашем случае ею является EnumProc). "Обратный вызов" (callback) здесь означает всего лишь то, что Вы вызываете БИБЛИОТЕЧНУЮ функцию, а она при своей работе снова вызывает ВАШУ функцию, как бы совершая при этом "возврат" в Ваш код.
Таким образом, термины callback и stdcall не связаны друг с другом совершенно никак. Может быть и callback без stdcall, может быть и stdcall без всяких callback"ов.
← →
Daniel (2004-02-02 00:54) [18]TCallbackFunction = function: Integer of object
YourFunc: TCallbackFunction;
А нельзя ли просто:
FunctionThatRequireCallBack(TMethod(YourFunc).Code); ??
← →
dmk (2004-02-02 01:33) [19]2 Daniel (02.02.04 00:54) [18]
Не получится.
Invalid type cast.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.02.10;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.008 c