大悟还俗

邮箱 key_ok@qq.com 我的收集 http://pan.baidu.com/share/home?uk=1177427271
  新随笔  :: 联系 :: 订阅 订阅  :: 管理

带标题的编辑框

Posted on 2013-10-21 16:51  大悟还俗_2  阅读(300)  评论(0编辑  收藏  举报
unit ExEdit;
 
interface
 
uses
  System.Classes, Vcl.Controls, Winapi.Windows, Vcl.Graphics, Vcl.StdCtrls,
  System.SysUtils, Winapi.messages;
 
type
 
  TBorders = class(TPersistent)
  private
    FRight: Boolean;
    FBottom: Boolean;
    FTop: Boolean;
    FLeft: Boolean;
    FPen: TPen;
  public
    constructor Create;
    destructor Destroy; override;
  published
    property Pen: TPen read FPen write FPen;
    property Left: Boolean read FLeft write FLeft;
    property Right: Boolean read FRight write FRight;
    property Top: Boolean read FTop write FTop;
    property Bottom: Boolean read FBottom write FBottom;
  end;
 
  TAlterMode = (alterNone, alterFont, alterHeight);
 
  TExEdit = class(TWinControl)
  private
    FTitle: TCaption;
    FTitleLength: Integer;
    FLines: string;
    fAlterMode: TAlterMode;
    FBorders: TBorders;
    fMinHeight: Integer;
    fMaxFont: Integer;
    fOldText: string;
    fMinFont: Integer;
    fMaxHeight: Integer;
    procedure WMChar(var Msg: TWMChar); message WM_CHAR;
    procedure WMKeyDown(var Msg: TWMKeyDown); message WM_KEYDOWN;
    procedure WMPaint(var Msg: TWMPaint);message WM_PAINT;
    procedure setLines(const Value: string);
    procedure setTitle(const Value: TCaption);
    procedure Polyline(const Points: array of TPoint);
    function getSelection: TSelection;
    procedure checkMode(isRecursion: Boolean = False);
    procedure checkText;
    procedure setMaxHeight(const Value: Integer);
  protected
    { protected declarations }
    procedure CreateParams(var Params: TCreateParams); override;
    procedure Loaded();override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Font;
    property AlterMode: TAlterMode read fAlterMode write fAlterMode;
    property Borders: TBorders read FBorders write FBorders stored True;
    property Title: TCaption read FTitle write setTitle;
    property Lines: string read FLines write setLines;
    property MinFont: Integer read fMinFont write fMinFont default 12;
    property MaxHeight: Integer read fMaxHeight write setMaxHeight default 0;
  end;
 
implementation
 
{ TExEdit }
 
procedure TExEdit.checkMode(isRecursion: Boolean);
var
  vhdc: HDC;
  vidx,vpos,tmpH: Integer;
  vsize: TSize;
begin
 
  FLines := string(Text).Substring(FTitleLength);
 
  vhdc := GetDC(Self.Handle);
  vidx := Length(Text);
  vpos := Perform(EM_POSFROMCHAR,vidx - 1,0);
  SelectObject(vhdc, Font.Handle);
  Winapi.Windows.GetTextExtentPoint32(vhdc, 'A', 1, vsize);
  tmpH := HiWord(vpos)+vsize.cy + 5;
 
  if fAlterMode = alterNone then
  begin
    if (vpos = -1) or (tmpH > Height) then
      Perform(WM_CHAR,VK_BACK,$E0001);
  end;
 
  if fAlterMode = alterFont then
  begin
    if (vpos = -1) or (tmpH > Height) then
    begin
      Font.Size := Font.Size - 1;
      if fMinFont > Font.Size then
      begin
        Font.Size := fMinFont;
        Perform(WM_CHAR,VK_BACK,$E0001);
      end else
        checkMode(True);
    end
    else
    begin
      if not isRecursion and (fMaxFont > Font.Size) then
      begin
        Font.Size := Font.Size + 1;
        checkMode;
      end;
    end;
  end;
  if fAlterMode = alterHeight then
  begin
    if (vpos = -1) or (tmpH > Height) then
    begin
      Height := tmpH;
      if (fMaxHeight > 0) and (fMaxHeight < height) then
      begin
        Height := fMaxHeight;
        Perform(WM_CHAR,VK_BACK,$E0001);
      end else
        checkMode;
    end
    else
    begin
      Height := tmpH;
      if fMinHeight > Height then
        Height := fMinHeight;
    end;
  end;
end;
 
procedure TExEdit.checkText;
begin
  if fOldText <> Text then
  begin
    fOldText := Text;
    checkMode;
  end;
end;
 
constructor TExEdit.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FBorders := TBorders.Create;
  FBorders.Left := True;
  FBorders.Right := True;
  FBorders.Top := True;
  FBorders.Bottom := True;
  fMinFont := 12;
  fMaxHeight := 0;
end;
 
procedure TExEdit.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  CreateSubClass(Params, 'EDIT');
  with Params do
  begin
    Style := Style or ES_MULTILINE;
    { 完全重画 }
    Style := Style and not WS_CLIPCHILDREN;
    Style := Style and not WS_CLIPSIBLINGS;
    { 增加透明 }
    ExStyle := ExStyle or WS_EX_TRANSPARENT;
  end;
end;
 
destructor TExEdit.Destroy;
begin
  FBorders.Free;
  inherited Destroy;
end;
 
function TExEdit.getSelection: TSelection;
begin
  SendMessage(Handle, EM_GETSEL, NativeInt(@Result.StartPos),
  NativeInt(@Result.EndPos));
end;
 
procedure TExEdit.Loaded;
begin
  inherited;
  fMinHeight := Height;
  fMaxFont := Font.Size;
end;
 
type
  PPoints = ^TPoints;
  TPoints = array[0..0] of TPoint;
 
procedure TExEdit.Polyline(const Points: array of TPoint);
var
  vhdc: HDC;
begin
  vhdc := GetDC(Self.Handle);
  SelectObject(vhdc,Borders.Pen.Handle);
  SetROP2(vhdc, R2_COPYPEN);
  Winapi.Windows.Polyline(vhdc, PPoints(@Points)^, High(Points) + 1);
end;
 
procedure TExEdit.setLines(const Value: string);
begin
  FLines := Value;
  Text := Title + Lines;
end;
 
procedure TExEdit.setMaxHeight(const Value: Integer);
begin
  fMaxHeight := Value;
  if (fMaxHeight > 0) and (fMaxHeight < height) then
    fMaxHeight := Height;
end;
 
procedure TExEdit.setTitle(const Value: TCaption);
begin
  FTitle := Value;
  FTitleLength := Length(FTitle);
  Text := Title + Lines;
end;
 
procedure TExEdit.WMChar(var Msg: TWMChar);
var
  canInherited: Boolean;
begin
  canInherited := False;
  case Msg.CharCode of
    VK_BACK:
      canInherited :=
        (getSelection.StartPos >= FTitleLength)
          and (getSelection.EndPos > FTitleLength)
          and (Msg.KeyData <> 0);
  else
    canInherited := getSelection.StartPos >= FTitleLength;
  end;
  if canInherited then
  begin
    inherited;
    checkText;
  end;
end;
 
procedure TExEdit.WMKeyDown(var Msg: TWMKeyDown);
var
  canInherited: Boolean;
begin
  canInherited := False;
  case Msg.CharCode of
    VK_DELETE:
      canInherited := getSelection.StartPos >= FTitleLength;
  else
    canInherited := True;
  end;
  if canInherited then
  begin
    inherited;
    checkText;
  end;
end;
 
procedure TExEdit.WMPaint(var Msg: TWMPaint);
begin
  inherited;
  if Borders.Bottom then
    Polyline([Point(0, Height-1), Point(Width - 1, Height-1)]);
  if Borders.Left then
    Polyline([Point(0, 0), Point(0, Height - 1)]);
  if Borders.Right then
    Polyline([Point(Width - 1, 0), Point(Width - 1, Height - 1)]);
  if Borders.Top then
    Polyline([Point(0, 0), Point(Width - 1, 0)]);
end;
 
{ TBorders }
 
constructor TBorders.Create;
begin
  FPen := TPen.Create;
end;
 
destructor TBorders.Destroy;
begin
  FPen.Free;
  inherited Destroy;
end;
 
end.
View Code