![]() |
| ||
|
|
Новости |
Поиск |
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), но тоже пока безуспешно.
Заранее спасибо!
Сергей М. (2008-02-19 10:01:00) [41]
> Galiaf (19.02.08 01:26) [19]
Ключевоймомент во всей этой бодяге, что ты затеял, - ф-ция MakeObjectInstance().
Galiaf (2008-02-19 01:26:00) [42]С этого места по-подробнее
dsoft (2008-02-19 01:13:00) [43]Это мазохизм? Зачем пытаться повторять VCl, в API принято писать несколько по другому.
Сергей М. (2008-02-18 15:38:00) [44]
procedure TApplication.CreateHandle;
var
TempClass: TWndClass;
SysMenu: HMenu;
begin
if not FHandleCreated
{$IFDEF MSWINDOWS}
and not IsConsole then
{$ENDIF}
{$IFDEF LINUX}
then
{$ENDIF}
begin
{$IFDEF LINUX}
FObjectInstance := WinUtils.MakeObjectInstance(WndProc);
{$ENDIF}
{$IFDEF MSWINDOWS}
FObjectInstance := Classes.MakeObjectInstance(WndProc);
{$ENDIF}
WindowClass.lpfnWndProc := @DefWindowProc;
if not GetClassInfo(HInstance, WindowClass.lpszClassName, TempClass) then
begin
WindowClass.hInstance := HInstance;
if Windows.RegisterClass(WindowClass) = 0 then
raise EOutOfResources.Create(SWindowClass);
end;
FHandle := CreateWindow(WindowClass.lpszClassName, PChar(FTitle),
WS_POPUP or WS_CAPTION or WS_CLIPSIBLINGS or WS_SYSMENU
or WS_MINIMIZEBOX,
GetSystemMetrics(SM_CXSCREEN) div 2,
GetSystemMetrics(SM_CYSCREEN) div 2,
0, 0, 0, 0, HInstance, nil);
FTitle := '';
FHandleCreated := True;
SetWindowLong(FHandle, GWL_WNDPROC, Longint(FObjectInstance));
if NewStyleControls then
begin
SendMessage(FHandle, WM_SETICON, 1, GetIconHandle);
SetClassLong(FHandle, GCL_HICON, GetIconHandle);
end;
SysMenu := GetSystemMenu(FHandle, False);
DeleteMenu(SysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
DeleteMenu(SysMenu, SC_SIZE, MF_BYCOMMAND);
if NewStyleControls then DeleteMenu(SysMenu, SC_MOVE, MF_BYCOMMAND);
end;
end;
Galiaf (2008-02-18 15:35:00) [45]Вернемся к теме: ближайшие 8-9 часов компьютера я не увижу, а по этому прошу написать мне код процедуры TApplication.CreateHandle; для дальнейшего изучения. Спасибо.
Leonid Troyanovsky (2008-02-18 14:53:00) [46]
> Galiaf (18.02.08 14:38) [14]
> А по-подробнее можно?
Подробнее можно в библиотеке.
--
Regards, LVT.
Galiaf (2008-02-18 14:38:00) [47]А по-подробнее можно?
Leonid Troyanovsky (2008-02-18 14:23:00) [48]
> Galiaf (18.02.08 14:15) [12]
> О чем книга? Сколько весит?
Про дельфи, вестимо.
Кг 1.5 бумаги.
--
Regards, LVT.
Galiaf (2008-02-18 14:15:00) [49]О чем книга? Сколько весит?
Leonid Troyanovsky (2008-02-18 13:59:00) [50]
> Galiaf (18.02.08 13:45) [9]
> Пишу на чистом WinAPI, получаю мелкий размер программы,
Понятно. Мазохист.
Лучше получи удовольствие от книги.
Например, Чарльз Калверт. Дельфи Х: Энциклопедия пользовавателя.
--
Regards, LVT.
Сергей М. (2008-02-18 13:58:00) [51]
> учусь, получаю удовольствия
Похвально)
Galiaf (2008-02-18 13:45:00) [52]Пишу на чистом WinAPI, получаю мелкий размер программы, больший контроль над программой, учусь, получаю удовольствия от программирования больше чем на VCL...
Сергей М. (2008-02-18 12:49:00) [53]А ради чего вся эта жуткая каша из окон и форм тобой заварена ?
Galiaf (2008-02-18 12:38:00) [54]Сравню, когда окажусь за компьютером, а пока могу только предполагать или ждать прямого ответа на вопрос.
Сергей М. (2008-02-18 12:01:00) [55]
> Цикл здесь и однин для всей программы
Не для "всей программы", а для для окон, созданных в тек.треде.
> function tFrm.CreateWnd: boolean;
Сравни с
procedure TApplication.CreateHandle;
и сделай выводы.
Galiaf (2008-02-18 11:33:00) [56]ну да, не цикл - обработка сообщений. Цикл здесь и однин для всей программы
procedure tApp.Run;
var
Msg: tMsg;
begin
if not MainForm.CreateWnd then exit;
while GetMessage(Msg, 0, 0, 0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end
end;
или его для каждой формы свой нужно создавать???
создание формы выглядит так
function tFrm.CreateWnd: boolean;
var
wc: tWndClassEx;
begin
result:=true;
zeromemory(@wc,sizeof(wc));
with wc do begin
cbSize:=sizeof(wc);
style:=cs_hredraw or cs_vredraw;
wc.cbClsExtra:=0;
wc.cbWndExtra:=0;
lpfnWndProc:=@WndProc;
wc.hInstance:=HInstance;
wc.hIcon:=LoadIcon(0,idi_application);
hCursor:=LoadCursor(0, idc_Arrow);
wc.hbrBackground:=COLOR_BTNFACE+1;
wc.lpszMenuName:=nil;
lpszClassName:=cName;
end;
if RegisterClassEx(wc)=0 then
result:=false
else
handle:=CreateWindowEx(WS_EX_TOPMOST or WS_EX_TOOLWINDOW, cName, capt, WS_POPUP, left, top, width, height, 0, 0, HInstance, nil);
if handle=0 then begin
result:=false;
exit
end;
show
end;
Сергей М. (2008-02-18 11:04:00) [57]
> Цикл обработки сообщений у меня для всех окон один - это
Это не цикл, не выдумывай.
Galiaf (2008-02-18 10:38:00) [58]Цикл обработки сообщений у меня для всех окон один - это
function WndProc(wnd: HWND; msg: integer; wParam: wParam; lParam: lParam): lResult; stdCall;
begin
result:=0;
case msg of
wm_Destroy:
begin
PostQuitMessage(0);
Exit
end;
else Result:=DefWindowProc(wnd,msg,wparam,lparam)
end;//case
end;
Прописывать обработку сообщений здесь не получиться т.к. окон может быть много, да и доступа к модулю main.pas из модуля wnd.pas нет и быть не должно(пишу с расчетом на то, что в будующем буду пользоваться этим модулем и в других программах). Единственный вариант - это прописать там события класса tApp, который создается в модуле wnd.pas и тот в свою очередь будет обрабатывать события главного окна, а оно обрабатывать события дочернего окна и т.д.
tFormClass = class of tFrm;
tApp = class
private
MainForm: tFrm;
public
constructor Create;
destructor Destroy; override;
procedure CreateForm(FormClass: tFormClass; var FormName);
procedure Run;
end;
И по этому я хотел прописать перехват только нужных сообщений в дочернем классе формы который описывается в main.pas
tMainForm = class(tFrm)
procedure FormCreate;
private
procedure Load;
procedure Draw;
protected
procedure WMPaint(var Msg : TWMPaint); message wm_paint;
end;
Но процедура WMPaint не выполняется даже если в WndProc отсылать сообщение о перересовке.
Так же покажу процедуру для создания формы в классе tApp, потому, что этот код мне не полностью понятен, я его переписывал из forms.pas, может быть я тут допустил ошибку, но он работает, форма создается.
procedure tApp.CreateForm(FormClass: tFormClass; var FormName);
var
Form: tFrm;
begin
Form:=tFrm(FormClass.NewInstance);
tFrm(FormName):=Form;
try
Form.Create;
except
tFrm(FormName) := nil;
raise;
end;
if MainForm = nil then begin
MainForm := TFrm(Form);
end;
end;
Сергей М. (2008-02-18 09:22:00) [59]Показывай код
Бегущий человек (2008-02-18 03:45:00) [60]У Вас должен после CreateWindowEx запускацца цикл обработки сообщений...до Application.Terminate. Советую глянуть примеры на masm32