title: Make a TDBEdit show the characters remaining
body: <p>The problem I'm wanting to solve is to display to the user the remaining characters left in a field as they are typing into a TDBEdit.</p>
  
  <p>Currently I'm doing something along the lines of</p>
  
  <pre><code>lCharRemaining.Caption := Field.Size - length(dbedit.text);
  </code></pre>
  
  <p>i.e. updating a label in the OnChange event for the TDBEdit, which works perfectly fine.  However I'm wanting to do this for a number of TDBEdits and tried to write a custom component that would display the length remaining within the edit box on the right.  It however interferes with editing.  I was perhaps thinking that I could display a hint while someone was typing indicating the remaining space in the field - any suggestions?</p>
  
  <p>Here is the code for my component (if someone can suggest improvements).</p>
  
  <pre><code>unit DBEditWithLenghtCountdown;
  
  interface
  
  uses
    SysUtils, Classes, Controls, StdCtrls, Mask, DBCtrls, messages, Graphics;
  
  type
    TDBEditWithLenghtCountdown = class(TDBEdit)
    private
      { Private declarations }
      FCanvas: TCanvas;
      procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
    protected
      { Protected declarations }
      property Canvas: TCanvas read FCanvas;
      procedure WndProc(var Message: TMessage); override;
    public
      { Public declarations }
      function CharactersRemaining : integer;
      constructor Create(AOwner: TComponent); override;
      destructor Destroy; override;
    published
      { Published declarations }
    end;
  
  procedure Register;
  
  implementation
  
  uses
    db, Types;
  
  procedure Register;
  begin
    RegisterComponents('Samples', [TDBEditWithLenghtCountdown]);
  end;
  
  { TDBEditWithLenghtCountdown }
  
  function TDBEditWithLenghtCountdown.CharactersRemaining: integer;
  begin
    result := -1;
    if Assigned(Field)then
    begin
      result := Field.Size - Length(Text);
    end;
  end;
  
  constructor TDBEditWithLenghtCountdown.Create(AOwner: TComponent);
  begin
    inherited Create(AOwner);
    FCanvas := TControlCanvas.Create;
    TControlCanvas(FCanvas).Control := Self;
  end;
  
  destructor TDBEditWithLenghtCountdown.Destroy;
  begin
    FCanvas.Free;
    inherited;
  end;
  
  procedure TDBEditWithLenghtCountdown.WMPaint(var Message: TWMPaint);
  var
    R: TRect;
    Remaining : string;
    WidthOfText: Integer;
    x: Integer;
  begin
    inherited;
    if not focused then
      exit;
  
  
    Remaining := IntToStr(CharactersRemaining);
    R := ClientRect;
    Inc(R.Left, 1);
    Inc(R.Top, 1);
    Canvas.Brush.Assign(Self.Brush);
    Canvas.Brush.Style := bsClear;
    Canvas.Font.Assign(Self.Font);
    Canvas.Font.Color := clRed;
  
    WidthOfText := Canvas.TextWidth(Remaining);
    x := R.right - WidthOfText - 4;
    Canvas.TextOut(x,2, Remaining);
  end;
  
  procedure TDBEditWithLenghtCountdown.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; // case
  end;
  
  end.
  </code></pre>