WEB开发网      濠电姷鏁告慨鐑藉极閸涘﹦绠鹃柍褜鍓氱换娑欐媴閸愬弶鎼愮痪鍓ф嚀閳规垿鎮╃€圭姴顥濋梺姹囧€楅崑鎾诲Φ閸曨垰绠涢柛顐f礃椤庡秹姊虹粙娆惧剳闁哥姵鍔欐俊鐢稿礋椤栨艾鍞ㄩ梺闈浤涙担鎻掍壕闁圭儤顨嗛埛鎺楁煕閺囥劌浜滄い蹇e弮閺屸€崇暆鐎n剛鏆犻柧浼欑到閵嗘帒顫濋悡搴d画缂佹鍨垮缁樻媴缁涘娈┑顔斤公缁犳捇銆佸鎰佹▌濠电姭鍋撳ù锝囩《閺€浠嬫煟濡鍤嬬€规悶鍎辫灃闁绘ê寮堕崯鐐电磼閸屾氨效鐎规洘绮忛ˇ瀵哥棯閹佸仮鐎殿喖鐖煎畷鐓庘槈濡警鐎崇紓鍌欑劍椤ㄥ棗鐣濋幖浣歌摕闁绘棃顥撻弳瀣煟濡も偓閻楀棗鈻撳Δ鍛拺閻犲洠鈧櫕鐏€闂佸搫鎳愭慨鎾偩閻ゎ垬浜归柟鐑樼箖閺呮繈姊洪棃娑氬婵☆偅鐟╅、娆掔疀閺冨倻鐦堥梺姹囧灲濞佳勭閿曞倹鐓曢柕濞垮劤閸╋絾顨ラ悙鏉戝妤犵偞锕㈤、娆撴嚃閳哄骞㈤梻鍌欐祰椤鐣峰Ο鑲╃煋妞ゆ棁锟ユ禍褰掓煙閻戞ɑ灏ù婊冪秺濮婅櫣绱掑Ο铏逛桓闂佹寧娲嶉弲娑滅亱闂佸憡娲﹂崹閬嶅煕閹达附鐓欓柤娴嬫櫅娴犳粌鈹戦垾鐐藉仮闁诡喗顨呴埥澶愬箳閹惧褰囩紓鍌欑贰閸犳牠顢栭崨鎼晣闁稿繒鍘х欢鐐翠繆椤栨粎甯涙繛鍛喘濮婄粯鎷呴悷閭﹀殝缂備浇顕ч崐鍨嚕缂佹ḿ绡€闁搞儯鍔嶅▍鍥⒑缁嬫寧婀扮紒瀣崌瀹曘垽鎮介崨濠勫幗闁瑰吋鐣崹濠氬煀閺囥垺鐓ユ慨妯垮煐閻撶喖鐓崶銉ュ姢缂佸宕电槐鎺旂磼濡偐鐣虹紓浣虹帛缁诲牆鐣峰鈧俊姝岊槺缂佽鲸绻堝缁樻媴缁涘娈愰梺鎼炲妺閸楀啿鐣烽鐐茬骇闁瑰濮靛▓楣冩⒑缂佹ɑ鈷掗柍宄扮墦瀵偊宕掗悙瀵稿幈闂佹娊鏁崑鎾绘煛閸涱喚鎳呮俊鍙夊姇铻i悶娑掑墲閺傗偓闂備胶绮崝鏇炍熸繝鍥у惞闁绘柨鐨濋弨鑺ャ亜閺冨洦顥夐柛鏂诲€濋幗鍫曟倷閻戞ḿ鍘遍梺鍝勬储閸斿本鏅堕鐐寸厱婵炲棗绻掔粻濠氭煛鐏炵晫效鐎规洦鍋婂畷鐔碱敆閳ь剙鈻嶉敐鍥╃=濞达絾褰冩禍鐐節閵忥絾纭炬い鎴濇川缁粯銈i崘鈺冨幍闁诲孩绋掑玻璺ㄧ不濮椻偓閺屻劌鈽夊Ο澶癸絾銇勯妸锝呭姦闁诡喗鐟╅、鏃堝礋椤撴繄绀勯梻鍌欐祰椤曟牠宕伴弽顐ょ濠电姴鍊婚弳锕傛煙椤栫偛浜版俊鑼额嚙閳规垿鍩勯崘銊хシ濡炪値鍘鹃崗妯侯嚕鐠囨祴妲堥柕蹇曞閳哄懏鐓忓璺虹墕閸旀挳鏌涢弬娆炬Ш缂佽鲸鎸婚幏鍛矙鎼存挸浜鹃柛婵勫劤閻挾鎲搁悧鍫濈瑨闁哄绶氶弻鐔煎礈瑜忕敮娑㈡煛閸涱喗鍊愰柡灞诲姂閹倝宕掑☉姗嗕紦 ---闂傚倸鍊搁崐鎼佸磹閻戣姤鍊块柨鏃堟暜閸嬫挾绮☉妯哄箻婵炲樊浜滈悡娑㈡煕濞戝崬骞樻い鏂挎濮婅櫣鎹勯妸銉︾彚闂佺懓鍤栭幏锟�
开发学院软件开发Delphi 研究心得------->Seskin控件包中Ses... 阅读

