Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Перехват сообщений самодельным окном. [D7, WinXP]


Страницы:   1 2 3

Galiaf ©   (2008-02-18 00:24:00) 

Доброго времени суток! Столкнулся с проблемой перехвата сообщений или событий окном созданным средствами WinAPI.<br>
В общем я создаю класс окна в одном модуле(wnd.pas) и дочерний класс в другом(main.pas), при этом у меня одна локальная процедура WndProc для всех окон. Я пробовал прописывать в дочернем классе процедуру для перехвата сообщений как делал это раньше на VCL
procedure WMPaint(var Msg : TWMPaint);  message wm_paint;
Ничего не получилось, наверное я неправильно понимаю как работает такой способ перехвата, может быть надо присваивать каждому классу свой хэндл, ведь сообщения посылаются владельцу хэндла, но я не знаю как такое реализовать. <br>
Теперь пробую сделать события как на VCL (onPaint), но тоже пока безуспешно.
Заранее спасибо!


Galiaf   (2008-02-22 13:29:00) [21]

регулярная функция/процедура, имеется в виду цикл?


Сергей М.   (2008-02-22 13:17:00) [22]

Вот с этого и начни.


Galiaf   (2008-02-22 13:14:00) [23]

нет


Сергей М.   (2008-02-20 16:49:00) [24]

Разницу между регулярной функцией/процедурой и функциональным/процедурным методом Делфи-объектапонимаешь ?

Как представлен метод любого объекта в памяти Делфи-приложения понимаешь ?


Сергей М.   (2008-02-20 16:33:00) [25]


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


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

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

Означает и используется по-разному, в зависимости от тек.контекста.


Galiaf   (2008-02-20 13:52:00) [26]


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

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


Galiaf   (2008-02-20 11:46:00) [27]

Пользовался - не интересно.
Как можно сделать проще и быстрее?


dsoft   (2008-02-20 00:54:00) [28]

Ну уж, если так сильно прижало, воспользуйтесь библиотекой KOL.


dsoft   (2008-02-20 00:51:00) [29]

А какой смысл городить всю эту конструкция классов? Можно и проще и быстрее.


Galiaf   (2008-02-20 00:33:00) [30]

А про стратегию написания программ на API хотелось бы почитать по-подробнее


Galiaf   (2008-02-20 00:21:00) [31]

И чем же исходники "мазахистов" хуже исходников на сях? Если я пишу на API в первую очередь для того, чтобы столкнуться со сложностями и преодалив их положить что-либо в свою копилку опыта, то почему бы не перелопатить тот же VCL?


dsoft   (2008-02-19 23:31:00) [32]


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


Ну объясни, на кой этот огород. Что из этого должно получится? Пытаешься создать свой велосипед (VCL)? Ну для начала посмотри хотя бы не исходники, которые тебе предлагают мазохисты, а "С"-шные. Перевести их на Pascal небольшой труд, но зато поймешь стратегию написания программ на API. Но если же упрямо будешь городить то, что здесь предлагаешь, то очень скоро твои программы перестанут быть "маленькими".


Сергей М.   (2008-02-19 15:58:00) [33]


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


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

Тот что ниже - "только что собранный", считай что это "экстракт" из кучи VCL-кода, который ты не понимаешь, но от которой ты желаешь избавиться.


Galiaf   (2008-02-19 15:53:00) [34]

Благодарю. До завтра компьютера мне не видеть, а по этому буду изучать вышеизложенный код на экране мобильного телефона.
А откуда этот код взят? Личные наработки, взятый откуда-то или только что собранный?


Сергей М.   (2008-02-19 12:57:00) [35]

Скопируй этот код к себе в проект:


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   (2008-02-19 11:40:00) [36]

без посторонней помощи не разберусь, тупо переписывая CreateHandle, только больше запутываюсь, нужно теперь все удалять и попытаться вставить только нужное в свой код, потому что переписывание результатов не дало.
Кто-нибудь сталкивался с такой задачей или вместе со мной на догадках строите свои предложения?


Сергей М.   (2008-02-19 11:24:00) [37]


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


Как ни странно, я тоже не исключаю)


Galiaf   (2008-02-19 11:22:00) [38]

Полностью переписал процедуру CreateHandle, все равно не форма не хочет перехватывать сообщения. Не исключаю тот вариант, что я сделал это неправильно.


Galiaf   (2008-02-19 10:54:00) [39]

function MakeObjectInstance(Method: TWndMethod): Pointer;- кучка непонятного кода, буду разбираться...


Galiaf   (2008-02-19 10:42:00) [40]


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

Щас копну в этом направлении, хотя как приспособить его у меня пока не знаю


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо