📄 scustomcomboedit.pas
字号:
unit sCustomComboEdit;
{$I sDefs.inc}
{.$DEFINE LOGGED}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Mask, acntUtils, buttons, menus, sCalcUnit, sConst, sSpeedButton,
sGraphUtils, sCommonData, sDefaults, sMaskEdit, sSkinProps, sBitBtn,
sGlyphUtils{$IFDEF DELPHI6}, Variants{$ENDIF};
type
{$IFNDEF NOTFORHELP}
TCloseUpEvent = procedure (Sender: TObject; Accept: Boolean) of object;
TsCustomComboEdit = class;
TsEditButton = class(TsSpeedButton)
private
FOwner : TsCustomComboEdit;
public
constructor Create(AOwner: TComponent); override;
procedure DrawStandardGlyph;
procedure PaintTo(DC : hdc; R : TPoint);
procedure PrepareCache; override;
procedure DrawGlyph; reintroduce;
procedure Paint; override;
function GlyphWidth : integer; override;
function GlyphHeight : integer; override;
end;
{$ENDIF} // NOTFORHELP
TsCustomComboEdit = class(TsMaskEdit)
{$IFNDEF NOTFORHELP}
private
FButton: TsEditButton;
FClickKey: TShortCut;
FReadOnly: Boolean;
FDirectInput: Boolean;
FAlignment: TAlignment;
FPopupWindowAlign: TPopupWindowAlign;
FGlyphMode: TsGlyphMode;
FPopupWidth: integer;
FDisabledKind: TsDisabledKind;
FShowButton: boolean;
procedure EditButtonClick(Sender: TObject);
procedure EditButtonMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure EditButtonMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
function GetDroppedDown: Boolean;
procedure SetDirectInput(Value: Boolean);
procedure SetReadOnly(Value: Boolean);
procedure SetAlignment(Value: TAlignment);
procedure CMCancelMode(var Message: TCMCancelMode); message CM_CANCELMODE;
procedure WMPaste(var Message: TWMPaste); message WM_PASTE;
procedure WMCut(var Message: TWMCut); message WM_CUT;
procedure CMFocuseChanged(var Message: TCMFocusChanged); message CM_FOCUSCHANGED;
procedure SetPopupWidth(const Value: integer);
procedure SetDisabledKind(const Value: TsDisabledKind);
procedure SetShowButton(const Value: boolean);
protected
FOnButtonClick: TNotifyEvent;
procedure SetEditRect; override;
function IsActive : boolean; override;
procedure PaintBorder(DC : hdc); override;
procedure PaintText; override;
procedure OurPaintHandler(DC : hdc); override;
function GetReadOnly: Boolean; virtual;
procedure KeyPress(var Key: Char); override;
procedure PopupWindowShow; virtual;
procedure PopupWindowClose; virtual;
procedure CreateParams(var Params: TCreateParams); override;
procedure Change; override;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure ButtonClick; dynamic;
property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
property PopupAlign: TPopupWindowAlign read FPopupWindowAlign write FPopupWindowAlign default pwaRight;
public
FDefBmpName : string;
FPopupWindow: TWinControl;
constructor Create(AOwner: TComponent); override;
procedure CreateWnd; override;
destructor Destroy; override;
procedure Invalidate; override;
procedure AfterConstruction; override;
procedure Loaded; override;
procedure WndProc (var Message: TMessage); override;
procedure DoClick;
procedure SelectAll; virtual;
property Button: TsEditButton read FButton;
property DroppedDown: Boolean read GetDroppedDown;
property PopupWidth : integer read FPopupWidth write SetPopupWidth default 197;
{$ENDIF} // NOTFORHELP
published
{$IFNDEF NOTFORHELP}
property Align; // KJS
property Anchors; // KJS
property AutoSelect;
property DragCursor;
property DragMode;
property EditMask;
property Enabled;
property Font;
property HideSelection;
property ImeMode;
property ImeName;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property TabOrder;
property TabStop;
property Text;
property Visible;
property OnChange;
property OnClick;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnStartDrag;
property OnContextPopup;
{$ENDIF} // NOTFORHELP
{:@event}
property OnButtonClick: TNotifyEvent read FOnButtonClick write FOnButtonClick;
property ShowButton : boolean read FShowButton write SetShowButton default True;
property ClickKey: TShortCut read FClickKey write FClickKey default scAlt + vk_Down;
property DisabledKind : TsDisabledKind read FDisabledKind write SetDisabledKind default DefDisabledKind;
property GlyphMode : TsGlyphMode read FGlyphMode write FGlyphMode;
property DirectInput: Boolean read FDirectInput write SetDirectInput default True;
property ReadOnly: Boolean read GetReadOnly write SetReadOnly default False;
end;
implementation
uses sStyleSimply, sCurrencyEdit{$IFDEF CHECKXP}, UxTheme, Themes{$ENDIF}, sMaskData,
sVCLUtils, sMessages, sAlphaGraph, sSkinManager
{$IFDEF LOGGED}, sDebugMsgs{$ENDIF};
constructor TsEditButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FOwner := TsCustomComboEdit(AOwner);
SkinData.SkinSection := s_SPEEDBUTTON;
{$IFDEF CHECKXP}
Flat := True;
{$ENDIF}
Cursor := crArrow;
Align := alRight;
Width := 22;
ShowCaption := False;
end;
{ TsCustomComboEdit }
constructor TsCustomComboEdit.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
SkinData.COC := COC_TsComboEdit;
FDisabledKind := DefDisabledKind;
FDefBmpName := '';
FGlyphMode := TsGlyphMode.Create(Self);
AutoSize := False;
FDirectInput := True;
FClickKey := scAlt + vk_Down;
FPopupWindowAlign := pwaRight;
FShowButton := True;
FButton := TsEditButton.Create(Self);
FButton.Parent := Self;
FButton.Visible := True;
FButton.OnClick := EditButtonClick;
FButton.OnMouseDown := EditButtonMouseDown;
FButton.OnMouseUp := EditButtonMouseUp;
Height := 21;
FPopupWidth := 197;
end;
destructor TsCustomComboEdit.Destroy;
begin
OnKeyDown := nil;
if Assigned(FGlyphMode) then FreeAndNil(FGlyphMode);
if Assigned(FButton) then FButton.OnClick := nil;
inherited Destroy;
end;
procedure TsCustomComboEdit.PopupWindowShow;
var
P: TPoint;
Y: Integer;
begin
if (FPopupWindow <> nil) and not (ReadOnly or DroppedDown) then begin
FPopupWindow.Visible := False;
FPopupWindow.Width := FPopupWidth;
P := Parent.ClientToScreen(Point(Left, Top));
Y := P.Y + Height;
if Y + FPopupWindow.Height > Screen.DesktopHeight then Y := P.Y - FPopupWindow.Height;
case FPopupWindowAlign of
pwaRight: begin
Dec(P.X, FPopupWindow.Width - Width);
if P.X < Screen.DesktopLeft then Inc(P.X, FPopupWindow.Width - Width);
end;
pwaLeft: begin
if P.X + FPopupWindow.Width > Screen.DesktopWidth then Dec(P.X, FPopupWindow.Width - Width);
end;
end;
if P.X < Screen.DesktopLeft
then P.X := Screen.Desktopleft
else if P.X + FPopupWindow.Width > Screen.DesktopWidth then P.X := Screen.DesktopWidth - FPopupWindow.Width;
SetWindowPos(FPopupWindow.Handle, HWND_TOPMOST, P.X, Y, FPopupWindow.Width, FPopupWindow.Height, {SWP_NOACTIVATE or }SWP_SHOWWINDOW);
FPopupWindow.Visible := True;
end;
end;
procedure TsCustomComboEdit.Change;
begin
if not DroppedDown then inherited Change;
end;
procedure TsCustomComboEdit.KeyDown(var Key: Word; Shift: TShiftState);
begin
inherited KeyDown(Key, Shift);
if (FClickKey = ShortCut(Key, Shift)) and (GlyphMode.Width > 0) then begin
EditButtonClick(Self);
Key := 0;
end;
SetEditRect
end;
procedure TsCustomComboEdit.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if not RestrictDrawing then SkinData.BGChanged := True;
inherited MouseDown(Button, Shift, X, Y);
if DroppedDown then PopupWindowClose;
SetEditRect
end;
procedure TsCustomComboEdit.SetEditRect;
var
Loc: TRect;
begin
if Parent = nil then Exit;
SendMessage(Handle, EM_GETRECT, 0, LongInt(@Loc));
Loc.Bottom := ClientHeight;
Loc.Right := ClientWidth - FButton.Width;// - 2;
Loc.Top := 0;
Loc.Left := 0;
SendMessage(Handle, EM_SETRECTNP, 0, LongInt(@Loc));
SendMessage(Handle, EM_GETRECT, 0, LongInt(@Loc)); {debug}
end;
function TsCustomComboEdit.GetDroppedDown : Boolean;
begin
Result := (FPopupWindow <> nil) and FPopupWindow.Visible;
end;
procedure TsCustomComboEdit.CMCancelMode(var Message: TCMCancelMode);
begin
if (Message.Sender <> Self) and
(Message.Sender <> FPopupWindow) and
(Message.Sender <> FButton) and
((FPopupWindow <> nil) and
not FPopupWindow.ContainsControl(Message.Sender)) then PopupWindowClose;
end;
procedure TsCustomComboEdit.EditButtonClick(Sender: TObject);
begin
if not FReadOnly then ButtonClick;
end;
procedure TsCustomComboEdit.DoClick;
begin
EditButtonClick(Self);
end;
procedure TsCustomComboEdit.ButtonClick;
begin
if Assigned(FOnButtonClick) then FOnButtonClick(Self);
if DroppedDown then PopupWindowClose else begin
if CanFocus then SetFocus;
PopupWindowShow;
end;
end;
procedure TsCustomComboEdit.SelectAll;
begin
if {DirectInput and} (Text <> '') then //inherited SelectAll;
SendMessage(Handle, EM_SETSEL, 0, -1);//Length(Text)); // v4.44
end;
procedure TsCustomComboEdit.SetDirectInput(Value: Boolean);
begin
inherited ReadOnly := not Value or FReadOnly;
FDirectInput := Value;
end;
procedure TsCustomComboEdit.WMPaste(var Message: TWMPaste);
begin
if not FDirectInput or ReadOnly then Exit;
inherited;
end;
procedure TsCustomComboEdit.WMCut(var Message: TWMCut);
begin
if not FDirectInput or ReadOnly then Exit;
inherited;
end;
procedure TsCustomComboEdit.SetReadOnly(Value: Boolean);
begin
if Value <> FReadOnly then begin
FReadOnly := Value;
inherited ReadOnly := Value or not FDirectInput;
// if Assigned(Button) then Button.Enabled := not FReadOnly; for future???
end;
end;
procedure TsCustomComboEdit.SetAlignment(Value: TAlignment);
begin
if FAlignment <> Value then begin
FAlignment := Value;
SkinData.Invalidate;
end;
end;
procedure TsCustomComboEdit.WndProc(var Message: TMessage);
begin
{$IFDEF LOGGED}
AddToLog(Message);
{$ENDIF}
case Message.Msg of
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -