Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Компоненты";
Текущий архив: 2006.06.25;
Скачать: [xml.tar.bz2];

Вниз

Свой 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.01 c
3-1146121628
Ильичев С.А.
2006-04-27 11:07
2006.06.25
SELECT после INSERT


2-1149608848
Iehbr
2006-06-06 19:47
2006.06.25
Что за глюк???


2-1149502986
новик
2006-06-05 14:23
2006.06.25
преобрпзование типов int64 в int


5-1134398300
Domkrat
2005-12-12 17:38
2006.06.25
ScrollBar width


2-1149674994
ksenia
2006-06-07 14:09
2006.06.25
реестр





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский