Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.03.04;
Скачать: CL | DM;

Вниз

Вопрос к гуру от почти гуру. Доступ к 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.



Страницы: 1 вся ветка

Текущий архив: 2002.03.04;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.012 c
1-9129
ATLANTIDO
2002-02-14 17:56
2002.03.04
CobmoBox


3-9063
NickBat
2002-02-06 17:42
2002.03.04
Inerbase


1-9200
KS
2002-02-13 15:36
2002.03.04
Borland Delphi


1-9148
ЕвгенийА
2002-02-13 23:37
2002.03.04
Видео изображение меняет размеры в зависимости от размеров chart


7-9311
Никто
2001-11-30 04:20
2002.03.04
Системный таймер в XP (55 or 10 ms)