Не могу перекрыть базовый метод [Delphi]

dimon72

Хочу перекрыть метод из юнита Classes. Дописываю в конце объявления метода (в Classes) "virtual", сохраняю юнит. В методе класса-наследника дописываю "override". При компиляции говорит, что нельзя перекрыть статический метод. Непонятно. Я же в базовом классе объявил этот метод виртуальным. Что здесь не правильно?

klyv

может, потому что
нельзя перекрыть статический метод
?
проблема в том, что он статический, а не виртуальный/невиртуальный

dimon72

Я не совсем понял. А "virtual" тогда для чего дописывают?

yolki

потому что нельзя менять системные исходники. они даны AS IS, так сказать FYI.
Если очень надо - переписывай Classes.pas в каталог своего проекта и включай его в проект. Ещё лучше - переобзови его как myClasses.pas.

yolki

Если нужно серьёзное расширение базовых классов, советую посмотреть в сторону JCL - это опенсорсная коллекция библиотек, которые существенно расширяют модули Classes, SysUtils и им подобные.

dimon72

потому что нельзя менять системные исходники. они даны AS IS, так сказать FYI.
Если очень надо - переписывай Classes.pas в каталог своего проекта и включай его в проект. Ещё лучше - переобзови его как myClasses.pas.
Да, я уже понял. Засада, блин. Буду делать свой юнит.

dimon72

Если нужно серьёзное расширение базовых классов, советую посмотреть в сторону JCL - это опенсорсная коллекция библиотек, которые существенно расширяют модули Classes, SysUtils и им подобные.
А они идут как надстройка над системными библиотеками или устанавливаются вместо их?

yolki

как отдельные юниты будут.
ну и будут называться типа jcClasses, jcStrUtils etc

dimon72

Понятно. Спасибо. А VCL-то можно перекомпилить. ;) 1. стираешь *.dcu-файл, нужной тебе библиотеки, который лежит в директории Lib. 2. Закидываешь в эту же директорию правленный *.pas той же библиотеки. В программе, использующей эту библиотеку, делаешь "Compile All". Компилятор создаст новый *.dcu. 3. Можешь удалить правленный *.pas из директории Lib. Всё. Таким образом мне-таки удалось перекрыть метод NextToken класса TParser, который реализован с ошибкой.
Так что "не боги горшки обжигают". Это я к твоему "аффтор...зачем использовать говно 20-давности..." в соседней теме. Откуда тебе знать, зачем я TC использую? Может он и говно, но я его на КПК под Dos гоняю, потому что мне удобно. Такие дела.

kill-still

исходники подменять нельзя, а вот переопределять классы - влёгкую!
вот вам пример:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

const
TMWM__SpecialInvalidate = WM_USER + 1111;

type
TEdit = class(StdCtrls.TEdit)
private
FClarity : Boolean;
procedure SetClarity(const Value: Boolean);
{ Private declarations }
protected
{ Protected declarations }
procedure CMEraseBkgnd (var Message: TWMEraseBkgnd); Message WM_ERASEBKGND;
procedure WMSetText (var Message: TWMSetText);
procedure SpecialInvalidate(var Message: TMessage); message TMWM__SpecialInvalidate;
procedure CNCTLCOLOREDIT (var Message: TWMCTLCOLOREDIT); message CN_CTLCOLOREDIT;
procedure WMKeyDown (var Message: TWMKeyDown); message WM_KEYDOWN;
procedure WMKillFocus (Var Message: TWMKillFocus); Message WM_KillFocus;
procedure WMLButtonDown (Var Message: TWMLButtonDown); Message WM_LButtonDown;
procedure WMMove (Var Message: TWMLButtonDown); Message WM_Move;
procedure WMMouseMove (Var Message: TWMMouseMove); Message WM_MouseMove;
procedure CreateParams(var Params: TCreateParams); override;
procedure CreateWnd; override;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
procedure Invalidate; override;
property Clarity:Boolean read FClarity write SetClarity default True;
end;

TForm1 = class(TForm)
Edit1: TEdit;
private
{ Private declarations }
public
{ Public declarations }
end;


var
Form1: TForm1;

implementation

{$R *.dfm}

{ TEdit }

procedure TEdit.CMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
if Clarity then
Message.Result := 1;
end;

procedure TEdit.CNCTLCOLOREDIT(var Message: TWMCTLCOLOREDIT);
begin
if Clarity then
with Message do
begin
SetBkMode(ChildDC,Windows.TRANSPARENT);
Result:=GetStockObject(HOLLOW_BRUSH);
end
else inherited;
end;

constructor TEdit.Create(AOwner: TComponent);
begin
inherited create(AOwner);
BorderStyle := bsNone;
BevelKind := bkNone;
Clarity:=true;
end;

procedure TEdit.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
if (CsDesigning in ComponentState) then exit;
with Params do
begin
ExStyle:=ExStyle or WS_EX_TRANSPARENT;
end;
end;

procedure TEdit.CreateWnd;
begin
inherited CreateWnd;
if Clarity then
begin
SetWindowLong(Parent.Handle, GWL_STYLE,
GetWindowLong(Parent.Handle, GWL_STYLE) and not WS_CLIPCHILDREN);
end;
end;

procedure TEdit.Invalidate;
begin
if Clarity then PostMessage(Handle,TMWM__SpecialInvalidate,0,0)
else inherited;
end;

procedure TEdit.SetClarity(const Value: Boolean);
begin
FClarity := Value;
end;

procedure TEdit.SpecialInvalidate(var Message: TMessage);
var
rect:TRect;
begin
if Parent<>nil then
begin
rect:=ClientRect;
rect.TopLeft:=Parent.ScreenToClient(ClientToScreen(rect.TopLeft;
rect.BottomRight:=Parent.ScreenToClient(ClientToScreen(rect.BottomRight;
InvalidateRect(Parent.Handle,@rect,true);
RedrawWindow(Handle,nil,0,RDW_FRAME+RDW_INVALIDATE)
end;
end;

procedure TEdit.WMKeyDown(var Message: TWMKeyDown);
begin
SendMessage(Handle,TMWM__SpecialInvalidate,0,0);
inherited;
PostMessage(Handle,TMWM__SpecialInvalidate,0,0);
end;

procedure TEdit.WMKillFocus(var Message: TWMKillFocus);
begin
inherited;
if not (csDesigning in ComponentState) then
PostMessage(Handle,TMWM__SpecialInvalidate,0,0)
end;

procedure TEdit.WMLButtonDown(var Message: TWMLButtonDown);
begin
inherited;
if not (csDesigning in ComponentState) then
PostMessage(Handle,TMWM__SpecialInvalidate,0,0);
end;

procedure TEdit.WMMouseMove(var Message: TWMMouseMove);
begin
inherited;
if not (csDesigning in ComponentState) then
PostMessage(Handle,TMWM__SpecialInvalidate,0,0);
end;

procedure TEdit.WMMove(var Message: TWMLButtonDown);
begin
inherited;
//if not (csDesigning in ComponentState) then
PostMessage(Handle,TMWM__SpecialInvalidate,0,0);
end;

procedure TEdit.WMSetText(var Message: TWMSetText);
begin
inherited;
if not (csDesigning in ComponentState) then
PostMessage(Handle,TMWM__SpecialInvalidate,0,0);
end;

end.

Но гораздо правильнее запихать его в пэкадж, и присвоить какое-нибудь собственное имя.

dimon72

исходники подменять нельзя
В смысле? Перекомпилировать как раз можно. Другое дело, что нежалательно их корректировать.

Corrector

А что за задача возникла такая, что надо менять Classes.pas? Напиши, порешаем.

yolki

Скажем так - почему возникло желание перекрывать неперекрываемый метод?
Всё, что пользователю может взбрести в голову перекрывать - объявлено как virtual. Например, Sort у TStringList-a

kill-still

Не всё. :o
примеры что-то не могу уже припомнить.
?например wm_paint у всяких компонентов(нед ide под рукой, завтра мб гляну)

yolki

а зачем wm_paint перекрывать?!
если ты рисуешь на компоненте нечто, для чего этот компонент не предназначен - это же бред. для этого есть TImage.

kill-still

имадж - графический компонент.
рисую я обычно на контролах.

yolki

почему для этих целей не подходит image?
ведь канвас и там и там, а у имаджа ещё и перерисовку не надо свою писать...

kill-still

Много чем...
Хотя бы тем, что не контролы не могут получать фокус.

kill-still

перерисовку не надо свою писать...
Ещё как надо, а тут - подправил чуток и ок! =)

yolki

что-то я тогда не понимаю.
можешь привести конкретный пример?

kill-still

Например - выше в теме эдит с прозрачным фоном.
Оставить комментарий
Имя или ник:
Комментарий: