Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.02.27;
Скачать: CL | DM;

Вниз

Реализация функций обратного вызова   Найти похожие ветки 

 
Piter ©   (2005-01-16 19:37) [0]

Вот пишу модуль для работы с RAS. Есть класс, инкапсулирующий RAS соединение.

Но вот незадача - никак не могу решить, что передавать при вызове RasDial.
Туда нужно передать или Handle окна или адрес Callback процедуры для обратной связи (чтобы Windows оповещала о ходе подключения). И как реализовать?

Каждому экземпляру класса создавать окно для связи? Но как указать главную процедуру окна? (не может быть методом класса)
Callback функцию указать тоже не могу - опять же метод класса нельзя указывать...

Пока придумал только одно решение - каждый экземпляр создает окно и с помощью SetWindowLong устанавливает значение GWL_USERDATA, которое является указателем на метод нужного класса.
Соответственно, есть какая-то универсальная процедура окна, которая извлекает GWL_USERDATA и вызывает метод по этому адресу.

Есть решения покрасивее?


 
Anatoly Podgoretsky ©   (2005-01-16 19:55) [1]

Кто тебя заставляет указывать метод класса, кепзывай как сказано процедуру.


 
Piter ©   (2005-01-16 20:21) [2]

Анатолий, но все таки вы наверное понимаете, что классов может быть хоть 1000, а процедура одна?


 
Anatoly Podgoretsky ©   (2005-01-16 20:25) [3]

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


 
Anatoly Podgoretsky ©   (2005-01-16 20:27) [4]

Посмотри на DataSource, он один может обслуживать любое голичество визуальных компонент.


 
Piter ©   (2005-01-16 20:29) [5]

Anatoly Podgoretsky ©   (16.01.05 20:25) [3]

Понятно...

То есть, вы предлагаете составить список, где можно будет определить соответствие handle и нужного объекта?


 
Anatoly Podgoretsky ©   (2005-01-16 20:40) [6]

Нет я не предлагаю, а говорю процедуры и классы могут нормально соществовать. А как решать тебе виднее, по твоей задаче.
Все АПИ оно не объектно ориентированое, а большинство программ как раз наоборот и это никак не мешает.
Взляни хоть на туже Indy, ICS, NM


 
Anatoly Podgoretsky ©   (2005-01-16 20:41) [7]

А вот класс, аналогичный DataSource, самое то по задаче и обходится без всяких списков.


 
Набережных С.   (2005-01-16 20:51) [8]

unit MakeInstance;

interface

uses
 Windows;

function MakeInstanceStdCall(Obj: TObject; MethodAddr: Pointer): Pointer;
procedure FreeInstanceStdCall(Inst: Pointer);

implementation

var
 FCS: TRTLCriticalSection;
 BlockList: PInstanceBlock = nil;

const
 Page_Size = 4096;

type
 PInstanceBlock = ^TInstanceBlock;
 TInstanceBlock = packed record
   Code:  array[0..31 - SizeOf(PInstanceBlock)] of Byte;
   Next:  PInstanceBlock;
 end;

 TBlockList = array[0..Page_Size div SizeOf(TInstanceBlock)] of TInstanceBlock;
 PBlockList = ^TBlockList;

procedure FreeInstanceStdCall(Inst: Pointer);
begin
 if Inst = nil then Exit;
 EnterCriticalSection(FCS);
 PInstanceBlock(Inst).Next:=BlockList;
 BlockList:=Inst;
 LeaveCriticalSection(FCS);
end;

function MakeInstanceStdCall(Obj: TObject; MethodAddr: Pointer): Pointer;
const
 CodeBlock: array [0..12] of Byte =
   (
    $58,             // POP EAX
    $68,             // PUSH DWORD_Const <= Obj
     0, 0, 0, 0,
    $50,             // PUSH EAX
    $68,             // PUSH DWORD_Const <= MethodAddr
     0, 0, 0, 0,
    $C3              // RET
    );

type
 PCodeBlock = ^TCodeBlock;
 TCodeBlock = packed record
   Code1:     Word;
   Self:      TObject;
   Code2:     Word;
   MtdAddr:   Pointer;
   Code3:     Byte;
 end;

var
 n: integer;
begin
 EnterCriticalSection(FCS);

 if BlockList = nil then
 begin
   BlockList:=VirtualAlloc(nil, Page_Size, MEM_COMMIT or MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
   for n:=0 to (Page_Size div SizeOf(TInstanceBlock)) - 2 do
     PBlockList(BlockList)[n].Next:=@PBlockList(BlockList)[n + 1];
   PBlockList(BlockList)[(Page_Size div SizeOf(TInstanceBlock)) - 1].Next:=nil;
 end;
 Result:=BlockList;
 BlockList:=BlockList.Next;

 LeaveCriticalSection(FCS);

 Move(CodeBlock, Result^, SizeOf(CodeBlock));
 with PCodeBlock(Result)^ do
 begin
   Self:=Obj;
   MtdAddr:=MethodAddr;
 end;
end;

procedure InitProc;
begin
 InitializeCriticalSection(FCS);
end;

procedure FinalProc;
begin
 DeleteCriticalSection(FCS);
end;

initialization
 InitProc;

finalization
 FinalProc;

end.


Метод должен быть объявлен как StdCall и иметь те же параметры, что и callback функция. Пример:

//Прототип: function(SomeParam1: TSome_Type1; SomeParam2: TSome_Type2): bool; stdcall;
TMyClass = class(...
private
 function MyCallBack(SomeParam1: TSome_Type1; SomeParam2: TSome_Type2): bool; stdcall;
end;
var
 MyObj: TMyClass;
 P: Pointer;
...
 P:=MakeInstanceStdCall(MyObj, @TMyClass.MyCallBack);

Полученный указатель передаешь как адрес Callback функции.


 
Piter ©   (2005-01-16 23:56) [9]

Какой-то хакерский код...


 
VMcL ©   (2005-01-17 07:59) [10]

>>Piter ©  (16.01.05 23:56) [9]

Не более хакерский, чем MakeObjectInstance() и иже с ним.

WBW.



Страницы: 1 вся ветка

Текущий архив: 2005.02.27;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.026 c
3-1106567792
denis24
2005-01-24 14:56
2005.02.27
Использование *.mdb по сети


4-1105956362
lutik_
2005-01-17 13:06
2005.02.27
Опять DLL


14-1107448391
DSKalugin
2005-02-03 19:33
2005.02.27
Из реального объявления. Вакансия


1-1107930530
vvv_spb
2005-02-09 09:28
2005.02.27
DBGrid.FieldCout


14-1107444139
iZEN
2005-02-03 18:22
2005.02.27
Редактор TXT/hex/etc.