Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Создание окна [Win95/98]


Страницы:   1 2

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));


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо