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

Вниз

Свой TEdit   Найти похожие ветки 

 
Ling ©   (2005-10-24 19:22) [0]

Поискал я, поискал, но ничего толкового не нашёл.
Уже долгое время у меня мечта сделать свой TEdit, с собственной прорисовкой содержимого.

Большая необходимость в нём возникает, когда например нужно редактировать ячейку таблицы, оформленной в каком-нибудь стиле, с бэкграундом, артшрифтами, неровным положением текста и т.д.

Быо бы просто великолепно и удобно, создать свой редактор строки, с вынесенной в событие прорисовкой onFrameDraw, onTextDraw, onCursorDraw свойством транспарент и т.д.

Я в принципе всё это смогу сделать, но меня смущает то, что это виндовый контрол, и я не слишком хорошо знаю специфику его работы, то есть я хочу сказать, что не знаю, как сделать, что-бы он работал так-же хорошо, как и обычный TEdit.

Например как прицепить к нему стандартное выпадающее меню правки, какие события обрабатывать на вставку, удаление, вырезание, как правильно сделать мигающий курсор- через внутренний экземпляр TTimer, или по другому, как правильно отслеживать потерю и получение фокуса, и вообще какими особенностями обладает этот компонент.

Я хотел бы попросить Мастеров, у которых есть наработки в этой области, немного помочь мне советами 8)))


 
Ling ©   (2005-10-24 19:58) [1]

(жирным выделены вопросы)
Я решил, что TMyEdit должен наследоваться от   class(TGraphicControl).
Добавил ему свойство
   Property Text:string read FText write SetText;

Думаю для начала, нужно сделать, что-бы мой компонент хоть как-нибудь отображался. Не долго жумая нахожу первого попавшегося наследника от того же класса, им оказался
 TGauge = class(TGraphicControl)
с панели Samples. Смотрим, как он прорисовывается... вроде всё просто

procedure TGauge.Paint;
var
 TheImage: TBitmap;
 OverlayImage: TBltBitmap;
 PaintRect: TRect;
begin
 with Canvas do
 begin
   TheImage := TBitmap.Create;
   try
     TheImage.Height := Height;
     TheImage.Width := Width;
     PaintBackground(TheImage);
     PaintRect := ClientRect;
     if FBorderStyle = bsSingle then InflateRect(PaintRect, -1, -1);
     OverlayImage := TBltBitmap.Create;
     try
       OverlayImage.MakeLike(TheImage);
       PaintBackground(OverlayImage);
       case FKind of
         gkText: PaintAsNothing(OverlayImage, PaintRect);
         gkHorizontalBar, gkVerticalBar: PaintAsBar(OverlayImage, PaintRect);
         gkPie: PaintAsPie(OverlayImage, PaintRect);
         gkNeedle: PaintAsNeedle(OverlayImage, PaintRect);
       end;
       TheImage.Canvas.CopyMode := cmSrcInvert;
       TheImage.Canvas.Draw(0, 0, OverlayImage);
       TheImage.Canvas.CopyMode := cmSrcCopy;
       if ShowText then PaintAsText(TheImage, PaintRect);
     finally
       OverlayImage.Free;
     end;
     Canvas.CopyMode := cmSrcCopy;
     Canvas.Draw(0, 0, TheImage);
   finally
     TheImage.Destroy;
   end;
 end;
end;


но возникает вопрос- Зачем создаются два битмапа. Какой смысл в рисовании на OverlayImage, а не на TheImage?


 
Ling ©   (2005-10-24 19:59) [2]

Завтра продолжу в 20:00 кончается инет


 
Igorek ©   (2005-10-24 20:25) [3]

См. в msdn раздел User Controls.
Но, чесно говоря, трудное это дело - писать контролы с самого нуля...


 
PAVIA ©   (2005-10-24 20:39) [4]

Я тоже в этом плохо разбираюсь. По-этому с удовольствием выслушаю мнение профисионалов.
Но помойму нужно делать от другого класса.
TEdit. -Являеться оконным компонентом. По-этуму я счел использовать для подобной цели. TCustomControl он удовлетволил меня в большей степени чем TGraphicControl. Дальше идет примерный наброссок.  Многое закоментированно так-как не все доделанно. Вернее даже это экспеременальный скрипт. Нужно со многим еще разобраться.
type
 TCustomAditor = class(TCustomControl)
 private
{    procedure WMCaptureChanged(var Msg: TMessage); message WM_CAPTURECHANGED;
   procedure WMCopy(var Message: TMessage); message WM_COPY;
   procedure WMCut(var Message: TMessage); message WM_CUT;
   procedure WMDropFiles(var Msg: TMessage); message WM_DROPFILES;
   procedure WMEraseBkgnd(var Msg: TMessage); message WM_ERASEBKGND;
 }  procedure WMGetDlgCode(var Msg: TWMGetDlgCode); message WM_GETDLGCODE;
 {  procedure WMHScroll(var Msg: TWMScroll); message WM_HSCROLL;
   procedure WMPaste(var Message: TMessage); message WM_PASTE;
   procedure WMCancelMode(var Message:TMessage); message WM_CANCELMODE;
}   procedure WMKillFocus(var Msg: TWMKillFocus); message WM_KILLFOCUS;
   procedure WMMouseWheel(var Msg: TMessage); message WM_MOUSEWHEEL;
   procedure WMSetCursor(var Msg: TWMSetCursor); message WM_SETCURSOR;
   procedure WMSetFocus(var Msg: TWMSetFocus); message WM_SETFOCUS;
   procedure WMSize(var Msg: TWMSize); message WM_SIZE;
//    procedure WMVScroll(var Msg: TWMScroll); message WM_VSCROLL;
   { Private declarations }
 private
{    FHScrollBar : TScrollBar;
   FVScrollBar : TScrollBar;
}
   FBorderStyle: TBorderStyle;
   procedure CreateParams(var Params: TCreateParams); override;
   procedure KeyDown(var Key: Word; Shift: TShiftState); override;
   procedure KeyPress(var Key: Char); override;
protected
   procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
   procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
   procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
   procedure Paint; override;
//    procedure WndProc(var Msg: TMessage); override;

   { Protected declarations }
 public
//    procedure CutToClipboard;
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
 { Public declarations }
 published
   property Color;
   property ParentColor;
   { Published declarations }
 end;
...

procedure TCustomAditor.WMKillFocus(var Msg: TWMKillFocus);
begin
 inherited;
 Windows.HideCaret(Handle);
 Windows.DestroyCaret;
end;

procedure TCustomAditor.WMSetFocus(var Msg: TWMSetFocus);
var cw,ch:integer;
begin
 cw:=2;
 ch:=14;
 CreateCaret(Handle,0, cw, ch);
 ShowCaret(Handle);
//  UpdateCaret;
end;


Выше также показанно, как работать с кореткой. Правдо, нужно добавить, чтобы каретка встовала в свое положение.Насчет фокуса при щелчке мышкой по компоненту ему нужно установить фокус  Windows.SetFocus(Handle);
Ты пошол TGauge, а это визуальный компонент. Для того, чтобы прогрессбар не моргал используют двойную буфиризацию. По-этому там рисуеться на OverlayImage.


 
umbra ©   (2005-10-24 20:44) [5]


> Но помойму нужно делать от другого класса.


TCustomEdit


 
Ling ©   (2005-10-25 12:27) [6]

Вчера переосмыслил работу будущего компонента, действительно, нужно делать родителем либо TWinControl, либо TCustomEdit.

Для пробы создал от TCustomEdit, добавил Pen, Brush, Canvas, переопределил:
   procedure WMPaint(var Message: TWMPaint); message WM_PAINT;

procedure TMyEdit2.WMPaint(var Message: TWMPaint);
var
 X, Y, W, H, S: Integer;
begin
 with FCanvas do
 begin
   Pen := FPen;
   Brush := FBrush;
   X := Pen.Width div 2;
   Y := X;
   W := Width - Pen.Width + 1;
   H := Height - Pen.Width + 1;
   if Pen.Width = 0 then
   begin
     Dec(W);
     Dec(H);
   end;
   if W < H then S := W else S := H;
   Inc(X, (W - S) div 2);
   Inc(Y, (H - S) div 2);
   W := S;
   H := S;
   Ellipse(X, Y, X + W, Y + H);
 end;
end;


Хммм.... Я и не знал, что WM_PAINT вызывается постоянно.... обнаруживаю посреди эдита постоянно мигающий элипс, в остальном всё работает как в эдите.
Вопрос к мастерам - Paint так и должен постоянно вызываться и без конца перерисовывать контрол, или я что-то забываю сделать, может мне нужно установить какой-нибудь флаг в messege, или что-то в этом роде, что-бы просигналить о том, что перерисовка произведена?

Попробовал поменять родителя на TWinControl , остался только мерцающий элипс.

Хмм.... если я перегрузил WM_Paint, то почему же потомок TCustomEdit продолжает отрисовывать фрейм, и даже буквы.... Поковырялся в родителях, нашёл
   procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT;


переопределяю, ставлю всё тот-же код еллипса,
хмм... уже лучше.... имеем белый прямоугольник, и всё тот-же мерцающий эллипс, букв не видно. ...Думаем, как избавиться от белого прямоугольника.


 
Ling ©   (2005-10-25 13:06) [7]

Ошибочка - буквы по прежнему прорисовываются.
К тому же обнаруживаем неприятный эффект - дельфа начинает страшно тормозить из-за постоянной перерисовки.

Долго сидел, и рассматривал работу TCustomEdit..... появляются сомнения в том, что я смогу полностью переопределить перерисовку этого контрола. Он создаёт виндовый эдит, и общается с ним посредством сообщений..... хотя может можно сделать виндовый эдит, скрыть его, оставив при этом в рабочем состоянии, и рисовать самому, опять-таки обмениваясь с ним сообщениями.
Похоже придётся делать рдителем TWinControl, тот покрайней мере ничего не рисует

PAVIA © -спасибо за каретку 8))

Уважаемые мастера - выскажите пожалуйста своё мнение, от какого родителя лучше создавать такой контрол, и почему


 
umbra ©   (2005-10-25 14:49) [8]


> Paint так и должен постоянно вызываться и без конца перерисовывать
> контрол


Да, обработчики сообщений автоматически вызываются, когда контрол получает соответствующее сообщение. А перерисовка происходит в ответ практически на все действия пользователя.


 
Ling ©   (2005-10-25 15:23) [9]

umbra - спасибо 8))

Пока делал другую работу наткнулся на следующее:
TCustomControl
Этот класс происходит от класса TWinControl. Он вводит концепцию канвы и содержит метод Paint( ), предоставляющий расширенный контроль над внешним видом вашего компонента. Этот класс используется в основном для создания пользовательских оконных элементов


Наверно надо будет использовать его, как и предлагал PAVIA ©


 
umbra ©   (2005-10-25 15:30) [10]


> TCustomControl


Но тогда все, что касается текста надо будет писать с нуля


 
Юрий Зотов ©   (2005-10-26 04:57) [11]

> Ling

Если нужно изменить только прорисовку содержимого, то наследуйтесь от TCustomEdit, а прорисовку делайте по примеру TDBEdit в обработчике WM_PAINT.


 
Avega   (2005-12-09 09:42) [12]

Удалено модератором
Примечание: Offtopic



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

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

Наверх




Память: 0.51 MB
Время: 0.034 c
15-1148972466
TButton
2006-05-30 11:01
2006.06.25
тех.док.


4-1142613185
AndreyRus
2006-03-17 19:33
2006.06.25
Аналог IOCTL_SCSI_RESCAN_BUS в Windows 2003


15-1148898228
vidiv
2006-05-29 14:23
2006.06.25
"http://www.microsoft.com/rus/getthefacts/topics/ipi.mspx"...


4-1143534352
serg111111
2006-03-28 12:25
2006.06.25
Как в имеющемся приложениия написать сервис?


2-1149612650
qazwsx
2006-06-06 20:50
2006.06.25
Как получать параметры переданные через командную строку?