研究心得------->Seskin控件包中SeskinEdit汉字问题的解决办法

 2006-02-04 13:41:33 来源:WEB开发网 闂傚倸鍊搁崐鎼佸磹妞嬪孩顐芥慨姗嗗厳缂傛氨鎲稿鍫罕闂備礁婀遍搹搴ㄥ窗閺嶎偆涓嶆い鏍仦閻撱儵鏌i弴鐐测偓鍦偓姘炬嫹闂傚倸鍊搁崐鎼佸磹妞嬪海鐭嗗〒姘e亾妤犵偛顦甸弫鎾绘偐閹绘帞鈧參姊哄Ч鍥х仼闁诲繑鑹鹃悾鐑藉蓟閵夛妇鍘甸梺瑙勵問閸犳牠銆傛總鍛婄厱閹艰揪绱曟牎闂侀潧娲ょ€氫即鐛幒妤€绠f繝闈涘暙娴滈箖鏌i姀鈶跺湱澹曟繝姘厵闁绘劦鍓氶悘杈ㄤ繆閹绘帞澧涚紒缁樼洴瀹曞崬螖閸愬啠鍓濈换娑樼暆婵犱胶鏁栫紓浣介哺閹瑰洤鐣烽幒鎴僵闁瑰吀鐒﹂悗鎼佹⒒娴g儤鍤€闁搞倖鐗犻獮蹇涙晸閿燂拷濠电姷鏁告慨鐑藉极閸涘﹥鍙忔い鎾卞灩缁狀垶鏌涢幇闈涙灈鐎瑰憡绻冮妵鍕箻鐎靛摜鐣奸梺纭咁潐濞茬喎顫忕紒妯肩懝闁逞屽墮宀h儻顦查悡銈夋煏閸繃鍋繛宸簻鎯熼梺瀹犳〃閼冲爼宕濋敃鈧—鍐Χ閸℃鐟愰梺鐓庡暱閻栧ジ宕烘繝鍥у嵆闁靛骏绱曢崢顏堟⒑閹肩偛鍔楅柡鍛⊕缁傛帟顦寸紒杈ㄥ笚濞煎繘鍩℃担閿嬵潟闂備浇妗ㄩ悞锕傚箲閸ヮ剙鏋侀柟鍓х帛閺呮悂鏌ㄩ悤鍌涘闂傚倸鍊搁崐鎼佸磹妞嬪孩顐芥慨姗嗗厳缂傛氨鎲稿鍫罕闂備礁婀遍搹搴ㄥ窗閺嶎偆涓嶆い鏍仦閻撱儵鏌i弴鐐测偓鍦偓姘炬嫹  闂傚倸鍊搁崐鎼佸磹閻戣姤鍤勯柤鍝ユ暩娴犳氨绱撻崒娆掑厡缂侇噮鍨堕妴鍐川閺夋垹鍘洪悗骞垮劚椤︻垶宕¢幎鑺ョ厪闊洦娲栨牎闂佽瀵掗崜鐔奉潖閾忓湱纾兼俊顖氭惈椤秴顪冮妶鍡楀闁告鍥х叀濠㈣泛谩閻斿吋鐓ラ悗锝庡厴閸嬫挻绻濆顓涙嫼閻熸粎澧楃敮鎺撶娴煎瓨鐓曢柟鎯ь嚟閳藉鏌嶇紒妯荤叆妞ゎ偅绻堥幊婊呭枈濡顏归梻鍌欑閹诧紕绮欓幋锔哄亼闁哄鍨熼弸鏃堟煛閸愶絽浜剧紓浣虹帛缁嬫挻绂掗敃鍌氱<婵﹩鍓﹂悗鎶芥⒒娴e摜锛嶇紒顕呭灦楠炴垿宕堕鍌氱ウ闁诲函缍嗘禍鏍绩娴犲鐓欓梺顓ㄧ畱婢ь垱銇勯弬鍨偓瑙勭┍婵犲洦鍊锋い蹇撳閸嬫捇寮借濞兼牕鈹戦悩瀹犲闁稿被鍔庨幉姝岀疀濞戞ḿ鐤呴梺鍦檸閸犳寮查幖浣圭叆闁绘洖鍊圭€氾拷
核心提示:公司采用Seskin控件包来开发,却发现SeskinEdit在使用汉字是有问题,研究心得------->Seskin控件包中SeskinEdit汉字问题的解决办法,主要是由汉字时光标定位不准,鼠标选字也选不准,其实TCanvas提供了一个TextLength方法,在去文本长度时汉字没有问题,于是看了其代码
公司采用Seskin控件包来开发。却发现SeskinEdit在使用汉字是有问题。主要是由汉字时光标定位不准。鼠标选字也选不准。
于是看了其代码。发现它在计算文本长度时采用的函数TextLength有问题。
其实TCanvas提供了一个TextLength方法,在去文本长度时汉字没有问题。
所以把这里替换下来就行了。
替换后的se_controls单元中的TSeCustomEdit的代码如下
 TSeCustomEdit = class(TSeCustomControl)
 PRivate
   FText: WideString;
   FLMouseSelecting: boolean;
   FCaretPosition: integer;
   FSelStart: integer;
   FSelLength: integer;
   FFirstVisibleChar: integer;
   FPopupMenu: TSeCustomPopupMenu;
   FAutoSelect: boolean;
   FCharCase: TEditCharCase;
   FHideSelection: Boolean;
   FMaxLength: Integer;
   FReadOnly: Boolean;
   FOnChange: TNotifyEvent;
   FPassWordChar: WideChar;
   FPasswordKind: TPasswordKind;
   FTextAlignment: TAlignment;
   FActionStack: TEditActionStack;
   FPopupMenuDropShadow: boolean;
   FPopupMenuShowAnimationTime: integer;
   FPopupMenuBlendValue: integer;
   FPopupMenuShadowWidth: integer;
   FPopupMenuShowAnimation: TSeAnimationRec;
   FPopupMenuBlend: boolean;
   FContextMenuOptions: TSePopupMenuOptions;
   procedure UpdateFirstVisibleChar;
   procedure UpdateCaretePosition;
   procedure UpdateCarete;

   procedure WMGetDlgCode(var Msg: TWMGetDlgCode); message WM_GETDLGCODE;
   procedure WMCopy(var Message: TMessage); message WM_COPY;
   procedure WMPaste(var Message: TMessage); message WM_PASTE;
   procedure WMCut(var Message: TMessage); message WM_CUT;
   procedure WMUnDo(var Message: TMessage); message WM_UNDO;
   procedure WMContexMenu(var Message: TMessage); message WM_CONTEXTMENU;
   procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message
     WM_LBUTTONDBLCLK;
   { unicode }
   procedure WMImeStartComposition(var Message: TMessage); message
     WM_IME_STARTCOMPOSITION;
   procedure WMImeComposition(var Msg: TMessage); message WM_IME_COMPOSITION;
   { VCL messages }
   procedure CMEnabledChanged(var Msg: TMessage); message CM_ENABLEDCHANGED;
   procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
   procedure CMTextChanged(var Msg: TMessage); message CM_TEXTCHANGED;

   function GetSelText: WideString;
   function GetVisibleSelText: WideString;
   function GetNextWordBeging(StartPosition: integer): integer;
   function GetPrivWordBeging(StartPosition: integer): integer;
   function GetSelStart: integer;
   function GetSelLength: integer;
   function GetText: WideString;
   procedure SetText(const Value: WideString);
   procedure SetFont(Value: TFont);
   procedure SetCaretPosition(const Value: integer);
   procedure SetSelLength(const Value: integer);
   procedure SetSelStart(const Value: integer);
   procedure SetAutoSelect(const Value: boolean);
   procedure SetCharCase(const Value: TEditCharCase);
   procedure SetHideSelection(const Value: Boolean);
   procedure SetMaxLength(const Value: Integer);
   procedure SetPasswordChar(const Value: WideChar);
   procedure SetCursor(const Value: TCursor);
   procedure SetTextAlignment(const Value: TAlignment);
   procedure SetPasswordKind(const Value: TPasswordKind);
   procedure SetPopupMenuBlendValue(const Value: integer);
   procedure SetPopupMenuDropShadow(const Value: boolean);
   procedure SetPopupMenuShadowWidth(const Value: integer);
   procedure SetPopupMenuShowAnimation(const Value: TSeAnimationRec);
   procedure SetPopupMenuShowAnimationTime(const Value: integer);
   procedure SetPopupMenuBlend(const Value: boolean);
   procedure SetContextMenuOptions(const Value: TSePopupMenuOptions);
 protected
   function GetEditRect: TRect; virtual;
   function GetPasswordCharWidth: integer; virtual;
   function GetCharX(A: integer): integer;
   function GetCoordinatePosition(x: integer): integer;
   function GetSelRect: TRect; virtual;
   function GetAlignmentFlags: integer;

   procedure PaintBuffer; override;

   procedure PaintText; virtual;
   procedure PaintBackground(Rect: TRect; Canvas: TCanvas); virtual;
   procedure PaintSelectedText; virtual;
   procedure DrawPasswordChar(SymbolRect: TRect; Selected: boolean); virtual;

   function ValidText(NewText: WideString): boolean; virtual;
   function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override;

   procedure BorderChanged; override;
   procedure HasFocus; override;
   procedure KillFocus; override;
   procedure MouseDown(Button: TMouseButton; Shift: TShiftState; x, y:
     integer);
     override;
   procedure MouseUp(Button: TMouseButton; Shift: TShiftState; x, y: integer);
     override;
   procedure MouseMove(Shift: TShiftState; x, y: integer); override;
   procedure KeyDown(var Key: Word; Shift: TShiftState); override;
   procedure KeyPress(var Key: Char); override;
   procedure SelectWord;
   procedure Change; dynamic;

   function CreatePopupMenu(AOwner: TComponent): TSeCustomPopupMenu; virtual;
   function CreatePopupMenuItem(AOwner: TComponent): TSeCustomItem; virtual;
   procedure BuildPopupMenu;
   procedure UpdatePopupMenuItems; virtual;
   procedure DoUndo(Sender: TObject);
   procedure DoCut(Sender: TObject);
   procedure DoCopy(Sender: TObject);
   procedure DoPaste(Sender: TObject);
   procedure DoDelete(Sender: TObject);
   procedure DoSelectAll(Sender: TObject);

   property CaretPosition: integer read FCaretPosition write SetCaretPosition;
   property PopupMenu: TSeCustomPopupMenu read FPopupMenu;
 public
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
   procedure Loaded; override;

   procedure ShowCaret; virtual;
   procedure HideCaret; virtual;

   procedure CopyToClipboard;
   procedure PasteFromClipboard;
   procedure CutToClipboard;
   procedure ClearSelection;
   procedure SelectAll;
   procedure Clear;

   procedure UnDo;

   procedure InsertChar(Ch: WideChar);
   procedure InsertText(AText: WideString);
   procedure InsertAfter(Position: integer; S: WideString; Selected: boolean);
   procedure DeleteFrom(Position, Length: integer; MoveCaret: boolean);

   property SelStart: integer read GetSelStart write SetSelStart;
   property SelLength: integer read GetSelLength write SetSelLength;
   property SelText: WideString read GetSelText;
 published
   property Anchors;
   property AutoSelect: boolean read FAutoSelect write SetAutoSelect default
     true;
   property AutoSize;
   property Blending;
   property BevelSides;
   property BevelInner;
   property BevelOuter;
   property BevelKind;
   property BevelWidth;
   property BorderWidth;
   property CharCase: TEditCharCase read FCharCase write SetCharCase default
     ecNormal;
   property Constraints;
   property Color;
   property Cursor write SetCursor;
   property DragCursor;
   property DragKind;
   property DragMode;
   property Enabled;
   property ImeMode;
   property ImeName;
   property Font write SetFont;
   property HideSelection: Boolean read FHideSelection write SetHideSelection
     default True;
   property MaxLength: Integer read FMaxLength write SetMaxLength default 0;
   property Performance;
   property ParentFont;
   property ParentShowHint;
   property PasswordKind: TPasswordKind read FPasswordKind write
     SetPasswordKind;
   property PasswordWideChar: WideChar read FPasswordChar write SetPasswordChar
     default WideChar(#0);
   property ContextMenuOptions: TSePopupMenuOptions read FContextMenuOptions
     write SetContextMenuOptions;
   property ReadOnly: Boolean read FReadOnly write FReadOnly default False;
   property ShowHint;
   property TabOrder;
   property TabStop default true;
   property Text: WideString read GetText write SetText;
   property TextAlignment: TAlignment read FTextAlignment write SetTextAlignment
     default taLeftJustify;

   property Visible;

   property OnChange: TNotifyEvent read FOnChange write FOnChange;
   property OnClick;
   property OnDblClick;
   property OnDragDrop;
   property OnDragOver;
   property OnEndDock;
   property OnEndDrag;
   property OnEnter;
   property OnExit;
   property OnKeyDown;
   property OnKeyPress;
   property OnKeyUp;
   property OnMouseDown;
   property OnMouseMove;
   property OnMouseUp;
   property OnStartDock;
   property OnStartDrag;
 end;



{ TSeCustomEdit ===============================================================}

constructor TSeCustomEdit.Create(AOwner: TComponent);
begin
 inherited;
 FActionStack := TEditActionStack.Create(Self);
 FContextMenuOptions := TSePopupMenuOptions.Create;

 Performance := kspDoubleBuffer;

 BevelKind := kbkSingle;
 BevelWidth := 1;
 BorderWidth := 3;

 TabStop := true;
 Width := 121;
 Height := 21;
 Color := clWindow;

 FTextAlignment := taLeftJustify;
 FAutoSelect := true;
 AutoSize := true;
 FCharCase := ecNormal;
 FHideSelection := true;
 FMaxLength := 0;
 FReadOnly := false;
 FPasswordChar := WideChar(#0);

 FLMouseSelecting := false;

 FCaretPosition := 0;
 FSelStart := 0;
 FSelLength := 0;
 FFirstVisibleChar := 1;

 ControlStyle := ControlStyle + [csCaptureMouse];

 FPopupMenuBlend := false;
 FPopupMenuBlendValue := 150;
 FPopupMenuDropShadow := false;
 FPopupMenuShadowWidth := 4;
 FPopupMenuShowAnimationTime := 300;

 Cursor := Cursor;
end;

destructor TSeCustomEdit.Destroy;
begin
 if FPopupMenu <> nil then
   FPopupMenu.Free;
 FContextMenuOptions.Free;
 FActionStack.Free;
 inherited;
end;

procedure TSeCustomEdit.Loaded;
begin
 inherited;
 AdjustSize;
end;

procedure TSeCustomEdit.HasFocus;
begin
 inherited;
 UpdateCarete;
 CaretPosition := 0;
 if AutoSelect then
   SelectAll;
end;

procedure TSeCustomEdit.KillFocus;
begin
 inherited;
 DestroyCaret;
 Invalidate;
end;

function TSeCustomEdit.GetCharX(a: integer): integer;
var
 WholeTextWidth    : integer;
 EditRectWidth     : integer;
begin
 Result := GetEditRect.Left;

 if PasswordKind <> pkNone then
   WholeTextWidth := Length(Text) * GetPasswordCharWidth
 else
   {WholeTextWidth := TextWidth(Canvas, Copy(Text, 1, Length(Text)),
     DT_NOPREFIX); }
   WholeTextWidth := Canvas.TextWidth(Copy(Text, 1, Length(Text)));

 if a > 0 then
 begin
   Canvas.Font.Assign(ControlFont);
   if PasswordKind <> pkNone then
   begin
     if a <= Length(Text) then
       Result := Result + (a - FFirstVisibleChar + 1) * GetPasswordCharWidth
     else
       Result := Result + (Length(Text) - FFirstVisibleChar + 1) *
         GetPasswordCharWidth;
   end
   else
   begin
     if a <= Length(Text) then
       Result := Result + Canvas.TextWidth(Copy(Text, FFirstVisibleChar, a -
         FFirstVisibleChar + 1))
         //Result := Result + TextWidth(Canvas, Copy(Text, FFirstVisibleChar, a - FFirstVisibleChar + 1), DT_NOPREFIX)
     else
       Result := Result + Canvas.TextWidth(Copy(Text, FFirstVisibleChar,
         Length(Text) - FFirstVisibleChar + 1));
     //Result := Result + TextWidth(Canvas, Copy(Text, FFirstVisibleChar, Length(Text) - FFirstVisibleChar + 1), DT_NOPREFIX);
   end;
 end;

 EditRectWidth := GetEditRect.Right - GetEditRect.Left;
 if WholeTextWidth < EditRectWidth then
   case TextAlignment of
     taRightJustify: Result := Result + (EditRectWidth - WholeTextWidth);
     taCenter: Result := Result + ((EditRectWidth - WholeTextWidth) div 2);
   end;
end;

function TSeCustomEdit.GetCoordinatePosition(x: integer): integer;
var
 CurX              : double;
 TmpX,
   WholeTextWidth,
   EditRectWidth   : integer;
begin
 Result := FFirstVisibleChar - 1;
 if Length(Text) = 0 then
   Exit;

 if PasswordKind <> pkNone then
   WholeTextWidth := Length(Text) * GetPasswordCharWidth
 else
   WholeTextWidth := Canvas.TextWidth(Copy(Text, 1, Length(Text)));
 //WholeTextWidth :=TextWidth(Canvas, Copy(Text, 1, Length(Text)), DT_NOPREFIX);

 EditRectWidth := GetEditRect.Right - GetEditRect.Left;
 TmpX := x;
 if WholeTextWidth < EditRectWidth then
   case TextAlignment of
     taRightJustify: TmpX := x - (EditRectWidth - WholeTextWidth);
     taCenter: TmpX := x - ((EditRectWidth - WholeTextWidth) div 2);
   end;

 if PasswordKind <> pkNone then
 begin
   Result := Result + (TmpX - GetEditRect.Left) div GetPasswordCharWidth;
   if Result < 0 then
     Result := 0
   else
     if Result > Length(Text) then
       Result := Length(Text);
 end
 else
 begin
   Canvas.Font.Assign(ControlFont);
   {CurX := GetEditRect.Left + TextWidth(Canvas, Text[FFirstVisibleChar],
     DT_NOPREFIX) / 2; }
   CurX := GetEditRect.Left + Canvas.TextWidth(Text[FFirstVisibleChar]) / 2;
   while (CurX < TmpX) and (Result + 1 <= Length(Text)) and (CurX <
     GetEditRect.Right) do
   begin
     //CurX := CurX + TextWidth(Canvas, Text[Result + 1], DT_NOPREFIX) / 2;
     CurX := CurX + Canvas.TextWidth(Text[Result + 1]) / 2;
     if Result + 1 + 1 <= Length(Text) then
       //CurX := CurX + TextWidth(Canvas, Text[Result + 1 + 1], DT_NOPREFIX) / 2;
       CurX := CurX + Canvas.TextWidth(Text[Result + 1 + 1]) / 2;
     Result := Result + 1;
   end;
 end;
end;

function TSeCustomEdit.GetEditRect: TRect;
begin
 with Result do
 begin
   Result := GetBorderRect;

   Canvas.Font.Assign(ControlFont);
   Result.Bottom := Result.Top + Canvas.TextHeight('Pq');
 end;
end;

function TSeCustomEdit.GetAlignmentFlags: integer;
begin
 case FTextAlignment of
   taCenter: Result := DT_CENTER;
   taRightJustify: Result := DT_RIGHT;
 else
   Result := DT_LEFT;
 end;
end;

procedure TSeCustomEdit.KeyDown(var Key: word; Shift: TShiftState);
var
 TmpS              : WideString;
 OldCaretPosition  : integer;
begin
 inherited KeyDown(Key, Shift);
 OldCaretPosition := CaretPosition;
 case Key of
   VK_END: CaretPosition := Length(Text);
   VK_HOME: CaretPosition := 0;
   VK_LEFT:
     if ssCtrl in Shift then
       CaretPosition := GetPrivWordBeging(CaretPosition)
     else
       CaretPosition := CaretPosition - 1;
   VK_RIGHT:
     if ssCtrl in Shift then
       CaretPosition := GetNextWordBeging(CaretPosition)
     else
       CaretPosition := CaretPosition + 1;
   VK_DELETE, 8:                       {Delete or BackSpace key was pressed}
     if not ReadOnly then
     begin
       if SelLength <> 0 then
       begin
         if Shift = [ssShift] then
           CutToClipboard
         else
           ClearSelection;
       end
       else
       begin
         TmpS := Text;
         if TmpS <> '' then
           if Key = VK_DELETE then
           begin
             FActionStack.FragmentDeleted(CaretPosition + 1, TmpS[CaretPosition
               + 1]);
             Delete(TmpS, CaretPosition + 1, 1);
           end
           else
           begin                       {BackSpace key was pressed}
             if CaretPosition > 0 then
               FActionStack.FragmentDeleted(CaretPosition,
                 TmpS[CaretPosition]);
             Delete(TmpS, CaretPosition, 1);
             CaretPosition := CaretPosition - 1;
           end;
         Text := TmpS;
       end;
     end;
   VK_INSERT:
     if Shift = [ssCtrl] then
       CopyToClipboard
     else
       if Shift = [ssShift] then
         PasteFromClipboard;
   Ord('c'),
     Ord('C'):
     if Shift = [ssCtrl] then
       CopyToClipboard;
   Ord('v'),
     Ord('V'):
     if Shift = [ssCtrl] then
       PasteFromClipboard;
   Ord('x'),
     Ord('X'):
     if Shift = [ssCtrl] then
       CutToClipboard;
   Ord('z'), Ord('Z'):
     if Shift = [ssCtrl] then
       UnDo;
 end;

 if Key in [VK_END, VK_HOME, VK_LEFT, VK_RIGHT] then
 begin
   if ssShift in Shift then
   begin
     if SelLength = 0 then
       FSelStart := OldCaretPosition;
     FSelStart := CaretPosition;
     FSelLength := FSelLength - (CaretPosition - OldCaretPosition);
   end
   else
     FSelLength := 0;
   Invalidate;
 end;
 UpdateCaretePosition;
end;

procedure TSeCustomEdit.KeyPress(var Key: Char);
begin
 inherited KeyPress(Key);

 if (Ord(Key) >= 32) and not ReadOnly then
   InsertChar(charToWideChar(Key));
end;

procedure TSeCustomEdit.MouseDown(Button: TMouseButton; Shift: TShiftState;
 x, y: integer);
begin
 inherited;
 if Button = mbLeft then
   FLMouseSelecting := true;

 SetFocus;

 if Button = mbLeft then
 begin
   CaretPosition := GetCoordinatePosition(x);
   SelLength := 0;
 end;
end;

procedure TSeCustomEdit.PaintBuffer;
var
 R                 : TRect;
begin
 R := GetEditRect;
 R.Bottom := FHeight - R.Top;

 PaintBackground(R, Canvas);

 if (Self is TSeCustomComboBox) and (TSeCustomComboBox(Self).ComboStyle =
   kcsDropDownList) then
   Exit;

 if Focused or not HideSelection then
   FillRect(Canvas, GetSelRect, clHighlight);

 PaintText;

 if Focused or not HideSelection then
   PaintSelectedText;
end;

procedure TSeCustomEdit.PaintBackground(Rect: TRect; Canvas: TCanvas);
begin
 FillRect(Canvas, Rect, Color);
end;

procedure TSeCustomEdit.PaintText;
var
 TmpRect           : TRect;
 CurChar           : integer;
 LPWCharWidth      : integer;
begin
 TmpRect := GetEditRect;

 if PasswordKind <> pkNone then
 begin
   LPWCharWidth := GetPasswordCharWidth;
   for CurChar := 0 to Length(Text) - FFirstVisibleChar + 1 - 1 do
     DrawPasswordChar(Rect(CurChar * LPWCharWidth + GetCharX(0),
       TmpRect.Top,
       (CurChar + 1) * LPWCharWidth + GetCharX(0),
       TmpRect.Bottom), false);
 end
 else
 begin
   Canvas.Font.Assign(ControlFont);
   DrawText(Canvas, Copy(Text, FFirstVisibleChar, Length(Text) -
     FFirstVisibleChar + 1),
     TmpRect, GetAlignmentFlags or DT_NOPREFIX);
 end;
end;

procedure TSeCustomEdit.UpdateFirstVisibleChar;
var
 LEditRect         : TRect;
begin
 if FFirstVisibleChar >= (FCaretPosition + 1) then
 begin
   FFirstVisibleChar := FCaretPosition;
   if FFirstVisibleChar < 1 then
     FFirstVisibleChar := 1;
 end
 else
 begin
   LEditRect := GetEditRect;

   if PasswordKind <> pkNone then
     while ((FCaretPosition - FFirstVisibleChar + 1) * GetPasswordCharWidth >
       LEditRect.Right - LEditRect.Left)
       and (FFirstVisibleChar < Length(Text)) do
       Inc(FFirstVisibleChar)
   else
   begin
     Canvas.Font.Assign(ControlFont);
     {while (TextWidth(Canvas, Copy(Text, FFirstVisibleChar, FCaretPosition -
       FFirstVisibleChar + 1), DT_NOPREFIX) > LEditRect.Right - LEditRect.Left)
       and (FFirstVisibleChar < Length(Text)) do
       Inc(FFirstVisibleChar); }
     while (Canvas.TextWidth(Copy(Text, FFirstVisibleChar, FCaretPosition -
       FFirstVisibleChar + 1)) > LEditRect.Right - LEditRect.Left)
       and (FFirstVisibleChar < Length(Text)) do
       Inc(FFirstVisibleChar);
   end;
 end;
 Invalidate;
end;

procedure TSeCustomEdit.MouseMove(Shift: TShiftState; x, y: integer);
var
 OldCaretPosition  : integer;
 TmpNewPosition    : integer;
begin
 inherited;
 if FLMouseSelecting then
 begin
   TmpNewPosition := GetCoordinatePosition(x);
   OldCaretPosition := CaretPosition;
   if (x > GetEditRect.Right) then
     CaretPosition := TmpNewPosition + 1
   else
     CaretPosition := TmpNewPosition;
   if SelLength = 0 then
     FSelStart := OldCaretPosition;
   FSelStart := CaretPosition;
   FSelLength := FSelLength - (CaretPosition - OldCaretPosition);
 end;
end;

procedure TSeCustomEdit.MouseUp(Button: TMouseButton; Shift: TShiftState;
 x, y: integer);
begin
 inherited;
 FLMouseSelecting := false;
end;

procedure TSeCustomEdit.CopyToClipboard;
var
 Data              : THandle;
 DataPtr           : Pointer;
 Size              : Cardinal;
 S                 : WideString;
begin
 if PasswordKind = pkNone then
   if Length(SelText) > 0 then
   begin
     S := SelText;
     if not IsWinNT then
     begin
       Clipboard.AsText := S;
     end
     else
     begin
       Size := Length(S);
       Data := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, 2 * Size + 2);
       try
         DataPtr := GlobalLock(Data);
         try
           Move(PWideChar(S)^, DataPtr^, 2 * Size + 2);
           Clipboard.SetAsHandle(CF_UNICODETEXT, Data);
         finally
           GlobalUnlock(Data);
         end;
       except
         GlobalFree(Data);
         raise;
       end;
     end;
   end;
end;

procedure TSeCustomEdit.PasteFromClipboard;
var
 Data              : THandle;
 Insertion         : WideString;
begin
 if ReadOnly then
   Exit;

 if Clipboard.HasFormat(CF_UNICODETEXT) then
 begin
   Data := Clipboard.GetAsHandle(CF_UNICODETEXT);
   try
     if Data <> 0 then
       Insertion := PWideChar(GlobalLock(Data));
   finally
     if Data <> 0 then
       GlobalUnlock(Data);
   end;
 end
 else
   Insertion := Clipboard.AsText;

 InsertText(Insertion);
end;

procedure TSeCustomEdit.PaintSelectedText;
var
 TmpRect           : TRect;
 CurChar           : integer;
 LPWCharWidth      : integer;
begin
 TmpRect := GetSelRect;

 if PasswordKind <> pkNone then
 begin
   LPWCharWidth := GetPasswordCharWidth;
   for CurChar := 0 to Length(GetVisibleSelText) - 1 do
     DrawPasswordChar(Rect(CurChar * LPWCharWidth + TmpRect.Left,
       TmpRect.Top,
       (CurChar + 1) * LPWCharWidth + TmpRect.Left,
       TmpRect.Bottom),
       true);
 end
 else
 begin
   Canvas.Font.Assign(ControlFont);
   Canvas.Font.Color := clHighlightText;
   DrawText(Canvas, GetVisibleSelText, TmpRect, GetAlignmentFlags or
     DT_NOPREFIX)
 end;
end;

function TSeCustomEdit.GetVisibleSelText: WideString;
begin
 if SelStart + 1 >= FFirstVisibleChar then
   Result := SelText
 else
   Result := Copy(SelText, FFirstVisibleChar - SelStart, Length(SelText) -
     (FFirstVisibleChar - SelStart) + 1);
end;

procedure TSeCustomEdit.BuildPopupMenu;
var
 TmpItem           : TSeCustomItem;
begin
 FPopupMenu := CreatePopupMenu(Self);

 if FPopupMenu = nil then
   Exit;

 TmpItem := CreatePopupMenuItem(FPopupMenu);
 with TmpItem do
 begin
   Caption := SEditUndo;
   OnClick := DoUndo;
 end;
 FPopupMenu.Items.Add(TmpItem);

 TmpItem := CreatePopupMenuItem(FPopupMenu);
 TmpItem.Caption := '-';
 FPopupMenu.Items.Add(TmpItem);

 TmpItem := CreatePopupMenuItem(FPopupMenu);
 with TmpItem do
 begin
   Caption := SEditCut;
   OnClick := DoCut;
 end;
 FPopupMenu.Items.Add(TmpItem);

 TmpItem := CreatePopupMenuItem(FPopupMenu);
 with TmpItem do
 begin
   Caption := SEditCopy;
   OnClick := DoCopy;
 end;
 FPopupMenu.Items.Add(TmpItem);

 TmpItem := CreatePopupMenuItem(FPopupMenu);
 with TmpItem do
 begin
   Caption := SEditPaste;
   OnClick := DoPaste;
 end;

Tags:研究 心得 amp

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接