Форум: "WinAPI";
Текущий архив: 2003.10.27;
Скачать: [xml.tar.bz2];
Внизподмена WndProc Найти похожие ветки
← →
jonni (2003-08-18 02:51) [0]идея значит вот какая......
пишу класс.... из себя он представляет простое окно определённого названия класса.
В главной программе я регестрирую класс.
И далее уже пользуясь своим классом создаю несколько окон.
мой Create у класса:
//создаю окно
CreateWindowEx(bla bla bla);
//переопределяю WndProc
oldLV:=Pointer(SetWindowLong(hTrayIconWnd,GWL_WNDPROC,longint(@IconWnd Proc)));
где function IconWndProc(Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; определена таким образом.
ВСЁ РАБОТАЕТ ПРЕКРАСТНО, НО.....
у меня в классе определена переменная:
TMyClass=class;
private
myperemennay:String;
.............
Мне её нужно использовать в функцие IconWndProc, НО т.к. функция IconWndProc не являеться объектом и/или методом класса, мне переменная myperemennaya в теле функции не доступна!!!!
как мне можно решить эту проблему???
нужно либо делать IconWndProc методом классаа (Я НЕ МОГУ ДОБИТЬСЯ ЧТО БЫ ВСЁ ПРИ ЭТОМ РАБОТАЛО.... делая так:
определяя функцыю в классе и описываю вот так:
TMyClass.IconWndProc():LRESULT;stdcall;
и соответственно
oldLV:=Pointer(SetWindowLong(hTrayIconWnd,GWL_WNDPROC,longint(@TMyClas s.IconWndProc)));
НЕ РАБОТАЕТ
), либо как то получать переменние данного класса... как это сделать я не знаю....
всё написано только на API (Windows,Messages)..
если кто с этим сталкивался расскажите пожалуйста.
← →
Крот (2003-08-18 08:33) [1]Посмотри как в Dlephi устроена подмена WndProc в классе TWinControl
← →
Игорь Шевченко (2003-08-18 10:10) [2]MakeObjectInstance
← →
jonni (2003-08-18 13:13) [3]to Крот:
я уже посмотрел....... как то..... не получилось.....
to Игорь Шевченко:
MakeObjectInstance......хмм.... а где это такое???
на скока я понимаю (точнее мне Delphi skazalo) это в Forms.pas.. а у меня то ведь только Windows,MEssages... и всё... :(
может есть что конкретного посоветовать?
← →
Игорь Шевченко (2003-08-18 14:13) [4]
> нужно либо делать IconWndProc методом классаа (Я НЕ МОГУ
> ДОБИТЬСЯ ЧТО БЫ ВСЁ ПРИ ЭТОМ РАБОТАЛО.... делая так:
MakeObjectInstance.
RTFS: forms.pas
← →
VMcL (2003-08-18 16:44) [5]>Игорь Шевченко © (18.08.03 14:13) [4]
D6 - Classes.pas
← →
PVOzerski (2003-08-18 17:30) [6]Может, мой путь и извратный, но я когда-то использовал в похожей задаче GetWindowLong и SetWindowLong. Сначала один раз загонял по GWL_USERDATA адрес экземпляра класса, потом на каждом сообщении извлекал это значение и передавал всё полученное в метод Dispatch. Получалось, как в VCL, даже message handler"ы в стиле Delphi работали, хотя механизм совсем другой.
← →
jonni (2003-08-18 18:00) [7]to VMcL и >Игорь Шевченко
извините но я же писал что у меня нету ничего кроме Windows.pas i messages.pas
я пишу ТОЛЬКО на API
to PVOzerski что такое адресс экземпляра класса??
как его получить??
что с ним можно делать?
← →
PVOzerski (2003-08-18 18:26) [8]2jonni © (18.08.03 18:00):
по сути, сама переменная типа класс.
т.е.,
type
tMyClass=class(...
...
end;
....
var
MyClass:tMyClass;
так вот, этот MyClass и есть то самое, что надо "пристегнуть" к окошку через SetWindowLong. А в callback"е вытягивать его через GetWindowLong как longint, приведением типов обращать в tMyClass и вызывать его Dispatch.
P.S. В описании класса в методе DefaultHandler делал вызов DefWindowProc.
← →
Марсианин (2003-08-18 18:55) [9]>PVOzerski © (18.08.03 17:30) [6]
по-моему это самый нормальный способ. Фень Юань например только так и делает
← →
jonni (2003-08-18 21:10) [10]Фень Юань делает вот как...........
регистрасия класса:
//----------------------------
wcex.lpfnWndProc = (WNDPROC)(void *)m_Thunk;
//----------------------------
Create в самом классе ():
//----------------------------
ThunkInit(m_Thunk, this);
(WNDPROC)SetWindowLong(m_hWnd,GWL_WNDPROC,(LONG)(void *)m_Thunk);
//----------------------------
m_Thunk ThunkData; <--- конечно же....
где собственно:
typedef unsigned char ThunkData[9];
и
void inline ThunkInit(ThunkData t, void * This)
{ t[0] = 0xB9; // mov ecx,
*((DWORD *)(t+1)) = (DWORD) This; // this
*((DWORD *)(t+5)) = 0x20FF018B; // mov eax, [ecx]
// jmp [eax]
}
КАК ЭТО ПЕРЕВЕСТИ НА Delphi
помогите плз.....
← →
Ray Adams (2003-08-19 00:37) [11]Грубый косук из моей программы для работы с OpenGl. Там есть обьект TRWinGl=class(TObject), который сам создает окно и использует свои же методы для обработки.
private
procedure WndProc(var AMsg: TMessage);
public
FNewWndProc:pointer;
FNewWndProc := Classes.MakeObjectInstance(WndProc);//Поучаем адрес
h_Wnd := CreateWindowEx(dwExStyle, // Extended window styles
"OpenGL", // Class name
PChar(FWND_TITLE), // Window title (caption)
dwStyle, // Window styles
0, 0, // Window position
Width, Height, // Size of window
0, // No parent window
0, // No menu
hInstance, // Instance
FNewWndProc); // Pass self
------
Может не совсем понятно обьяснил, просто не могу сюда запихать весь текст из юнита.
← →
jonni (2003-08-19 00:59) [12]to Ray Adams dlya togo chto bi ispol"zovat" Classes.MakeObjectInstance(WndProc) нужен модуль Classes, а я не использую этот модуль!!! только Windows&Messages....
люди помогите перевести C++(код выше ) на Delphi плиззз
← →
Крот (2003-08-19 06:15) [13]
type
TThuncData = Array[0..8] of byte;
procedure ThunkInit(t: TThunkData; this: Pointer)
begin
t[0] := $b9;
Move(t[1], DWORD(this), sizeof(DWORD));
Move(t[1 + (sizeof(DWORD)], $20ff018b, sizeof(DWORD));
end;
//где то в классе есть переменная типа TThunkData
FThunk: TThunkData;
wcex.lpfnWndProc := TFNWndProc(@FThuncData[0]);
//в методе Create
ThunkInit(FThunk, Pointer(self));
SetWindowLong(Handle, GWL_WNDPROC, Pointer(@FThunk));
Мне кажется, так. Но я, признаться, не понял как этот код работает. Похоже на механизм переходников в WTL, но где собственно вызов оконной процедуры? По-моему, в результате всех
этих манипуляций в ecx просто поместили указатель на объект и все.
← →
Игорь Шевченко (2003-08-19 09:05) [14]jonni © (18.08.03 18:00)
А никто и не говорит об использовании. Но посмотреть, как реализована функция MakeObjectInstance в Forms.pas или в Classes.pas я думаю, религия позволяет ? Или чукча не читатель ни грамма ?
← →
Марсианин (2003-08-19 16:51) [15]>Игорь Шевченко © (19.08.03 09:05) [14]
идти по стопам Delphi - не самое мудрое решение. там это реализовано СЛИШКОМ сложно. но поглядеть не мешает
>jonni © (18.08.03 21:10) [10]
Фень Юань делает вот как...........
в инете нашел? странно. у меня в книге все по-другому.
посмотри исходник WLTScreensaver на DelphiGFX
← →
PVOzerski (2003-08-20 14:28) [16]Еще раз вернусь к своему подходу, попробую разжевать.
1) Я делаю обычный callback, никакой не метод класса, и он делает ровно следующее: по прибытии любого сообщения, кроме WM_CREATE, выдергивает из GWL_USERDATA 4 байта, конвертит их в переменную типа мой_класс, и вызывает ее метод dispatch, передавая туда код и параметры сообщения. А уже dispatch вызовет handler"ы-методы а-ля Delphi VCL. Если же сообщение WM_CREATE (оно возникает сразу после CreateWindow<Ex>), в этот момент "штатным образом" по смещению GWL_USERDATA должен жить 0. Если это действительно так (проверить ведь не сложно), перед вызовом dispatch надо загнать туда адрес класса. Для этого я использую глобальную переменную типа tObject, которой непосредственно перед CreateWindow присваиваю значение переменной типа мой_класс, которую хочу "пристегнуть" к окну. Естественно, глобальная переменная доступна из callback-функции, и ее значение без проблем через SetWindowLong загоняется, куда надо. В принципе, конечно, в таком виде конструкция не совсем thread-safe, но ее вполне можно и улучшить.
← →
jonni (2003-08-20 16:19) [17]и всё же я схожусь к тому что делать надо через GWL_WNDPROC..
oldLV:=Pointer(SetWindowLong(hTrayIconWnd,GWL_WNDPROC,longint(MakeObje ctInstance(@IconWnd Proc))));
vot tak vse chudesno rabotaet no tol"ko problema
v tooy samoy MakeObjectInstance.... v Calsses.pas ona ochen" bol"shaya... logiki poka ya ne ochen" ponyal tam..
zato u Фень Юань vse eto v paru strochek kak vidno...
v исходник WLTScreensaver на DelphiGFX imeet ochen" shozhuyu kartinu kak i u Фень Юань....... pitayus" vikusit" to chto nuzhno....
vsem bol"shoe spasibo... est" teper" nad chem zadumat"sya i v chem razobrat"sya
tol"ko ostalsya vopros.... vse zhe smisl MakeObjectInstance...
videlyaet pamyat" pod snosku na novuyu funkciyu...... chto esche?
← →
jonni (2003-08-20 22:15) [18]Всем огромное спасиба.......
задача решена.........
//--opisanie classa---
.....
private
FWndCallback,oldproc: Pointer;
function WindowCallback(hWnd: HWnd; Msg, myWParam, myLParam: Longint): Longint; stdcall;
.....
//------------------
//----CREATE CLESS--------
MyWnd:=CreateWindowEx();
FWndCallback := VirtualAlloc(nil, 12, MEM_RESERVE OR MEM_COMMIT, PAGE_EXECUTE_READWRITE);
asm
mov EAX, Self
mov ECX, [EAX].TMyWnd.FWndCallback
mov word ptr [ECX+0], $6858 // pop EAX
mov dword ptr [ECX+2], EAX // push _Self_
mov word ptr [ECX+6], $E950 // push EAX
mov EAX, OFFSET(TMyWnd.WindowCallback)
sub EAX, ECX
sub EAX, 12
mov dword ptr [ECX+8], EAX // jmp TLiteFrame.WindowCallback
end;
oldproc := Pointer(GetWindowLong(MyWnd,GWL_WNDPROC));
SetWindowLong(MyWnd,GWL_WNDPROC,DWORD(FWndCallback));
//---END CREATE CLASS--------
//----destroy class----
......
VirtualFree(FWndCallback, 0, MEM_RELEASE);
......
//----end destroy-------
//---
function TMyWnd.WindowCallback(hWnd: HWnd; Msg, myWParam, myLParam: Integer): Longint;
......
Result := CallWindowProc(oldproc, MyWnd, Msg, myWParam, myLParam);
.....
//---
....
← →
имя (2003-08-21 07:34) [19]Удалено модератором
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2003.10.27;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.012 c