
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[34.239.152.207] |
![]() |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Вот накропал об юзаемой мной самоделке. Представляю на обозрение уважаемых колег.
![]() ![]() unit ow; interface uses Windows; Type TWindowAttr = record Title: PChar; Style: Longint; ExStyle: Longint; X, Y, W, H: Integer; Menu:HMenu; end; Pwindow=^TWindow; TWindow= object HWindow,ParentWindow:HWnd; CHief:PWindow; wndClass:TwndClass; Attr:TwindowAttr; constructor Init(PChief:PWindow); destructor Done;virtual; Function AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;virtual; procedure Create(HParent:HWnd);virtual; end; procedure runapplication(MainWindow:Pwindow); implementation function WindowProc(Window: HWnd; AMessage :word; WParam,LParam: Longint): longint; stdcall; var Pw:Pwindow; begin if Amessage=wm_create then begin pw:=pcreatestruct(Lparam).lpCreateParams; pw^.HWindow:=Window; setWindowLong(Window,gwl_UserData,longint(pw)); end; pw:=pointer(getwindowlong(window,gwl_Userdata)); if pw<>nil then windowproc:=pw^.AcceptMessage(Window,Amessage,wparam,lparam) else windowProc:=defwindowproc(window,Amessage,wparam,lparam); end; constructor Twindow.init(PChief:PWindow); begin WndClass.Style := cs_hRedraw or cs_vRedraw; WndClass.lpfnWndProc := @WindowProc; WndClass.cbClsExtra := 0; WndClass.cbWndExtra := 0; WndClass.hInstance := HInstance; WndClass.hIcon := LoadIcon(0, idi_Application); WndClass.hCursor := LoadCursor(0, idc_Arrow); WndClass.hbrBackground := color_window; WndClass.lpszMenuName := nil; wndClass.lpszClassName := 'zenIA'; attr.Title:='Main Window'; attr.Style:=ws_visible or ws_overlappedwindow; attr.ExStyle:= 0; attr.X:=cw_UseDefault; attr.Y:=cw_UseDefault; attr.w:=cw_UseDefault; attr.H:=cw_UseDefault; attr.Menu:=0; Chief:=PChief; end; destructor TWindow.done; begin DestroyWindow(HWindow); end; function TWindow.AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint; begin AcceptMessage:=0; case AMessage of wm_destroy:begin postquitmessage(0);exit;end; wm_create: begin exit; end; end; AcceptMessage:=defwindowproc(window,Amessage,wparam,lparam); end; procedure TWindow.Create(HParent:Hwnd); var wnd:TWndClass; begin ParentWindow:=HParent; registerClass(wndClass); CreatewindowEx(Attr.ExStyle,wndClass.lpszClassName,Attr.Title,attr.style,attr.x, attr.y,attr.w,attr.h,ParentWindow,attr.menu,Hinstance,@self); end; procedure runapplication(MainWindow:Pwindow); var AMessage:TMsg; begin MainWindow^.create(0); UpdateWindow(MainWindow^.hWindow); while GetMessage(AMessage, 0, 0, 0) do begin TranslateMessage(AMessage); DispatchMessage(AMessage); end; end; begin end. Дабы не изовраться вконец, опускаю большинство теоретических выкладок, касающихся основ работы Винды и начинаю по сути. Не много о терминах. Под «Оконным объектом» я понимаю объект производный от TWindow, ответственный за работу окна Виндовс, под «Окном Виндовс» я понимаю квадратик с заголовком, выводимый функцией CreateWindowEx J Что к чему. Мой оконный объект TWindow. Содержит следующие переменные: Hwindow:HWnd; — хендл окна Виндовс, управляемого данным оконным объектом; ParentWindow:HWnd; — хендл окна Виндовс родительского окна. CHief:PWindow;- указатель на оконный объект родительского окна. Данную переменную я использую для вызова метода AcceptMessage родительского объекта, минуя систему сообщений. wndClass:TwndClass; - запись, содержащая свойства оконного класса, передаваемая в функцию RegisterClass, подробнее в справочниках по Винде. Attr:TwindowAttr – запись, содержащая свойства окна Виндовс, назначение полей соответствует типу, записанному в стандартной OWL; Методы объекта constructor Init(PChief:PWindow); - конструктор, по умолчанию производит заполнение wndClass и Attr destructor Done;virtual; - деструктор. Function AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;virtual; Главный обработчик сообщений. Вызывается функцией обратного вызова окна Виндовс, связанного с данным оконным объектом. procedure Create(HParent:HWnd);virtual;- регистрирует оконный класс и выводит окно Виндовс. В юните также находится процедура RunApplication, ответственная за главный цикл работы программы и WindowProc, являющаяся Call Back-функцией окон. Примитивное приложение ![]() ![]() var w:Twindow; begin w.init(nil); w.attr.title:=’Hello Word!’; RunApplication(@W); end. Как оно работает. Для работы системы необходим готовый экземпляр производного объекта от tWindow. Процедура runapplication производит выведение окна главного оконного объекта и цикл получения сообщений. Оконная процедура окна (WindowProc) при создании получает указатель на оконный объект, который, будет руководить реакцией на сообщения. Данный указатель сохраняется с помощью функции SetWindowLong. При получении сообщения окном его оконная процедура с помощью функции GetWindowLong получает указатель на «свой» оконный объект и вызывает его метод AcceptMessage, передавая ему, полученное сообщение. Как с этой самоделкой работать. Вопрос конечно, творческий, но в общих чертах так: Описать объект производный от tWindow. При необходимости из конструктора поменять свойства окна объекта (если меняете стиль в wndClass, не забудьте также в поле lpszClassName дать классу новое имя). Переопределить метод AcceptMessage, в котором описать реакцию окна на сообщения. Поскольку вопрос принципиальный, то остановлюсь на некоторых моментах. Этот метод должен работать как процедурные функции, т.е. в случае если сообщение не обработано, AcceptMessage должен возвратить DefWindowProc. Кроме этого, если переопределяется объект главного окна, не забудте обработать сообщение wm_destroy. Как минимум вызвать PostQuitMessage, и если надо вызвать деструктор оконного объекта, иначе Ваша программа останется висеть в памяти, не смотря на закрытие окна. В завершении небольшой пример работы с модулем. Данная программа выводит на экран два окна: родительское — оранжевого цвета и дочернее — серое, вызывающее при щелчке по нем стандартный диалог. Пример обильно снабжаю комментариями, поэтому, с Вашего позволения, даю его без пояснений. ![]() ![]() uses OW, Windows; type {тип дочернего оконного объекта} tChildWindow=object(TWindow) constructor Init(pChief:Pwindow); function AcceptMessage(Window:HWnd;AMessage:Word;WParam,LParam:longint):longint;virtual; end; constructor tChildWindow.Init(pChief:Pwindow); begin inherited init(PChief); with Attr do begin Style:=ws_child or ws_visible or ws_dlgframe; {окно является дочерним, видимым и окружено толстой рамкой} {далее устанавливаются положение и размеры дочернего окна} x:=10; y:=10; w:=100; h:=75; end; end; {Функция обработки сообщений} function tchildWindow.AcceptMessage(Window:HWnd;AMessage:Word;WParam,LParam:longint):longint; begin AcceptMessage:=0; case Amessage of {в ответ на получение сообщения в случае нажатия девой клавиши мыши выводится соответствующее сообщение} wm_lButtonDown:begin MessageBox(HWindow,'Вы нажали левую клавишу мыши','Зафиксировано сообщение',mb_iconexclamation);exit;end; end; AcceptMessage:=DefWindowProc(Window,AMessage,WParam,LParam); end; {тип главного окна окна} type tMainWindow=object(TWindow) Brush:Hbrush; {кисть, которой будет закрашен фон главного окна} pChild:^tChildWindow; {указатель на тип дочернего оконного объекта} constructor Init(pChief:Pwindow); destructor done;virtual; function AcceptMessage(Window:HWnd;AMessage:Word;WParam,LParam:longint):longint;virtual; end; constructor tMainWindow.Init(pChief:Pwindow); begin inherited init(PChief); {создаем непрерывную кисть оранжевого цвета} Brush:=CreatesolidBrush($00bbff); {хендл кисти соответствующему полю переменной wndClass} wndClass.hbrBackground:=brush; {необходимо изменить имя оконного класса, так как хочется, чтобы иные окна создаваемыми производными от tWindow сохраняли первоначальные свойства (в данном случае серый цвет)} wndclass.lpszClassName:='PARENT'; {изменяем заголовок окна} attr.title:='Нас не подолати!'; {создаем экземпляр оконного объекта дочернего окна} New(pChild,init(@self)); end; destructor tMainWindow.done; begin {создаваемые объекты, в том числе и кисти надо убирать после использования} deleteobject(Brush); {освобождаем память занятую дочерним оконным объектом} dispose(pChild,done); end; {Функция обработки сообщений} function tMAinWindow.AcceptMessage(Window:HWnd;AMessage:Word;WParam,LParam:longint):longint; begin AcceptMessage:=0; case Amessage of {если получено сообщение о создании главного окна создаем и дочернее} wm_create:begin pChild.Create(HWindow);exit;end; {если получено сообщение о разрушении главного окна, вызываем деструктор оконного объекта и завершаем приложение} wm_destroy: begin done; PostQuitMessage(0);exit;end; end; AcceptMessage:=DefWindowProc(Window,AMessage,WParam,LParam); end; {экземпляр главного оконного объекта} var MAinWindow:TMainWindow; begin MainWindow.init(nil); runApplication(@Mainwindow); end. M Женя, следи почаще за своими выражениями! |
Сообщ.
#2
,
|
|
|
ТРЕТЬЯ ЧАСТЬ МАРЛИЗОНСКОГО БАЛЕТА
Итак, выкладываю третью подверсию. Какие внесены дополнения. 1. Описаны типы для открытых массивов (удобная штука для обращения к динамической памяти): paChar; paWord, paShortIn и т.д. 2. Предусмотрена возможность работы с немодальными диалоговыми окнами для этого хендлы диалогов записываются в открытый массив HDIALOGS:PALongint переменная NModelessDialogs:bword хранит количество элементов в массиве. Для записи нового элемента используется процедура procedure AddModelessDialog(Window:HWnd); а для удаления — procedure DeleteModelessDialog(Window:HWnd); кроме этого для удобства Описаны ряд функций для удобства создания немодальных диалогов с «регистрацией» их: function OWCreateDialog(Instance: hInst; TemplateName: PChar; WndParent: hWnd; DialogFunc: TFNDlgProc): hWnd; — аналог CreateDialog function OWCreateDialogParam(Instance: hInst; TemplateName: PChar; WndParent: hWnd; DialogFunc: TFNDlgProc; Param: lParam): hWnd; — аналог CreateDialogParam. function OWCreateDialogIndirect(Instance: hInst; const Template: TDlgTemplate; WndParent: hWnd; DialogFunc: TFNDlgProc): hWnd; — аналог CreateDialogIndirect. function OWCreateDialogIndirectParam(Instance: hInst; const Template: TDlgTemplate; WndParent: hWnd; DialogFunc: TFNDlgProc; Param: lParam): hWnd; — аналог CreateDialogIndirectParam А также function DestroyDialog(Wnd: hWnd): Bool; вызывающая для диалога DestroyWindow с удалением хендла данного диалога из массива. Обратите внимание !!! Если Вы собираетесь использовать в своей программе немодальные диалоговые окна, используйте для создания цикла обработки сообщений вместо функции RunApplication новую функцию RunApplicationD по синтаксису аналогичную предыдущей. В четвертой версии юнита RunApplication 3. У объекта TWindow появился потомок TDialogWindow, являющийся гибридом обычного окна и диалога. С пользовательской точки зрения новый тип отличается а) наличием поля pRESOURCETEMPLATE:pChar; которое может содержать имя ресурса, содержащего шаблон диалога (при этом необходимо, чтобы имя класса ресурса совпадало со значением WndClass.lpzName). Если это поле не содержит имени ресурса, то окно создается на основании переменной Attr (размеры интерпретируются как данные в логических, а не экранных единицах, а меню придется загрузить вручную). б) Если программа использует этот тип окна то, для обработки сообщений необходимо использовать функцию RunApplicationD В четвертой версии юнита RunApplication. в) окно не получает wm_create, но получает wm_initdialog. Что дальше? В следующем обновлении предусмотрю возможность работы с акселераторами, а то не надо было, так и не предусмотрел. Прикреплённый файл ![]() |
![]() |
Сообщ.
#3
,
|
|
У тебя часть заголовка отсутствует в первом исходнике.
|
Сообщ.
#4
,
|
|
|
romtek, я все-равно исходников у себя не оставил…
![]() Доброе время суток, в систему были внесены следующие изменения: Добавлены процедуры procedure OnAcceleratorsTable(Window, ACCTABLE:Handle); — подключает систему акселераторов Window — хендл окна, который будет принимать события быстрых клавиш. ACCTABLE — хендл таблицы акселераторов (например загруженной LoadAccelerators). procedure OffAcceleratorsTable; — отключает таблицу акселераторов. Таблица акселераторов никак не изменяется, поэтому выгружать или разрушать ее придется «вручную». Удалена процедура RunApplicationD — вместо нее теперь используется обновленная RunApplication. Особенности реализации Для работы с акселераторами введены 2 внутренние переменные hACCELERATORSTABLE:HACCEL и hACCELERATORSWINDOW:HWND в которых сохраняются хендлы таблицы акселераторов и окна, принимающего их сообщения. Циклы обработки событий в зависимости от наличия немодальных диалогов и акселераторов записаны в процедурах WindowProcessing, WindowMLDialogProcessing, WindowAcceleratorsProcessing, WindowAcceleratorsMLDialogProcessing ссылки на которые устанавливаются процедурами OnAcceleratorsTable, OffAcceleratorsTable, AddModelessDialog, DeleteModelessDialog Пример схожий с предыдущим, но с подключением акселераторов uses Windows,OW; {$R OW} type tMeDialogWindow=object(tDialogWindow){Мой объектный тип} constructor init(pChief:PWindow); function AcceptMessage(Window:HWnd;AMessage:Word;WPARAM,LParam:longint):longint;virtual; {метод обработки сообщений} end; constructor tMeDialogWindow.init(pChief:PWindow); begin inherited init(pChief); pRESOURCETEMPLATE:='DLG';{Окно будет создано из ресурса} end; function tMeDialogWindow.AcceptMessage(Window:HWnd;AMessage:Word;WPARAM,LParam:longint):longint; begin AcceptMessage:=0; case AMessage of wm_initdialog: begin OnAcceleratorsTable(Window,LoadAccelerators(Hinstance,'ACC')); {При создании данного окна активируется система обработки сообщений от акселераторов, таблица грузится из ресурса} exit; end; wm_command: begin case LoWord(WParam) of 101: destroyWindow(Window);{Если сообщение от кнопки то выходим (101 - идентификатор кнопки из ресурса)} 102:begin MessageBox(Window,’Внимание окно будет закрыто’,’Нажаты “Горячие клавиши”’,0);destroyWindow(Window);end;{Если сообщение от акселератора перед выходом информируем об этом (102 - идентификатор «горячей клавиши» из ресурса)} end; exit; end; WM_Destroy: begin postQuitMessage(0); exit; end; end; AcceptMessage:=DefWindowProc(Window,Amessage,Wparam,Lparam); end; var w:tMeDialogWindow; begin w.init(nil); RunApplication(@w); end. Ресурсный файл DLG DIALOG 18, 18, 140, 92 STYLE WS_VISIBLE | WS_OVERLAPPEDWINDOW CLASS "DWZENIA" CAPTION "DIALOG WINDOW" BEGIN PUSHBUTTON "ВЫХОД", 101, 10, 65, 120, 15, WS_CHILD | WS_VISIBLE | WS_TABSTOP CTEXT "ДЛЯ ВЫХОДА МОЖНО НАЖАТЬ CTRl+END", -1, 8, 7, 125, 50, WS_CHILD | WS_VISIBLE | WS_GROUP END ACC ACCELERATORS BEGIN VK_END, 102, VIRTKEY, CONTROL END Прикреплённый файл ![]() |
Сообщ.
#5
,
|
|
|
Ну все последнее-распоследнее усовершенствованице…
в tWindow и tDialogWindow введено поле isMainWindow:boolean, при установке которого в TRUE закрытие данного окна вызывает завершение приложения (что и делает функция runApplication), таким образом теперь при разрушении окна объекта, передаваемого runApplication, работа цикла обработки сообщений прекращается без дополнительной обработки в методе AcceptMessage. |
Сообщ.
#6
,
|
|
|
Я убрал все лишнее из метода AcceptMessage в прошлой версии.
А теперь немного о конвенциях. Я предлагаю создавать компоненты следующим образом: Когда Вы хотите в дочернем оконном типе обработать новые сообщения wm_message1 wm_message2 Вы 1. Описываете новые методы по типу: Function wmmessage1 (wParam,Lparam:longint):longint;virtual; Function wmmessage2 (wParam,Lparam:longint):longint;virtual;, в которых вы определяете реакцию на сообщение. 2. переопределяете метод AcceptMessage следующим образом function TWindow.AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint; begin CASE Amessage OF wm_Message1: AcceptMessage:=wmmessage1 (wParam ,Lparam); wm_Message2: AcceptMessage:=wmmessage2 (wParam ,Lparam); ELSE AcceptMessage:=inherited AcceptMessage (Window, Amessage, WParam, LParam); end; И в конце добью последним примером — выводится окно с дочерним uses OW,Windows; type {Дочернее окно} PChildWindow=^TChildWindow; TChildWindow=object(TWINDOW) constructor init(pChief:pWindow); function AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;virtual; {метод должен вызывать метод обработки события wm_paint} function WMPAINT(WPARAM,LPARAM:Longint):longint;virtual; {окно будет по-особенному перересовываться} end; constructor tChildWindow.init(pChief:pWindow); begin inherited init(pChief); wndClass.lpszClassName:='CHILD'; {мы хотим изменить свойство класса окна и потому класс должен быть перергистрирован под новым именем} wndClass.hbrBackground:=createSolidBrush($aa00); {фон у окна будет зеленым} Attr.Style:=ws_child or ws_visible or ws_thickframe; {это будет видимое дочернее окно с толстой рамкой} end; function tChildWindow.AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint; begin Case AMessage of WM_Paint:WMPAINT(WPARAM, LPARAM); {для перерисовки вызывается метод WMPAINT } ELSE TWINDOW.ACCEPTMESSAGE(WINDOW,AMESSAGE,WPARAM,LPARAM); end; end; function tChildWindow.WMPAINT(WPARAM,LPARAM:Longint):longint; {пишем текст при помощи } DRAWTEXT var dc:HDC;TPS:TPAINTSTRUCT;tr:TRect; begin dc:=BeginPaint(HWindow,TPS); GetClientRect(HWindow,TR); setbkMode(dc,transparent); DRAWTEXT(dc,'Hello World',11,tr,dt_center or dt_vcenter or dt_singleline); EndPaint(HWindow,TPS); end; type {А это оконный объект главного окна} tNewWindow=object(tWindow) Child:tChildWindow; {наше дочернее окно} function AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;virtual; function WMCREATE(WPARAM,LPARAM:Longint):longint;virtual;{Это лучшее место для создания дочерних окон} end; function tNewWindow.WMCREATE(WPARAM,LPARAM:Longint):longint; var tr:trect; begin GetClientRect(hWindow,tr); Child.init(@self); {инициализация дочернего оконного объекта} {Эти свой ства не возможно было установить при инициализации дочернего оконного объека} Child.Attr.x:=getSystemMetrics(sm_cyCaption); Child.Attr.y:=Child.Attr.x; Child.Attr.W:=tr.right-Child.Attr.x shl 1; Child.Attr.H:=tr.Bottom-Child.Attr.x shl 1; Child.Create(hWindow); {создание дочернего оконного объекта} deleteobject(Child.wndclass.hbrBackground); {странно, но с этой командой тоже работает J} wmCreate:=0; end; function tNewWindow.AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint; begin Case AMessage of wm_Create: ACCEPTMESSAGE:=WMCREATE(WPARAM, LPARAM);{в ответ на получение сообщения о создании собственного окна вызываем WMCREATE, создающий окно дочернего объекта} else acceptMessage:=inherited AcceptMessage(Window,AMessage,WParam,LParam); end; end; var TNW:TNEWWINDOW; {экземпляр главного окна} begin TnW.init(nil); runApplication(@TnW); {процедура обеспечивающая прием и диспетчеризацию сообщений} end. |
Сообщ.
#7
,
|
|
|
Привет всем.
Спешу и падаю сообщить о внесении изменений в модуль OW.pas. С пользовательской точки зрения важно следующее: 1 .У типа tDialogWindow появился метод procedure Exec(HParent:HWnd);virtual;, выводящий окно в ввиде модального диалога. 2. У него же появилось свойство isModal:boolean; равняющееся ИСТИНА если окно выведено как модальное. НЕ ИЗМЕНЯЙТЕ ЗНАЧЕНИЕ ЭТОГО СВОЙСТВА. 3. У этого же типа появился виртуальный метод Close, вызываемый если пользователь пытается закрыть окно (пользуясь системным меню, нажимая на крестик или, нажмая на клавиатуре Alt+F4). Переопределяя этот метод можно отменить закрытие окна, например, чтобы спросить о необходимости сохранится. 4 Там же. Добавлено свойство DefProc:tAcceptMessage оно содержит указатель на процедуру умолчательной обработки мессаги. НЕ ИЗМЕНЯЙТЕ ЕГО. 5. Облегчено создание окон из диалога без указания имени класса. 6. Предусмотрен случай создания экземпляром оконного класса, окна Виндовс при уже имеющемся. В этом случае существующее окно уничтожается. КОД МОДУЛЯ OW см. ДАЛЕЕ в СООБЩЕНИЯХ В заключении пример, иллюстрирующий новые возможности. Прикреплённый файл ![]() |
Сообщ.
#8
,
|
|
|
Да пожалуйста, хотя сами ратовали за применения тегов [CODE]
![]() Облегчено создание диалоговых окон внутри DLL. Введено новое поле объекта tDialogWindow — hResourceInstance, которое используется для вызова диалогов используется в качестве Instance. Для примера описана функция ModalDialogWindow описанная в Server.dll, воспринимающая хендл родительского окна и выводящая модальный диалог. library Server; {$R Server.res} uses OW,Window; {$R Resource} function ShowModalDialog(Window.HWnd):stdcall;export; var ModalDialogWindow: tDialogWindow begin ModalDialogWindow.init(nil); ModalDialogWindow.hResourceInstance:=GetModuleInstance('Server.dll'); ModalDialogWindow.pResoucetemplate:='DLG_MAIN'; ModalDialogWindow.Exec(Window); end; exports ModalDialogWindow name 'ModalDialogWindow'; begin end. Ресурсный файл server.rc DLG_MAIN DIALOG 18, 18, 154, 112 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "MODAL DIALOG" CCLASS "DWZENIA" BEGIN LTEXT "Я МОДАЛЬНЫЙ ДИАЛОГ", -1, 1, 1, 150, 110, WS_CHILD | WS_VISIBLE | WS_GROUP END Цепляю к сообщению последнюю версию модуля OW. Прикреплённый файл ![]() |
Сообщ.
#9
,
|
|
|
Теперь система поддерживает MDI
Дополнена цепочка обработки сообщений. Теперь оконная процедура (не предназначена для модификации) вызывает для обработки сообщения метод function PreProc(Window: HWnd; AMessage :word; WParam, LParam: Longint):boolean;virtual;, если данный метод возвращает TRUE, для обработки вызывается метод Function AcceptMessage. Это нововведение — для создания производных типов. Например, если Вы хотите создать окно с анимацией, Вы можете создать таймер, по сообщению которого будут сменяться кадры анимации, обрабатывать их в методе PreProc и возвращать FALSE, таким образом, для программистов, использующих Ваш класс, отпадет кусок работы. Для создания MDI-приложений в юните OW предопределены новые типы Оконный тип дочернего окна MDI. tMDIChildWindow=object(tWindow) constructor Init(PChief:PWindow); procedure Create(HParent:HWnd);virtual; Function AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;virtual; function PreProc(Window: HWnd; AMessage :word; WParam, LParam: Longint):boolean;virtual; end; NB 1. Родителем данного окна передаваемого в конструктор, может быть только тип tFrameWindow или его наследник. Параметр Hparent метода Create игнорируется (в методе используется hMDIClient родительского оконного объекта) 2. Данный тип должен быть динамическим и создаваться функцией или процедурой New, Коллекция pMDIChildWIndow tMDICollection=object Count:Word; - количество элементов Items:papMDIChildWIndow; - динамический массив элементов Constructor Init; Destructor Done; Function FindItem(Item:pMDIChildWIndow):integer; - поиск элемента в коллекции Function Add(Item:pMDIChildWIndow):word; - добавление элемента Procedure Delete(n:word); - удаление элемента Function GetItem(n:Word):pMDIChildWindow; - получение элемента end; Окнный объект главного MDI-окна pFrameWindow=^tFrameWindow; {$I d:\projects\basis\COLLECTION1.INC} tFrameWindow=object(tWindow) hMDIClient:hWnd; - хендл окна-клиента hMenuChilds:hMenu; - Popup-меню, куда будут добавляться названия создаваемых дочерних окон idFirstChild:word; - идентификатор первого дочернего окна, следующим окнам будут присваивается следующие по порядку номера (идентификатор пересылается с сообщением wm_command, если пользователь, щелкнул по заголовку данного окна) ChildsCollection:tMDICollection; - колекция указателей на дочерние окна. ActiveChild:Pointer; — указатель на активное дочернее окно. procedure Cascade; — упорядочивает дочерние окна. procedure HorizontalTile; — упорядочивает дочерние окна. procedure VerticalTile;— упорядочивает дочерние окна. constructor Init(PChief:PWindow); destructor Done;virtual; Function AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;virtual; function PreProc(Window: HWnd; AMessage :word; WParam, LParam: Longint):boolean;virtual; end; Да, чуть не забыл напомнить об особенности Windows — некоторые сообщения должны передаваться на умолчательную обработку. Если Вы не помните какие, то воспользуйтесь функцией Function IsDefaultMessage(Window:byte;AMessage:word):boolean;, где Window может быть константами idMDIFrame и idMDIChild, а Amessage — номер сообщения. Функция возвращает True, если данное сообщение должно быть обработано по умолчанию. |
![]() |
Сообщ.
#10
,
|
|
Женя, сходи на Вики. Там статьи лучше писать. И про обрамление тегами не забывай.
![]() |
Сообщ.
#11
,
|
|
|
Низко берете, коллега, не меньше книги!!!
На подходе еще ActiveX-контейнеры ![]() |
Сообщ.
#12
,
|
|
|
Кажись топик тонет...
Обновленная версия. Пришлось возвратить сохранение ссылки на объект tDialogWindow через SetWindowLong, дабы вернуть возможность создавать диалоги предопределенного системой класса (напомню, что это происходит если в ресурсе диалога не указано имя класса). Да и как-то забыл, что уже давненько положение и размеры окна tDialogWindow выражаются в пикселях, а не логических единицах. Прикреплённый файл ![]() |
![]() |
Сообщ.
#13
,
|
|
ZenIA, а тонет этот топик по той причине, что никому не нужен WinAPI. Если кому нужны окна, использует или OWL, или KOL/другие библиотеки для Дельфи/Free Pascal.
|
Сообщ.
#14
,
|
|
|
Цитата Romtek @ ZenIA, а тонет этот топик по той причине, что никому не нужен WinAPI. 5 баллов !!!! ![]() |
![]() |
Сообщ.
#15
,
|
|
ZenIA, а ты докажи, что я не прав.
![]() |