Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.004 c
4-9331
NetBreaker666
2001-12-25 16:16
2002.03.04
Люди, понимаю, что мне пить надо меньше, на как получить список процессов.


1-9182
skiph
2002-02-08 07:46
2002.03.04
OLE


1-9151
Tsatur Soft
2002-02-16 23:35
2002.03.04
Срочно!


1-9163
Brand
2002-02-11 23:41
2002.03.04
Завершение Windows


3-9061
Wizd
2002-02-06 14:23
2002.03.04
Как удалить из DBF таблицы кучу ненужных полей? ...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский