Squeak.ru - шаблоны программирования

Как настроить отрисовку контрольного текста TEdit?

Я хотел бы нарисовать кусок TEdit.Text, используя Font.Color, отличный от значения по умолчанию. Есть какие-нибудь примеры, как это сделать?

Я пытаюсь сделать что-то вроде этого:

ПРИМЕЧАНИЕ: то, что изображено на этом скриншоте, - всего лишь небрежный набросок, но он убеждает меня, какую проблему можно решить.

18.03.2012

  • Вы можете поделиться своим решением, чтобы мы могли его обсудить и оставить отзыв (снимок экрана не является решением). 19.03.2012
  • @kobik, может быть серия простых вопросов, посвященных конкретным проблемам, на которые я наткнулся. Но это может случиться позже, сейчас я не застрял. 19.03.2012

Ответы:


1

Edit элементы управления не имеют поддержки рисования владельцем, но вы можете рисовать вручную, создав подклассы и обработав WM_PAINT (среди многих других сообщений). Это выполнимо, но было бы очень сложно реализовать на 100% правильно. Из документов: Разработка пользовательских элементов управления отрисовкой в ​​Visual C ++:

Обратите внимание, что рисование владельцем будет работать для большинства элементов управления. Однако это не работает для элементов управления редактированием; а что касается элемента управления списком, он работает только для стиля просмотра отчета

Мне также было интересно узнать, насколько глубока кроличья нора, поэтому
Вот пример кода с использованием класса интерпозера (все еще необходимо реализовать выбор, но пользовательский рисунок работает, когда курсор находится в элементе управления):

type
  TEdit = class(StdCtrls.TEdit)
  private
    FCanvas: TCanvas;
    procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  protected
    procedure WndProc(var Message: TMessage); override;
    procedure Paint; virtual;
    procedure PaintWindow(DC: HDC); override;
    property Canvas: TCanvas read FCanvas;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

...

constructor TEdit.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FCanvas := TControlCanvas.Create;
  TControlCanvas(FCanvas).Control := Self;
end;

destructor TEdit.Destroy;
begin
  FCanvas.Free;
  inherited Destroy;
end;

procedure TEdit.Paint;
var
  R: TRect;
  I: Integer;
  S: String;
begin
  R := ClientRect;
  Inc(R.Left, 1);
  Inc(R.Top, 1);
  Canvas.Brush.Assign(Self.Brush);
  Canvas.Font.Assign(Self.Font);
  for I := 1 to Length(Text) do
  begin
    if Text[I] in ['0'..'9'] then
      Canvas.Font.Color := clRed
    else
      Canvas.Font.Color := clGreen;
    S := Text[I];
    DrawText(Canvas.Handle, PChar(S), -1, R, DT_LEFT or DT_NOPREFIX or
      DT_WORDBREAK or DrawTextBiDiModeFlagsReadingOnly);
    Inc(R.Left,Canvas.TextWidth(S));
  end;
end;

procedure TEdit.PaintWindow(DC: HDC);
begin
  FCanvas.Lock;
  try
    FCanvas.Handle := DC;
    try
      TControlCanvas(FCanvas).UpdateTextFlags;
      Paint;
    finally
      FCanvas.Handle := 0;
    end;
  finally
    FCanvas.Unlock;
  end;
end;

procedure TEdit.WMPaint(var Message: TWMPaint);
begin
  ControlState := ControlState+[csCustomPaint];
  inherited;
  ControlState := ControlState-[csCustomPaint];
end;

procedure TEdit.WndProc(var Message: TMessage);
begin
  inherited WndProc(Message);
  with Message do
    case Msg of
      CM_MOUSEENTER, CM_MOUSELEAVE, WM_LBUTTONUP, WM_LBUTTONDOWN,
      WM_KEYDOWN, WM_KEYUP,
      WM_SETFOCUS, WM_KILLFOCUS,
      CM_FONTCHANGED, CM_TEXTCHANGED:
      begin
        Invalidate;
      end;
   end; 
end;

введите описание изображения здесь

19.03.2012
  • Спасибо, этот пример действительно подтолкнул меня к изучению и указывает на многочисленные нюансы, которые я полностью упустил (например, csCustomPaint). 20.03.2012
  • Поскольку вы не используете собственную поверхность элемента управления, вы должны учитывать все возможные варианты отображения. Например, помимо выбора, вы также должны учитывать, когда текст должен отображаться, начиная с символа, отличного от первого - когда текст больше, чтобы соответствовать элементу управления, и пользователь прокрутил его до конца. На самом деле вы будете развивать свой элемент управления редактированием, а не использовать его! .. 20.03.2012
  • @SertacAkyuz Я только что использовал код, предоставленный kobik, с изменениями только того, как отрисовывается текст, и все упомянутые вами случаи обрабатываются должным образом. Конечно, это произошло 5 лет спустя и в другой версии ОС и Delphi, но в качестве справки приведенный выше код отлично справился с тем, что мне пришлось делать. 23.08.2017

  • 2

    Нет. Стандартный tEdit не поддерживает пользовательский рисунок или текст с несколькими цветами. В качестве альтернативы вы можете использовать tRichEdit с WantReturns = False.

    18.03.2012
  • Я согласен с тем, что добавление поддержки пользовательских чертежей - это настоящая PITA, учитывая то, что она происходит непосредственно от TWinControl, однако я доказал, что это вполне выполнимо. 19.03.2012
  • @user - я был бы удивлен, если ваш пользовательский рисунок будет работать, когда курсор находится в элементе управления. Имеет ли это? 19.03.2012
  • @SertacAkyuz, было бы действительно смелым заявлением сказать, что моя попытка до сих пор работает :-) Тем не менее, я не уверен, что это вообще невыполнимо. 19.03.2012
  • @Mike W, элементы управления редактированием не имеют поддержки рисования владельцем, но вы можете настроить его, выделив его на подклассы и обработав WM_PAINT (среди многих других сообщений). Это выполнимо, но это будет мир боли. 19.03.2012
  • @kobik - согласился. Я должен был сказать, что у него нет встроенной поддержки 20.03.2012

  • 3

    Некоторые улучшения в солюшене кобиков:

    procedure TMyEdit.Paint;
    var
      R: TRect;
      I: Integer;
    
      NewColor : TColor;
      NewBackColor : TColor;
    
      procedure DrawEx(S: String);
      begin
         if ((i-1)>=Self.SelStart) and ((i-1)<=(Self.SelStart+(Self.SelLength-1)))
            and (Self.SelLength>0) and (Self.focused)
           then begin
             Canvas.Font.Color  := clWhite;
             Canvas.Brush.Color := NewColor;
           end else begin
             Canvas.Font.Color  := NewColor;
             Canvas.Brush.Color := NewBackColor;
           end;
         Canvas.Brush.Style := bsSolid;
         DrawText(Canvas.Handle, PChar(S), -1, R, DT_LEFT or DT_NOPREFIX or
           DT_WORDBREAK or DrawTextBiDiModeFlagsReadingOnly);
      end;
    
    begin
      R := ClientRect;
      Inc(R.Left, 1);
      Inc(R.Top, 1);
      Canvas.Brush.Assign(Self.Brush);
      Canvas.Font.Assign(Self.Font);
    
      if Self.Focused then begin
          NewBackColor       := clYellow;
          Canvas.Brush.Color := NewBackColor;
          Canvas.Brush.Style := bsSolid;
          Canvas.FillRect(ClientRect);
          Canvas.DrawFocusRect(ClientRect);
        end else NewBackColor := clWhite;
    
      for I:=1 to Length(Text) do begin
       if PasswordChar=#0 then begin
         if Text[I] in ['0'..'9'] then begin
           NewColor := clRed;
           DrawEx(Text[I]);
          end else begin
           NewColor := clGreen;
           DrawEx(Text[I]);
          end;
         Inc(R.Left,Canvas.TextWidth(Text[I]));
        end else begin //with passwordchar
           NewColor := clBlack;
           DrawEx(PasswordChar);
         Inc(R.Left,Canvas.TextWidth(PasswordChar));
        end;
      end;
    end;
    
    19.02.2014

    4

    Еще одно небольшое улучшение, переопределив процедуру CreateParams, которая устраняет мерцание во время выделения текста (перемещение мыши при нажатой левой кнопке):

    procedure TMyEdit.CreateParams(var Params: TCreateParams);
    begin
        inherited;
        if csDesigning in ComponentState then
            exit;
        Params.ExStyle := Params.ExStyle or WS_EX_COMPOSITED;
    end;
    
    11.11.2019
    Новые материалы

    Угловая структура архитектуры
    Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

    «Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
    Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

    Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
    В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

    Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
    React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

    Создайте API с помощью Python FastAPI
    Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

    Веселье с прокси-сервером JavaScript
    Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

    Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
    Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...