unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, DBGrids, StdCtrls,Mask, DB, Themes;
type
Tpjp = class(TCustomEdit)
private
ButtonWidth:Integer;
FPressed: Boolean;
FTracking: Boolean;
FMouseInControl: Boolean;
FEditStyle: TEditStyle;
procedure WMPaint(var Message: TWMPaint); message wm_Paint;
procedure WMSetCursor(var Message: TWMSetCursor); message WM_SetCursor;
procedure WMCancelMode(var Message: TMessage); message WM_CancelMode;
procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
procedure WMKillFocus(var Message: TMessage); message WM_KillFocus;
procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message wm_LButtonDblClk;
procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
protected
procedure CreateParams(var Params: TCreateParams); override;
procedure PaintWindow(DC: HDC); override;
function ButtonRect: TRect;
function OverButton(const P: TPoint): Boolean;
procedure TrackButton(X,Y: Integer);
procedure StopTracking;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure DoEditButtonClick;dynamic;
procedure KeyPress(var Key: Char); override;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure BoundsChanged;
public
constructor Create(Owner: TComponent); override;
property Pressed: Boolean read FPressed;
property EditStyle: TEditStyle read FEditStyle write FEditStyle;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Edit1Change(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
aPJP:Tpjp;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses XPMan;
{$R *.dfm}
{ Tpjp }
procedure Tpjp.BoundsChanged;
var
R: TRect;
begin
R := Rect(0, 0, Width - 2, Height);
if EditStyle <> esSimple then
Dec(R.Right, ButtonWidth+2);
SendMessage(Handle, EM_SETRECTNP, 0, LongInt(@R));
SendMessage(Handle, EM_SCROLLCARET, 0, 0);
if SysLocale.FarEast then
SetImeCompositionWindow(Font, R.Left, R.Top);
end;
function Tpjp.ButtonRect: TRect;
begin
Result := Self.GetClientRect;
Result := Rect(Result.Right - ButtonWidth,2,Result.Right-1,Result.Bottom);
if ThemeServices.ThemesEnabled then
Dec(Result.Left,1);Dec(Result.Top,3);Inc(Result.Right,2);Inc(Result.Bottom,1);
end;
procedure Tpjp.CMMouseEnter(var Message: TMessage);
begin
inherited;
if ThemeServices.ThemesEnabled and not FMouseInControl then
begin
FMouseInControl := True;
Invalidate;
end;
end;
procedure Tpjp.CMMouseLeave(var Message: TMessage);
begin
inherited;
if ThemeServices.ThemesEnabled and FMouseInControl then
begin
FMouseInControl := False;
Invalidate;
end;
end;
constructor Tpjp.Create(Owner: TComponent);
begin
inherited Create(Owner);
ButtonWidth := GetSystemMetrics(SM_CXVSCROLL);
FPressed := False;
EditStyle := esSimple;
end;
procedure Tpjp.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.Style := Params.Style or ES_MULTILINE;
end;
procedure Tpjp.DoEditButtonClick;
begin
ShowMessage('Clicked');
end;
procedure Tpjp.KeyDown(var Key: Word; Shift: TShiftState);
begin
if (EditStyle = esEllipsis) and (Key = VK_RETURN) and (Shift = [ssCtrl]) then
begin
DoEditButtonClick;
//KillMessage(Handle, WM_CHAR);
end
else
inherited KeyDown(Key, Shift);
end;
procedure Tpjp.KeyPress(var Key: Char);
begin
if Key = #13 then Key := #0;
inherited KeyPress(Key);
end;
procedure Tpjp.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
begin
if (Button = mbLeft) and
OverButton(Point(X,Y)) and (EditStyle <> esSimple) then
begin
MouseCapture := True;
FTracking := True;
TrackButton(X, Y);
end;
inherited MouseDown(Button, Shift, X, Y);
end;
procedure Tpjp.MouseMove(Shift: TShiftState; X, Y: Integer);
var
ListPos: TPoint;
MousePos: TSmallPoint;
begin
if FTracking then
begin
TrackButton(X, Y);
ListPos := Point(X, Y);
if PtInRect(ButtonRect, ListPos) then
begin
StopTracking;
MousePos := PointToSmallPoint(ListPos);
SendMessage(Handle, WM_LBUTTONDOWN, 0, Integer(MousePos));
Exit;
end;
end;
inherited MouseMove(Shift, X, Y);
end;
procedure Tpjp.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
var
WasPressed: Boolean;
begin
WasPressed := Pressed;
StopTracking;
if (Button = mbLeft) and WasPressed then
DoEditButtonClick;
inherited MouseUp(Button, Shift, X, Y);
end;
function Tpjp.OverButton(const P: TPoint): Boolean;
begin
Result := PtInRect(ButtonRect, P);
end;
procedure Tpjp.PaintWindow(DC: HDC);
var
R: TRect;
Flags: Integer;
W, X, Y: Integer;
Details: TThemedElementDetails;
begin
if EditStyle <> esSimple then
begin
R := ButtonRect;
Flags := 0;
case EditStyle of
esPickList:
begin
if ThemeServices.ThemesEnabled then
begin
if Pressed then
Details := ThemeServices.GetElementDetails(tcDropDownButtonPressed)
else
if FMouseInControl then
Details := ThemeServices.GetElementDetails(tcDropDownButtonHot)
else
Details := ThemeServices.GetElementDetails(tcDropDownButtonNormal);
ThemeServices.DrawElement(DC, Details, R);
end
else
begin
if Pressed then
Flags := DFCS_FLAT or DFCS_PUSHED;
DrawFrameControl(DC, R, DFC_SCROLL, Flags or DFCS_SCROLLCOMBOBOX);
end;
end;
esEllipsis:
begin
if ThemeServices.ThemesEnabled then
begin
if Pressed then
Details := ThemeServices.GetElementDetails(tbPushButtonPressed)
else
if FMouseInControl then
Details := ThemeServices.GetElementDetails(tbPushButtonHot)
else
Details := ThemeServices.GetElementDetails(tbPushButtonNormal);
ThemeServices.DrawElement(DC, Details, R);
end
else
begin
if Pressed then Flags := BF_FLAT;
DrawEdge(DC, R, EDGE_RAISED, BF_RECT or BF_MIDDLE or Flags);
end;
X := R.Left + ((R.Right - R.Left) shr 1) - 1 + Ord(Pressed);
Y := R.Top + ((R.Bottom - R.Top) shr 1) - 1 + Ord(Pressed);
W := ButtonWidth shr 3;
if W = 0 then W := 1;
PatBlt(DC, X, Y, W, W, BLACKNESS);
PatBlt(DC, X - (W * 2), Y, W, W, BLACKNESS);
PatBlt(DC, X + (W * 2), Y, W, W, BLACKNESS);
end;
end;
ExcludeClipRect(DC, R.Left, R.Top, R.Right, R.Bottom);
end;
inherited PaintWindow(DC);
end;
procedure Tpjp.StopTracking;
begin
if FTracking then
begin
TrackButton(-1, -1);
FTracking := False;
MouseCapture := False;
end;
end;
procedure Tpjp.TrackButton(X, Y: Integer);
var
NewState: Boolean;
R: TRect;
begin
R := ButtonRect;
NewState := PtInRect(R, Point(X, Y));
if Pressed <> NewState then
begin
FPressed := NewState;
InvalidateRect(Handle, @R, False);
end;
end;
procedure Tpjp.WMCancelMode(var Message: TMessage);
begin
StopTracking;
inherited;
end;
procedure Tpjp.WMKillFocus(var Message: TMessage);
begin
if not SysLocale.FarEast then inherited
else
begin
ImeName := Screen.DefaultIme;
ImeMode := imDontCare;
inherited;
ActivateKeyboardLayout(Screen.DefaultKbLayout, KLF_ACTIVATE);
end;
end;
procedure Tpjp.WMLButtonDblClk(var Message: TWMLButtonDblClk);
begin
with Message do
if OverButton(Point(XPos, YPos)) then
Exit;
DoEditButtonClick;
inherited;
end;
procedure Tpjp.WMPaint(var Message: TWMPaint);
begin
//-------------------
PaintHandler(Message);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
aPJP := Tpjp.Create(Self);
with aPJP do
begin
Parent := Self;
Left := 10;
Top := 10;
EditStyle := esEllipsis;
end;
end;
procedure Tpjp.WMSetCursor(var Message: TWMSetCursor);
var
P: TPoint;
begin
GetCursorPos(P);
P := ScreenToClient(P);
if (EditStyle <> esSimple) and OverButton(P) then
Windows.SetCursor(LoadCursor(0, idc_Arrow))
else
inherited;
end;
procedure Tpjp.WMSetFocus(var Message: TWMSetFocus);
begin
inherited;
BoundsChanged;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(aPJP) then aPJP.Free;
end;
procedure TForm1.Edit1Change(Sender: TObject);
begin
ShowMessage('bbb');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.Click;
end;
end.