WindowProc всередині об’єкта
Всім доброго доби! У мене таке запитання: Чи можна призначити вікну віконну процедуру всередині об'єкта?
Я правильно зрозумів питання.
private OldProc: TWndMethod; процес NewProc(var msg: TMessage);
procedure TForm1.FormCreate(Sender: TObject); begin OldProc := ScrollBox1.WindowProc; ScrollBox1.WindowProc := NewProc; end;
procedure TForm1.NewProc(var msg: TMessage); begin OldProc(msg); case msg.Msg of WM_VSCROLL: label1.caption:="vert"; WM_HSCROLL: label1.caption: = "horiz"; end; end;
Правильно, лише реалізація не та. Я мав на увазі (чому відразу не написав?
Справа в тому, що я не використовую VCL.
Я може неправильно зрозумів, але у вихідниках TApplication у конструкторі (виклик CreateHandle) створюється вікно з віконною функцією WndProc, яка є методом самого TApplication. Хоча, можливо, я не нищу, адже TApplication це VCL. Подивися, може, допоможе.
З методом об'єкта не вийде через неявний параметр Self.
Але якщо Ви не використовуєте VCL, то чому б не призначити вікну звичайну функцію, не метод об'єкта (SetWindowLong з GWL_WNDPROC)? Це точно пройде.
"З методом об'єкта не вийде через неявний параметр Self."
А детальніше не можна? Начебто, в TApplication.CreateHandle саме SetWindowLong викликається з методом класу TApplication.
Загалом це можна зробити, але я не знаю як. Метод об'єкта, адже він теж містить код, значить можна якось дістати покажчик на цей код. ?
так млинець, WndProc - метод TApplication
FObjectInstance := MakeObjectInstance(WndProc); FHandle :=CreateWindow(WindowClass.lpszClassName, PChar(FTitle), ляля SetWindowLong(FHandle, GWL_WNDPROC, Longint(FObjectInstance));
те, що відбувається в MakeObjectInstance вище мого розуміння :)
http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1028003759&n=0 тут до речі є код :) треба в чужі питання іноді заглядати :)
Так, такий спосіб також відомий. В кінці не забудьте відновити все назад і викликати FreeObjectInstance.
Але незрозуміло - Ви ж кажете, що не використовуєте VCL, то звідки ж об'єкт з'явився?
Це теж до VCL? :-)))
Слово "Visual" не повинно вводити в оману. Це всього лише не цілком точна назва, аСУТЬ- у коді.
Чи я щось не так зрозумів?
До речі, писати у верхньому регістрі очевидно неправильні речі не варто було б :))
TObject - це основний елемент мови Object Pascal, і розробники помістили його у модулі бібліотеки часу виконання, описується він у модулі System і до VCL жодного відношення не має.
У MakeObjectInstance віконна процедура пов'язується з об'єктом. У пам'яті динамічно створюється код, який приймає параметри віконної процедури, створює запис типу TMessage і передає їх "віконної" функції об'єкта, яка вже шукає потрібний обробник повідомлення для об'єкта. Весь цей код знаходиться в модулі Forms, отже, вся VCL все одно потрапить у програму. Щоб цього уникнути, потрібно видерти з модуля Forms весь код, пов'язаний з MakeObjectInstance.
> розробники помістили його у модулі бібліотеки часу виконання
І що з того? Від цього він перестав бути частиною VCL?
У run-time модулях можуть жити і візуальні об'єкти. Вони також перестають бути частиною VCL?
Хіба VCL -це тільки те, що входить до палітри компонентів IDE?
А те, що вони входять в RTL, говорить тільки про те, що VCL складається як з run-time, так і design-time модулів. От і все.
Отже, "очевидно неправильні речі", згідно з структурою довідки Delphi, є не менш очевидно правильними. У будь-якому регістрі. :о)
Виявляється, я все життя говорив прозою.
Занадто вже ємним поняття VCL виходить. VCL, VCL і нічого крім VCL :-(
> Старий паскаліст (03.08.02 16:33)
Ще раз подивився в тій же довідці - модулі Windows, ShellAPI і подібні до них в VCL не числяться.
Так що не все так погано, колега - системні бібліотеки частиною VCL все ж таки не є. :о)
Що дає нам, старим паскалістам, певну віддушину.
1) використання класів саме собою використання VCL не означає. VCL – це бібліотека, класи – частина синтаксису Object Pascal, з використанням якої, зокрема, написана VCL. Тип tObject визначений у модулі системи. За всієї поваги до Ю.Зотова, змушений підтримати "Ги-ги..".
2) Метод у класі – штука досить кумедна. По-перше, має неявний параметр Self, по-друге, процедурна змінна procedure/function(. )of object - це, на відміну від звичайної процедурної змінної, не покажчик на точку входу, а масив із двох покажчиків - на точку входу і на блок даних. Виходячи з викладеного, очевидно, що використовувати метод як WndProc практично неможливо.
> VCL – це бібліотека, класи – частина синтаксису Object Pascal
Безперечно. Тому, якщо ми використовуємо СВОЮ ієрархію класів, ні від чого не успадковану, а повністю і самого нуля написану ручками - то ми використовуємо ТІЛЬКИ мову і нічого більше. Але як тільки ми успадкували хоча б один свійклас від TObject з модуля System, або від будь-якого його нащадка – ми використовуємо VCL.
Тому я написав - "Якщо Ви мали на увазі TMyObject = class (TObject)".
2Юрій Зотов: Знову не можу з Вами погодитися. Модуль System не є частиною VCL, він відноситься до RTL і практично необхідний для будь-якої програми, що хоч використовує VCL, хоч не використовує. А тип tObject визначений саме у модулі System. Вирази type tX=class end; та type tY=class(tObject) end; насправді еквівалентні, і клас tX є неявним нащадком tObject і містить у собі той самий набір властивостей і методів, як і tY. А з Вашого твердження, таким чином, випливає, що будь-яке використання будь-яких класів у програмі означає використання VCL, що суперечить вами ж висловленому судженню про ієрархію класів, що ні від чого не залежить, як шляхи невикористання VCL.
2Юрій Зотов а якщо він мав на увазі просто "TMyObject = class"? :-)))))
Взагалі кажучи, важко на Дельфі написати ієрархію класів, не успадковану від TObject. (Пережитки турбопаскаля поза рахунок).
Проте Борланд подолав це вузьке місце – див. вище.
> А з Вашого твердження, таким чином, випливає, що використання будь-яких класів у програмі означає використання VCL.
Саме так. На підтвердження я навів структуру довідки Delphi - з неї випливає, що сама Borland розглядає модуль System як частину VCL. Якщо ж це так, то вся RTL є частиною VCL - а тоді, навіть написавши у програмі не те що слово "class", а просто виклик будь-якої вбудованої функції, ми вже використовуємо VCL.
> . що суперечить вами ж висловленому судженню про ієрархію класів, що ні від чого не залежить, як шляхи невикористання VCL.
Ні, не суперечить.Тому що це судження, звісно, суто гіпотетичне. Реалізувати таку незалежну ієрархію практично неможливо, бо сам компілятор вже " заточений " під TObject, як базовий клас.
> а якщо він мав на увазі просто "TMyObject = class"?
. то це, як усі ми знаємо, абсолютно одне й те саме.
Панове, я пропоную припинити цю теоретичну дискусію. Ми чудово розуміємо одне одного і питання зводиться лише до того, чи є RTL частиною VCL, чи ні. Відповідаючи "так", ми маємо визнати правоту однієї сторони, відповідаючи "ні" - іншій стороні.
Ми дивимося на це по-різному і навряд чи хтось зможе переконати когось. Розсудити нас, мабуть, може лише Borland, а звертатися до неї щодо термінології навряд чи має сенс.
Але від суперечки я отримав насолоду. Дякую.
Я тут залізу з приводу, що рахувати VCL, а що ні. Імху свою висловлю. :o) Це краще у Borland запитати. Але можна і на структуру каталогу джерел подивитися - там чітко видно, що Borland вважає RTL, що VCL, що CLX і т.д.
Цитата з довідки Delphi5 :Когда ви збираєтеся Classs of your own in Object Pascal, вони повинні бути переміщені відTObject. Використовуючи нові класи відVCL's base class(або один з його послідовників), ви надаєте свої класи з принциповою функціональністю і надійністю, що вони працюють з VCL.
Таким чином, Borland називає TObjectбазовим класом VCL. Оскільки всі класи успадковуються від TObject, то використання класів є використання VCL.
АЛЕ, об'єкти в Object Pascal можна оголосити і майже забутою директивоюobject. І ось тут VCL вже не до того, т.к. за такого визначення об'єкт перестав бути спадкоємцем TObject, отжене використовує VCL.