Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.03.04;
Скачать: [xml.tar.bz2];




Вниз

Вопрос к гуру от почти гуру. Доступ к protected методам 


cpp   (2002-02-15 11:32) [0]

Вот процедура формы Пример из справки Delphi

procedure TForm1.SaveAsBmpClick(Sender: TObject);
var
Source: TComponent;
SysPal : LogPal;
tempCanvas: TCanvas;
sourceRect, destRect: TRect;
image2save: TImage;
notUsed: HWND;
begin
Source := FindComponent(Edit1.Text);
if (not Source is TControl) or
((not Source is TWinControl) and ((Source as TControl).Parent = nil)) then
begin
Beep;
ShowMessage(Edit1.Text + " is not a valid control.");
Exit;
end;
tempCanvas := TCanvas.Create;
try
with Source as TControl do
tempCanvas.Handle := GetDeviceContext(notUsed);

Обратите внимание метод GetDeviceContext - protected !
не проходят конструкции типа

tempCanvas.Handle := (Source as TControl).GetDeviceContext(notUsed);
tempCanvas.Handle := TControl(Source).GetDeviceContext(notUsed);

В чём дело?



troits   (2002-02-15 11:36) [1]

TMyClass = class(TWinControl)
public
function GetDeviceContext(var WindowHandle: HWnd): HDC; override;
end;

function TMyClass.GetDeviceContext(var WindowHandle: HWnd): HDC;
begin
result := inherited;
end;

...

tempCanvas.Handle := TMyClass(Source).GetDeviceContext(notUsed);



troits   (2002-02-15 11:48) [2]

Да... А в примере баги явные - например, перед else ;
Так что торопились, наверное - не проверяли...



Юрий Федоров   (2002-02-15 11:56) [3]

Не надо писать своего потомка, потому что сам класс
TForm1 является потомком TControl и TWinControl.
То есть типизировать можно под TForm1 :

tempCanvas.Handle := TForm1(Source).GetDeviceContext(notUsed);
Только без использования As



Digitman (M)   (2002-02-15 12:11) [4]

Пример, видимо, с ошибкой. либо когда-то Борланд объявил его в public, а затем, по каким-то причинам (в принципе - по вполне понятным) решил перенести в protected, а хэлп не подредактировал в соответствии с изменениями. Что ж , и великий Борланд имеет право на ошибку, согласись ?

Ну, что тут можно сделать ? Попробуй "выдрать" участки кода, реализующие функ-ть этого метода, из модуля Controls прямо в свой код. Не так уж там и много : собственно тело TControl.GetDeviceContext() и тело TWinControl.GetDeviceContext(), которое исполняется для объекта, являющегося Parent для текущего контрола. Всего-то в общ.сложности - дюжина доп.строчек. Можно даже прямо на WinAPI их реализовать. Мороки, конечно, чуть больше, но, если оч.нужно, то не так уж и проблематично получить тот же результат "через задний кирильцо")



troits   (2002-02-15 12:16) [5]

>Юрий Федоров
Честно говоря, я не вижу никаких преимуществ Вашего способа. Все равно придется переносить GetDeviceContext в public. А объявлением вспомогательного класса пример становится более понятным - мы не "замусориваем" класс TForm.



Digitman (M)   (2002-02-15 12:39) [6]

А вообще-то GetDeviceContext() здесь вызывается не для TControl(Source) , а для self. Компилятор, не обнаружив public-метода у Source as TControl, справедливо подставил вызов собственного protected-метода объекта Self. Скомпилировано будет без ошибок (здесь не рассматриваем явные синтакс.ляпы в примере), но работать, конечно же, будет неверно : в *.BMP будет сохранен совершенно не тот BMP-образ, который ожидался (хотя размер образа будет совпадать с размерами контрола на форме)



Юрий Зотов (M)   (2002-02-15 12:42) [7]

troits © (15.02.02 12:16)

Ничего никуда переносить не нужно. И никаких своих потомков писать тоже не нужно. Общий способ доступа к protected-секции любого класса - это объявить в своем юните потомка этого класса (только объявить, больше ничего не требуется). Например:

type
TFriendClass = class(TSomeClass);

После этого в своем юните Вы получаете доступ к protected-секции класса TSomeClass, приводя его к TFriendClass.

А поскольку класс TForm1 у Вас уже и так объявлен, то можно приводить к TForm1.



troits   (2002-02-15 12:45) [8]

Да. Был не прав.



Digitman (M)   (2002-02-15 13:14) [9]

Да, <Юрий Зотов> прав. Все, что надо здесь - это объявить дружественный класс как вспомогательный тип. К нему-то и следует, в конечном итоге, приводить тип найденного по FindComponent() контрола. Сойдемся на том, что в своем примере Борланд все же допустил ошибку, связанную с отсутствием декларации друж.класса и некорректного приведения типа.

С учетом всех этих замечаний участок проблемного кода в примере должен будет выглядеть так :


type
TFriendControl = class(TControl);//дружественный класс
...

tempCanvas.Handle := TFriendControl(Source).GetDeviceContext(notUsed);

вот и все, вот и заработало как надо)



cpp   (2002-02-15 13:19) [10]

Пример без ошибок и Digitman (M) прав.



cpp   (2002-02-15 13:21) [11]

когда говорил что

Компилятор, не обнаружив public-метода у Source as TControl, справедливо подставил вызов собственного protected-метода объекта Self.




Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.03.04;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.74 MB
Время: 0.024 c
1-9195            IronHawk              2002-02-12 15:37  2002.03.04  
ПРОСТО ! Быстрый, тупой, вопрос !


7-9298            Unkown                2001-11-26 12:26  2002.03.04  
Чем протестировать компьютер?


1-9155            sammy                 2002-02-07 08:33  2002.03.04  
как создать hint


14-9285           Геннадий              2002-01-18 07:51  2002.03.04  
Ребята, подскажите где можно скачать бесплатную версию InterBase


1-9166            VSoft                 2002-02-14 07:49  2002.03.04  
Кол-во файлов и их имена в определенном каталоге