Форум: "Основная";
Текущий архив: 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.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.03.04;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.005 c