![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Создание окна [Win95/98]
rel_ © (2003-10-21 08:45:00)
Мастера, необходимо сгенерить дочернее окно на контроле.
В общем виде делаю так: в конструкторе получаю Parent и затем вызываю след. методы:
type
TWndProc = function(wnd:HWND; Msg : Integer; Wparam:Wparam; Lparam:Lparam):Lresult of object; stdcall;
...
FWndProc : TWndProc;
...
function TGame.InitClass : boolean;
begin
wndClass.style:=cs_hredraw or cs_vredraw;
wndClass.lpfnWndProc:=@FWndProc;
wndClass.cbClsExtra:=0;
wndClass.cbWndExtra:=0;
wndClass.hInstance:=HInstance;
wndClass.hIcon:=LoadIcon(0,idi_application);
wndClass.hCursor:=LoadCursor(0,idc_arrow);
wndClass.hbrBackground:=COLOR_BTNFACE+1;
wndClass.lpszMenuName:=nil;
wndClass.lpszClassName:="TGame";
Result:=Boolean(RegisterClass(wndClass)<>0);
end;
function TAnyClass.MakeWindow(): HWND;
begin
result :=
CreateWindow("TAnyClass","",
WS_VISIBLE or WS_CHILD or WS_CLIPSIBLINGS,
10, 10, 200, 200,
FParent.Handle, 0, HInstance, nil );
end;
Так вот MakeWindow() возвращает "0" - соответственно, ничего не создаётся. Подскажите, что делаю не так (в примере не приведены процедуры сбора сообщении, отображения окна и т.д.).
rel_ (2003-10-22 13:28:00) [1]
to Digitman © Просто огромное спасибо. Не представляешь, как ты мне помог.
Digitman (2003-10-22 12:43:00) [2]
для разрушения окна в WinAPI имеется ф-ция DestroyWindow()
rel_ (2003-10-22 12:20:00) [3]
to Digitman ©
>>здрааасть ! как же "ничего нет" ? ты хоть посмотрел бы, что там творится у тебя, прежде чем утверждать такую несуразицу)
Я наверное не так выразился. я имею в виду, что нетничего, что бы касалось моего класса. А то, что ты привёл, конечно есть.
Ура!!! всё абсолютно понятно, всё получилось.
НУ СПАСИБО!!!
Маленький вопросик: я в деструкторе класса пишу:
postMessage(FHandle, WM_DESTROY, 0,0);
данное сообщение обрабатываю так:
WM_DESTROY: PostQuitMessage (0);
Результат: удаляется класс и закрывается всё приложение. Причина не совсем понятна. Как корректно удалить мой класс(удалив окно класса)???
Digitman (2003-10-22 11:51:00) [4]
> В dpr файле ничего нет
здрааасть ! как же "ничего нет" ? ты хоть посмотрел бы, что там творится у тебя, прежде чем утверждать такую несуразицу)
а там (в dpr-файле) у тебя следующее :
programm Такая_то
uses .. Такие_то_модули
....
begin
//здесь начинается выполнение кода приложения !
Application.Initialize; // объект TApplication автоматически создан, здесь он явно инициализируется
Application.CreateForm(TКлассМоейГлавнойФормы, переменная);
Application.Run; // этот метод стартует цикл обработки сообщений для всех окон (существующих и потенциально создаваемых тобой в будущем) осн.код.потока процесса приложения
end;
т.о., создавая в осн.код.потокеновые верхнеуровневые или дочерние окна, нет необходимости заботиться о создании цикла обработки сообщений для них - цикл уже запущен и работает.
в цикле этом есть вызов ф-ции DispatchMessage(), которая как раз и предназначена для вызова соответствующих оконных процедур тех окон, которые были когда либо созданы данным код.потоком (автоматически сгенерированным компилятором кодом или впоследствии тобой явно) и которым адресованы сообщения, выбираемые из очереди сообщений данному код.потоку предшествующим вызовом GetMessage()
rel_ (2003-10-22 10:38:00) [5]
Digitman © Мне кажется, что говорим немного о разных вещах:
Идея проста - некая имитация класса TControl. Я хочу, чтобы мой класс создавал окно и отлавливал его сообщения. В dpr файле ничего нет. Весь механизм регистрации класса окна, создания его и обработки сообщений должен быть внутри моего класса.
Пример:
мой класс: TMyWindow.
1) Создаю проект, в классе TForm1 объявляю переменную MyNewWindow : TMyWindow.
2) Где нибудь (например при нажатии некой кнопки) создаю экземпляр моего класса MyNewWindow := TMyWindow.Create(Selef) (Self в данном случае Form1). И больше не делаю ничего.
3) Результат - окно (некий контрол) на фомре Form1. И я не забочусь об отработке сообщений окна, созданного классом TMyWindow, всё зашито внутри класса TMyWindow. Т.е. объект MyNewWindow полностью поддерживает окно, им созданное.
Нечто, например, в вроде класса TButton - контрол(окно), а внутри него весь механизм.
Digitman (2003-10-22 10:04:00) [6]
я не понял, кем и какими средствами у тебя создается гл.окно приложения
в случае использования станд.класса TApplication оно создается автоматически, и цикл обработки сообщений запускается автоматически (в теле Application.Run), но ты же говоришь, что делаешь все непосредственно на WinAPI ... поясни вот это ... приведи текст dpr-файла своего проекта
rel_ (2003-10-22 09:54:00) [7]
to Digitman © Если не трудно, давай вернёмся ко вчерашней теме. Посмотрел на реализацию класса TApplication и его метода Run - мало, что понял.
Как мне поместить цикл сбора сообщений вне класса, если я хочу, чтобы он был инкапсулирован внутри класса и обрабатывал сообщения именyо от окна созданного текущим объектом класса?
rel_ (2003-10-21 16:03:00) [8]
to Digitman © Я тебя наверное уже совсем замучал. Пока поковыряюсь сам. Рез-т обязательно скажу.
Огромное спасибо!!!
Digitman (2003-10-21 15:56:00) [9]
> В какой момент я должен вызывать деструктор класса
в твоем случае - практически в любой
> У меня возникает непонятный эффект - окно Parent закрывается
> лишь при втором нажатии на Close
мы здесь вроде бы не о родителе говорим ... о доч.окне
> У меня цикл должен быть в классе зашит
зачем ?? ты посмотри на реализацию класса TApplication и его метода Run() !
rel_ (2003-10-21 15:40:00) [10]
to Digitman © (21.10.03 14:42) [21]
>>цикл помести в коде, который выполняется при старте приложения
>>перевым делом приложение создает объект TGame (в конструкторе которого создается окно) и где-то следом помести цикл
У меня цикл должен быть в классе зашит, а не во приложении его использующем.
rel_ (2003-10-21 15:35:00) [11]
В какой момент я должен вызывать деструктор класса???
У меня возникает непонятный эффект - окно Parent закрывается лишь при втором нажатии на Close в системном меню. Может это из-за неправильного вызова деструктора моего класса?
Digitman (2003-10-21 15:19:00) [12]
> Помещу, например в процедуре SetParent
что поместишь ? цикл ? нельзя туда его !
> есть возможность сменить Parent, не убивая при этом окно
см.реализацию метода TWinControl.SetParentWindow
rel_ (2003-10-21 14:58:00) [13]
Понятно. Помещу, например в процедуре SetParent (как в VCL).
A есть возможность сменить Parent, не убивая при этом окно???
Digitman (2003-10-21 14:42:00) [14]
цикл помести в коде, который выполняется при старте приложения
перевым делом приложение создает объект TGame (в конструкторе которого создается окно) и где-то следом помести цикл
rel_ (2003-10-21 14:36:00) [15]
Всё просто OK за одним исключением:
Где мне повесить цикл обработки сообщений ?
while (GetMessage(Msg, 0, 0, 0)) do begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
Он должен запускаться сразу после создания окна
Если вешаю его в конструкторе - то, сам понимаешь, объект не созадаётся, т.к. курсор из конструктора не выходит до закрытия окна.
rel_ (2003-10-21 12:50:00) [16]
to Digitman ©
Огромное спасибо - сейчас ухожу - о результатах сообщу позже.
Digitman (2003-10-21 12:28:00) [17]
в данной реализации - что угодно, указатель на любую stdcall-callback-ф-цию, все равно колбек будет изменен
rel_ (2003-10-21 12:21:00) [18]
to Digitman ©
Вроде понятно:
ф-ей SetWindowLong(hWnd,GWL_WNDPROC,DWORD(FNewCallback)); я переопределю обработчик сообщений, но перед строкой
hWnd:=CreateWindowEx(.., ParentHwnd,..,hInstance,..);
в описание класса в wndClass.lpfnWndProc:=??? что изначально передавать???
Игорь Шевченко (2003-10-21 12:10:00) [19]
> Если не трудно, просвети меня.
Вообще-то для просвещения служит волшебная кнопка F1 или исходники VCL...
Digitman (2003-10-21 12:07:00) [20]
поля класса TMyClass :
hWnd: THandle;
FOldCallback : Pointer;
FNewCallback : Pointer;
метод-обработчик ок.сообщений в классе TMyClass
function TMyClass.WndProc(Wnd: HWND; Msg: UINT; mywParam: WPARAM;
mylParam: LPARAM): LRESULT; stdcall;
begin
case Msg of
...
else
Result:=CallWindowProc(FOldCallback,wnd, msg, mywparam, mylparam);
end;
end;
в конструкторе (или любом другом методе) класса TMyClass
hWnd:=CreateWindowEx(.., ParentHwnd,..,hInstance,..);
FNewCallback := VirtualAlloc(nil, 12, MEM_RESERVE OR MEM_COMMIT, PAGE_EXECUTE_READWRITE);
asm
mov EAX, Self
mov ECX, [EAX].FNewCallback
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(WndProc)
sub EAX, ECX
sub EAX, 12
mov dword ptr [ECX+8], EAX // jmp
end;
FOldCallback := Pointer(GetWindowLong(hWnd,GWL_WNDPROC));
SetWindowLong(hWnd,GWL_WNDPROC,DWORD(FNewCallback));