Конференция "WinAPI" » Перехват сообщений самодельным окном. [D7, WinXP]
 
  • Сергей М. © (19.02.08 10:01) [20]

    > Galiaf   (19.02.08 01:26) [19]


    Ключевой момент во всей этой бодяге, что ты затеял, - ф-ция MakeObjectInstance().
  • Galiaf © (19.02.08 10:42) [21]

    > Сергей М. ©   (19.02.08 10:01) [20]

    Щас копну в этом направлении, хотя как приспособить его у меня пока не знаю
  • Galiaf © (19.02.08 10:54) [22]
    function MakeObjectInstance(Method: TWndMethod): Pointer;

    - кучка непонятного кода, буду разбираться...
  • Galiaf © (19.02.08 11:22) [23]
    Полностью переписал процедуру CreateHandle, все равно не форма не хочет перехватывать сообщения. Не исключаю тот вариант, что я сделал это неправильно.
  • Сергей М. © (19.02.08 11:24) [24]

    > Не исключаю тот вариант, что я сделал это неправильно


    Как ни странно, я тоже не исключаю)
  • Galiaf © (19.02.08 11:40) [25]
    без посторонней помощи не разберусь, тупо переписывая CreateHandle, только больше запутываюсь, нужно теперь все удалять и попытаться вставить только нужное в свой код, потому что переписывание результатов не дало.
    Кто-нибудь сталкивался с такой задачей или вместе со мной на догадках строите свои предложения?
  • Сергей М. © (19.02.08 12:57) [26]
    Скопируй этот код к себе в проект:


    const
     InstanceCount = 313;

    { Object instance management }

    type
     PObjectInstance = ^TObjectInstance;
     TObjectInstance = packed record
       Code: Byte;
       Offset: Integer;
       case Integer of
         0: (Next: PObjectInstance);
         1: (Method: TWndMethod);
     end;

    type
     PInstanceBlock = ^TInstanceBlock;
     TInstanceBlock = packed record
       Next: PInstanceBlock;
       Code: array[1..2] of Byte;
       WndProcPtr: Pointer;
       Instances: array[0..InstanceCount] of TObjectInstance;
     end;

    var
     InstBlockList: PInstanceBlock;
     InstFreeList: PObjectInstance;

    { Standard window procedure }
    { In    ECX = Address of method pointer }
    { Out   EAX = Result }

    function StdWndProc(Window: HWND; Message, WParam: Longint;
     LParam: Longint): Longint; stdcall; assembler;
    asm
           XOR     EAX,EAX
           PUSH    EAX
           PUSH    LParam
           PUSH    WParam
           PUSH    Message
           MOV     EDX,ESP
           MOV     EAX,[ECX].Longint[4]
           CALL    [ECX].Pointer
           ADD     ESP,12
           POP     EAX
    end;

    { Allocate an object instance }

    function CalcJmpOffset(Src, Dest: Pointer): Longint;
    begin
     Result := Longint(Dest) - (Longint(Src) + 5);
    end;

    function MakeObjectInstance(Method: TWndMethod): Pointer;
    const
     BlockCode: array[1..2] of Byte = (
       $59,       { POP ECX }
       $E9);      { JMP StdWndProc }
     PageSize = 4096;
    var
     Block: PInstanceBlock;
     Instance: PObjectInstance;
    begin
     if InstFreeList = nil then
     begin
       Block := VirtualAlloc(nil, PageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
       Block^.Next := InstBlockList;
       Move(BlockCode, Block^.Code, SizeOf(BlockCode));
       Block^.WndProcPtr := Pointer(CalcJmpOffset(@Block^.Code[2], @StdWndProc));
       Instance := @Block^.Instances;
       repeat
         Instance^.Code := $E8;  { CALL NEAR PTR Offset }
         Instance^.Offset := CalcJmpOffset(Instance, @Block^.Code);
         Instance^.Next := InstFreeList;
         InstFreeList := Instance;
         Inc(Longint(Instance), SizeOf(TObjectInstance));
       until Longint(Instance) - Longint(Block) >= SizeOf(TInstanceBlock);
       InstBlockList := Block;
     end;
     Result := InstFreeList;
     Instance := InstFreeList;
     InstFreeList := Instance^.Next;
     Instance^.Method := Method;
    end;

    { Free an object instance }

    procedure FreeObjectInstance(ObjectInstance: Pointer);
    begin
     if ObjectInstance <> nil then
     begin
       PObjectInstance(ObjectInstance)^.Next := InstFreeList;
       InstFreeList := ObjectInstance;
     end;
    end;


    ..

    Теперь смотри внимательно, как этот код используется:


    TFrm = class(..)
    ..
     hWnd: THandle;
     FDefWndProc: Pointer;
    ..
     procedure DefaultHandler(var Message); override; //!!!!
    ..
     procedure WndProc(var Message: TMessage);
    ..
     function CreateWnd: boolean;
     function DestroyWnd: boolean;
    ..
    end;

    function TFrm.CreateWnd: boolean;
    begin
    ..
     hWnd:=CreateWindowEx(..);
     ..
     SetWindowLong(Result, GWL_WNDPROC, Longint(MakeObjectInstance(WndProc)));
    ..
    end;

    function TFrm.DestroyWnd: boolean;
    var
     Instance: Pointer;
    begin
    ..
     Instance := Pointer(GetWindowLong(Wnd, GWL_WNDPROC));
     DestroyWindow(Wnd);
     if Instance <> @DefWindowProc then FreeObjectInstance(Instance);
    ..
    end;

    procedure TFrm.WndProc(var Message: TMessage);
    begin
     with Message do
       case Msg of
    ...
       else
          Dispatch(Msg);
       end
    end;

    procedure TFrm.DefaultHandler(var Message);
    begin
     with TMessage(Message) do begin
    ..
       Result := CallWindowProc(@WndProc, FHandle, Msg, WParam, LParam);
    ..
     end;
    end;

  • Galiaf (19.02.08 15:53) [27]
    Благодарю. До завтра компьютера мне не видеть, а по этому буду изучать вышеизложенный код на экране мобильного телефона.
    А откуда этот код взят? Личные наработки, взятый откуда-то или только что собранный?
  • Сергей М. © (19.02.08 15:58) [28]

    > откуда этот код взят?


    Тот что до "смотри внимательно" - из classes.pas, один в один.

    Тот что ниже - "только что собранный", считай что это "экстракт" из кучи VCL-кода, который ты не понимаешь, но от которой ты желаешь избавиться.
  • dsoft © (19.02.08 23:31) [29]

    > Galiaf   (19.02.08 01:26) [19]
    > С этого места по-подробнее


    Ну объясни, на кой этот огород. Что из этого должно получится? Пытаешься создать свой велосипед (VCL)? Ну для начала посмотри хотя бы не исходники, которые тебе предлагают мазохисты, а "С"-шные. Перевести их на Pascal небольшой труд, но зато поймешь стратегию написания программ на API. Но если же упрямо будешь городить то, что здесь предлагаешь, то очень скоро твои программы перестанут быть "маленькими".
  • Galiaf (20.02.08 00:21) [30]
    И чем же исходники "мазахистов" хуже исходников на сях? Если я пишу на API в первую очередь для того, чтобы столкнуться со сложностями и преодалив их положить что-либо в свою копилку опыта, то почему бы не перелопатить тот же VCL?
  • Galiaf (20.02.08 00:33) [31]
    А про стратегию написания программ на API хотелось бы почитать по-подробнее
  • dsoft © (20.02.08 00:51) [32]
    А какой смысл городить всю эту конструкция классов? Можно и проще и быстрее.
  • dsoft © (20.02.08 00:54) [33]
    Ну уж, если так сильно прижало, воспользуйтесь библиотекой KOL.
  • Galiaf (20.02.08 11:46) [34]
    Пользовался - не интересно.
    Как можно сделать проще и быстрее?
  • Galiaf © (20.02.08 13:52) [35]

    > Сергей М. ©   (19.02.08 12:57) [26]

    Огромное спасибо! Все работает, теперь моя форма умеет рисовать кружок, при этом весит 17 920 kb, понял не все по этому мне еще предстоит по сидеть, по изучать вышеприведенный код. Есть там пару ошибок но незначительные (путанница с именами переменных).
    Буду рад если мне объяснят что такое и для чего используется Instance и что за hInstance, читал про это в книгах, хэлпах но от человека нормального объяснения не слышал, по этому могу только думать о нем только как о каком-то описателе приложения, который зачем-то нужен.
  • Сергей М. © (20.02.08 16:33) [36]

    > что такое и для чего используется Instance и что за hInstance


    Instance - в общем случае экземпляр чего-либо.

    Префикс h обычно означает handle.

    Означает и используется по-разному, в зависимости от тек.контекста.
  • Сергей М. © (20.02.08 16:49) [37]
    Разницу между регулярной функцией/процедурой и функциональным/процедурным методом Делфи-объекта понимаешь ?

    Как представлен метод любого объекта в памяти Делфи-приложения понимаешь ?
  • Galiaf © (22.02.08 13:14) [38]
    нет
  • Сергей М. © (22.02.08 13:17) [39]
    Вот с этого и начни.
 
Конференция "WinAPI" » Перехват сообщений самодельным окном. [D7, WinXP]
Есть новые Нет новых   [134431   +15][b:0][p:0.003]