![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Перехват сообщений самодельным окном. [D7, WinXP]
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]
Щас копну в этом направлении, хотя как приспособить его у меня пока не знаю