![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
Есть куча примеров о там, как создать окно на WinAPI. Захотелось все это запихнуть все в один объект и не париться каждый раз с кодом, вот только с callback'ом возникли проблемы.
За код просьба сильно не пинать... Код:
{$C +}
program Project1;
uses
Windows, SysUtils, Messages;
const WndClassName = 'PROJECT1WCN';
type TWinCallback = function(aHandle : THandle; aMsg : Longint; awParam : WPARAM; alParam : LPARAM): Longint of object; stdcall;
type
TxForm = class(TObject)
private
fHandle : THandle;
fWndClassEx : WNDCLASSEX;
fWinCallback : TWinCallback;
function WinCallback(aHandle : THandle; aMsg : Longint; awParam : WPARAM; alParam : LPARAM): Longint; stdcall;
public
constructor Create;
destructor Destroy; override;
end;
{$R *.res}
{---------------------- TxForm ----------------------------}
constructor TxForm.Create;
begin
inherited Create;
fWinCallback := WinCallback;
ZeroMemory(@fWndClassEx, sizeof(fWndClassEx));
with fWndClassEx do
begin
cbSize := sizeof(fWndClassEx);
lpszClassName := WndClassName;
lpfnWndProc := @fWinCallback;
Style := CS_VREDRAW or CS_HREDRAW;
hInstance := hInstance;
hIcon := LoadIcon(hInstance, IDI_APPLICATION);
hCursor := LoadCursor(hInstance, IDC_ARROW);
hbrBackground := COLOR_BTNFACE + 1;
lpszMenuName := nil;
cbClsExtra := 0;
cbWndExtra := 0;
end;
ASSERT(RegisterClassEx(fWndClassEx)<>0, 'RegisterClassEx');
fHandle := CreateWindowEx(WS_EX_TOPMOST,
WndClassName,
'Proj1',
WS_OVERLAPPED,
100,
100,
200,
200,
0,
0,
hInstance,
nil);
ASSERT(fHandle <> 0, 'CreateWindowEx');
ShowWindow(fHandle, SW_SHOW);
UpdateWindow(fHandle);
end;
destructor TxForm.Destroy;
begin
inherited;
end;
function TxForm.WinCallback(aHandle : THandle; aMsg : Longint; awParam : WPARAM; alParam : LPARAM): Longint;
begin
Result := DefWindowProc(aHandle, aMsg, awParam, alParam);
end;
{---------------- End of TxForm ---------------------------}
//==============================================
var xForm : TxForm;
begin
xForm := TxForm.Create;
end.Как правильно реализовать? |
|
#2
|
|||
|
|||
|
Не уверен, что можно туда подсовывать метод объекта.
Попробуй подслвывать обычную процедуру. |
|
#3
|
|||
|
|||
|
Нашел в сети библиотеку WinLight, реализующую необходимый функционал. Выпилил ненужные мне функции и классы, вроде все работает
Код:
program Project1;
uses
Windows,
Messages,
SysUtils;
type
TWindowParams = record
Caption : PChar;
Style : DWord;
ExStyle : DWord;
X : Integer;
Y : Integer;
Width : Integer;
Height : Integer;
WndParent : THandle;
WndMenu : THandle;
Param : Pointer;
WindowClass : TWndClass;
end;
type
TxForm = class(TObject)
private
fWndCallback: Pointer;
fWndHandle : THandle;
FWndParams : TWindowParams;
function WindowCallback(hWnd: HWnd; Msg, WParam, LParam:Longint):Longint; stdcall;
protected
procedure CreateWindowParams(var WindowParams: TWindowParams); virtual;
public
constructor Create;
destructor Destroy; override;
property WndHandle: THandle read FWndHandle;
property WndCallback: Pointer read FWndCallback;
end;
{ TxForm }
constructor TxForm.Create;
begin
inherited Create;
FWndCallback := VirtualAlloc(nil,12,MEM_RESERVE or MEM_COMMIT,PAGE_EXECUTE_READWRITE);
asm
mov EAX, Self
mov ECX, [EAX].TxForm.FWndCallback
mov word ptr [ECX+0], $6858
mov dword ptr [ECX+2], EAX
mov word ptr [ECX+6], $E950
mov EAX, OFFSET(TxForm.WindowCallback)
sub EAX, ECX
sub EAX, 12
mov dword ptr [ECX+8], EAX
end;
CreateWindowParams(FWndParams);
RegisterClass(FWndParams.WindowClass);
with FWndParams do
CreateWindowEx(ExStyle, WindowClass.lpszClassName, Caption,
Style, X, Y, Width, Height,
WndParent, WndMenu, hInstance, Param
);
end;
procedure TxForm.CreateWindowParams(var WindowParams: TWindowParams);
var
WndClassName : string;
begin
Str(DWord(Self), WndClassName);
WndClassName := ClassName+'_'+WndClassName;
with FWndParams.WindowClass do
begin
style := CS_DBLCLKS;
lpfnWndProc := WndCallback;
cbClsExtra := 0;
cbWndExtra := 0;
lpszClassName := PChar(WndClassName);
hInstance := hInstance;
hIcon := LoadIcon(0, IDI_APPLICATION);
hCursor := LoadCursor(0, IDC_ARROW);
hbrBackground := COLOR_BTNFACE + 1;
lpszMenuName := '';
end;
with FWndParams do
begin
WndParent := 0;
Caption := 'xForm';
Style := WS_OVERLAPPEDWINDOW or WS_VISIBLE;
ExStyle := 0;
X := Integer(CW_USEDEFAULT);
Y := Integer(CW_USEDEFAULT);
Width := Integer(CW_USEDEFAULT);
Height := Integer(CW_USEDEFAULT);
WndMenu := 0;
Param := nil;
end;
end;
destructor TxForm.Destroy;
begin
UnregisterClass(FWndParams.WindowClass.lpszClassName, hInstance);
if IsWindow(FWndHandle) then DestroyWindow(FWndHandle);
VirtualFree(FWndCallback, 0, MEM_RELEASE);
inherited;
end;
function TxForm.WindowCallback(hWnd: HWnd; Msg, WParam,
LParam: Integer): Longint;
var
WindowMsg : TMessage;
begin
if FWndHandle = 0 then FWndHandle := hWnd;
case Msg of
WM_CLOSE: PostQuitMessage(0);
end;
Result := DefWindowProc(hWnd, Msg, WParam,LParam);
end;
{$R *.res}
var xw : TxForm;
msg : TMsg;
begin
xw := TxForm.Create;
while (getmessage(msg, 0, 0, 0)) do
begin
TranslateMessage(msg);
DispatchMessage(Msg);
end;
end.Ссылка на оригинал |