5648 lines
158 KiB
ObjectPascal
5648 lines
158 KiB
ObjectPascal
{-----------------------------------------------------------------------------
|
|
The contents of this file are subject to the Mozilla Public License
|
|
Version 1.1 (the "License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
http://www.mozilla.org/MPL/MPL-1.1.html
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
|
|
the specific language governing rights and limitations under the License.
|
|
|
|
The Original Code is: JvToolEdit.PAS, released on 2002-07-04.
|
|
|
|
The Initial Developers of the Original Code are: Fedor Koshevnikov, Igor Pavluk and Serge Korolev
|
|
Copyright (c) 1997, 1998 Fedor Koshevnikov, Igor Pavluk and Serge Korolev
|
|
Copyright (c) 2001,2002 SGB Software
|
|
All Rights Reserved.
|
|
|
|
Contributers:
|
|
Rob den Braasem [rbraasem att xs4all dott nl]
|
|
Polaris Software
|
|
rblaurindo
|
|
Andreas Hausladen
|
|
|
|
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
|
|
located at http://jvcl.sourceforge.net
|
|
|
|
Known Issues:
|
|
(rb) Move button related functionality from TJvCustomComboEdit to TJvEditButton
|
|
-----------------------------------------------------------------------------}
|
|
// $Id: JvToolEdit.pas 11281 2007-05-09 16:44:52Z ahuser $
|
|
|
|
unit JvToolEdit;
|
|
|
|
{$I jvcl.inc}
|
|
{$I crossplatform.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF UNITVERSIONING}
|
|
JclUnitVersioning,
|
|
{$ENDIF UNITVERSIONING}
|
|
{$IFDEF CLR}
|
|
Types, WinUtils, System.Text, System.IO, System.Reflection,
|
|
System.Runtime.InteropServices,
|
|
{$ENDIF CLR}
|
|
{$IFDEF MSWINDOWS}
|
|
Windows, Messages, ShellAPI, ActiveX,
|
|
{$ENDIF MSWINDOWS}
|
|
{$IFDEF VCL}
|
|
ShlObj,
|
|
{$ENDIF VCL}
|
|
{$IFDEF HAS_UNIT_VARIANTS}
|
|
Variants,
|
|
{$ENDIF HAS_UNIT_VARIANTS}
|
|
SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Menus,
|
|
Buttons, FileCtrl, Mask, ImgList, ActnList, ExtDlgs,
|
|
{$IFDEF VisualCLX}
|
|
Qt, QComboEdits, JvQExComboEdits, QWindows,
|
|
{$ENDIF VisualCLX}
|
|
JvVCL5Utils,
|
|
JvExControls, JvSpeedButton, JvTypes, JvExMask, JvExForms, JvButton,
|
|
JvDataSourceIntf;
|
|
|
|
const
|
|
scAltDown = scAlt + VK_DOWN;
|
|
DefEditBtnWidth = 21;
|
|
|
|
CM_POPUPCLOSEUP = CM_BASE + $0300; // arbitrary value
|
|
|
|
{$IFDEF CLR}
|
|
type
|
|
[ComImport, InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
|
IUnknown = IInterface;
|
|
{$ENDIF CLR}
|
|
|
|
{$IFNDEF COMPILER7_UP}
|
|
// Autocomplete stuff for Delphi 5 and 6. (missing in ShlObj)
|
|
type
|
|
IAutoComplete = interface(IUnknown)
|
|
['{00bb2762-6a77-11d0-a535-00c04fd7d062}']
|
|
function Init(hwndEdit: THandle; punkACL: IUnknown;
|
|
pwszRegKeyPath: LPCWSTR; pwszQuickComplete: LPCWSTR): HRESULT; stdcall;
|
|
function Enable(fEnable: BOOL): HRESULT; stdcall;
|
|
end;
|
|
|
|
const
|
|
{ IAutoComplete2 options }
|
|
ACO_NONE = 0;
|
|
ACO_AUTOSUGGEST = $1;
|
|
ACO_AUTOAPPEND = $2;
|
|
ACO_SEARCH = $4;
|
|
ACO_FILTERPREFIXES = $8;
|
|
ACO_USETAB = $10;
|
|
ACO_UPDOWNKEYDROPSLIST = $20;
|
|
ACO_RTLREADING = $40;
|
|
|
|
type
|
|
IAutoComplete2 = interface(IAutoComplete)
|
|
['{EAC04BC0-3791-11d2-BB95-0060977B464C}']
|
|
function SetOptions(dwFlag: DWORD): HRESULT; stdcall;
|
|
function GetOptions(var dwFlag: DWORD): HRESULT; stdcall;
|
|
end;
|
|
|
|
{$ENDIF !COMPILER7_UP}
|
|
|
|
// C++ Builder needs this HPPEMIT in order for the generated header to compile.
|
|
{$HPPEMIT 'typedef DelphiInterface<IEnumString> _di_IEnumString;'}
|
|
|
|
type
|
|
TFileExt = type string;
|
|
|
|
TCloseUpEvent = procedure(Sender: TObject; Accept: Boolean) of object;
|
|
TPopupAlign = (epaRight, epaLeft);
|
|
|
|
{$IFDEF VisualCLX}
|
|
TJvPopupWindowBase = TJvExCustomForm;
|
|
{$ENDIF VisualCLX}
|
|
{$IFDEF VCL}
|
|
TJvPopupWindowBase = TJvExCustomControl;
|
|
{$ENDIF VCL}
|
|
|
|
TJvPopupWindow = class(TJvPopupWindowBase)
|
|
private
|
|
FEditor: TWinControl;
|
|
FCloseUp: TCloseUpEvent;
|
|
{$IFDEF VCL}
|
|
procedure WMMouseActivate(var Msg: TMessage); message WM_MOUSEACTIVATE;
|
|
procedure WMActivate(var Msg: TWMActivate); message WM_ACTIVATE;
|
|
{$ENDIF VCL}
|
|
protected
|
|
FActiveControl: TWinControl;
|
|
FIsFocusable: Boolean;
|
|
{$IFDEF VCL}
|
|
procedure CreateParams(var Params: TCreateParams); override;
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
procedure SetParent(const Value: TWidgetControl); override;
|
|
function WidgetFlags: Integer; override;
|
|
{$ENDIF VisualCLX}
|
|
function GetValue: Variant; virtual; abstract;
|
|
procedure SetValue(const Value: Variant); virtual; abstract;
|
|
procedure InvalidateEditor;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer); override;
|
|
procedure CloseUp(Accept: Boolean); virtual;
|
|
{$IFDEF CLR}
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure KeyPress(var Key: Char); override;
|
|
{$ENDIF CLR}
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
function GetPopupText: string; virtual;
|
|
procedure Hide;
|
|
procedure Show(Origin: TPoint); virtual; // Polaris
|
|
{ Determines the ctrl that receives the keyboard input if the dropdown
|
|
window is showing, but the combo edit still has focus }
|
|
property ActiveControl: TWinControl read FActiveControl;
|
|
{ Determines whether the popup window may be activated }
|
|
property IsFocusable: Boolean read FIsFocusable;
|
|
property OnCloseUp: TCloseUpEvent read FCloseUp write FCloseUp;
|
|
end;
|
|
|
|
TJvEditButton = class(TJvImageSpeedButton)
|
|
private
|
|
FNoAction: Boolean;
|
|
{$IFDEF VCL}
|
|
procedure WMContextMenu(var Msg: TWMContextMenu); message WM_CONTEXTMENU;
|
|
{$ENDIF VCL}
|
|
function GetGlyph: TBitmap;
|
|
function GetNumGlyphs: TJvNumGlyphs;
|
|
function GetUseGlyph: Boolean;
|
|
procedure SetGlyph(const Value: TBitmap);
|
|
procedure SetNumGlyphs(Value: TJvNumGlyphs);
|
|
protected
|
|
{$IFDEF JVCLThemesEnabled}
|
|
FDrawThemedDropDownBtn: Boolean;
|
|
{$ENDIF JVCLThemesEnabled}
|
|
FStandard: Boolean; // Polaris
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer); override;
|
|
procedure PaintImage(Canvas: TCanvas; ARect: TRect; const Offset: TPoint;
|
|
AState: TJvButtonState; DrawMark: Boolean); override;
|
|
procedure Paint; override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
procedure Click; override;
|
|
|
|
property UseGlyph: Boolean read GetUseGlyph;// write FDrawGlyph;
|
|
property Glyph: TBitmap read GetGlyph write SetGlyph;
|
|
property NumGlyphs: TJvNumGlyphs read GetNumGlyphs write SetNumGlyphs;
|
|
end;
|
|
|
|
TGlyphKind = (gkCustom, gkDefault, gkDropDown, gkEllipsis);
|
|
TJvImageKind = (ikCustom, ikDefault, ikDropDown, ikEllipsis);
|
|
|
|
TJvCustomComboEdit = class;
|
|
|
|
TJvCustomComboEditActionLink = class(TWinControlActionLink)
|
|
protected
|
|
function IsCaptionLinked: Boolean; override;
|
|
function IsHintLinked: Boolean; override;
|
|
function IsImageIndexLinked: Boolean; override;
|
|
function IsOnExecuteLinked: Boolean; override;
|
|
function IsShortCutLinked: Boolean; override;
|
|
procedure SetHint(const Value: THintString); override;
|
|
procedure SetImageIndex(Value: Integer); override;
|
|
procedure SetOnExecute(Value: TNotifyEvent); override;
|
|
procedure SetShortCut(Value: TShortCut); override;
|
|
end;
|
|
|
|
TJvCustomComboEditActionLinkClass = class of TJvCustomComboEditActionLink;
|
|
|
|
{$IFDEF VCL}
|
|
TJvAutoCompleteOption = (acoAutoSuggest, acoAutoAppend, acoSearch,
|
|
acoFilterPrefixes, acoUseTab, acoUpDownKeyDropsList, acoRTLReading);
|
|
TJvAutoCompleteOptions = set of TJvAutoCompleteOption;
|
|
TJvAutoCompleteFileOption = (acfFileSystem, acfFileSysDirs, acfURLHistory, acfURLMRU);
|
|
TJvAutoCompleteFileOptions = set of TJvAutoCompleteFileOption;
|
|
{$ENDIF VCL}
|
|
|
|
TJvCustomComboEditDataConnector = class(TJvFieldDataConnector)
|
|
private
|
|
FEdit: TJvCustomComboEdit;
|
|
protected
|
|
procedure RecordChanged; override;
|
|
procedure UpdateData; override;
|
|
property Control: TJvCustomComboEdit read FEdit;
|
|
public
|
|
constructor Create(AEdit: TJvCustomComboEdit);
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
TJvCustomComboEditBase = TJvExCustomMaskEdit;
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
TJvCustomComboEditBase = TJvExCustomComboMaskEdit;
|
|
{$ENDIF VisualCLX}
|
|
|
|
TJvCustomComboEdit = class(TJvCustomComboEditBase)
|
|
private
|
|
FOnButtonClick: TNotifyEvent;
|
|
FOnPopupShown: TNotifyEvent;
|
|
FOnPopupHidden: TNotifyEvent;
|
|
FClickKey: TShortCut;
|
|
FReadOnly: Boolean;
|
|
FDirectInput: Boolean;
|
|
FAlwaysEnableButton: Boolean;
|
|
FAlwaysShowPopup: Boolean;
|
|
FPopupAlign: TPopupAlign;
|
|
FGroupIndex: Integer; // RDB
|
|
FDisabledColor: TColor; // RDB
|
|
FDisabledTextColor: TColor; // RDB
|
|
FOnKeyDown: TKeyEvent; // RDB
|
|
FImages: TCustomImageList;
|
|
FImageIndex: TImageIndex;
|
|
FImageKind: TJvImageKind;
|
|
FNumGlyphs: Integer;
|
|
FStreamedButtonWidth: Integer;
|
|
FStreamedFixedWidth: Boolean;
|
|
FOnEnabledChanged: TNotifyEvent;
|
|
{ We hide the button by setting its width to 0, thus we have to store the
|
|
width the button should have when shown again in FSavedButtonWidth: }
|
|
FSavedButtonWidth: Integer;
|
|
FDataConnector: TJvCustomComboEditDataConnector;
|
|
{$IFDEF VCL}
|
|
FAlignment: TAlignment;
|
|
FAutoCompleteIntf: IAutoComplete;
|
|
FAutoCompleteItems: TStrings;
|
|
FAutoCompleteOptions: TJvAutoCompleteOptions;
|
|
FTextChanged: Boolean;
|
|
procedure SetAutoCompleteItems(Strings: TStrings);
|
|
procedure SetAutoCompleteOptions(const Value: TJvAutoCompleteOptions);
|
|
procedure SetAlignment(Value: TAlignment);
|
|
function GetFlat: Boolean;
|
|
procedure ReadCtl3D(Reader: TReader);
|
|
procedure ReadParentCtl3D(Reader: TReader);
|
|
procedure SetFlat(const Value: Boolean);
|
|
function GetParentFlat: Boolean;
|
|
procedure SetParentFlat(const Value: Boolean);
|
|
function IsFlatStored: Boolean;
|
|
{$ENDIF VCL}
|
|
function BtnWidthStored: Boolean;
|
|
function GetButtonFlat: Boolean;
|
|
function GetButtonHint: string;
|
|
function GetButtonWidth: Integer;
|
|
function GetDirectInput: Boolean;
|
|
function GetGlyph: TBitmap;
|
|
function GetGlyphKind: TGlyphKind;
|
|
function GetMinHeight: Integer;
|
|
function GetNumGlyphs: TNumGlyphs;
|
|
function GetPopupVisible: Boolean;
|
|
function GetShowButton: Boolean;
|
|
function GetTextHeight: Integer;
|
|
function IsImageIndexStored: Boolean;
|
|
function IsCustomGlyph: Boolean;
|
|
procedure EditButtonClick(Sender: TObject);
|
|
procedure ReadGlyphKind(Reader: TReader);
|
|
procedure RecreateGlyph;
|
|
procedure SetButtonFlat(const Value: Boolean);
|
|
procedure SetButtonHint(const Value: string);
|
|
procedure SetButtonWidth(Value: Integer);
|
|
procedure SetGlyph(Value: TBitmap);
|
|
procedure SetGlyphKind(Value: TGlyphKind);
|
|
procedure SetImageIndex(const Value: TImageIndex);
|
|
procedure SetImageKind(const Value: TJvImageKind);
|
|
procedure SetImages(const Value: TCustomImageList);
|
|
procedure SetNumGlyphs(const Value: TNumGlyphs);
|
|
procedure SetShowButton(const Value: Boolean);
|
|
procedure SetDataConnector(const Value: TJvCustomComboEditDataConnector);
|
|
{$IFDEF COMPILER6_UP}
|
|
procedure UpdateBtnBounds(var NewLeft, NewTop, NewWidth, NewHeight: Integer);
|
|
{$ENDIF COMPILER6_UP}
|
|
{ (rb) renamed from UpdateEdit }
|
|
procedure UpdateGroup; // RDB
|
|
{$IFDEF VCL}
|
|
procedure CMWantSpecialKey(var Msg: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
|
|
procedure CMBiDiModeChanged(var Msg: TMessage); message CM_BIDIMODECHANGED;
|
|
procedure CMCancelMode(var Msg: TCMCancelMode); message CM_CANCELMODE;
|
|
procedure CMCtl3DChanged(var Msg: TMessage); message CM_CTL3DCHANGED;
|
|
procedure CNCtlColor(var Msg: TMessage); message CN_CTLCOLOREDIT;
|
|
procedure WMPaint(var Msg: TWMPaint); message WM_PAINT; // RDB
|
|
procedure CMPopupCloseup(var Msg: TMessage); message CM_POPUPCLOSEUP;
|
|
{$IFDEF JVCLThemesEnabled}
|
|
procedure WMNCPaint(var Msg: TWMNCPaint); message WM_NCPAINT;
|
|
procedure WMNCCalcSize(var Msg: TWMNCCalcSize); message WM_NCCALCSIZE;
|
|
{$ENDIF JVCLThemesEnabled}
|
|
procedure WMNCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST;
|
|
{$ENDIF VCL}
|
|
protected
|
|
FButton: TJvEditButton; // Polaris
|
|
FBtnControl: TWinControl;
|
|
FPopupVisible: Boolean; // Polaris
|
|
FFocused: Boolean; // Polaris
|
|
FPopup: TWinControl;
|
|
function CreateDataConnector: TJvCustomComboEditDataConnector; virtual;
|
|
{$IFDEF COMPILER6_UP}
|
|
{$IFDEF VCL}
|
|
procedure CustomAlignPosition(Control: TControl; var NewLeft, NewTop, NewWidth,
|
|
NewHeight: Integer; var AlignRect: TRect; AlignInfo: TAlignInfo); override;
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
procedure CustomAlignPosition(Control: TControl; var NewLeft,
|
|
NewTop, NewWidth, NewHeight: Integer; var AlignRect: TRect); override;
|
|
{$ENDIF VisualCLX}
|
|
{$ENDIF COMPILER6_UP}
|
|
{$IFDEF VCL}
|
|
procedure WndProc(var Msg: TMessage); override;
|
|
{$ENDIF VCL}
|
|
procedure WMClear(var Msg: TMessage); message WM_CLEAR;
|
|
procedure WMCut(var Msg: TMessage); message WM_CUT;
|
|
procedure WMPaste(var Msg: TMessage); message WM_PASTE;
|
|
procedure AdjustSize; override;
|
|
procedure FocusKilled(NextWnd: THandle); override;
|
|
procedure FocusSet(PrevWnd: THandle); override;
|
|
procedure EnabledChanged; override;
|
|
procedure FontChanged; override;
|
|
procedure DoEnter; override;
|
|
procedure DoExit; override;
|
|
procedure DoCtl3DChanged; virtual;
|
|
function DoEraseBackground(Canvas: TCanvas; Param: Integer): Boolean; override;
|
|
{ Repositions the child controls; checkbox }
|
|
procedure UpdateControls; virtual;
|
|
{ Updates the margins of the edit box }
|
|
procedure UpdateMargins; dynamic;
|
|
{ Returns the margins of the edit box }
|
|
procedure GetInternalMargins(var ALeft, ARight: Integer); virtual;
|
|
procedure CreatePopup; virtual;
|
|
procedure HidePopup; virtual; // (ahuser): WARNING: Do not release or free the component in HidePopup -> else AV in MouseUp
|
|
procedure ShowPopup(Origin: TPoint); virtual;
|
|
{$IFDEF VisualCLX}
|
|
procedure DoFlatChanged; override;
|
|
procedure Paint; override;
|
|
{$ENDIF VisualCLX}
|
|
function AcceptPopup(var Value: Variant): Boolean; virtual;
|
|
function EditCanModify: Boolean; override;
|
|
function GetActionLinkClass: TControlActionLinkClass; override;
|
|
function GetPopupValue: Variant; virtual;
|
|
function GetReadOnly: Boolean; virtual;
|
|
function GetSettingCursor: Boolean;
|
|
procedure AcceptValue(const Value: Variant); virtual;
|
|
procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override;
|
|
procedure AdjustHeight;
|
|
procedure ButtonClick; dynamic;
|
|
procedure Change; override;
|
|
procedure CreateWnd; override;
|
|
{$IFDEF VCL}
|
|
procedure CreateParams(var Params: TCreateParams); override;
|
|
procedure CreateAutoComplete; virtual;
|
|
procedure DestroyWnd; override;
|
|
procedure DestroyAutoComplete; virtual;
|
|
procedure UpdateAutoComplete; virtual;
|
|
function GetAutoCompleteSource: IEnumString; virtual;
|
|
{$ENDIF VCL}
|
|
procedure DefineProperties(Filer: TFiler); override;
|
|
procedure DoChange; virtual; //virtual Polaris
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure KeyPress(var Key: Char); override;
|
|
procedure Loaded; override;
|
|
procedure LocalKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); // RDB
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
procedure PopupChange; virtual;
|
|
procedure PopupCloseUp(Sender: TObject; Accept: Boolean); virtual; //virtual Polaris
|
|
procedure AsyncPopupCloseUp(Accept: Boolean); virtual;
|
|
procedure PopupDropDown(DisableEdit: Boolean); virtual;
|
|
procedure SetClipboardCommands(const Value: TJvClipboardCommands); override; // RDB
|
|
procedure SetDirectInput(Value: Boolean); // Polaris
|
|
procedure SetDisabledColor(const Value: TColor); virtual; // RDB
|
|
procedure SetDisabledTextColor(const Value: TColor); virtual; // RDB
|
|
procedure SetGroupIndex(const Value: Integer); // RDB
|
|
procedure SetPopupValue(const Value: Variant); virtual;
|
|
procedure SetReadOnly(Value: Boolean); virtual;
|
|
procedure SetShowCaret; // Polaris
|
|
procedure UpdatePopupVisible;
|
|
{$IFDEF VCL}
|
|
property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
property Alignment;
|
|
{$ENDIF VisualCLX}
|
|
property AlwaysEnableButton: Boolean read FAlwaysEnableButton write FAlwaysEnableButton default False;
|
|
property AlwaysShowPopup: Boolean read FAlwaysShowPopup write FAlwaysShowPopup default False;
|
|
{$IFDEF VCL}
|
|
property AutoCompleteItems: TStrings read FAutoCompleteItems write SetAutoCompleteItems;
|
|
property AutoCompleteOptions: TJvAutoCompleteOptions read FAutoCompleteOptions
|
|
write SetAutoCompleteOptions default [];
|
|
{$ENDIF VCL}
|
|
property Button: TJvEditButton read FButton;
|
|
property ButtonFlat: Boolean read GetButtonFlat write SetButtonFlat default False;
|
|
property ButtonHint: string read GetButtonHint write SetButtonHint;
|
|
property ButtonWidth: Integer read GetButtonWidth write SetButtonWidth stored BtnWidthStored;
|
|
property ClickKey: TShortCut read FClickKey write FClickKey default scAltDown;
|
|
property DirectInput: Boolean read GetDirectInput write SetDirectInput default True;
|
|
property DisabledColor: TColor read FDisabledColor write SetDisabledColor default clWindow; // RDB
|
|
property DisabledTextColor: TColor read FDisabledTextColor write SetDisabledTextColor default clGrayText; // RDB
|
|
{$IFDEF VCL}
|
|
property Flat: Boolean read GetFlat write SetFlat {$IFDEF VisualCLX} default False; {$ENDIF VisualCLX}
|
|
{$IFDEF VCL} stored IsFlatStored; {$ENDIF VCL}
|
|
property ParentFlat: Boolean read GetParentFlat write SetParentFlat default True;
|
|
{$ENDIF VCL}
|
|
property Glyph: TBitmap read GetGlyph write SetGlyph stored IsCustomGlyph;
|
|
property GroupIndex: Integer read FGroupIndex write SetGroupIndex default -1;
|
|
property ImageIndex: TImageIndex read FImageIndex write SetImageIndex stored IsImageIndexStored default -1;
|
|
property ImageKind: TJvImageKind read FImageKind write SetImageKind default ikCustom;
|
|
property Images: TCustomImageList read FImages write SetImages;
|
|
property NumGlyphs: TNumGlyphs read GetNumGlyphs write SetNumGlyphs default 1;
|
|
property OnButtonClick: TNotifyEvent read FOnButtonClick write FOnButtonClick;
|
|
property OnKeyDown: TKeyEvent read FOnKeyDown write FOnKeyDown;
|
|
property PopupAlign: TPopupAlign read FPopupAlign write FPopupAlign default epaRight;
|
|
property PopupVisible: Boolean read GetPopupVisible;
|
|
property ReadOnly: Boolean read GetReadOnly write SetReadOnly default False;
|
|
property SettingCursor: Boolean read GetSettingCursor;
|
|
property ShowButton: Boolean read GetShowButton write SetShowButton default True;
|
|
property OnEnabledChanged: TNotifyEvent read FOnEnabledChanged write FOnEnabledChanged;
|
|
property OnPopupShown: TNotifyEvent read FOnPopupShown write FOnPopupShown;
|
|
property OnPopupHidden: TNotifyEvent read FOnPopupHidden write FOnPopupHidden;
|
|
|
|
property DataConnector: TJvCustomComboEditDataConnector read FDataConnector write SetDataConnector;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
class function DefaultImageIndex: TImageIndex; virtual;
|
|
class function DefaultImages: TCustomImageList; virtual;
|
|
procedure DoClick;
|
|
procedure SelectAll;
|
|
{$IFDEF VisualCLX}
|
|
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
|
|
{$ENDIF VisualCLX}
|
|
{ Backwards compatibility; moved to public&published; eventually remove }
|
|
property GlyphKind: TGlyphKind read GetGlyphKind write SetGlyphKind;
|
|
{$IFDEF VCL}
|
|
property Ctl3D;
|
|
{$ENDIF VCL}
|
|
end;
|
|
|
|
TJvComboEdit = class(TJvCustomComboEdit)
|
|
public
|
|
property Button;
|
|
published
|
|
//Polaris
|
|
property Action;
|
|
property Align;
|
|
property Alignment;
|
|
property AlwaysEnableButton;
|
|
property AlwaysShowPopup;
|
|
property Anchors;
|
|
property AutoSelect;
|
|
property AutoSize;
|
|
{$IFDEF VCL}
|
|
property AutoCompleteItems;
|
|
property AutoCompleteOptions;
|
|
{$IFDEF COMPILER6_UP}
|
|
property BevelEdges;
|
|
property BevelInner;
|
|
property BevelKind default bkNone;
|
|
property BevelOuter;
|
|
{$ENDIF COMPILER6_UP}
|
|
property BiDiMode;
|
|
property DragCursor;
|
|
property DragKind;
|
|
property Flat;
|
|
property ImeMode;
|
|
property ImeName;
|
|
property OEMConvert;
|
|
property ParentBiDiMode;
|
|
property ParentFlat;
|
|
property OnEndDock;
|
|
property OnStartDock;
|
|
{$ENDIF VCL}
|
|
property BorderStyle;
|
|
property ButtonFlat;
|
|
property ButtonHint;
|
|
property ButtonWidth;
|
|
property CharCase;
|
|
property ClickKey;
|
|
property ClipboardCommands; // RDB
|
|
property Color;
|
|
property Constraints;
|
|
property DirectInput;
|
|
property DisabledColor; // RDB
|
|
property DisabledTextColor; // RDB
|
|
property DragMode;
|
|
property EditMask;
|
|
property Enabled;
|
|
property Font;
|
|
property Glyph;
|
|
property HideSelection;
|
|
property ImageIndex;
|
|
property ImageKind;
|
|
property Images;
|
|
property MaxLength;
|
|
property NumGlyphs;
|
|
property ParentColor;
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property PopupMenu;
|
|
property ReadOnly;
|
|
property ShowHint;
|
|
property ShowButton;
|
|
property TabOrder;
|
|
property TabStop;
|
|
property Text;
|
|
property Visible;
|
|
property OnButtonClick;
|
|
property OnChange;
|
|
property OnClick;
|
|
property OnContextPopup;
|
|
property OnDblClick;
|
|
property OnDragDrop;
|
|
property OnDragOver;
|
|
property OnEndDrag;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnKeyDown; // RDB
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
property OnMouseDown;
|
|
property OnMouseEnter;
|
|
property OnMouseLeave;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnStartDrag;
|
|
|
|
property DataConnector;
|
|
end;
|
|
|
|
{ TJvFileDirEdit }
|
|
{ The common parent of TJvFilenameEdit and TJvDirectoryEdit }
|
|
{ For internal use only; it's not intended to be used separately }
|
|
|
|
type
|
|
TExecOpenDialogEvent = procedure(Sender: TObject; var AName: string; var AAction: Boolean) of object;
|
|
|
|
TJvFileDirEdit = class(TJvCustomComboEdit)
|
|
private
|
|
FErrMode: Cardinal;
|
|
FMultipleDirs: Boolean;
|
|
FOnDropFiles: TNotifyEvent;
|
|
FOnBeforeDialog: TExecOpenDialogEvent;
|
|
FOnAfterDialog: TExecOpenDialogEvent;
|
|
{$IFDEF VCL}
|
|
FAcceptFiles: Boolean;
|
|
FMRUList: IUnknown;
|
|
FHistoryList: IUnknown;
|
|
FFileSystemList: IUnknown;
|
|
FAutoCompleteFileOptions: TJvAutoCompleteFileOptions;
|
|
FAutoCompleteSourceIntf: IEnumString;
|
|
procedure SetAutoCompleteFileOptions(const Value: TJvAutoCompleteFileOptions);
|
|
procedure SetDragAccept(Value: Boolean);
|
|
procedure SetAcceptFiles(Value: Boolean);
|
|
procedure WMDropFiles(var Msg: TWMDropFiles); message WM_DROPFILES;
|
|
{$IFDEF JVCLThemesEnabled}
|
|
procedure CMSysColorChange(var Msg: TMessage); message CM_SYSCOLORCHANGE;
|
|
{$ENDIF JVCLThemesEnabled}
|
|
{$ENDIF VCL}
|
|
protected
|
|
{$IFDEF VCL}
|
|
procedure CreateHandle; override;
|
|
procedure DestroyWindowHandle; override;
|
|
procedure DestroyAutoComplete; override;
|
|
procedure UpdateAutoComplete; override;
|
|
function GetAutoCompleteSource: IEnumString; override;
|
|
{$ENDIF VCL}
|
|
function GetLongName: string; virtual; abstract;
|
|
function GetShortName: string; virtual; abstract;
|
|
procedure DoAfterDialog(var FileName: string; var Action: Boolean); dynamic;
|
|
procedure DoBeforeDialog(var FileName: string; var Action: Boolean); dynamic;
|
|
procedure ReceptFileDir(const AFileName: string); virtual; abstract;
|
|
procedure ClearFileList; virtual;
|
|
procedure Change; override;
|
|
procedure DisableSysErrors;
|
|
procedure EnableSysErrors;
|
|
{$IFDEF VCL}
|
|
property AutoCompleteFileOptions: TJvAutoCompleteFileOptions read FAutoCompleteFileOptions write
|
|
SetAutoCompleteFileOptions;
|
|
property AutoCompleteOptions default [acoAutoSuggest];
|
|
{$ENDIF VCL}
|
|
property ImageKind default ikDefault;
|
|
property MaxLength;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
property LongName: string read GetLongName;
|
|
property ShortName: string read GetShortName;
|
|
published
|
|
{$IFDEF VCL}
|
|
property AcceptFiles: Boolean read FAcceptFiles write SetAcceptFiles default True;
|
|
{$ENDIF VCL}
|
|
property OnBeforeDialog: TExecOpenDialogEvent read FOnBeforeDialog write FOnBeforeDialog;
|
|
property OnAfterDialog: TExecOpenDialogEvent read FOnAfterDialog write FOnAfterDialog;
|
|
property OnDropFiles: TNotifyEvent read FOnDropFiles write FOnDropFiles;
|
|
property OnButtonClick;
|
|
property ClipboardCommands; // RDB
|
|
property DisabledTextColor; // RDB
|
|
property DisabledColor; // RDB
|
|
property OEMConvert default True; // Mantis 3621
|
|
end;
|
|
|
|
TFileDialogKind = (dkOpen, dkSave, dkOpenPicture, dkSavePicture);
|
|
|
|
TJvFilenameEdit = class(TJvFileDirEdit)
|
|
private
|
|
FDialog: TOpenDialog;
|
|
FDialogKind: TFileDialogKind;
|
|
FAddQuotes: Boolean;
|
|
procedure CreateEditDialog;
|
|
function GetFileName: TFileName;
|
|
function GetDefaultExt: TFileExt;
|
|
{$IFDEF VCL}
|
|
function GetFileEditStyle: TFileEditStyle;
|
|
{$ENDIF VCL}
|
|
function GetFilter: string;
|
|
function GetFilterIndex: Integer;
|
|
function GetInitialDir: string;
|
|
function GetHistoryList: TStrings;
|
|
function GetOptions: TOpenOptions;
|
|
function GetDialogTitle: string;
|
|
function GetDialogFiles: TStrings;
|
|
procedure SetDialogKind(Value: TFileDialogKind);
|
|
procedure SetFileName(const Value: TFileName);
|
|
procedure SetDefaultExt(Value: TFileExt);
|
|
{$IFDEF VCL}
|
|
procedure SetFileEditStyle(Value: TFileEditStyle);
|
|
{$ENDIF VCL}
|
|
procedure SetFilter(const Value: string);
|
|
procedure SetFilterIndex(Value: Integer);
|
|
procedure SetInitialDir(const Value: string);
|
|
procedure SetHistoryList(Value: TStrings);
|
|
procedure SetOptions(Value: TOpenOptions);
|
|
procedure SetDialogTitle(const Value: string);
|
|
function IsCustomTitle: Boolean;
|
|
function IsCustomFilter: Boolean;
|
|
protected
|
|
procedure PopupDropDown(DisableEdit: Boolean); override;
|
|
procedure ReceptFileDir(const AFileName: string); override;
|
|
procedure ClearFileList; override;
|
|
function GetLongName: string; override;
|
|
function GetShortName: string; override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
class function DefaultImageIndex: TImageIndex; override;
|
|
property Dialog: TOpenDialog read FDialog;
|
|
property DialogFiles: TStrings read GetDialogFiles;
|
|
published
|
|
//Polaris
|
|
property Action;
|
|
property Align;
|
|
property AutoSize;
|
|
property AddQuotes: Boolean read FAddQuotes write FAddQuotes default True;
|
|
property DialogKind: TFileDialogKind read FDialogKind write SetDialogKind
|
|
default dkOpen;
|
|
property DefaultExt: TFileExt read GetDefaultExt write SetDefaultExt;
|
|
{$IFDEF VCL}
|
|
property AutoCompleteOptions;
|
|
property AutoCompleteFileOptions default [acfFileSystem];
|
|
{$IFDEF COMPILER6_UP}
|
|
property BevelEdges;
|
|
property BevelInner;
|
|
property BevelKind default bkNone;
|
|
property BevelOuter;
|
|
{$ENDIF COMPILER6_UP}
|
|
property Flat;
|
|
property ParentFlat;
|
|
{ (rb) Obsolete; added 'stored False', eventually remove }
|
|
property FileEditStyle: TFileEditStyle read GetFileEditStyle write SetFileEditStyle stored False;
|
|
{$ENDIF VCL}
|
|
property FileName: TFileName read GetFileName write SetFileName stored False;
|
|
property Filter: string read GetFilter write SetFilter stored IsCustomFilter;
|
|
property FilterIndex: Integer read GetFilterIndex write SetFilterIndex default 1;
|
|
property InitialDir: string read GetInitialDir write SetInitialDir;
|
|
{ (rb) Obsolete; added 'stored False', eventually remove }
|
|
property HistoryList: TStrings read GetHistoryList write SetHistoryList stored False;
|
|
property DialogOptions: TOpenOptions read GetOptions write SetOptions default [ofHideReadOnly];
|
|
property DialogTitle: string read GetDialogTitle write SetDialogTitle stored IsCustomTitle;
|
|
property AutoSelect;
|
|
property ButtonHint;
|
|
property ButtonFlat;
|
|
property BorderStyle;
|
|
property CharCase;
|
|
property ClickKey;
|
|
property Color;
|
|
property DirectInput;
|
|
{$IFDEF VCL}
|
|
property DragCursor;
|
|
property BiDiMode;
|
|
property DragKind;
|
|
property ParentBiDiMode;
|
|
property ImeMode;
|
|
property ImeName;
|
|
property OnEndDock;
|
|
property OnStartDock;
|
|
{$ENDIF VCL}
|
|
property DragMode;
|
|
property EditMask;
|
|
property Enabled;
|
|
property Font;
|
|
property Glyph;
|
|
property GroupIndex;
|
|
property ImageIndex;
|
|
property Images;
|
|
property ImageKind;
|
|
property NumGlyphs;
|
|
property ButtonWidth;
|
|
property HideSelection;
|
|
property Anchors;
|
|
property Constraints;
|
|
property ParentColor;
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property PopupMenu;
|
|
property ReadOnly;
|
|
property ShowHint;
|
|
property ShowButton;
|
|
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 OnMouseEnter;
|
|
property OnMouseLeave;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnStartDrag;
|
|
property OnContextPopup;
|
|
end;
|
|
|
|
TDirDialogKind = (dkVCL, dkWin32);
|
|
|
|
TJvDirectoryEdit = class(TJvFileDirEdit)
|
|
private
|
|
{$IFDEF VCL}
|
|
FOptions: TSelectDirOpts;
|
|
{$ENDIF VCL}
|
|
FInitialDir: string;
|
|
FDialogText: string;
|
|
FDialogKind: TDirDialogKind;
|
|
protected
|
|
FMultipleDirs: Boolean; // Polaris (???)
|
|
procedure PopupDropDown(DisableEdit: Boolean); override;
|
|
procedure ReceptFileDir(const AFileName: string); override;
|
|
function GetLongName: string; override;
|
|
function GetShortName: string; override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
class function DefaultImageIndex: TImageIndex; override;
|
|
published
|
|
//Polaris
|
|
property Action;
|
|
property Align;
|
|
property AutoSize;
|
|
property DialogKind: TDirDialogKind read FDialogKind write FDialogKind default dkVCL;
|
|
property DialogText: string read FDialogText write FDialogText;
|
|
{$IFDEF VCL}
|
|
property AutoCompleteOptions;
|
|
property AutoCompleteFileOptions default [acfFileSystem, acfFileSysDirs];
|
|
{$IFDEF COMPILER6_UP}
|
|
property BevelEdges;
|
|
property BevelInner;
|
|
property BevelKind default bkNone;
|
|
property BevelOuter;
|
|
{$ENDIF COMPILER6_UP}
|
|
property Flat;
|
|
property ParentFlat;
|
|
property DialogOptions: TSelectDirOpts read FOptions write FOptions default [sdAllowCreate];
|
|
{$ENDIF VCL}
|
|
property InitialDir: string read FInitialDir write FInitialDir;
|
|
property MultipleDirs: Boolean read FMultipleDirs write FMultipleDirs default False;
|
|
property AutoSelect;
|
|
property ButtonHint;
|
|
property ButtonFlat;
|
|
property BorderStyle;
|
|
property CharCase;
|
|
property ClickKey;
|
|
property Color;
|
|
property DirectInput;
|
|
{$IFDEF VCL}
|
|
property DragCursor;
|
|
property BiDiMode;
|
|
property ParentBiDiMode;
|
|
property ImeMode;
|
|
property ImeName;
|
|
property DragKind;
|
|
property OnEndDock;
|
|
property OnStartDock;
|
|
{$ENDIF VCL}
|
|
property DragMode;
|
|
property EditMask;
|
|
property Enabled;
|
|
property Font;
|
|
property Glyph;
|
|
property GroupIndex;
|
|
property ImageIndex;
|
|
property Images;
|
|
property ImageKind;
|
|
property NumGlyphs;
|
|
property ButtonWidth;
|
|
property HideSelection;
|
|
property Anchors;
|
|
property Constraints;
|
|
property ParentColor;
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property PopupMenu;
|
|
property ReadOnly;
|
|
property ShowHint;
|
|
property ShowButton;
|
|
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 OnMouseEnter;
|
|
property OnMouseLeave;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnStartDrag;
|
|
property OnContextPopup;
|
|
end;
|
|
|
|
TCalendarStyle = (csPopup, csDialog);
|
|
TYearDigits = (dyDefault, dyFour, dyTwo);
|
|
|
|
const
|
|
{$IFDEF DEFAULT_POPUP_CALENDAR}
|
|
dcsDefault = csPopup;
|
|
{$ELSE}
|
|
dcsDefault = csDialog;
|
|
{$ENDIF DEFAULT_POPUP_CALENDAR}
|
|
|
|
type
|
|
TExecDateDialog = procedure(Sender: TObject; var ADate: TDateTime;
|
|
var Action: Boolean) of object;
|
|
TJvInvalidDateEvent = procedure(Sender: TObject; const DateString: string;
|
|
var NewDate: TDateTime; var Accept: Boolean) of object;
|
|
TPreferredDateFormat = (pdLocale, pdLocaleOnly, pdCustom, pdCustomOnly);
|
|
|
|
TJvCustomDateEditDataConnector = class(TJvCustomComboEditDataConnector)
|
|
private
|
|
FDefaultDate: TDateTime;
|
|
FDefaultDateIsNow: Boolean;
|
|
procedure SetDefaultDateIsNow(const Value: Boolean);
|
|
function IsDefaultDateStored: Boolean;
|
|
protected
|
|
procedure RecordChanged; override;
|
|
procedure UpdateData; override;
|
|
public
|
|
procedure Assign(Source: TPersistent); override;
|
|
published
|
|
property DefaultDate: TDateTime read FDefaultDate write FDefaultDate stored IsDefaultDateStored;
|
|
property DefaultDateIsNow: Boolean read FDefaultDateIsNow write SetDefaultDateIsNow default False;
|
|
end;
|
|
|
|
TJvCustomDateEdit = class(TJvCustomComboEdit)
|
|
private
|
|
FMinDate: TDateTime; // Polaris
|
|
FMaxDate: TDateTime; // Polaris
|
|
FTitle: string;
|
|
FOnAcceptDate: TExecDateDialog;
|
|
FOnInvalidDate: TJvInvalidDateEvent;
|
|
FDefaultToday: Boolean;
|
|
FPopupColor: TColor;
|
|
FCheckOnExit: Boolean;
|
|
FBlanksChar: Char;
|
|
FCalendarHints: TStringList;
|
|
FStartOfWeek: TDayOfWeekName;
|
|
FWeekends: TDaysOfWeek;
|
|
FWeekendColor: TColor;
|
|
FCustomDateFormat: string;
|
|
FYearDigits: TYearDigits;
|
|
FDateFormatPreferred: TPreferredDateFormat;
|
|
FDateFormat: string[10];
|
|
FDateFormat2: string[10];
|
|
FFormatting: Boolean;
|
|
// Polaris
|
|
procedure SetMinDate(Value: TDateTime);
|
|
procedure SetMaxDate(Value: TDateTime);
|
|
// Polaris
|
|
function GetDate: TDateTime;
|
|
procedure SetCustomDateFormat(const Value: string);
|
|
procedure SetDateFormatPreferred(Value: TPreferredDateFormat);
|
|
function IsDateFormatStored: Boolean;
|
|
function IsDateFormatPreferredStored: Boolean;
|
|
procedure SetYearDigits(Value: TYearDigits);
|
|
function GetPopupColor: TColor;
|
|
procedure SetPopupColor(Value: TColor);
|
|
function GetDialogTitle: string;
|
|
procedure SetDialogTitle(const Value: string);
|
|
function IsCustomTitle: Boolean;
|
|
function IsDateStored: Boolean;
|
|
function GetCalendarStyle: TCalendarStyle;
|
|
procedure SetCalendarStyle(Value: TCalendarStyle);
|
|
function GetCalendarHints: TStrings;
|
|
procedure SetCalendarHints(Value: TStrings);
|
|
procedure CalendarHintsChanged(Sender: TObject);
|
|
procedure SetWeekendColor(Value: TColor);
|
|
procedure SetWeekends(Value: TDaysOfWeek);
|
|
procedure SetStartOfWeek(Value: TDayOfWeekName);
|
|
procedure SetBlanksChar(Value: Char);
|
|
function TextStored: Boolean;
|
|
// Polaris
|
|
function StoreMinDate: Boolean;
|
|
function StoreMaxDate: Boolean;
|
|
// Polaris
|
|
function FourDigitYear: Boolean;
|
|
{$IFDEF VCL}
|
|
procedure WMContextMenu(var Msg: TWMContextMenu); message WM_CONTEXTMENU;
|
|
{$ENDIF VCL}
|
|
protected
|
|
// Polaris
|
|
FDateAutoBetween: Boolean;
|
|
procedure SetDate(Value: TDateTime); virtual;
|
|
function DoInvalidDate(const DateString: string; var ANewDate: TDateTime): Boolean; virtual;
|
|
procedure SetDateAutoBetween(Value: Boolean); virtual;
|
|
procedure TestDateBetween(var Value: TDateTime); virtual;
|
|
// Polaris
|
|
procedure DoExit; override;
|
|
procedure Change; override;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure KeyPress(var Key: Char); override;
|
|
{$IFDEF VCL}
|
|
procedure CreateWindowHandle(const Params: TCreateParams); override;
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
procedure CreateWidget; override;
|
|
{$ENDIF VisualCLX}
|
|
function AcceptPopup(var Value: Variant): Boolean; override;
|
|
procedure AcceptValue(const Value: Variant); override;
|
|
procedure SetPopupValue(const Value: Variant); override;
|
|
function GetDateFormat: string;
|
|
procedure ApplyDate(Value: TDateTime); virtual;
|
|
procedure UpdateFormat;
|
|
procedure UpdatePopup;
|
|
procedure PopupDropDown(DisableEdit: Boolean); override;
|
|
procedure SetParent(AParent: TWinControl); override;
|
|
function GetDefaultDateFormat: string; virtual;
|
|
function GetDefaultDateFormatPreferred: TPreferredDateFormat; virtual;
|
|
function CreateDataConnector: TJvCustomComboEditDataConnector; override;
|
|
|
|
property BlanksChar: Char read FBlanksChar write SetBlanksChar default ' ';
|
|
property CalendarHints: TStrings read GetCalendarHints write SetCalendarHints;
|
|
property CheckOnExit: Boolean read FCheckOnExit write FCheckOnExit default False;
|
|
property DefaultToday: Boolean read FDefaultToday write FDefaultToday default False;
|
|
property DialogTitle: string read GetDialogTitle write SetDialogTitle stored IsCustomTitle;
|
|
property EditMask stored False;
|
|
property Formatting: Boolean read FFormatting;
|
|
property ImageKind default ikDefault;
|
|
property PopupColor: TColor read GetPopupColor write SetPopupColor default clMenu;
|
|
property CalendarStyle: TCalendarStyle read GetCalendarStyle
|
|
write SetCalendarStyle default dcsDefault;
|
|
property StartOfWeek: TDayOfWeekName read FStartOfWeek write SetStartOfWeek default Mon;
|
|
property Weekends: TDaysOfWeek read FWeekends write SetWeekends default [Sun];
|
|
property WeekendColor: TColor read FWeekendColor write SetWeekendColor default clRed;
|
|
property DateFormat: string read FCustomDateFormat write SetCustomDateFormat stored IsDateFormatStored;
|
|
property DateFormatPreferred: TPreferredDateFormat read FDateFormatPreferred
|
|
write SetDateFormatPreferred stored IsDateFormatPreferredStored;
|
|
property YearDigits: TYearDigits read FYearDigits write SetYearDigits default dyDefault;
|
|
property OnAcceptDate: TExecDateDialog read FOnAcceptDate write FOnAcceptDate;
|
|
property OnInvalidDate: TJvInvalidDateEvent read FOnInvalidDate write FOnInvalidDate;
|
|
property MaxLength stored False;
|
|
{ Text is already stored via Date property }
|
|
property Text stored False;
|
|
public
|
|
// Polaris
|
|
property DateAutoBetween: Boolean read FDateAutoBetween write SetDateAutoBetween default True;
|
|
property MinDate: TDateTime read FMinDate write SetMinDate stored StoreMinDate;
|
|
property MaxDate: TDateTime read FMaxDate write SetMaxDate stored StoreMaxDate;
|
|
procedure ValidateEdit; override;
|
|
// Polaris
|
|
constructor Create(AOwner: TComponent); override;
|
|
class function DefaultImageIndex: TImageIndex; override;
|
|
destructor Destroy; override;
|
|
procedure CheckValidDate; virtual;
|
|
function GetDateMask: string;
|
|
procedure UpdateMask; virtual;
|
|
property Date: TDateTime read GetDate write SetDate stored IsDateStored;
|
|
property PopupVisible;
|
|
end;
|
|
|
|
TJvDateEdit = class(TJvCustomDateEdit)
|
|
// Polaris
|
|
protected
|
|
procedure SetDate(Value: TDateTime); override;
|
|
// Polaris
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
property EditMask;
|
|
published
|
|
property Date;
|
|
property DateFormat;
|
|
property DateFormatPreferred;
|
|
property DateAutoBetween; // Polaris
|
|
property MinDate; // Polaris
|
|
property MaxDate; // Polaris
|
|
property Align; // Polaris
|
|
property Action;
|
|
property AutoSelect;
|
|
property AutoSize;
|
|
property BlanksChar;
|
|
property BorderStyle;
|
|
property ButtonHint;
|
|
property ButtonFlat;
|
|
property CalendarHints;
|
|
property CheckOnExit;
|
|
property ClickKey;
|
|
property Color;
|
|
property DefaultToday;
|
|
property DialogTitle;
|
|
property DirectInput;
|
|
{$IFDEF VCL}
|
|
property DragCursor;
|
|
{$IFDEF COMPILER6_UP}
|
|
property BevelEdges;
|
|
property BevelInner;
|
|
property BevelKind default bkNone;
|
|
property BevelOuter;
|
|
{$ENDIF COMPILER6_UP}
|
|
property BiDiMode;
|
|
property DragKind;
|
|
property Flat;
|
|
property ParentBiDiMode;
|
|
property ParentFlat;
|
|
property ImeMode;
|
|
property ImeName;
|
|
property OnEndDock;
|
|
property OnStartDock;
|
|
{$ENDIF VCL}
|
|
property DragMode;
|
|
property Enabled;
|
|
property Font;
|
|
property Glyph;
|
|
property GroupIndex;
|
|
property ImageIndex;
|
|
property Images;
|
|
property ImageKind;
|
|
property NumGlyphs;
|
|
property ButtonWidth;
|
|
property HideSelection;
|
|
property Anchors;
|
|
property Constraints;
|
|
property MaxLength;
|
|
property ParentColor;
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property PopupAlign;
|
|
property PopupColor;
|
|
property PopupMenu;
|
|
property ReadOnly;
|
|
property ShowHint;
|
|
property ShowButton;
|
|
property CalendarStyle;
|
|
property StartOfWeek;
|
|
property Weekends;
|
|
property WeekendColor;
|
|
property YearDigits;
|
|
property TabOrder;
|
|
property TabStop;
|
|
property Text;
|
|
property Visible;
|
|
property OnAcceptDate;
|
|
property OnInvalidDate;
|
|
property OnButtonClick;
|
|
property OnChange;
|
|
property OnClick;
|
|
property OnDblClick;
|
|
property OnDragDrop;
|
|
property OnDragOver;
|
|
property OnEndDrag;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
property OnMouseDown;
|
|
property OnMouseEnter;
|
|
property OnMouseLeave;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnStartDrag;
|
|
property OnContextPopup;
|
|
property ClipboardCommands; // RDB
|
|
property DisabledTextColor; // RDB
|
|
property DisabledColor; // RDB
|
|
property OnKeyDown; // RDB
|
|
|
|
property DataConnector;
|
|
end;
|
|
|
|
EComboEditError = class(EJVCLException);
|
|
|
|
{ Utility routines }
|
|
|
|
procedure DateFormatChanged;
|
|
|
|
function EditorTextMargins(Editor: TCustomEdit): TPoint;
|
|
{$IFDEF VCL}
|
|
function PaintComboEdit(Editor: TJvCustomComboEdit; const AText: string;
|
|
AAlignment: TAlignment; StandardPaint: Boolean;
|
|
var ACanvas: TControlCanvas; var Msg: TWMPaint): Boolean;
|
|
function PaintEdit(Editor: TCustomEdit; const AText: string;
|
|
AAlignment: TAlignment; PopupVisible: Boolean;
|
|
DisabledTextColor: TColor; StandardPaint: Boolean;
|
|
var ACanvas: TControlCanvas; var Msg: TWMPaint): Boolean;
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
function PaintComboEdit(Editor: TJvCustomComboEdit; const AText: string;
|
|
AAlignment: TAlignment; StandardPaint: Boolean; Flat: Boolean; ACanvas: TCanvas): Boolean;
|
|
{ PaintEdit (CLX) needs an implemented EM_GETRECT message handler or a
|
|
TCustomComboEdit/TCustomComboMask class. If no EM_GETTEXT handler exists or
|
|
the class is derived from another class, it uses the ClientRect of the edit
|
|
control. }
|
|
function PaintEdit(Editor: TCustomEdit; const AText: WideString;
|
|
AAlignment: TAlignment; PopupVisible: Boolean;
|
|
DisabledTextColor: TColor; StandardPaint: Boolean; Flat: Boolean;
|
|
ACanvas: TCanvas): Boolean;
|
|
{$ENDIF VisualCLX}
|
|
|
|
{$IFDEF VisualCLX}
|
|
const
|
|
OBM_COMBO = 1;
|
|
{$ENDIF VisualCLX}
|
|
|
|
function LoadDefaultBitmap(Bmp: TBitmap; Item: Integer): Boolean;
|
|
|
|
function IsInWordArray(Value: Word; const A: array of Word): Boolean;
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
const
|
|
UnitVersioning: TUnitVersionInfo = (
|
|
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_32/run/JvToolEdit.pas $';
|
|
Revision: '$Revision: 11281 $';
|
|
Date: '$Date: 2007-05-09 18:44:52 +0200 (mer., 09 mai 2007) $';
|
|
LogPath: 'JVCL\run'
|
|
);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
implementation
|
|
|
|
uses
|
|
{$IFDEF HAS_UNIT_RTLCONSTS}
|
|
RTLConsts,
|
|
{$ENDIF HAS_UNIT_RTLCONSTS}
|
|
Math, Consts,
|
|
{$IFDEF COMPILER6_UP}
|
|
MaskUtils,
|
|
{$ENDIF COMPILER6_UP}
|
|
{$IFDEF VCL}
|
|
MultiMon,
|
|
{$IFNDEF CLR}
|
|
JvBrowseFolder,
|
|
{$ENDIF !CLR}
|
|
{$ENDIF VCL}
|
|
JvPickDate, JvJCLUtils, JvJVCLUtils,
|
|
JvThemes, JvResources, JvConsts;
|
|
|
|
{$R JvToolEdit.res}
|
|
|
|
type
|
|
{$IFDEF CLR}
|
|
TCustomEditAccessProtected = class(TCustomEdit)
|
|
public
|
|
property Ctl3D;
|
|
property BorderStyle;
|
|
end;
|
|
{$ELSE}
|
|
|
|
{$HINTS OFF}
|
|
TCustomMaskEditAccessPrivate = class(TCustomEdit)
|
|
private
|
|
// Do not remove these fields, although they are not used.
|
|
{$IFDEF COMPILER6_UP}
|
|
FEditMask: TEditMask;
|
|
{$ELSE}
|
|
FEditMask: string;
|
|
{$ENDIF COMPILER6_UP}
|
|
FMaskBlank: Char;
|
|
FMaxChars: Integer;
|
|
FMaskSave: Boolean;
|
|
FMaskState: TMaskedState;
|
|
FCaretPos: Integer;
|
|
FBtnDownX: Integer;
|
|
FOldValue: string;
|
|
FSettingCursor: Boolean;
|
|
end;
|
|
{$HINTS ON}
|
|
|
|
TCustomEditAccessProtected = class(TCustomEdit);
|
|
{$ENDIF CLR}
|
|
TCustomFormAccessProtected = class(TCustomForm);
|
|
TWinControlAccessProtected = class(TWinControl);
|
|
|
|
const
|
|
sDirBmp = 'JvDirectoryEditGLYPH'; { Directory editor button glyph }
|
|
sFileBmp = 'JvFilenameEditGLYPH'; { Filename editor button glyph }
|
|
sDateBmp = 'JvCustomDateEditGLYPH'; { Date editor button glyph }
|
|
|
|
{$IFDEF JVCLThemesEnabled}
|
|
// (rb) should/can these be put in a separate resource file?
|
|
sDirXPBmp = 'JvDirectoryEditXPGLYPH';
|
|
sFileXPBmp = 'JvFilenameEditXPGLYPH';
|
|
{$ENDIF JVCLThemesEnabled}
|
|
|
|
{$IFDEF VCL}
|
|
|
|
const
|
|
ACLO_NONE = 0; // don't enumerate anything
|
|
ACLO_CURRENTDIR = 1; // enumerate current directory
|
|
ACLO_MYCOMPUTER = 2; // enumerate MyComputer
|
|
ACLO_DESKTOP = 4; // enumerate Desktop Folder
|
|
ACLO_FAVORITES = 8; // enumerate Favorites Folder
|
|
ACLO_FILESYSONLY = 16; // enumerate only the file system
|
|
ACLO_FILESYSDIRS = 32; // enumerate only the file system dirs, UNC shares, and UNC servers.
|
|
|
|
//IID_IAutoCompList: TGUID = (D1:$00BB2760; D2:$6A77; D3:$11D0; D4:($A5, $35, $00, $C0, $4F, $D7, $D0, $62));
|
|
//IID_IObjMgr: TGUID = (D1:$00BB2761; D2:$6A77; D3:$11D0; D4:($A5, $35, $00, $C0, $4F, $D7, $D0, $62));
|
|
//IID_IACList: TGUID = (D1:$77A130B0; D2:$94FD; D3:$11D0; D4:($A5, $44, $00, $C0, $4F, $D7, $d0, $62));
|
|
//IID_IACList2: TGUID = (D1:$470141a0; D2:$5186; D3:$11d2; D4:($bb, $b6, $00, $60, $97, $7b, $46, $4c));
|
|
//IID_ICurrentWorkingDirectory: TGUID = (D1:$91956d21; D2:$9276; D3:$11d1; D4:($92, $1a, $00, $60, $97, $df, $5b, $d4));
|
|
|
|
{$IFDEF CLR}
|
|
CLSID_AutoComplete = '{00BB2763-6A77-11D0-A535-00C04FD7D062}';
|
|
CLSID_ACLMulti = '{00BB2765-6A77-11D0-A535-00C04FD7D062}';
|
|
CLSID_ACLHistory = '{00BB2764-6A77-11D0-A535-00C04FD7D062}';
|
|
CLSID_ACLMRU = '{6756A641-DE71-11D0-831B-00AA005B4383}';
|
|
CLSID_ACListISF = '{03C036F1-A186-11D0-824A-00AA005B4383}';
|
|
{$ELSE}
|
|
CLSID_AutoComplete: TGUID = (D1:$00BB2763; D2:$6A77; D3:$11D0; D4:($A5, $35, $00, $C0, $4F, $D7, $D0, $62));
|
|
CLSID_ACLHistory: TGUID = (D1:$00BB2764; D2:$6A77; D3:$11D0; D4:($A5, $35, $00, $C0, $4F, $D7, $D0, $62));
|
|
CLSID_ACListISF: TGUID = (D1:$03C036F1; D2:$A186; D3:$11D0; D4:($82, $4A, $00, $AA, $00, $5B, $43, $83));
|
|
CLSID_ACLMRU: TGUID = (D1:$6756a641; D2:$de71; D3:$11d0; D4:($83, $1b, $0, $aa, $0, $5b, $43, $83));
|
|
CLSID_ACLMulti: TGUID = (D1:$00BB2765; D2:$6A77; D3:$11D0; D4:($A5, $35, $00, $C0, $4F, $D7, $D0, $62));
|
|
{$ENDIF CLR}
|
|
|
|
//#if (_WIN32_IE >= 0x0600)
|
|
//CLSID_ACLCustomMRU: TGUID = (D1:$6935db93; D2:$21e8; D3:$4ccc; D4:($be, $b9, $9f, $e3, $c7, $7a, $29, $7a));
|
|
//#endif
|
|
|
|
type
|
|
{$IFDEF CLR}
|
|
TAutoCompleteSource = class(TInterfacedObject, IEnumString)
|
|
private
|
|
FComboEdit: TJvCustomComboEdit;
|
|
FCurrentIndex: Integer;
|
|
protected
|
|
{ IEnumString }
|
|
function Next(celt: Longint; rgelt: array of string; out pceltFetched: Longint): HResult;
|
|
function Skip(celt: Longint): HResult;
|
|
function Reset: HResult;
|
|
function Clone(out enm: IEnumString): HResult;
|
|
public
|
|
constructor Create(AComboEdit: TJvCustomComboEdit; const StartIndex: Integer); virtual;
|
|
end;
|
|
{$ELSE}
|
|
TAutoCompleteSource = class(TInterfacedObject, IEnumString)
|
|
private
|
|
FComboEdit: TJvCustomComboEdit;
|
|
FCurrentIndex: Integer;
|
|
protected
|
|
{ IEnumString }
|
|
function Next(celt: Longint; out elt; pceltFetched: PLongint): HRESULT; stdcall;
|
|
function Skip(celt: Longint): HRESULT; stdcall;
|
|
function Reset: HRESULT; stdcall;
|
|
function Clone(out enm: IEnumString): HRESULT; stdcall;
|
|
public
|
|
constructor Create(AComboEdit: TJvCustomComboEdit; const StartIndex: Integer); virtual;
|
|
end;
|
|
{$ENDIF CLR}
|
|
|
|
{$IFDEF CLR}
|
|
[ComImport, InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
|
{$ENDIF CLR}
|
|
IACList = interface(IUnknown)
|
|
['{77A130B0-94FD-11D0-A544-00C04FD7d062}']
|
|
{$IFDEF CLR}[PreserveSig]{$ENDIF CLR}
|
|
function Expand(pszExpand: string): HRESULT; {$IFNDEF CLR}stdcall;{$ENDIF}
|
|
end;
|
|
|
|
{$IFDEF CLR}
|
|
[ComImport, InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
|
{$ENDIF CLR}
|
|
IACList2 = interface(IACList)
|
|
['{470141a0-5186-11d2-bbb6-0060977b464c}']
|
|
{$IFDEF CLR}[PreserveSig]{$ENDIF CLR}
|
|
function SetOptions(dwFlag: DWORD): HRESULT; {$IFNDEF CLR}stdcall;{$ENDIF}
|
|
{$IFDEF CLR}[PreserveSig]{$ENDIF CLR}
|
|
function GetOptions(var pdwFlag: DWORD): HRESULT; {$IFNDEF CLR}stdcall;{$ENDIF}
|
|
end;
|
|
|
|
{$IFDEF CLR}
|
|
[ComImport, InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
|
{$ENDIF CLR}
|
|
IObjMgr = interface(IUnknown)
|
|
['{00BB2761-6A77-11D0-a535-00c04fd7d062}']
|
|
{$IFDEF CLR}[PreserveSig]{$ENDIF CLR}
|
|
function Append(punk: IUnknown): HRESULT; {$IFNDEF CLR}stdcall;{$ENDIF}
|
|
{$IFDEF CLR}[PreserveSig]{$ENDIF CLR}
|
|
function Remove(punk: IUnknown): HRESULT; {$IFNDEF CLR}stdcall;{$ENDIF}
|
|
end;
|
|
|
|
type
|
|
{ TDateHook is used to only have 1 hook per application for monitoring
|
|
date changes;
|
|
|
|
We can't use WM_WININICHANGE or CM_WININICHANGE in the controls
|
|
itself, because it comes too early. (The Application object does the
|
|
changing on receiving WM_WININICHANGE; The Application object receives it
|
|
later than the forms, controls etc.
|
|
}
|
|
|
|
TDateHook = class(TObject)
|
|
private
|
|
FCount: Integer;
|
|
FHooked: Boolean;
|
|
FWinIniChangeReceived: Boolean;
|
|
protected
|
|
function FormatSettingsChange(var Msg: TMessage): Boolean;
|
|
procedure Hook;
|
|
procedure UnHook;
|
|
public
|
|
procedure Add;
|
|
procedure Delete;
|
|
end;
|
|
|
|
var
|
|
GDateHook: TDateHook = nil;
|
|
|
|
{$ENDIF VCL}
|
|
|
|
var
|
|
GDateImageIndex: TImageIndex = -1;
|
|
GDefaultComboEditImagesList: TImageList = nil;
|
|
GDirImageIndex: TImageIndex = -1;
|
|
GFileImageIndex: TImageIndex = -1;
|
|
{$IFDEF JVCLThemesEnabled}
|
|
GDirImageIndexXP: TImageIndex = -1;
|
|
GFileImageIndexXP: TImageIndex = -1;
|
|
{$ENDIF JVCLThemesEnabled}
|
|
|
|
//=== Local procedures =======================================================
|
|
|
|
{$IFDEF VCL}
|
|
|
|
function DateHook: TDateHook;
|
|
begin
|
|
if GDateHook = nil then
|
|
GDateHook := TDateHook.Create;
|
|
Result := GDateHook;
|
|
end;
|
|
|
|
{$ENDIF VCL}
|
|
|
|
function ClipFilename(const FileName: string; const Clip: Boolean): string;
|
|
var
|
|
Params: string;
|
|
begin
|
|
if FileExists(FileName) then
|
|
Result := FileName
|
|
else
|
|
if DirectoryExists(FileName) then
|
|
Result := IncludeTrailingPathDelimiter(FileName)
|
|
else
|
|
if Clip then
|
|
SplitCommandLine(FileName, Result, Params)
|
|
else
|
|
Result := FileName;
|
|
end;
|
|
|
|
function ExtFilename(const FileName: string): string;
|
|
begin
|
|
if (Pos(' ', FileName) > 0) and (FileName[1] <> '"') then
|
|
Result := Format('"%s"', [FileName])
|
|
else
|
|
Result := FileName;
|
|
end;
|
|
|
|
function NvlDate(DateValue, DefaultValue: TDateTime): TDateTime;
|
|
begin
|
|
if DateValue = NullDate then
|
|
Result := DefaultValue
|
|
else
|
|
Result := DateValue;
|
|
end;
|
|
|
|
{$IFDEF VisualCLX}
|
|
|
|
procedure DrawSelectedText(Canvas: TCanvas; const R: TRect; X, Y: Integer;
|
|
const Text: WideString; SelStart, SelLength: Integer;
|
|
HighlightColor, HighlightTextColor: TColor);
|
|
var
|
|
W, H, Width: Integer;
|
|
S: WideString;
|
|
SelectionRect: TRect;
|
|
Brush: TBrushRecall;
|
|
PenMode: TPenMode;
|
|
FontColor: TColor;
|
|
begin
|
|
W := R.Right - R.Left;
|
|
H := R.Bottom - R.Top;
|
|
if (W <= 0) or (H <= 0) then
|
|
Exit;
|
|
|
|
S := Copy(Text, 1, SelStart);
|
|
if S <> '' then
|
|
begin
|
|
Canvas.TextRect(R, X, Y, S);
|
|
Inc(X, Canvas.TextWidth(S));
|
|
end;
|
|
|
|
S := Copy(Text, SelStart + 1, SelLength);
|
|
if S <> '' then
|
|
begin
|
|
Width := Canvas.TextWidth(S);
|
|
Brush := TBrushRecall.Create(Canvas.Brush);
|
|
PenMode := Canvas.Pen.Mode;
|
|
try
|
|
SelectionRect := Rect(Max(X, R.Left), R.Top,
|
|
Min(X + Width, R.Right), R.Bottom);
|
|
Canvas.Pen.Mode := pmCopy;
|
|
Canvas.Brush.Color := HighlightColor;
|
|
Canvas.FillRect(SelectionRect);
|
|
FontColor := Canvas.Font.Color;
|
|
Canvas.Font.Color := HighlightTextColor;
|
|
Canvas.TextRect(R, X, Y, S);
|
|
Canvas.Font.Color := FontColor;
|
|
finally
|
|
Canvas.Pen.Mode := PenMode;
|
|
Brush.Free;
|
|
end;
|
|
Inc(X, Width);
|
|
end;
|
|
|
|
S := Copy(Text, SelStart + SelLength + 1, MaxInt);
|
|
if S <> '' then
|
|
Canvas.TextRect(R, X, Y, S);
|
|
end;
|
|
|
|
{$ENDIF VisualCLX}
|
|
|
|
function ParentFormVisible(AControl: TControl): Boolean;
|
|
var
|
|
Form: TCustomForm;
|
|
begin
|
|
Form := GetParentForm(AControl);
|
|
Result := Assigned(Form) and Form.Visible;
|
|
end;
|
|
|
|
//=== Global procedures ======================================================
|
|
|
|
procedure DateFormatChanged;
|
|
var
|
|
I: Integer;
|
|
|
|
procedure IterateControls(AControl: TWinControl);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with AControl do
|
|
for I := 0 to ControlCount - 1 do
|
|
begin
|
|
if Controls[I] is TJvCustomDateEdit then
|
|
TJvCustomDateEdit(Controls[I]).UpdateMask
|
|
else
|
|
if Controls[I] is TWinControl then
|
|
IterateControls(TWinControl(Controls[I]));
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if Screen <> nil then
|
|
for I := 0 to Screen.FormCount - 1 do
|
|
IterateControls(Screen.Forms[I]);
|
|
end;
|
|
|
|
{$IFDEF VisualCLX}
|
|
function EditorTextMargins(Editor: TCustomEdit): TPoint;
|
|
var
|
|
I: Integer;
|
|
ed: TCustomEditAccessProtected;
|
|
begin
|
|
ed := TCustomEditAccessProtected(Editor);
|
|
if ed.BorderStyle = bsNone then
|
|
I := 0
|
|
else
|
|
if Supports(Editor, IComboEditHelper) then
|
|
begin
|
|
if (Editor as IComboEditHelper).GetFlat then
|
|
I := 1
|
|
else
|
|
I := 2;
|
|
end
|
|
else
|
|
I := 2;
|
|
{if GetWindowLong(ed.Handle, GWL_STYLE) and ES_MULTILINE = 0 then
|
|
Result.X := (SendMessage(ed.Handle, EM_GETMARGINS, 0, 0) and $0000FFFF) + I
|
|
else}
|
|
Result.X := I;
|
|
Result.Y := I;
|
|
end;
|
|
{$ENDIF VisualCLX}
|
|
|
|
{$IFDEF VCL}
|
|
function EditorTextMargins(Editor: TCustomEdit): TPoint;
|
|
var
|
|
DC: HDC;
|
|
I: Integer;
|
|
SaveFont: HFONT;
|
|
SysMetrics, Metrics: TTextMetric;
|
|
ed: TCustomEditAccessProtected;
|
|
begin
|
|
ed := TCustomEditAccessProtected(Editor);
|
|
if NewStyleControls then
|
|
begin
|
|
if ed.BorderStyle = bsNone then
|
|
I := 0
|
|
else
|
|
if ed.Ctl3D then
|
|
I := 1
|
|
else
|
|
I := 2;
|
|
if GetWindowLong(ed.Handle, GWL_STYLE) and ES_MULTILINE = 0 then
|
|
Result.X := (SendMessage(ed.Handle, EM_GETMARGINS, 0, 0) and $0000FFFF) + I
|
|
else
|
|
Result.X := I;
|
|
Result.Y := I;
|
|
end
|
|
else
|
|
begin
|
|
if ed.BorderStyle = bsNone then
|
|
I := 0
|
|
else
|
|
begin
|
|
DC := GetDC(HWND_DESKTOP);
|
|
GetTextMetrics(DC, SysMetrics);
|
|
SaveFont := SelectObject(DC, ed.Font.Handle);
|
|
GetTextMetrics(DC, Metrics);
|
|
SelectObject(DC, SaveFont);
|
|
ReleaseDC(HWND_DESKTOP, DC);
|
|
I := SysMetrics.tmHeight;
|
|
if I > Metrics.tmHeight then
|
|
I := Metrics.tmHeight;
|
|
I := I div 4;
|
|
end;
|
|
Result.X := I;
|
|
Result.Y := I;
|
|
end;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
function IsInWordArray(Value: Word; const A: array of Word): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := True;
|
|
for I := 0 to High(A) do
|
|
if A[I] = Value then
|
|
Exit;
|
|
Result := False;
|
|
end;
|
|
|
|
function LoadDefaultBitmap(Bmp: TBitmap; Item: Integer): Boolean;
|
|
begin
|
|
{$IFDEF VCL}
|
|
{$IFDEF CLR}
|
|
Bmp.Handle := LoadBitmap(0, Item);
|
|
{$ELSE}
|
|
Bmp.Handle := LoadBitmap(0, PChar(Item));
|
|
{$ENDIF CLR}
|
|
Result := Bmp.Handle <> 0;
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
Result := True;
|
|
case Item of
|
|
OBM_COMBO:
|
|
begin
|
|
Bmp.Width := QStyle_sliderLength(Application.Style.Handle);
|
|
Bmp.Height := Bmp.Width;
|
|
Bmp.Canvas.Start;
|
|
DrawFrameControl(Bmp.Canvas.Handle, Rect(0, 0, Bmp.Width, Bmp.Height),
|
|
DFC_SCROLL, DFCS_SCROLLDOWN);
|
|
Bmp.Canvas.Stop;
|
|
end;
|
|
else
|
|
Bmp.Width := 0;
|
|
Bmp.Height := 0;
|
|
Result := False;
|
|
end;
|
|
{$ENDIF VisualCLX}
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
function PaintComboEdit(Editor: TJvCustomComboEdit; const AText: string;
|
|
AAlignment: TAlignment; StandardPaint: Boolean;
|
|
var ACanvas: TControlCanvas; var Msg: TWMPaint): Boolean;
|
|
begin
|
|
if not (csDestroying in Editor.ComponentState) then
|
|
begin
|
|
Result := PaintEdit(Editor, AText, AAlignment, Editor.PopupVisible,
|
|
Editor.FDisabledTextColor, StandardPaint, ACanvas, Msg);
|
|
end
|
|
else
|
|
Result := True;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
{$IFDEF VisualCLX}
|
|
function PaintComboEdit(Editor: TJvCustomComboEdit; const AText: string;
|
|
AAlignment: TAlignment; StandardPaint: Boolean; Flat: Boolean;
|
|
ACanvas: TCanvas): Boolean;
|
|
begin
|
|
if not (csDestroying in Editor.ComponentState) then
|
|
begin
|
|
Result := PaintEdit(Editor, AText, AAlignment, Editor.PopupVisible,
|
|
Editor.FDisabledTextColor, StandardPaint, Flat, ACanvas);
|
|
end
|
|
else
|
|
Result := True;
|
|
end;
|
|
{$ENDIF VisualCLX}
|
|
|
|
{$IFDEF VCL}
|
|
function PaintEdit(Editor: TCustomEdit; const AText: string;
|
|
AAlignment: TAlignment; PopupVisible: Boolean;
|
|
DisabledTextColor: TColor; StandardPaint: Boolean;
|
|
var ACanvas: TControlCanvas; var Msg: TWMPaint): Boolean;
|
|
type
|
|
TEd = TCustomEditAccessProtected;
|
|
const
|
|
AlignStyle: array [Boolean, TAlignment] of DWORD =
|
|
((WS_EX_LEFT, WS_EX_RIGHT, WS_EX_LEFT),
|
|
(WS_EX_RIGHT, WS_EX_LEFT, WS_EX_LEFT));
|
|
var
|
|
LTextWidth, X: Integer;
|
|
EditRect: TRect;
|
|
DC: HDC;
|
|
PS: TPaintStruct;
|
|
S: string;
|
|
ExStyle: DWORD;
|
|
begin
|
|
Result := True;
|
|
if csDestroying in Editor.ComponentState then
|
|
Exit;
|
|
if TEd(Editor).UseRightToLeftAlignment then
|
|
ChangeBiDiModeAlignment(AAlignment);
|
|
if StandardPaint and not (csPaintCopy in TEd(Editor).ControlState) then
|
|
begin
|
|
if SysLocale.MiddleEast and TEd(Editor).HandleAllocated and (TEd(Editor).IsRightToLeft) then
|
|
begin { This keeps the right aligned text, right aligned }
|
|
ExStyle := DWORD(GetWindowLong(TEd(Editor).Handle, GWL_EXSTYLE)) and (not WS_EX_RIGHT) and
|
|
(not WS_EX_RTLREADING) and (not WS_EX_LEFTSCROLLBAR);
|
|
if TEd(Editor).UseRightToLeftReading then
|
|
ExStyle := ExStyle or WS_EX_RTLREADING;
|
|
if TEd(Editor).UseRightToLeftScrollBar then
|
|
ExStyle := ExStyle or WS_EX_LEFTSCROLLBAR;
|
|
ExStyle := ExStyle or
|
|
AlignStyle[TEd(Editor).UseRightToLeftAlignment, AAlignment];
|
|
if DWORD(GetWindowLong(TEd(Editor).Handle, GWL_EXSTYLE)) <> ExStyle then
|
|
SetWindowLong(TEd(Editor).Handle, GWL_EXSTYLE, ExStyle);
|
|
end;
|
|
Result := False;
|
|
{ return false if we need to use standard paint handler }
|
|
Exit;
|
|
end;
|
|
{ Since edit controls do not handle justification unless multi-line (and
|
|
then only poorly) we will draw right and center justify manually unless
|
|
the edit has the focus. }
|
|
if ACanvas = nil then
|
|
begin
|
|
ACanvas := TControlCanvas.Create;
|
|
ACanvas.Control := Editor;
|
|
end;
|
|
DC := Msg.DC;
|
|
if DC = 0 then
|
|
DC := BeginPaint(TEd(Editor).Handle, PS);
|
|
ACanvas.Handle := DC;
|
|
try
|
|
ACanvas.Font := TEd(Editor).Font;
|
|
with ACanvas do
|
|
begin
|
|
SendRectMessage(Editor.Handle, EM_GETRECT, 0, EditRect);
|
|
if not (NewStyleControls and TEd(Editor).Ctl3D) and (TEd(Editor).BorderStyle = bsSingle) then
|
|
begin
|
|
Brush.Color := clWindowFrame;
|
|
FrameRect(TEd(Editor).ClientRect);
|
|
end;
|
|
S := AText;
|
|
LTextWidth := TextWidth(S);
|
|
if PopupVisible then
|
|
X := EditRect.Left
|
|
else
|
|
begin
|
|
case AAlignment of
|
|
taLeftJustify:
|
|
X := EditRect.Left;
|
|
taRightJustify:
|
|
X := EditRect.Right - LTextWidth;
|
|
else
|
|
X := (EditRect.Right + EditRect.Left - LTextWidth) div 2;
|
|
end;
|
|
end;
|
|
if SysLocale.MiddleEast then
|
|
UpdateTextFlags;
|
|
if not TEd(Editor).Enabled then
|
|
begin
|
|
// if PS.fErase then // (p3) fErase is not set to true when control is disabled
|
|
TEd(Editor).Perform(WM_ERASEBKGND, ACanvas.Handle, 0);
|
|
|
|
SaveDC(ACanvas.Handle);
|
|
try
|
|
ACanvas.Brush.Style := bsClear;
|
|
ACanvas.Font.Color := DisabledTextColor;
|
|
ACanvas.TextRect(EditRect, X, EditRect.Top, S);
|
|
finally
|
|
RestoreDC(ACanvas.Handle, -1);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
Brush.Color := TEd(Editor).Color;
|
|
ACanvas.TextRect(EditRect, X, EditRect.Top, S);
|
|
end;
|
|
end;
|
|
finally
|
|
ACanvas.Handle := 0;
|
|
if Msg.DC = 0 then
|
|
EndPaint(TEd(Editor).Handle, PS);
|
|
end;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
{$IFDEF VisualCLX}
|
|
{ PaintEdit (CLX) needs an implemented EM_GETRECT message handler. If no
|
|
EM_GETTEXT handler exists or the edit control does not implement
|
|
IComboEditHelper, it uses the ClientRect of the edit control. }
|
|
|
|
function PaintEdit(Editor: TCustomEdit; const AText: WideString;
|
|
AAlignment: TAlignment; PopupVisible: Boolean;
|
|
DisabledTextColor: TColor; StandardPaint: Boolean; Flat: Boolean;
|
|
ACanvas: TCanvas): Boolean;
|
|
var
|
|
LTextWidth, X: Integer;
|
|
EditRect: TRect;
|
|
S: WideString;
|
|
ed: TCustomEditAccessProtected;
|
|
SavedFont: TFontRecall;
|
|
SavedBrush: TBrushRecall;
|
|
Offset: Integer;
|
|
R: TRect;
|
|
EditHelperIntf: IComboEditHelper;
|
|
begin
|
|
Result := True;
|
|
if csDestroying in Editor.ComponentState then
|
|
Exit;
|
|
ed := TCustomEditAccessProtected(Editor);
|
|
if StandardPaint and not (csPaintCopy in ed.ControlState) then
|
|
begin
|
|
Result := False;
|
|
{ return false if we need to use standard paint handler }
|
|
Exit;
|
|
end;
|
|
SavedFont := TFontRecall.Create(ACanvas.Font);
|
|
SavedBrush := TBrushRecall.Create(ACanvas.Brush);
|
|
try
|
|
ACanvas.Font := ed.Font;
|
|
|
|
// paint Border
|
|
R := ed.ClientRect;
|
|
Offset := 0;
|
|
if (ed.BorderStyle = bsSingle) then
|
|
begin
|
|
ACanvas.Start;
|
|
QStyle_drawPanel(QWidget_style(Editor.Handle), ACanvas.Handle,
|
|
R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top, QWidget_colorGroup(Editor.Handle),
|
|
True, 2, nil);
|
|
ACanvas.Stop;
|
|
//QGraphics.DrawEdge(ACanvas, R, esLowered, esLowered, ebRect)
|
|
end
|
|
else
|
|
begin
|
|
if Flat then
|
|
QGraphics.DrawEdge(ACanvas, R, esNone, esLowered, ebRect);
|
|
Offset := 2;
|
|
end;
|
|
|
|
with ACanvas do
|
|
begin
|
|
if Supports(Editor, IComboEditHelper, EditHelperIntf) then
|
|
begin
|
|
EditRect := EditHelperIntf.GetEditorRect;
|
|
EditHelperIntf := nil;
|
|
end
|
|
else
|
|
begin
|
|
EditRect := Rect(0, 0, 0, 0);
|
|
SendMessage(Editor.Handle, EM_GETRECT, 0, Integer(@EditRect));
|
|
end;
|
|
if IsRectEmpty(EditRect) then
|
|
begin
|
|
EditRect := ed.ClientRect;
|
|
if ed.BorderStyle = bsSingle then
|
|
InflateRect(EditRect, -2, -2);
|
|
end
|
|
else
|
|
InflateRect(EditRect, -Offset, -Offset);
|
|
if Flat and (ed.BorderStyle = bsSingle) then
|
|
begin
|
|
Brush.Color := clWindowFrame;
|
|
FrameRect(ACanvas, ed.ClientRect);
|
|
end;
|
|
S := AText;
|
|
LTextWidth := TextWidth(S);
|
|
if PopupVisible then
|
|
X := EditRect.Left
|
|
else
|
|
begin
|
|
case AAlignment of
|
|
taLeftJustify:
|
|
X := EditRect.Left;
|
|
taRightJustify:
|
|
X := EditRect.Right - LTextWidth;
|
|
else
|
|
X := (EditRect.Right + EditRect.Left - LTextWidth) div 2;
|
|
end;
|
|
end;
|
|
if not ed.Enabled then
|
|
begin
|
|
if Supports(ed, IJvWinControlEvents) then
|
|
(ed as IJvWinControlEvents).DoEraseBackground(ACanvas, 0);
|
|
ACanvas.Brush.Style := bsClear;
|
|
ACanvas.Font.Color := DisabledTextColor;
|
|
ACanvas.TextRect(EditRect, X, EditRect.Top + 1, S);
|
|
end
|
|
else
|
|
begin
|
|
Brush.Color := ed.Color;
|
|
DrawSelectedText(ACanvas, EditRect, X, EditRect.Top + 1, S,
|
|
ed.SelStart, ed.SelLength,
|
|
clHighlight, clHighlightText);
|
|
end;
|
|
end;
|
|
finally
|
|
SavedFont.Free;
|
|
SavedBrush.Free;
|
|
end;
|
|
end;
|
|
{$ENDIF VisualCLX}
|
|
|
|
{$IFDEF VCL}
|
|
|
|
//=== { TAutoCompleteSource } ================================================
|
|
|
|
constructor TAutoCompleteSource.Create(AComboEdit: TJvCustomComboEdit; const StartIndex: Integer);
|
|
begin
|
|
inherited Create;
|
|
FComboEdit := AComboEdit;
|
|
FCurrentIndex := StartIndex;
|
|
end;
|
|
|
|
function TAutoCompleteSource.Clone(out enm: IEnumString): HRESULT;
|
|
begin
|
|
{ Save state }
|
|
try
|
|
enm := TAutoCompleteSource.Create(FComboEdit, FCurrentIndex);
|
|
Result := S_OK;
|
|
except
|
|
Result := E_UNEXPECTED;
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF CLR}
|
|
function TAutoCompleteSource.Next(celt: Longint; rgelt: array of string; out pceltFetched: Longint): HResult;
|
|
var
|
|
Fetched: Integer;
|
|
S: string;
|
|
begin
|
|
if Length(rgelt) = 0 then
|
|
begin
|
|
Result := E_FAIL;
|
|
Exit;
|
|
end;
|
|
|
|
Fetched := 0;
|
|
|
|
while (Fetched < celt) and (FCurrentIndex < FComboEdit.AutoCompleteItems.Count) do
|
|
begin
|
|
S := FComboEdit.AutoCompleteItems[FCurrentIndex];
|
|
rgelt[Fetched] := S;
|
|
Inc(FCurrentIndex);
|
|
Inc(Fetched);
|
|
end;
|
|
|
|
if TObject(pceltFetched) <> nil then
|
|
pceltFetched := Fetched;
|
|
|
|
if Fetched = celt then
|
|
Result := S_OK
|
|
else
|
|
Result := S_FALSE;
|
|
end;
|
|
{$ELSE}
|
|
function TAutoCompleteSource.Next(celt: Integer; out elt;
|
|
pceltFetched: PLongint): HRESULT;
|
|
var
|
|
Fetched: Integer;
|
|
S: string;
|
|
Ptr: POleStr;
|
|
Size: Integer;
|
|
begin
|
|
if Pointer(elt) = nil then
|
|
begin
|
|
Result := E_FAIL;
|
|
Exit;
|
|
end;
|
|
|
|
Fetched := 0;
|
|
|
|
while (Fetched < celt) and (FCurrentIndex < FComboEdit.AutoCompleteItems.Count) do
|
|
begin
|
|
S := FComboEdit.AutoCompleteItems[FCurrentIndex];
|
|
Size := (Length(S) + 1) * SizeOf(WideChar);
|
|
Ptr := CoTaskMemAlloc(Size);
|
|
if Ptr = nil then
|
|
begin
|
|
Result := E_OUTOFMEMORY;
|
|
Exit;
|
|
end;
|
|
StringToWideChar(S, Ptr, Size);
|
|
|
|
TOleStrList(elt)[Fetched] := Ptr;
|
|
|
|
Inc(FCurrentIndex);
|
|
Inc(Fetched);
|
|
end;
|
|
|
|
if Assigned(pceltFetched) then
|
|
pceltFetched^ := Fetched;
|
|
|
|
if Fetched = celt then
|
|
Result := S_OK
|
|
else
|
|
Result := S_FALSE;
|
|
end;
|
|
{$ENDIF CLR}
|
|
|
|
function TAutoCompleteSource.Reset: HRESULT;
|
|
begin
|
|
FCurrentIndex := 0;
|
|
Result := S_OK;
|
|
end;
|
|
|
|
function TAutoCompleteSource.Skip(celt: Integer): HRESULT;
|
|
begin
|
|
Inc(FCurrentIndex, celt);
|
|
if FCurrentIndex < FComboEdit.AutoCompleteItems.Count then
|
|
Result := S_OK
|
|
else
|
|
begin
|
|
Result := S_FALSE;
|
|
FCurrentIndex := FComboEdit.AutoCompleteItems.Count;
|
|
end;
|
|
end;
|
|
|
|
//=== { TDateHook } ==========================================================
|
|
|
|
procedure TDateHook.Add;
|
|
begin
|
|
if FCount = 0 then
|
|
Hook;
|
|
Inc(FCount);
|
|
end;
|
|
|
|
procedure TDateHook.Delete;
|
|
begin
|
|
if FCount > 0 then
|
|
Dec(FCount);
|
|
if FCount = 0 then
|
|
UnHook;
|
|
end;
|
|
|
|
function TDateHook.FormatSettingsChange(var Msg: TMessage): Boolean;
|
|
begin
|
|
Result := False;
|
|
if (Msg.Msg = WM_WININICHANGE) and Application.UpdateFormatSettings then
|
|
begin
|
|
// Let the application obj do the changing; we receive the message
|
|
// before the application obj, thus jump over it:
|
|
PostMessage(Application.Handle, WM_NULL, 0, 0);
|
|
FWinIniChangeReceived := True;
|
|
end
|
|
else
|
|
if (Msg.Msg = WM_NULL) and FWinIniChangeReceived then
|
|
begin
|
|
FWinIniChangeReceived := False;
|
|
DateFormatChanged;
|
|
end;
|
|
end;
|
|
|
|
procedure TDateHook.Hook;
|
|
begin
|
|
if FHooked then
|
|
Exit;
|
|
|
|
Application.HookMainWindow(FormatSettingsChange);
|
|
FHooked := True;
|
|
end;
|
|
|
|
procedure TDateHook.UnHook;
|
|
begin
|
|
if not FHooked then
|
|
Exit;
|
|
|
|
Application.UnhookMainWindow(FormatSettingsChange);
|
|
FHooked := False;
|
|
end;
|
|
|
|
{$ENDIF VCL}
|
|
|
|
//=== { TJvCustomComboEditDataConnector } ====================================
|
|
|
|
constructor TJvCustomComboEditDataConnector.Create(AEdit: TJvCustomComboEdit);
|
|
begin
|
|
inherited Create;
|
|
FEdit := AEdit;
|
|
end;
|
|
|
|
procedure TJvCustomComboEditDataConnector.RecordChanged;
|
|
begin
|
|
if Field.IsValid then
|
|
begin
|
|
FEdit.ReadOnly := not Field.CanModify;
|
|
FEdit.Text := Field.AsString;
|
|
end
|
|
else
|
|
begin
|
|
FEdit.Text := '';
|
|
FEdit.ReadOnly := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEditDataConnector.UpdateData;
|
|
begin
|
|
Field.AsString := FEdit.Text;
|
|
FEdit.Text := Field.AsString; // update to stored value
|
|
end;
|
|
|
|
//=== { TJvCustomComboEdit } =================================================
|
|
|
|
constructor TJvCustomComboEdit.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FDataConnector := CreateDataConnector;
|
|
ControlStyle := ControlStyle + [csCaptureMouse];
|
|
// AutoSize := False; // Polaris
|
|
Height := 21;
|
|
FDirectInput := True;
|
|
FClickKey := scAltDown;
|
|
FPopupAlign := epaRight;
|
|
FBtnControl := TWinControl.Create(Self);
|
|
with FBtnControl do
|
|
ControlStyle := ControlStyle + [csReplicatable];
|
|
FBtnControl.Width := DefEditBtnWidth;
|
|
FBtnControl.Height := 17;
|
|
FBtnControl.Visible := True;
|
|
{$IFDEF VCL}
|
|
FBtnControl.Parent := Self;
|
|
{$IFDEF COMPILER6_UP}
|
|
FBtnControl.Align := alCustom;
|
|
{$ELSE}
|
|
FBtnControl.Align := alRight;
|
|
{$ENDIF COMPILER6_UP}
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
FBtnControl.Parent := Self.ClientArea;
|
|
FBtnControl.Left := Self.ClientArea.Width - DefEditBtnWidth;
|
|
FBtnControl.Anchors := [akRight, akTop, akBottom];
|
|
{$ENDIF VisualCLX}
|
|
FButton := TJvEditButton.Create(Self);
|
|
FButton.SetBounds(0, 0, FBtnControl.Width, FBtnControl.Height);
|
|
FButton.Visible := True;
|
|
FButton.Align := alClient;
|
|
FButton.OnClick := EditButtonClick;
|
|
FButton.Parent := FBtnControl;
|
|
|
|
FAlwaysEnableButton := False;
|
|
(* ++ RDB ++ *)
|
|
FDisabledColor := clWindow;
|
|
FDisabledTextColor := clGrayText;
|
|
FGroupIndex := -1;
|
|
FStreamedButtonWidth := -1;
|
|
FImageKind := ikCustom;
|
|
FImageIndex := -1;
|
|
FNumGlyphs := 1;
|
|
{$IFDEF VCL}
|
|
FAutoCompleteItems := TStringList.Create;
|
|
FAutoCompleteOptions := [];
|
|
CoInitialize(nil);
|
|
{$ENDIF VCL}
|
|
inherited OnKeyDown := LocalKeyDown;
|
|
(* -- RDB -- *)
|
|
end;
|
|
|
|
destructor TJvCustomComboEdit.Destroy;
|
|
begin
|
|
PopupCloseUp(Self, False);
|
|
FButton.OnClick := nil;
|
|
{$IFDEF VCL}
|
|
DestroyAutoComplete;
|
|
FAutoCompleteItems.Free;
|
|
{$ENDIF VCL}
|
|
FDataConnector.Free;
|
|
inherited Destroy;
|
|
{$IFDEF VCL}
|
|
// call after WM_DESTROY
|
|
CoUninitialize;
|
|
{$ENDIF VCL}
|
|
end;
|
|
|
|
function TJvCustomComboEdit.AcceptPopup(var Value: Variant): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.AcceptValue(const Value: Variant);
|
|
begin
|
|
if Text <> VarToStr(Value) then
|
|
begin
|
|
Text := Value;
|
|
Modified := True;
|
|
UpdatePopupVisible;
|
|
//DoChange; (ahuser) "Text := Value" triggers Change;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.ActionChange(Sender: TObject;
|
|
CheckDefaults: Boolean);
|
|
begin
|
|
if Sender is TCustomAction then
|
|
with TCustomAction(Sender) do
|
|
begin
|
|
if not CheckDefaults or not Assigned(Self.Images) then
|
|
Self.Images := TCustomImageList(ActionList.Images);
|
|
if not CheckDefaults or Self.Enabled then
|
|
Self.Enabled := Enabled;
|
|
if not CheckDefaults or (Self.HelpContext = 0) then
|
|
Self.HelpContext := HelpContext;
|
|
if not CheckDefaults or (Self.Hint = '') then
|
|
Self.ButtonHint := Hint;
|
|
if not CheckDefaults or (Self.ImageIndex = -1) then
|
|
Self.ImageIndex := ImageIndex;
|
|
if not CheckDefaults or (Self.ClickKey = scNone) then
|
|
Self.ClickKey := ShortCut;
|
|
if not CheckDefaults or Self.Visible then
|
|
Self.Visible := Visible;
|
|
if not CheckDefaults or not Assigned(Self.OnButtonClick) then
|
|
Self.OnButtonClick := OnExecute;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.AdjustHeight;
|
|
var
|
|
DC: HDC;
|
|
SaveFont: HFONT;
|
|
I: Integer;
|
|
SysMetrics, Metrics: TTextMetric;
|
|
begin
|
|
DC := GetDC(HWND_DESKTOP);
|
|
GetTextMetrics(DC, SysMetrics);
|
|
SaveFont := SelectObject(DC, Font.Handle);
|
|
GetTextMetrics(DC, Metrics);
|
|
SelectObject(DC, SaveFont);
|
|
ReleaseDC(HWND_DESKTOP, DC);
|
|
if NewStyleControls then
|
|
begin
|
|
if not Flat then
|
|
I := 8
|
|
else
|
|
I := 6;
|
|
I := GetSystemMetrics(SM_CYBORDER) * I;
|
|
end
|
|
else
|
|
begin
|
|
I := SysMetrics.tmHeight;
|
|
if I > Metrics.tmHeight then
|
|
I := Metrics.tmHeight;
|
|
I := I div 4 + GetSystemMetrics(SM_CYBORDER) * 4;
|
|
end;
|
|
if Height < Metrics.tmHeight + I then
|
|
Height := Metrics.tmHeight + I;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.AdjustSize;
|
|
var
|
|
MinHeight: Integer;
|
|
begin
|
|
inherited AdjustSize;
|
|
if not (csLoading in ComponentState) then
|
|
begin
|
|
MinHeight := GetMinHeight;
|
|
{ text edit bug: if size to less than MinHeight, then edit ctrl does
|
|
not display the text }
|
|
if Height < MinHeight then
|
|
begin
|
|
Height := MinHeight;
|
|
Exit;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if (FPopup <> nil) and (csDesigning in ComponentState) then
|
|
FPopup.SetBounds(0, Height + 1, 10, 10);
|
|
end;
|
|
UpdateControls;
|
|
UpdateMargins;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.AsyncPopupCloseUp(Accept: Boolean);
|
|
begin
|
|
PostMessage(Handle, CM_POPUPCLOSEUP, Ord(Accept), 0);
|
|
end;
|
|
|
|
function TJvCustomComboEdit.BtnWidthStored: Boolean;
|
|
begin
|
|
if (FImageKind = ikDefault) and (DefaultImages <> nil) and (DefaultImageIndex >= 0) then
|
|
Result := ButtonWidth <> Max(DefaultImages.Width + 6, DefEditBtnWidth)
|
|
else
|
|
if FImageKind = ikDropDown then
|
|
Result := ButtonWidth <> GetSystemMetrics(SM_CXVSCROLL)
|
|
else
|
|
Result := ButtonWidth <> DefEditBtnWidth;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.ButtonClick;
|
|
begin
|
|
if Assigned(FOnButtonClick) then
|
|
FOnButtonClick(Self);
|
|
|
|
if (FPopup <> nil) and FPopupVisible then
|
|
PopupCloseUp(FPopup, True)
|
|
else
|
|
PopupDropDown(True);
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.Change;
|
|
begin
|
|
DataConnector.Modify;
|
|
if not PopupVisible then
|
|
DoChange
|
|
else
|
|
PopupChange;
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
|
|
procedure TJvCustomComboEdit.CMBiDiModeChanged(var Msg: TMessage);
|
|
begin
|
|
inherited;
|
|
if FPopup <> nil then
|
|
FPopup.BiDiMode := BiDiMode;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.CMCancelMode(var Msg: TCMCancelMode);
|
|
begin
|
|
if (Msg.Sender <> Self) and (Msg.Sender <> FPopup) and
|
|
(Msg.Sender <> FButton) and ((FPopup <> nil) and
|
|
not FPopup.ContainsControl(Msg.Sender)) then
|
|
PopupCloseUp(FPopup, False);
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.CMCtl3DChanged(var Msg: TMessage);
|
|
begin
|
|
inherited;
|
|
DoCtl3DChanged;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.CMPopupCloseup(var Msg: TMessage);
|
|
begin
|
|
PopupCloseUp(Self, Boolean(Msg.WParam));
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.CMWantSpecialKey(var Msg: TCMWantSpecialKey);
|
|
begin
|
|
inherited;
|
|
{ Ignore tabs when popup is visible }
|
|
if PopupVisible and (Msg.CharCode = VK_TAB) then
|
|
Msg.Result := 1;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.CNCtlColor(var Msg: TMessage);
|
|
var
|
|
TextColor: Longint;
|
|
begin
|
|
inherited;
|
|
if NewStyleControls then
|
|
begin
|
|
TextColor := ColorToRGB(Font.Color);
|
|
if not Enabled and (ColorToRGB(Color) <> ColorToRGB(clGrayText)) then
|
|
TextColor := ColorToRGB(clGrayText);
|
|
SetTextColor(Msg.WParam, TextColor);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.CreateAutoComplete;
|
|
begin
|
|
if HandleAllocated and not (csDesigning in ComponentState) and
|
|
{not Assigned(FAutoCompleteIntf) and} (AutoCompleteOptions <> []) then
|
|
begin
|
|
{ Create the autocomplete object. }
|
|
{$IFDEF CLR}
|
|
FAutoCompleteIntf :=
|
|
Activator.CreateInstance(System.Type.GetTypeFromCLSID(Guid.Create(CLSID_AutoComplete))) as IAutoComplete;
|
|
if FAutoCompleteIntf <> nil then
|
|
{$ELSE}
|
|
if Succeeded(CoCreateInstance(CLSID_AutoComplete, nil, CLSCTX_INPROC_SERVER, IAutoComplete,
|
|
FAutoCompleteIntf)) then
|
|
{$ENDIF CLR}
|
|
begin
|
|
{ Initialize the autocomplete object. }
|
|
FAutoCompleteIntf.Init(Self.Handle, GetAutoCompleteSource, nil, nil);
|
|
end
|
|
else
|
|
FAutoCompleteIntf := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.DestroyAutoComplete;
|
|
begin
|
|
FAutoCompleteIntf := nil;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.CreateParams(var Params: TCreateParams);
|
|
const
|
|
Alignments: array [TAlignment] of LongWord = (ES_LEFT, ES_RIGHT, ES_CENTER);
|
|
begin
|
|
inherited CreateParams(Params);
|
|
Params.Style := Params.Style or
|
|
ES_MULTILINE or WS_CLIPCHILDREN or Alignments[FAlignment];
|
|
end;
|
|
|
|
{$ENDIF VCL}
|
|
|
|
procedure TJvCustomComboEdit.CreatePopup;
|
|
begin
|
|
{ Notification }
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.CreateWnd;
|
|
begin
|
|
inherited CreateWnd;
|
|
UpdateControls;
|
|
UpdateMargins;
|
|
{$IFDEF VCL}
|
|
if AutoCompleteOptions <> [] then
|
|
begin
|
|
CreateAutoComplete;
|
|
UpdateAutoComplete;
|
|
end;
|
|
{$ENDIF VCL}
|
|
end;
|
|
|
|
{$IFDEF COMPILER6_UP}
|
|
{$IFDEF VCL}
|
|
procedure TJvCustomComboEdit.CustomAlignPosition(Control: TControl;
|
|
var NewLeft, NewTop, NewWidth, NewHeight: Integer;
|
|
var AlignRect: TRect; AlignInfo: TAlignInfo);
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
procedure TJvCustomComboEdit.CustomAlignPosition(Control: TControl; var NewLeft,
|
|
NewTop, NewWidth, NewHeight: Integer; var AlignRect: TRect);
|
|
{$ENDIF VisualCLX}
|
|
begin
|
|
if Control = FBtnControl then
|
|
UpdateBtnBounds(NewLeft, NewTop, NewWidth, NewHeight);
|
|
end;
|
|
{$ENDIF COMPILER6_UP}
|
|
|
|
class function TJvCustomComboEdit.DefaultImageIndex: TImageIndex;
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
class function TJvCustomComboEdit.DefaultImages: TCustomImageList;
|
|
begin
|
|
if GDefaultComboEditImagesList = nil then
|
|
GDefaultComboEditImagesList := TImageList.CreateSize(14, 12);
|
|
Result := TCustomImageList(GDefaultComboEditImagesList);
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.DefineProperties(Filer: TFiler);
|
|
begin
|
|
inherited DefineProperties(Filer);
|
|
|
|
Filer.DefineProperty('GlyphKind', ReadGlyphKind, nil, False);
|
|
{$IFDEF VCL}
|
|
Filer.DefineProperty('Ctl3D', ReadCtl3D, nil, False);
|
|
Filer.DefineProperty('ParentCtl3D', ReadParentCtl3D, nil, False);
|
|
{$ENDIF VCL}
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
procedure TJvCustomComboEdit.DestroyWnd;
|
|
begin
|
|
inherited DestroyWnd;
|
|
{ Mantis #3642 }
|
|
DestroyAutoComplete;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
procedure TJvCustomComboEdit.DoChange;
|
|
begin
|
|
inherited Change;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.DoClick;
|
|
begin
|
|
EditButtonClick(Self);
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.WMClear(var Msg: TMessage);
|
|
begin
|
|
Text := '';
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.WMCut(var Msg: TMessage);
|
|
begin
|
|
if FDirectInput and not ReadOnly then
|
|
inherited;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.WMPaste(var Msg: TMessage);
|
|
begin
|
|
if FDirectInput and not ReadOnly then
|
|
inherited;
|
|
UpdateGroup;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.DoCtl3DChanged;
|
|
begin
|
|
UpdateMargins;
|
|
UpdateControls;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.DoEnter;
|
|
begin
|
|
if AutoSelect and not (csLButtonDown in ControlState) then
|
|
SelectAll;
|
|
inherited DoEnter;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.DoExit;
|
|
begin
|
|
DataConnector.UpdateRecord;
|
|
inherited DoExit;
|
|
end;
|
|
|
|
{$IFDEF VisualCLX}
|
|
procedure TJvCustomComboEdit.DoFlatChanged;
|
|
begin
|
|
inherited DoFlatChanged;
|
|
UpdateControls;
|
|
UpdateMargins;
|
|
end;
|
|
{$ENDIF VisualCLX}
|
|
|
|
procedure TJvCustomComboEdit.FocusKilled(NextWnd: THandle);
|
|
var
|
|
Sender: TWinControl;
|
|
begin
|
|
inherited FocusKilled(NextWnd);
|
|
FFocused := Screen.ActiveControl <> Self;
|
|
if not FFocused then
|
|
begin
|
|
Sender := FindControl(NextWnd);
|
|
if (Sender <> Self) and (Sender <> FPopup) and
|
|
{(Sender <> FButton)} ((FPopup <> nil) and
|
|
not FPopup.ContainsControl(Sender)) then
|
|
begin
|
|
{ MSDN : While processing this message (WM_KILLFOCUS), do not make any
|
|
function calls that display or activate a window.
|
|
}
|
|
AsyncPopupCloseUp(False);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.DoEraseBackground(Canvas: TCanvas; Param: Integer): Boolean;
|
|
begin
|
|
Result := True;
|
|
if csDestroying in ComponentState then
|
|
{ (rb) Implementation diffs; some return True other False }
|
|
Exit;
|
|
if Enabled then
|
|
Result := inherited DoEraseBackground(Canvas, Param)
|
|
else
|
|
begin
|
|
Canvas.Brush.Color := FDisabledColor;
|
|
Canvas.Brush.Style := bsSolid;
|
|
Canvas.FillRect(ClientRect);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.FocusSet(PrevWnd: THandle);
|
|
begin
|
|
inherited FocusSet(PrevWnd); // triggers OnExit and OnEnter => Focus could be changed
|
|
FFocused := Screen.ActiveControl = Self;
|
|
if FFocused then
|
|
SetShowCaret;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.EditButtonClick(Sender: TObject);
|
|
begin
|
|
if (not FReadOnly) or AlwaysEnableButton then
|
|
ButtonClick;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.EditCanModify: Boolean;
|
|
begin
|
|
Result := not FReadOnly;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.EnabledChanged;
|
|
begin
|
|
inherited EnabledChanged;
|
|
Invalidate;
|
|
FButton.Enabled := Enabled;
|
|
if Assigned(FOnEnabledChanged) then
|
|
FOnEnabledChanged(Self);
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.FontChanged;
|
|
begin
|
|
inherited FontChanged;
|
|
if HandleAllocated then
|
|
UpdateMargins;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.GetActionLinkClass: TControlActionLinkClass;
|
|
begin
|
|
Result := TJvCustomComboEditActionLink;
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
function TJvCustomComboEdit.GetAutoCompleteSource: IEnumString;
|
|
begin
|
|
Result := TAutoCompleteSource.Create(Self, 0);
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
function TJvCustomComboEdit.GetButtonFlat: Boolean;
|
|
begin
|
|
Result := FButton.Flat;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.GetButtonHint: string;
|
|
begin
|
|
Result := FButton.Hint;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.GetButtonWidth: Integer;
|
|
begin
|
|
if ShowButton then
|
|
Result := FButton.Width
|
|
else
|
|
Result := FSavedButtonWidth;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.GetDirectInput: Boolean;
|
|
begin
|
|
Result := FDirectInput;
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
|
|
function TJvCustomComboEdit.GetFlat: Boolean;
|
|
begin
|
|
Result := not Ctl3D;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.GetParentFlat: Boolean;
|
|
begin
|
|
Result := ParentCtl3D;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetFlat(const Value: Boolean);
|
|
begin
|
|
Ctl3D := not Value;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetParentFlat(const Value: Boolean);
|
|
begin
|
|
ParentCtl3D := Value;
|
|
end;
|
|
|
|
{$ENDIF VCL}
|
|
|
|
function TJvCustomComboEdit.GetGlyph: TBitmap;
|
|
begin
|
|
Result := FButton.Glyph;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.GetGlyphKind: TGlyphKind;
|
|
begin
|
|
Result := TGlyphKind(FImageKind);
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.GetInternalMargins(var ALeft, ARight: Integer);
|
|
const
|
|
CPixelsBetweenEditAndButton = 2;
|
|
begin
|
|
ARight := ARight + FBtnControl.Width + CPixelsBetweenEditAndButton;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.GetMinHeight: Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := GetTextHeight;
|
|
if BorderStyle = bsSingle then
|
|
I := I + GetSystemMetrics(SM_CYBORDER) * 4 + 1;
|
|
Result := I;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.GetNumGlyphs: TNumGlyphs;
|
|
begin
|
|
if ImageKind <> ikCustom then
|
|
Result := FNumGlyphs
|
|
else
|
|
Result := FButton.NumGlyphs;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.GetPopupValue: Variant;
|
|
begin
|
|
if FPopup is TJvPopupWindow then
|
|
Result := TJvPopupWindow(FPopup).GetValue
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
function TJvCustomComboEdit.GetPopupVisible: Boolean;
|
|
begin
|
|
Result := (FPopup <> nil) and FPopupVisible;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.GetReadOnly: Boolean;
|
|
begin
|
|
Result := FReadOnly;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.GetSettingCursor: Boolean;
|
|
begin
|
|
{$IFDEF CLR}
|
|
Result := Boolean(GetPrivateField(Self, 'FSettingCursor'));
|
|
{$ELSE}
|
|
Result := TCustomMaskEditAccessPrivate(Self).FSettingCursor;
|
|
{$ENDIF CLR}
|
|
end;
|
|
|
|
function TJvCustomComboEdit.GetShowButton: Boolean;
|
|
begin
|
|
Result := FBtnControl.Visible;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.GetTextHeight: Integer;
|
|
var
|
|
DC: HDC;
|
|
SaveFont: HFONT;
|
|
SysMetrics, Metrics: TTextMetric;
|
|
begin
|
|
DC := GetDC(HWND_DESKTOP);
|
|
try
|
|
GetTextMetrics(DC, SysMetrics);
|
|
SaveFont := SelectObject(DC, Font.Handle);
|
|
GetTextMetrics(DC, Metrics);
|
|
SelectObject(DC, SaveFont);
|
|
finally
|
|
ReleaseDC(HWND_DESKTOP, DC);
|
|
end;
|
|
// Result := Min(SysMetrics.tmHeight, Metrics.tmHeight); // Polaris
|
|
Result := Metrics.tmHeight; // Polaris
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.HidePopup;
|
|
begin
|
|
if FPopup is TJvPopupWindow then
|
|
begin
|
|
TJvPopupWindow(FPopup).Hide;
|
|
if Assigned(FOnPopupHidden) then
|
|
FOnPopupHidden(Self);
|
|
end;
|
|
end;
|
|
|
|
function TJvCustomComboEdit.IsCustomGlyph: Boolean;
|
|
begin
|
|
Result := Assigned(Glyph) and (ImageKind = ikCustom);
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
function TJvCustomComboEdit.IsFlatStored: Boolean;
|
|
begin
|
|
{ Same as IsCtl3DStored }
|
|
Result := not ParentCtl3D;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
function TJvCustomComboEdit.IsImageIndexStored: Boolean;
|
|
begin
|
|
Result :=
|
|
not (ActionLink is TJvCustomComboEditActionLink) or
|
|
not (ActionLink as TJvCustomComboEditActionLink).IsImageIndexLinked;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.KeyDown(var Key: Word; Shift: TShiftState);
|
|
//Polaris
|
|
var
|
|
Form: TCustomForm;
|
|
begin
|
|
UpdateGroup;
|
|
|
|
//Polaris
|
|
Form := GetParentForm(Self);
|
|
if (ssCtrl in Shift) then
|
|
case Key of
|
|
VK_RETURN:
|
|
if (Form <> nil) {and Form.KeyPreview} then
|
|
begin
|
|
{$IFDEF CLR}
|
|
Form.GetType.InvokeMember('KeyDown',
|
|
BindingFlags.Instance or BindingFlags.NonPublic or BindingFlags.InvokeMethod, nil, Form, [Key, Shift]);
|
|
{$ELSE}
|
|
TWinControlAccessProtected(Form).KeyDown(Key, Shift);
|
|
{$ENDIF CLR}
|
|
Key := 0;
|
|
end;
|
|
VK_TAB:
|
|
if (Form <> nil) {and Form.KeyPreview} then
|
|
begin
|
|
{$IFDEF CLR}
|
|
Form.GetType.InvokeMember('KeyDown',
|
|
BindingFlags.Instance or BindingFlags.NonPublic or BindingFlags.InvokeMethod, nil, Form, [Key, Shift]);
|
|
{$ELSE}
|
|
TWinControlAccessProtected(Form).KeyDown(Key, Shift);
|
|
{$ENDIF CLR}
|
|
Key := 0;
|
|
end;
|
|
end;
|
|
//Original
|
|
inherited KeyDown(Key, Shift);
|
|
if (FClickKey = ShortCut(Key, Shift)) and (ButtonWidth > 0) then
|
|
begin
|
|
EditButtonClick(Self);
|
|
Key := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.KeyPress(var Key: Char);
|
|
var
|
|
Form: TCustomForm;
|
|
begin
|
|
Form := GetParentForm(Self);
|
|
|
|
if (Key = Cr) or (Key = Esc) or ((Key = Lf) and PopupVisible) then
|
|
begin
|
|
if PopupVisible then
|
|
begin
|
|
//Polaris PopupCloseUp(FPopup, Key = Char(VK_RETURN));
|
|
PopupCloseUp(FPopup, Key <> Esc);
|
|
Key := #0;
|
|
end
|
|
else
|
|
begin
|
|
{ must catch and remove this, since is actually multi-line }
|
|
{$IFDEF VCL}
|
|
GetParentForm(Self).Perform(CM_DIALOGKEY, Byte(Key), 0);
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
TCustomFormAccessProtected(GetParentForm(Self)).NeedKey(Integer(Key), [], WideChar(Key));
|
|
{$ENDIF VisualCLX}
|
|
if Key = Cr then
|
|
begin
|
|
inherited KeyPress(Key);
|
|
Key := #0;
|
|
Exit;
|
|
end;
|
|
end;
|
|
end;
|
|
//Polaris
|
|
if Key in [Tab, Lf] then
|
|
begin
|
|
Key := #0;
|
|
{ (rb) Next code has no use because Key = #0? }
|
|
if (Form <> nil) {and Form.KeyPreview} then
|
|
{$IFDEF CLR}
|
|
Form.GetType.InvokeMember('KeyPress',
|
|
BindingFlags.Instance or BindingFlags.NonPublic or BindingFlags.InvokeMethod, nil, Form, [Key]);
|
|
{$ELSE}
|
|
TWinControlAccessProtected(Form).KeyPress(Key);
|
|
{$ENDIF CLR}
|
|
end;
|
|
//Polaris
|
|
inherited KeyPress(Key);
|
|
|
|
if (Key = #27) and DataConnector.Active then
|
|
begin
|
|
DataConnector.Reset;
|
|
Key := #0;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.Loaded;
|
|
begin
|
|
inherited Loaded;
|
|
if FStreamedButtonWidth >= 0 then
|
|
begin
|
|
SetButtonWidth(FStreamedButtonWidth);
|
|
if FStreamedFixedWidth then
|
|
with FButton do
|
|
ControlStyle := ControlStyle + [csFixedWidth];
|
|
end;
|
|
|
|
UpdateControls;
|
|
UpdateMargins;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.LocalKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
|
|
begin
|
|
UpdateGroup;
|
|
if Assigned(FOnKeyDown) then
|
|
FOnKeyDown(Sender, Key, Shift);
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
if (FPopup <> nil) and (Button = mbLeft) then
|
|
begin
|
|
if CanFocus then
|
|
SetFocus;
|
|
if not FFocused then
|
|
Exit;
|
|
if FPopupVisible then
|
|
PopupCloseUp(FPopup, False);
|
|
{else
|
|
if (not ReadOnly or AlwaysEnable) and (not DirectInput) then
|
|
PopupDropDown(True);}
|
|
end;
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.Notification(AComponent: TComponent; Operation: TOperation);
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
if (Operation = opRemove) and (AComponent = FImages) then
|
|
Images := nil;
|
|
if (Operation = opRemove) and (AComponent = FPopup) then
|
|
FPopup := nil;
|
|
end;
|
|
|
|
{$IFDEF VisualCLX}
|
|
procedure TJvCustomComboEdit.Paint;
|
|
begin
|
|
if Enabled then
|
|
inherited Paint
|
|
else
|
|
begin
|
|
if not PaintEdit(Self, Text, Alignment, PopupVisible,
|
|
DisabledTextColor, Focused and not PopupVisible, {Flat:}False, Canvas) then
|
|
inherited Paint;
|
|
end;
|
|
end;
|
|
{$ENDIF VisualCLX}
|
|
|
|
procedure TJvCustomComboEdit.PopupChange;
|
|
begin
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.PopupCloseUp(Sender: TObject; Accept: Boolean);
|
|
var
|
|
AValue: Variant;
|
|
begin
|
|
if (FPopup <> nil) and FPopupVisible then
|
|
begin
|
|
{$IFDEF VCL}
|
|
if GetCapture <> 0 then
|
|
SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
if Mouse.Capture <> nil then
|
|
Mouse.Capture := nil;
|
|
{$ENDIF VisualCLX}
|
|
AValue := GetPopupValue;
|
|
HidePopup;
|
|
try
|
|
try
|
|
if CanFocus and ParentFormVisible(Self) then
|
|
begin
|
|
SetFocus;
|
|
if GetFocus = Handle then
|
|
SetShowCaret;
|
|
end;
|
|
except
|
|
{ ignore exceptions }
|
|
end;
|
|
SetDirectInput(DirectInput);
|
|
Invalidate;
|
|
try
|
|
if Accept and AcceptPopup(AValue) and EditCanModify then
|
|
begin
|
|
AcceptValue(AValue);
|
|
if FFocused then
|
|
inherited SelectAll;
|
|
end
|
|
else
|
|
Reset;
|
|
except
|
|
Reset;
|
|
raise;
|
|
end;
|
|
finally
|
|
FPopupVisible := False;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.PopupDropDown(DisableEdit: Boolean);
|
|
var
|
|
P: TPoint;
|
|
Y: Integer;
|
|
SR: TJvSizeRect;
|
|
{$IFDEF VCL}
|
|
Monitor: TMonitor;
|
|
Rect: TRect;
|
|
{$ENDIF VCL}
|
|
begin
|
|
if not ((ReadOnly and not FAlwaysShowPopup) or FPopupVisible) then
|
|
begin
|
|
CreatePopup;
|
|
if FPopup = nil then
|
|
Exit;
|
|
|
|
P := Parent.ClientToScreen(Point(Left, Top));
|
|
{$IFDEF VCL}
|
|
Monitor := FindMonitor(MonitorFromWindow(Handle, MONITOR_DEFAULTTONEAREST));
|
|
Rect := GetWorkAreaRect(Monitor);
|
|
SR.Top := Rect.Top;
|
|
SR.Left := Rect.Left;
|
|
SR.Width := Rect.Right - Rect.Left;
|
|
SR.Height := Rect.Bottom - Rect.Top;
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
SR.Top := Screen.Top;
|
|
SR.Left := Screen.Left;
|
|
SR.Width := Screen.Width;
|
|
SR.Height := Screen.Height;
|
|
{$ENDIF VisualCLX}
|
|
Y := P.Y + Height;
|
|
if Y + FPopup.Height > SR.Top + SR.Height then
|
|
Y := P.Y - FPopup.Height;
|
|
case FPopupAlign of
|
|
epaRight:
|
|
begin
|
|
Dec(P.X, FPopup.Width - Width);
|
|
if P.X < SR.Left then
|
|
Inc(P.X, FPopup.Width - Width);
|
|
end;
|
|
epaLeft:
|
|
if P.X + FPopup.Width > SR.Left + SR.Width then
|
|
Dec(P.X, FPopup.Width - Width);
|
|
end;
|
|
if P.X < SR.Left then
|
|
P.X := SR.Left
|
|
else
|
|
if P.X + FPopup.Width > SR.Left + SR.Width then
|
|
P.X := SR.Left + SR.Width - FPopup.Width;
|
|
if Text <> '' then
|
|
SetPopupValue(Text)
|
|
else
|
|
SetPopupValue(Null);
|
|
if CanFocus then
|
|
SetFocus;
|
|
ShowPopup(Point(P.X, Y));
|
|
FPopupVisible := True;
|
|
if DisableEdit then
|
|
begin
|
|
inherited ReadOnly := True;
|
|
HideCaret(Handle);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
|
|
procedure TJvCustomComboEdit.ReadCtl3D(Reader: TReader);
|
|
begin
|
|
Flat := not Reader.ReadBoolean;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.ReadParentCtl3D(Reader: TReader);
|
|
begin
|
|
ParentFlat := Reader.ReadBoolean;
|
|
end;
|
|
|
|
{$ENDIF VCL}
|
|
|
|
procedure TJvCustomComboEdit.ReadGlyphKind(Reader: TReader);
|
|
const
|
|
sEnumValues: array [TGlyphKind] of string[12] =
|
|
('gkCustom', 'gkDefault', 'gkDropDown', 'gkEllipsis');
|
|
var
|
|
S: string;
|
|
GlyphKind: TGlyphKind;
|
|
begin
|
|
{ No need to drag in TypInfo.pas }
|
|
S := Reader.ReadIdent;
|
|
for GlyphKind := Low(TGlyphKind) to High(TGlyphKind) do
|
|
if SameText(S, sEnumValues[GlyphKind]) then
|
|
begin
|
|
ImageKind := TJvImageKind(GlyphKind);
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.RecreateGlyph;
|
|
var
|
|
NewGlyph: TBitmap;
|
|
|
|
function CreateEllipsisGlyph: TBitmap;
|
|
var
|
|
W, g, I: Integer;
|
|
begin
|
|
Result := TBitmap.Create;
|
|
with Result do
|
|
try
|
|
{$IFDEF VCL}
|
|
Monochrome := True;
|
|
{$ENDIF VCL}
|
|
Width := Max(1, FButton.Width - 6);
|
|
Height := 4;
|
|
W := 2;
|
|
g := (Result.Width - 3 * W) div 2;
|
|
if g <= 0 then
|
|
g := 1;
|
|
if g > 3 then
|
|
g := 3;
|
|
I := (Width - 3 * W - 2 * g) div 2;
|
|
{$IFDEF VisualCLX}
|
|
Canvas.Start;
|
|
{$ENDIF VisualCLX}
|
|
PatBlt(Canvas.Handle, I, 1, W, W, BLACKNESS);
|
|
PatBlt(Canvas.Handle, I + g + W, 1, W, W, BLACKNESS);
|
|
PatBlt(Canvas.Handle, I + 2 * g + 2 * W, 1, W, W, BLACKNESS);
|
|
{$IFDEF VisualCLX}
|
|
Canvas.Stop;
|
|
{$ENDIF VisualCLX}
|
|
except
|
|
Free;
|
|
raise;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
{ Delay until button is shown }
|
|
if not ShowButton then
|
|
Exit;
|
|
|
|
if FImageKind in [ikDropDown, ikEllipsis] then
|
|
begin
|
|
FButton.ImageIndex := -1;
|
|
FButton.NumGlyphs := 1;
|
|
end;
|
|
{$IFDEF JVCLThemesEnabled}
|
|
FButton.FDrawThemedDropDownBtn := FImageKind = ikDropDown;
|
|
{$ENDIF JVCLThemesEnabled}
|
|
|
|
case FImageKind of
|
|
ikDropDown:
|
|
begin
|
|
{$IFDEF JVCLThemesEnabled}
|
|
{ When XP Themes are enabled, ButtonFlat = False, GlyphKind = gkDropDown then
|
|
the glyph is the default themed dropdown button. When ButtonFlat = True, we
|
|
can't use that default dropdown button (because we then use toolbar buttons,
|
|
and there is no themed dropdown toolbar button) }
|
|
FButton.FDrawThemedDropDownBtn :=
|
|
ThemeServices.ThemesEnabled and not ButtonFlat;
|
|
if FButton.FDrawThemedDropDownBtn then
|
|
begin
|
|
FButton.ButtonGlyph.Glyph := nil;
|
|
FButton.Invalidate;
|
|
end
|
|
else
|
|
{$ENDIF JVCLThemesEnabled}
|
|
begin
|
|
LoadDefaultBitmap(FButton.ButtonGlyph.Glyph, OBM_COMBO);
|
|
FButton.Invalidate;
|
|
end;
|
|
end;
|
|
ikEllipsis:
|
|
begin
|
|
NewGlyph := CreateEllipsisGlyph;
|
|
try
|
|
FButton.ButtonGlyph.Glyph := NewGlyph;
|
|
FButton.Invalidate;
|
|
finally
|
|
NewGlyph.Destroy;
|
|
end;
|
|
end;
|
|
else
|
|
// FButton.ButtonGlyph.Glyph := nil;
|
|
FButton.Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SelectAll;
|
|
begin
|
|
if DirectInput then
|
|
inherited SelectAll;
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
|
|
procedure TJvCustomComboEdit.SetAlignment(Value: TAlignment);
|
|
begin
|
|
if FAlignment <> Value then
|
|
begin
|
|
FAlignment := Value;
|
|
RecreateWnd;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetAutoCompleteItems(Strings: TStrings);
|
|
begin
|
|
FAutoCompleteItems.Assign(Strings);
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetAutoCompleteOptions(const Value: TJvAutoCompleteOptions);
|
|
begin
|
|
if Value <> FAutoCompleteOptions then
|
|
begin
|
|
FAutoCompleteOptions := Value;
|
|
|
|
if not Assigned(FAutoCompleteIntf) then
|
|
CreateAutoComplete;
|
|
UpdateAutoComplete;
|
|
end;
|
|
end;
|
|
|
|
{$ENDIF VCL}
|
|
|
|
{$IFDEF VisualCLX}
|
|
procedure TJvCustomComboEdit.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
|
|
begin
|
|
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
|
|
UpdateControls;
|
|
UpdateMargins;
|
|
end;
|
|
{$ENDIF VisualCLX}
|
|
|
|
procedure TJvCustomComboEdit.SetButtonFlat(const Value: Boolean);
|
|
begin
|
|
FButton.Flat := Value;
|
|
{$IFDEF JVCLThemesEnabled}
|
|
{ When XP Themes are enabled, ButtonFlat = False, GlyphKind = gkDropDown then
|
|
the glyph is the default themed dropdown button. When ButtonFlat = True, we
|
|
can't use that default dropdown button, so we have to recreate the glyph
|
|
in this special case }
|
|
if ThemeServices.ThemesEnabled and (ImageKind = ikDropDown) then
|
|
RecreateGlyph;
|
|
{$ENDIF JVCLThemesEnabled}
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetButtonHint(const Value: string);
|
|
begin
|
|
FButton.Hint := Value;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetButtonWidth(Value: Integer);
|
|
begin
|
|
if csLoading in ComponentState then
|
|
begin
|
|
FStreamedButtonWidth := Value;
|
|
FStreamedFixedWidth := False;
|
|
end
|
|
else
|
|
if not ShowButton then
|
|
FSavedButtonWidth := Value
|
|
else
|
|
if (ButtonWidth <> Value) {or ((Value > 0) <> ShowButton)} then
|
|
begin
|
|
if Value > 1 then
|
|
FBtnControl.Visible := True
|
|
else
|
|
begin
|
|
FSavedButtonWidth := ButtonWidth;
|
|
FBtnControl.Visible := False;
|
|
end;
|
|
if csCreating in ControlState then
|
|
begin
|
|
FBtnControl.Width := Value;
|
|
FButton.Width := Value;
|
|
with FButton do
|
|
ControlStyle := ControlStyle - [csFixedWidth];
|
|
{ Some glyphs are size dependant (ellipses), thus recreate on size changes }
|
|
RecreateGlyph;
|
|
end
|
|
//else
|
|
//if (Value <> ButtonWidth) and (Value < ClientWidth) then begin
|
|
//Polaris
|
|
else
|
|
if (Value <> ButtonWidth) and
|
|
((Assigned(Parent) and (Value < ClientWidth)) or
|
|
(not Assigned(Parent) and (Value < Width))) then
|
|
begin
|
|
FBtnControl.SetBounds(FBtnControl.Left + FBtnControl.Width - Value,
|
|
FBtnControl.Top, Value, FBtnControl.Height);
|
|
FButton.Width := Value;
|
|
with FButton do
|
|
ControlStyle := ControlStyle - [csFixedWidth];
|
|
if HandleAllocated then
|
|
{$IFDEF VCL}
|
|
RecreateWnd;
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
Invalidate;
|
|
{$ENDIF VisualCLX}
|
|
{ Some glyphs are size dependant (ellipses), thus recreate on size changes }
|
|
RecreateGlyph;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetClipboardCommands(const Value: TJvClipboardCommands);
|
|
begin
|
|
if ClipboardCommands <> Value then
|
|
begin
|
|
inherited SetClipboardCommands(Value);
|
|
if ReadOnly and not (ClipboardCommands <= [caCopy]) then
|
|
ClipboardCommands := [caCopy];
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetDirectInput(Value: Boolean);
|
|
begin
|
|
inherited ReadOnly := not Value or FReadOnly;
|
|
FDirectInput := Value;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetDisabledColor(const Value: TColor);
|
|
begin
|
|
if FDisabledColor <> Value then
|
|
begin
|
|
FDisabledColor := Value;
|
|
if not Enabled then
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetDisabledTextColor(const Value: TColor);
|
|
begin
|
|
if FDisabledTextColor <> Value then
|
|
begin
|
|
FDisabledTextColor := Value;
|
|
if not Enabled then
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetGlyph(Value: TBitmap);
|
|
begin
|
|
ImageKind := ikCustom;
|
|
FButton.Glyph := Value;
|
|
FNumGlyphs := FButton.NumGlyphs;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetGlyphKind(Value: TGlyphKind);
|
|
begin
|
|
ImageKind := TJvImageKind(Value);
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetGroupIndex(const Value: Integer);
|
|
begin
|
|
FGroupIndex := Value;
|
|
UpdateGroup;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetImageIndex(const Value: TImageIndex);
|
|
begin
|
|
if FImageIndex <> Value then
|
|
begin
|
|
FImageIndex := Value;
|
|
if FImageKind = ikCustom then
|
|
FButton.ImageIndex := FImageIndex;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetImageKind(const Value: TJvImageKind);
|
|
begin
|
|
if FImageKind <> Value then
|
|
begin
|
|
FImageKind := Value;
|
|
RecreateGlyph;
|
|
case FImageKind of
|
|
ikCustom:
|
|
begin
|
|
FButton.Images := FImages;
|
|
FButton.ImageIndex := FImageIndex;
|
|
FButton.NumGlyphs := FNumGlyphs;
|
|
end;
|
|
ikDefault:
|
|
begin
|
|
FButton.Images := DefaultImages;
|
|
FButton.ImageIndex := DefaultImageIndex;
|
|
{ Default glyphs have a default width }
|
|
if Assigned(FButton.Images) and (FButton.ImageIndex >= 0) then
|
|
ButtonWidth := Max(FButton.Images.Width + 6, FButton.Width)
|
|
end;
|
|
ikDropDown:
|
|
if csLoading in ComponentState then
|
|
begin
|
|
if (FStreamedButtonWidth < 0) or FStreamedFixedWidth then
|
|
begin
|
|
ButtonWidth := GetSystemMetrics(SM_CXVSCROLL);
|
|
{ Setting ButtonWidth will set FStreamedFixedWidth to False, thus
|
|
reapply it. }
|
|
FStreamedFixedWidth := True;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
ButtonWidth := GetSystemMetrics(SM_CXVSCROLL);
|
|
{ Setting ButtonWidth will remove the csFixedWidth flag, thus
|
|
reapply it. }
|
|
with FButton do
|
|
ControlStyle := ControlStyle + [csFixedWidth];
|
|
end;
|
|
ikEllipsis: ;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetImages(const Value: TCustomImageList);
|
|
begin
|
|
FImages := Value;
|
|
if FImages <> nil then
|
|
FImages.FreeNotification(Self)
|
|
else
|
|
SetImageIndex(-1);
|
|
if ImageKind = ikCustom then
|
|
begin
|
|
FButton.Images := FImages;
|
|
FButton.ImageIndex := FImageIndex;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetNumGlyphs(const Value: TNumGlyphs);
|
|
begin
|
|
//if FGlyphKind in [gkDropDown, gkEllipsis] then
|
|
// FButton.NumGlyphs := 1
|
|
//else
|
|
//if FGlyphKind = gkDefault then
|
|
// FButton.NumGlyphs := FDefNumGlyphs
|
|
//else
|
|
FNumGlyphs := Value;
|
|
if ImageKind = ikCustom then
|
|
FButton.NumGlyphs := Value;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetPopupValue(const Value: Variant);
|
|
begin
|
|
if FPopup is TJvPopupWindow then
|
|
TJvPopupWindow(FPopup).SetValue(Value);
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetReadOnly(Value: Boolean);
|
|
begin
|
|
if Value <> FReadOnly then
|
|
begin
|
|
FReadOnly := Value;
|
|
inherited ReadOnly := Value or not FDirectInput;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetShowButton(const Value: Boolean);
|
|
begin
|
|
if ShowButton <> Value then
|
|
begin
|
|
if Value then
|
|
begin
|
|
{ FBtnControl needs to be visible first, otherwise only FSavedButtonWidth
|
|
is changed when setting ButtonWidth }
|
|
FBtnControl.Visible := True;
|
|
ButtonWidth := FSavedButtonWidth
|
|
end
|
|
else
|
|
ButtonWidth := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetDataConnector(const Value: TJvCustomComboEditDataConnector);
|
|
begin
|
|
if Value <> FDataConnector then
|
|
FDataConnector.Assign(Value);
|
|
end;
|
|
|
|
function TJvCustomComboEdit.CreateDataConnector: TJvCustomComboEditDataConnector;
|
|
begin
|
|
Result := TJvCustomComboEditDataConnector.Create(Self);
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.SetShowCaret;
|
|
const
|
|
CaretWidth: array [Boolean] of Integer = (1, 2);
|
|
begin
|
|
CreateCaret(Handle, 0, CaretWidth[fsBold in Font.Style], GetTextHeight);
|
|
ShowCaret(Handle);
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.ShowPopup(Origin: TPoint);
|
|
begin
|
|
if FPopup is TJvPopupWindow then
|
|
begin
|
|
TJvPopupWindow(FPopup).Show(Origin);
|
|
if Assigned(FOnPopupShown) then
|
|
FOnPopupShown(Self);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
procedure TJvCustomComboEdit.UpdateAutoComplete;
|
|
const
|
|
cAutoCompleteOptionValues: array [TJvAutoCompleteOption] of DWORD =
|
|
(ACO_AUTOSUGGEST, ACO_AUTOAPPEND,
|
|
ACO_SEARCH, ACO_FILTERPREFIXES, ACO_USETAB, ACO_UPDOWNKEYDROPSLIST,
|
|
ACO_RTLREADING);
|
|
var
|
|
Flags: DWORD;
|
|
Option: TJvAutoCompleteOption;
|
|
AutoComplete2: IAutoComplete2;
|
|
begin
|
|
if HandleAllocated and not (csDesigning in ComponentState) then
|
|
begin
|
|
if Supports(FAutoCompleteIntf, IAutoComplete2, AutoComplete2) then
|
|
begin
|
|
{ Set the options of the autocomplete object. }
|
|
Flags := 0;
|
|
for Option := Low(TJvAutoCompleteOption) to High(TJvAutoCompleteOption) do
|
|
if Option in AutoCompleteOptions then
|
|
Inc(Flags, cAutoCompleteOptionValues[Option]);
|
|
|
|
AutoComplete2.SetOptions(Flags);
|
|
end;
|
|
end;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
{$IFDEF COMPILER6_UP}
|
|
procedure TJvCustomComboEdit.UpdateBtnBounds(var NewLeft, NewTop, NewWidth, NewHeight: Integer);
|
|
var
|
|
BtnRect: TRect;
|
|
begin
|
|
if NewStyleControls then
|
|
{$IFDEF JVCLThemesEnabled}
|
|
if ThemeServices.ThemesEnabled then
|
|
begin
|
|
if BorderStyle = bsSingle then
|
|
begin
|
|
if Ctl3D then
|
|
BtnRect := Bounds(Width - FButton.Width - 2, 0,
|
|
FButton.Width, Height - 2)
|
|
else
|
|
BtnRect := Bounds(Width - FButton.Width - 1, 1,
|
|
FButton.Width, Height - 2);
|
|
end
|
|
else
|
|
BtnRect := Bounds(Width - FButton.Width, 0,
|
|
FButton.Width, Height);
|
|
end
|
|
else
|
|
{$ENDIF JVCLThemesEnabled}
|
|
begin
|
|
if BorderStyle = bsSingle then
|
|
begin
|
|
if not Flat then
|
|
BtnRect := Bounds(Width - FButton.Width - 4, 0,
|
|
FButton.Width, Height - 4)
|
|
else
|
|
BtnRect := Bounds(Width - FButton.Width - 2, 2,
|
|
FButton.Width, Height - 4)
|
|
end
|
|
else
|
|
BtnRect := Bounds(Width - FButton.Width, 0,
|
|
FButton.Width, Height);
|
|
end
|
|
else
|
|
BtnRect := Bounds(Width - FButton.Width, 0, FButton.Width, Height);
|
|
|
|
NewLeft := BtnRect.Left;
|
|
NewTop := BtnRect.Top;
|
|
NewWidth := BtnRect.Right - BtnRect.Left;
|
|
NewHeight := BtnRect.Bottom - BtnRect.Top;
|
|
end;
|
|
{$ENDIF COMPILER6_UP}
|
|
|
|
procedure TJvCustomComboEdit.UpdateControls;
|
|
begin
|
|
{ Notification }
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.UpdateGroup;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if (FGroupIndex <> -1) and (Owner <> nil) then
|
|
for I := 0 to Owner.ComponentCount - 1 do
|
|
if Owner.Components[I] is TJvCustomComboEdit then
|
|
with TJvCustomComboEdit(Owner.Components[I]) do
|
|
if (Name <> Self.Name) and (FGroupIndex = Self.FGroupIndex) then
|
|
Clear;
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.UpdateMargins;
|
|
var
|
|
LLeft, LRight, LTop: Integer;
|
|
Loc: TRect;
|
|
begin
|
|
{ Delay until Loaded and Handle is created }
|
|
if (csLoading in ComponentState) or not HandleAllocated then
|
|
Exit;
|
|
|
|
{UpdateMargins gets called whenever the layout of child controls changes.
|
|
It uses GetInternalMargins to determine the left and right margins of the
|
|
actual text area.}
|
|
|
|
AdjustHeight;
|
|
|
|
LTop := 0;
|
|
LLeft := 0;
|
|
LRight := 0;
|
|
{$IFDEF JVCLThemesEnabled}
|
|
{ If flat and themes are enabled, move the left edge of the edit rectangle
|
|
to the right, otherwise the theme edge paints over the border }
|
|
{ (rb) This was for a specific font/language; check if this is still necessary }
|
|
if ThemeServices.ThemesEnabled then
|
|
begin
|
|
if BorderStyle = bsSingle then
|
|
begin
|
|
if not Ctl3D then
|
|
LLeft := 3
|
|
else
|
|
begin
|
|
LLeft := 1;
|
|
LTop := 1;
|
|
end;
|
|
end;
|
|
end;
|
|
if ThemeServices.ThemesEnabled then
|
|
begin
|
|
if BorderStyle = bsSingle then
|
|
if Ctl3D then
|
|
LRight := 1
|
|
else
|
|
LRight := -1;
|
|
end
|
|
else
|
|
{$ENDIF JVCLThemesEnabled}
|
|
if (BorderStyle = bsSingle) and not Flat then
|
|
LTop := 2;
|
|
|
|
GetInternalMargins(LLeft, LRight);
|
|
|
|
{$IFDEF VCL}
|
|
SetRect(Loc, LLeft, LTop, Width - LRight-3, ClientHeight - 1);
|
|
SendRectMessage(Handle, EM_SETRECTNP, 0, Loc);
|
|
// (rb) EM_SETMARGINS necessary?
|
|
//SendMessage(Handle, EM_SETMARGINS, EC_RIGHTMARGIN or EC_LEFTMARGIN, MakeLong(LLeft, LRight));
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
SetRect(Loc, LLeft, LTop, Width - LRight - LTop-2, Height - 2 * LTop);
|
|
SetEditorRect(@Loc);
|
|
FBtnControl.Left := Loc.Right + 2;
|
|
FBtnControl.Height := Height - 2 * LTop;
|
|
{$ENDIF VisualCLX}
|
|
end;
|
|
|
|
procedure TJvCustomComboEdit.UpdatePopupVisible;
|
|
begin
|
|
FPopupVisible := (FPopup <> nil) and FPopup.Visible;
|
|
end;
|
|
|
|
{$IFDEF JVCLThemesEnabled}
|
|
procedure TJvCustomComboEdit.WMNCCalcSize(var Msg: TWMNCCalcSize);
|
|
begin
|
|
if ThemeServices.ThemesEnabled and Ctl3D and (BorderStyle = bsSingle) then
|
|
with Msg.CalcSize_Params^ do
|
|
InflateRect(rgrc[0], 1, 1);
|
|
inherited;
|
|
end;
|
|
{$ENDIF JVCLThemesEnabled}
|
|
|
|
{$IFDEF VCL}
|
|
procedure TJvCustomComboEdit.WMNCHitTest(var Msg: TWMNCHitTest);
|
|
var
|
|
P: TPoint;
|
|
begin
|
|
inherited;
|
|
if (Msg.Result = HTCLIENT) and not (csDesigning in ComponentState) and ShowButton then
|
|
begin
|
|
P := Point(FBtnControl.Left, FBtnControl.Top);
|
|
Windows.ClientToScreen(Handle, P);
|
|
if Msg.XPos > P.X then
|
|
Msg.Result := HTBORDER; {HTCAPTION;}
|
|
end;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
{$IFDEF JVCLThemesEnabled}
|
|
procedure TJvCustomComboEdit.WMNCPaint(var Msg: TWMNCPaint);
|
|
var
|
|
DC: HDC;
|
|
DrawRect: TRect;
|
|
Details: TThemedElementDetails;
|
|
begin
|
|
if ThemeServices.ThemesEnabled and Ctl3D and (BorderStyle = bsSingle) then
|
|
begin
|
|
DC := GetWindowDC(Handle);
|
|
try
|
|
GetWindowRect(Handle, DrawRect);
|
|
OffsetRect(DrawRect, -DrawRect.Left, -DrawRect.Top);
|
|
with DrawRect do
|
|
ExcludeClipRect(DC, Left + 1, Top + 1, Right - 1, Bottom - 1);
|
|
|
|
Details := ThemeServices.GetElementDetails(teEditTextNormal);
|
|
ThemeServices.DrawElement(DC, Details, DrawRect);
|
|
finally
|
|
ReleaseDC(Handle, DC);
|
|
end;
|
|
Msg.Result := 0;
|
|
end
|
|
else
|
|
inherited;
|
|
end;
|
|
{$ENDIF JVCLThemesEnabled}
|
|
|
|
{$IFDEF VCL}
|
|
procedure TJvCustomComboEdit.WMPaint(var Msg: TWMPaint);
|
|
var
|
|
Canvas: TControlCanvas;
|
|
begin
|
|
if csDestroying in ComponentState then
|
|
Exit;
|
|
if Enabled then
|
|
inherited
|
|
else
|
|
begin
|
|
Canvas := nil;
|
|
if not PaintEdit(Self, Text, FAlignment, PopupVisible,
|
|
DisabledTextColor, Focused and not PopupVisible, Canvas, Msg) then
|
|
inherited;
|
|
Canvas.Free;
|
|
end;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
{$IFDEF VCL}
|
|
procedure TJvCustomComboEdit.WndProc(var Msg: TMessage);
|
|
begin
|
|
if (((Msg.Msg >= WM_KEYFIRST) and (Msg.Msg <= WM_KEYLAST)) or (Msg.Msg = WM_CONTEXTMENU)) and
|
|
not SettingCursor and PopupVisible and
|
|
(FPopup is TJvPopupWindow) and Assigned(TJvPopupWindow(FPopup).ActiveControl) then
|
|
begin
|
|
with Msg do
|
|
Result := TJvPopupWindow(FPopup).ActiveControl.Perform(Msg, WParam, LParam);
|
|
|
|
if Msg.Result = 0 then
|
|
Exit;
|
|
end;
|
|
|
|
{ The AutoComplete functionality sends a WM_SETTEXT. But only SetTextBuf()
|
|
generates the required CM_TEXTCHANGED message after the WM_SETTEXT which is
|
|
now missing in this case. The following code ignores the SetTextBuf()
|
|
generated CM_TEXTCHANGE and performs it's own CM_TEXTCHANGE message after
|
|
each WM_SETTEXT. }
|
|
if (Msg.Msg = CM_TEXTCHANGED) and FTextChanged then // ignore the message generated by TControl.SetTextBuf()
|
|
begin
|
|
FTextChanged := False;
|
|
Exit;
|
|
end;
|
|
|
|
inherited WndProc(Msg);
|
|
|
|
if Msg.Msg = WM_SETTEXT then
|
|
begin
|
|
FTextChanged := False;
|
|
Perform(CM_TEXTCHANGED, 0, 0); // generate our own CM_TEXTCHANGED message
|
|
FTextChanged := True;
|
|
end;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
//=== { TJvCustomComboEditActionLink } =======================================
|
|
|
|
function TJvCustomComboEditActionLink.IsCaptionLinked: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TJvCustomComboEditActionLink.IsHintLinked: Boolean;
|
|
begin
|
|
Result := (Action is TCustomAction) and (FClient is TJvCustomComboEdit) and
|
|
((FClient as TJvCustomComboEdit).ButtonHint = (Action as TCustomAction).Hint);
|
|
end;
|
|
|
|
function TJvCustomComboEditActionLink.IsImageIndexLinked: Boolean;
|
|
begin
|
|
Result := inherited IsImageIndexLinked and (FClient is TJvCustomComboEdit) and
|
|
((FClient as TJvCustomComboEdit).ImageIndex = (Action as TCustomAction).ImageIndex);
|
|
end;
|
|
|
|
function TJvCustomComboEditActionLink.IsOnExecuteLinked: Boolean;
|
|
begin
|
|
Result := (Action is TCustomAction) and (FClient is TJvCustomComboEdit) and
|
|
(@(FClient as TJvCustomComboEdit).OnButtonClick = @Action.OnExecute);
|
|
end;
|
|
|
|
function TJvCustomComboEditActionLink.IsShortCutLinked: Boolean;
|
|
begin
|
|
Result := inherited IsImageIndexLinked and (FClient is TJvCustomComboEdit) and
|
|
((FClient as TJvCustomComboEdit).ClickKey = (Action as TCustomAction).ShortCut);
|
|
end;
|
|
|
|
procedure TJvCustomComboEditActionLink.SetHint(const Value: THintString);
|
|
begin
|
|
if IsHintLinked then
|
|
(FClient as TJvCustomComboEdit).ButtonHint := Value;
|
|
end;
|
|
|
|
procedure TJvCustomComboEditActionLink.SetImageIndex(Value: Integer);
|
|
begin
|
|
if IsImageIndexLinked then
|
|
(FClient as TJvCustomComboEdit).ImageIndex := Value;
|
|
end;
|
|
|
|
procedure TJvCustomComboEditActionLink.SetOnExecute(Value: TNotifyEvent);
|
|
begin
|
|
if IsOnExecuteLinked then
|
|
(FClient as TJvCustomComboEdit).OnButtonClick := Value;
|
|
end;
|
|
|
|
procedure TJvCustomComboEditActionLink.SetShortCut(Value: TShortCut);
|
|
begin
|
|
if IsShortCutLinked then
|
|
(FClient as TJvCustomComboEdit).ClickKey := Value;
|
|
end;
|
|
|
|
//=== { TJvCustomDateEditDataConnector } =====================================
|
|
|
|
procedure TJvCustomDateEditDataConnector.Assign(Source: TPersistent);
|
|
begin
|
|
inherited Assign(Source);
|
|
if Source is TJvCustomDateEditDataConnector then
|
|
begin
|
|
FDefaultDate := TJvCustomDateEditDataConnector(Source).FDefaultDate;
|
|
FDefaultDateIsNow := TJvCustomDateEditDataConnector(Source).DefaultDateIsNow;
|
|
end;
|
|
end;
|
|
|
|
function TJvCustomDateEditDataConnector.IsDefaultDateStored: Boolean;
|
|
begin
|
|
Result := FDefaultDate <> 0;
|
|
end;
|
|
|
|
procedure TJvCustomDateEditDataConnector.RecordChanged;
|
|
begin
|
|
if Field.IsValid then
|
|
begin
|
|
Control.ReadOnly := not Field.CanModify;
|
|
TJvCustomDateEdit(Control).Date := Field.AsDataTime;
|
|
end
|
|
else
|
|
inherited RecordChanged;
|
|
end;
|
|
|
|
procedure TJvCustomDateEditDataConnector.SetDefaultDateIsNow(const Value: Boolean);
|
|
begin
|
|
if Value <> FDefaultDateIsNow then
|
|
FDefaultDateIsNow := Value;
|
|
end;
|
|
|
|
procedure TJvCustomDateEditDataConnector.UpdateData;
|
|
begin
|
|
if TJvCustomDateEdit(Control).Date = 0 then
|
|
begin
|
|
if DefaultDateIsNow then
|
|
Field.AsDataTime := Now
|
|
else
|
|
if NullDate <> 0 then
|
|
Field.AsDataTime := DefaultDate
|
|
else
|
|
Field.Clear;
|
|
end
|
|
else
|
|
Field.AsDataTime := TJvCustomDateEdit(Control).Date;
|
|
TJvCustomDateEdit(Control).Date := Field.AsDataTime; // update
|
|
end;
|
|
|
|
//=== { TJvCustomDateEdit } ==================================================
|
|
|
|
constructor TJvCustomDateEdit.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
// Polaris
|
|
FDateAutoBetween := True;
|
|
FMinDate := NullDate;
|
|
FMaxDate := NullDate;
|
|
|
|
FBlanksChar := ' ';
|
|
FTitle := RsDateDlgCaption;
|
|
{$IFDEF VCL}
|
|
FPopupColor := clMenu;
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
FPopupColor := clWindow;
|
|
{$ENDIF VisualCLX}
|
|
// FDefNumGlyphs := 2;
|
|
FStartOfWeek := Mon;
|
|
FWeekends := [Sun];
|
|
FWeekendColor := clRed;
|
|
FYearDigits := dyDefault;
|
|
FCalendarHints := TStringList.Create;
|
|
FCalendarHints.OnChange := CalendarHintsChanged;
|
|
{$IFDEF VCL}
|
|
DateHook.Add;
|
|
{$ENDIF VCL}
|
|
FCustomDateFormat := GetDefaultDateFormat;
|
|
FDateFormatPreferred := GetDefaultDateFormatPreferred;
|
|
|
|
ControlState := ControlState + [csCreating];
|
|
try
|
|
UpdateFormat;
|
|
{$IFDEF DEFAULT_POPUP_CALENDAR}
|
|
FPopup := TJvPopupWindow(CreatePopupCalendar(Self,
|
|
{$IFDEF VCL} BiDiMode, {$ENDIF}{$IFDEF VisualCLX} bdLeftToRight, {$ENDIF}
|
|
// Polaris
|
|
FMinDate, FMaxDate));
|
|
TJvPopupWindow(FPopup).OnCloseUp := PopupCloseUp;
|
|
TJvPopupWindow(FPopup).Color := FPopupColor;
|
|
{$ENDIF DEFAULT_POPUP_CALENDAR}
|
|
ImageKind := ikDefault; { force update }
|
|
finally
|
|
ControlState := ControlState - [csCreating];
|
|
end;
|
|
end;
|
|
|
|
destructor TJvCustomDateEdit.Destroy;
|
|
begin
|
|
{$IFDEF VCL}
|
|
DateHook.Delete;
|
|
{$ENDIF VCL}
|
|
|
|
if FPopup is TJvPopupWindow then
|
|
begin
|
|
TJvPopupWindow(FPopup).OnCloseUp := nil;
|
|
FPopup.Parent := nil;
|
|
end;
|
|
FPopup.Free;
|
|
FPopup := nil;
|
|
FCalendarHints.OnChange := nil;
|
|
FCalendarHints.Free;
|
|
FCalendarHints := nil;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJvCustomDateEdit.CreateDataConnector: TJvCustomComboEditDataConnector;
|
|
begin
|
|
Result := TJvCustomDateEditDataConnector.Create(Self);
|
|
end;
|
|
|
|
function TJvCustomDateEdit.AcceptPopup(var Value: Variant): Boolean;
|
|
var
|
|
D: TDateTime;
|
|
begin
|
|
Result := True;
|
|
if Assigned(FOnAcceptDate) then
|
|
begin
|
|
if VarIsNull(Value) or VarIsEmpty(Value) then
|
|
D := NullDate
|
|
else
|
|
try
|
|
D := VarToDateTime(Value);
|
|
except
|
|
if DefaultToday then
|
|
D := SysUtils.Date
|
|
else
|
|
D := NullDate;
|
|
end;
|
|
FOnAcceptDate(Self, D, Result);
|
|
if Result then
|
|
Value := VarFromDateTime(D);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.AcceptValue(const Value: Variant);
|
|
begin
|
|
SetDate(VarToDateTime(Value));
|
|
UpdatePopupVisible;
|
|
if Modified then
|
|
inherited Change;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.ApplyDate(Value: TDateTime);
|
|
begin
|
|
SetDate(Value);
|
|
SelectAll;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.CalendarHintsChanged(Sender: TObject);
|
|
begin
|
|
FCalendarHints.OnChange := nil;
|
|
try
|
|
while CalendarHints.Count > 4 do
|
|
CalendarHints.Delete(CalendarHints.Count - 1);
|
|
finally
|
|
FCalendarHints.OnChange := CalendarHintsChanged;
|
|
end;
|
|
if not (csDesigning in ComponentState) then
|
|
UpdatePopup;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.Change;
|
|
begin
|
|
if not FFormatting then
|
|
inherited Change;
|
|
end;
|
|
|
|
// Polaris
|
|
|
|
procedure TJvCustomDateEdit.CheckValidDate;
|
|
var
|
|
ADate: TDateTime;
|
|
begin
|
|
if TextStored then
|
|
try
|
|
FFormatting := True;
|
|
try
|
|
SetDate(StrToDateFmt(FDateFormat, Text));
|
|
finally
|
|
FFormatting := False;
|
|
end;
|
|
except
|
|
if FDateFormat2 <> '' then
|
|
try
|
|
FFormatting := True;
|
|
try
|
|
SetDate(StrToDateFmt(FDateFormat2, Text));
|
|
finally
|
|
FFormatting := False;
|
|
end;
|
|
except
|
|
if CanFocus then
|
|
SetFocus;
|
|
ADate := Self.Date;
|
|
if DoInvalidDate(Text,ADate) then
|
|
Self.Date := ADate
|
|
else
|
|
raise;
|
|
end
|
|
else
|
|
begin
|
|
if CanFocus then
|
|
SetFocus;
|
|
ADate := Self.Date;
|
|
if DoInvalidDate(Text,ADate) then
|
|
Self.Date := ADate
|
|
else
|
|
raise;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF VisualCLX}
|
|
procedure TJvCustomDateEdit.CreateWidget;
|
|
begin
|
|
inherited CreateWidget;
|
|
if HandleAllocated then
|
|
UpdateMask;
|
|
end;
|
|
{$ENDIF VisualCLX}
|
|
|
|
{$IFDEF VCL}
|
|
procedure TJvCustomDateEdit.CreateWindowHandle(const Params: TCreateParams);
|
|
begin
|
|
inherited CreateWindowHandle(Params);
|
|
if Handle <> 0 then
|
|
UpdateMask;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
class function TJvCustomDateEdit.DefaultImageIndex: TImageIndex;
|
|
var
|
|
Bmp: TBitmap;
|
|
begin
|
|
if GDateImageIndex < 0 then
|
|
begin
|
|
Bmp := TBitmap.Create;
|
|
try
|
|
Bmp.LoadFromResourceName(HInstance, sDateBmp);
|
|
GDateImageIndex := DefaultImages.AddMasked(Bmp, clFuchsia);
|
|
finally
|
|
Bmp.Free;
|
|
end;
|
|
end;
|
|
|
|
Result := GDateImageIndex;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.DoExit;
|
|
begin
|
|
if not (csDesigning in ComponentState) and CheckOnExit then
|
|
CheckValidDate;
|
|
inherited DoExit;
|
|
end;
|
|
|
|
function TJvCustomDateEdit.DoInvalidDate(const DateString: string; var ANewDate: TDateTime): Boolean;
|
|
begin
|
|
Result := False;
|
|
if Assigned(FOnInvalidDate) then
|
|
FOnInvalidDate(Self, DateString, ANewDate, Result);
|
|
end;
|
|
|
|
function TJvCustomDateEdit.FourDigitYear: Boolean;
|
|
begin
|
|
Result := (FYearDigits = dyFour) or ((FYearDigits = dyDefault) and IsFourDigitYear);
|
|
end;
|
|
|
|
function TJvCustomDateEdit.GetCalendarHints: TStrings;
|
|
begin
|
|
Result := FCalendarHints;
|
|
end;
|
|
|
|
function TJvCustomDateEdit.GetCalendarStyle: TCalendarStyle;
|
|
begin
|
|
if FPopup <> nil then
|
|
Result := csPopup
|
|
else
|
|
Result := csDialog;
|
|
end;
|
|
|
|
function TJvCustomDateEdit.GetDate: TDateTime;
|
|
begin
|
|
if DefaultToday then
|
|
Result := SysUtils.Date
|
|
else
|
|
Result := NullDate;
|
|
Result := StrToDateFmtDef(FDateFormat, Text, Result);
|
|
end;
|
|
|
|
function TJvCustomDateEdit.GetDateFormat: string;
|
|
begin
|
|
Result := FDateFormat;
|
|
end;
|
|
|
|
function TJvCustomDateEdit.GetDateMask: string;
|
|
begin
|
|
Result := DefDateMask(FBlanksChar, FourDigitYear);
|
|
end;
|
|
|
|
function TJvCustomDateEdit.GetDialogTitle: string;
|
|
begin
|
|
Result := FTitle;
|
|
end;
|
|
|
|
function TJvCustomDateEdit.GetPopupColor: TColor;
|
|
begin
|
|
if FPopup is TJvPopupWindow then
|
|
Result := TJvPopupWindow(FPopup).Color
|
|
else
|
|
Result := FPopupColor;
|
|
end;
|
|
|
|
function TJvCustomDateEdit.IsCustomTitle: Boolean;
|
|
begin
|
|
{$IFDEF CLR}
|
|
Result := (CompareStr(RsDateDlgCaption, DialogTitle) <> 0) and (DialogTitle <> ''); // Polaris
|
|
{$ELSE}
|
|
Result := (AnsiCompareStr(RsDateDlgCaption, DialogTitle) <> 0) and (DialogTitle <> ''); // Polaris
|
|
{$ENDIF CLR}
|
|
end;
|
|
|
|
function TJvCustomDateEdit.IsDateStored: Boolean;
|
|
begin
|
|
Result := not DefaultToday;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.KeyDown(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
if not ReadOnly then
|
|
begin
|
|
if IsInWordArray(Key, [VK_PRIOR, VK_NEXT, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN,
|
|
VK_ADD, VK_SUBTRACT, VK_RETURN]) and PopupVisible then
|
|
begin
|
|
if FPopup is TJvPopupWindow then
|
|
TJvPopupWindow(FPopup).KeyDown(Key, Shift);
|
|
Key := 0;
|
|
end
|
|
else
|
|
if (Shift = []) and DirectInput then
|
|
begin
|
|
case Key of
|
|
VK_ADD:
|
|
begin
|
|
ApplyDate(NvlDate(Date, Now) + 1);
|
|
Key := 0;
|
|
end;
|
|
VK_SUBTRACT:
|
|
begin
|
|
ApplyDate(NvlDate(Date, Now) - 1);
|
|
Key := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
inherited KeyDown(Key, Shift);
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.KeyPress(var Key: Char);
|
|
begin
|
|
if not ReadOnly then
|
|
begin
|
|
if (Key in ['T', 't', '+', '-']) and PopupVisible then
|
|
begin
|
|
if FPopup is TJvPopupWindow then
|
|
TJvPopupWindow(FPopup).KeyPress(Key);
|
|
Key := #0;
|
|
end
|
|
else
|
|
if DirectInput then
|
|
case Key of
|
|
'T', 't':
|
|
begin
|
|
ApplyDate(Trunc(Now));
|
|
Key := #0;
|
|
end;
|
|
'+', '-':
|
|
Key := #0;
|
|
end;
|
|
end;
|
|
inherited KeyPress(Key);
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.PopupDropDown(DisableEdit: Boolean);
|
|
var
|
|
D: TDateTime;
|
|
Action: Boolean;
|
|
begin
|
|
if CalendarStyle = csDialog then
|
|
begin
|
|
D := Self.Date;
|
|
Action := SelectDate(Self, D, DialogTitle, StartOfWeek, Weekends, // Polaris (Self added)
|
|
WeekendColor, CalendarHints, MinDate, MaxDate); // Polaris
|
|
if CanFocus then
|
|
SetFocus;
|
|
if Action then
|
|
begin
|
|
if Assigned(FOnAcceptDate) then
|
|
FOnAcceptDate(Self, D, Action);
|
|
if Action then
|
|
begin
|
|
Self.Date := D;
|
|
if FFocused then
|
|
inherited SelectAll;
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
inherited PopupDropDown(DisableEdit);
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetParent(AParent: TWinControl);
|
|
begin
|
|
// This is here to help debugging parenting issues such as Mantis 3042
|
|
inherited SetParent(AParent);
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetBlanksChar(Value: Char);
|
|
begin
|
|
if Value <> FBlanksChar then
|
|
begin
|
|
if Value < ' ' then
|
|
Value := ' ';
|
|
FBlanksChar := Value;
|
|
UpdateMask;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetCalendarHints(Value: TStrings);
|
|
begin
|
|
FCalendarHints.Assign(Value);
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetCalendarStyle(Value: TCalendarStyle);
|
|
begin
|
|
if Value <> CalendarStyle then
|
|
case Value of
|
|
csPopup:
|
|
begin
|
|
if FPopup = nil then
|
|
FPopup := TJvPopupWindow(CreatePopupCalendar(Self,
|
|
{$IFDEF VCL} BiDiMode, {$ENDIF}{$IFDEF VisualCLX} bdLeftToRight, {$ENDIF}
|
|
FMinDate, FMaxDate)); // Polaris
|
|
TJvPopupWindow(FPopup).OnCloseUp := PopupCloseUp;
|
|
TJvPopupWindow(FPopup).Color := FPopupColor;
|
|
UpdatePopup;
|
|
end;
|
|
csDialog:
|
|
FreeAndNil(FPopup);
|
|
end;
|
|
end;
|
|
|
|
// Polaris
|
|
|
|
procedure TJvCustomDateEdit.SetDate(Value: TDateTime);
|
|
var
|
|
D: TDateTime;
|
|
SavedModified: Boolean;
|
|
begin
|
|
if not ValidDate(Value) or (Value = NullDate) then
|
|
if DefaultToday then
|
|
Value := SysUtils.Date
|
|
else
|
|
Value := NullDate;
|
|
D := Self.Date;
|
|
SavedModified := Modified;
|
|
TestDateBetween(Value); // Polaris
|
|
if Value = NullDate then
|
|
Text := ''
|
|
else
|
|
Text := FormatDateTime(FDateFormat, Value);
|
|
Modified := SavedModified or (D <> Self.Date);
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetDateAutoBetween(Value: Boolean);
|
|
var
|
|
D: TDateTime;
|
|
begin
|
|
if Value <> FDateAutoBetween then
|
|
begin
|
|
FDateAutoBetween := Value;
|
|
if Value then
|
|
begin
|
|
D := Date;
|
|
TestDateBetween(D);
|
|
if D <> Date then
|
|
Date := D;
|
|
end;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetDialogTitle(const Value: string);
|
|
begin
|
|
FTitle := Value;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetMaxDate(Value: TDateTime);
|
|
begin
|
|
if Value <> FMaxDate then
|
|
begin
|
|
//Check unacceptable MaxDate < MinDate
|
|
if (Value <> NullDate) and (FMinDate <> NullDate) and (Value < FMinDate) then
|
|
if FDateAutoBetween then
|
|
SetMinDate(Value)
|
|
else
|
|
{$IFDEF CLR}
|
|
raise EJVCLException.CreateFmt(RsEDateMaxLimit, [DateToStr(FMinDate)]);
|
|
{$ELSE}
|
|
raise EJVCLException.CreateResFmt(@RsEDateMaxLimit, [DateToStr(FMinDate)]);
|
|
{$ENDIF CLR}
|
|
FMaxDate := Value;
|
|
UpdatePopup;
|
|
if FDateAutoBetween then
|
|
SetDate(Date);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetMinDate(Value: TDateTime);
|
|
begin
|
|
if Value <> FMinDate then
|
|
begin
|
|
//!!!!! Necessarily check
|
|
|
|
// Check unacceptable MinDate > MaxDate [Translated]
|
|
if (Value <> NullDate) and (FMaxDate <> NullDate) and (Value > FMaxDate) then
|
|
if FDateAutoBetween then
|
|
SetMaxDate(Value)
|
|
else
|
|
{$IFDEF CLR}
|
|
raise EJVCLException.CreateFmt(RsEDateMinLimit, [DateToStr(FMaxDate)]);
|
|
{$ELSE}
|
|
raise EJVCLException.CreateResFmt(@RsEDateMinLimit, [DateToStr(FMaxDate)]);
|
|
{$ENDIF CLR}
|
|
FMinDate := Value;
|
|
UpdatePopup;
|
|
if FDateAutoBetween then
|
|
SetDate(Date);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetPopupColor(Value: TColor);
|
|
begin
|
|
if Value <> PopupColor then
|
|
begin
|
|
if FPopup is TJvPopupWindow then
|
|
TJvPopupWindow(FPopup).Color := Value;
|
|
FPopupColor := Value;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetPopupValue(const Value: Variant);
|
|
begin
|
|
inherited SetPopupValue(StrToDateFmtDef(FDateFormat, VarToStr(Value), SysUtils.Date));
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetStartOfWeek(Value: TDayOfWeekName);
|
|
begin
|
|
if Value <> FStartOfWeek then
|
|
begin
|
|
FStartOfWeek := Value;
|
|
UpdatePopup;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetWeekendColor(Value: TColor);
|
|
begin
|
|
if Value <> FWeekendColor then
|
|
begin
|
|
FWeekendColor := Value;
|
|
UpdatePopup;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetWeekends(Value: TDaysOfWeek);
|
|
begin
|
|
if Value <> FWeekends then
|
|
begin
|
|
FWeekends := Value;
|
|
UpdatePopup;
|
|
end;
|
|
end;
|
|
|
|
function TJvCustomDateEdit.GetDefaultDateFormat: string;
|
|
begin
|
|
Result := '';
|
|
end;
|
|
|
|
function TJvCustomDateEdit.IsDateFormatStored: Boolean;
|
|
begin
|
|
Result := (FCustomDateFormat <> GetDefaultDateFormat);
|
|
end;
|
|
|
|
function TJvCustomDateEdit.GetDefaultDateFormatPreferred: TPreferredDateFormat;
|
|
begin
|
|
Result := pdLocaleOnly;
|
|
end;
|
|
|
|
function TJvCustomDateEdit.IsDateFormatPreferredStored: Boolean;
|
|
begin
|
|
Result := (FDateFormatPreferred <> GetDefaultDateFormatPreferred);
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetDateFormatPreferred(Value: TPreferredDateFormat);
|
|
begin
|
|
if FDateFormatPreferred <> Value then
|
|
begin
|
|
FDateFormatPreferred := Value;
|
|
if not (csLoading in ComponentState) then
|
|
UpdateMask;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetCustomDateFormat(const Value: string);
|
|
begin
|
|
if FCustomDateFormat <> Value then
|
|
begin
|
|
FCustomDateFormat := Value;
|
|
if not (csLoading in ComponentState) then
|
|
begin
|
|
if FDateFormatPreferred in [pdCustom, pdCustomOnly] then
|
|
UpdateMask
|
|
else
|
|
UpdateFormat;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.SetYearDigits(Value: TYearDigits);
|
|
begin
|
|
if FYearDigits <> Value then
|
|
begin
|
|
FYearDigits := Value;
|
|
UpdateMask;
|
|
end;
|
|
end;
|
|
|
|
function TJvCustomDateEdit.StoreMaxDate: Boolean;
|
|
begin
|
|
Result := FMaxDate <> NullDate;
|
|
end;
|
|
|
|
function TJvCustomDateEdit.StoreMinDate: Boolean;
|
|
begin
|
|
Result := FMinDate <> NullDate;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.TestDateBetween(var Value: TDateTime);
|
|
begin
|
|
if FDateAutoBetween then
|
|
begin
|
|
if (FMinDate <> NullDate) and (Value <> NullDate) and (Value < FMinDate) then
|
|
Value := FMinDate;
|
|
if (FMaxDate <> NullDate) and (Value <> NullDate) and (Value > FMaxDate) then
|
|
Value := FMaxDate;
|
|
end;
|
|
end;
|
|
|
|
function TJvCustomDateEdit.TextStored: Boolean;
|
|
begin
|
|
{$IFDEF CLR}
|
|
Result := not IsEmptyStr(Text, [#0, ' ', AnsiChar(DateSeparator[1]), AnsiChar(FBlanksChar)]);
|
|
{$ELSE}
|
|
Result := not IsEmptyStr(Text, [#0, ' ', DateSeparator, FBlanksChar]);
|
|
{$ENDIF CLR}
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.UpdateFormat;
|
|
begin
|
|
if (FDateFormatPreferred in [pdLocale, pdLocaleOnly]) or (FCustomDateFormat = '') then
|
|
begin
|
|
FDateFormat := DefDateFormat(FourDigitYear);
|
|
if FDateFormatPreferred = pdLocale then
|
|
FDateFormat2 := FCustomDateFormat
|
|
else
|
|
FDateFormat2 := '';
|
|
end
|
|
else
|
|
begin
|
|
FDateFormat := FCustomDateFormat;
|
|
if FDateFormatPreferred = pdCustom then
|
|
FDateFormat2 := DefDateFormat(FourDigitYear)
|
|
else
|
|
FDateFormat2 := '';
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.UpdateMask;
|
|
var
|
|
DateValue: TDateTime;
|
|
OldFormat: string[10];
|
|
begin
|
|
DateValue := GetDate;
|
|
OldFormat := FDateFormat;
|
|
UpdateFormat;
|
|
if (GetDateMask <> EditMask) or (OldFormat <> FDateFormat) then
|
|
begin
|
|
{ force update }
|
|
EditMask := '';
|
|
EditMask := GetDateMask;
|
|
end;
|
|
UpdatePopup;
|
|
SetDate(DateValue);
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.UpdatePopup;
|
|
begin
|
|
if FPopup <> nil then
|
|
SetupPopupCalendar(FPopup, StartOfWeek,
|
|
Weekends, WeekendColor, CalendarHints, FourDigitYear,
|
|
MinDate, MaxDate); // Polaris
|
|
end;
|
|
|
|
procedure TJvCustomDateEdit.ValidateEdit;
|
|
begin
|
|
if TextStored then
|
|
CheckValidDate;
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
procedure TJvCustomDateEdit.WMContextMenu(var Msg: TWMContextMenu);
|
|
begin
|
|
if not PopupVisible then
|
|
inherited;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
//=== { TJvDateEdit } ========================================================
|
|
|
|
// (rom) unusual not to have it implemented in the Custom base class
|
|
|
|
constructor TJvDateEdit.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
UpdateMask;
|
|
end;
|
|
|
|
procedure TJvDateEdit.SetDate(Value: TDateTime);
|
|
begin
|
|
if not FDateAutoBetween then
|
|
if Value <> NullDate then
|
|
begin
|
|
if ((FMinDate <> NullDate) and (FMaxDate <> NullDate) and
|
|
((Value < FMinDate) or (Value > FMaxDate))) then
|
|
{$IFDEF CLR}
|
|
raise EJVCLException.CreateFmt(RsEDateOutOfRange, [FormatDateTime(FDateFormat, Value),
|
|
{$ELSE}
|
|
raise EJVCLException.CreateResFmt(@RsEDateOutOfRange, [FormatDateTime(FDateFormat, Value),
|
|
{$ENDIF CLR}
|
|
FormatDateTime(FDateFormat, FMinDate), FormatDateTime(FDateFormat, FMaxDate)])
|
|
else
|
|
if (FMinDate <> NullDate) and (Value < FMinDate) then
|
|
{$IFDEF CLR}
|
|
raise EJVCLException.CreateFmt(RsEDateOutOfMin, [FormatDateTime(FDateFormat, Value),
|
|
{$ELSE}
|
|
raise EJVCLException.CreateResFmt(@RsEDateOutOfMin, [FormatDateTime(FDateFormat, Value),
|
|
{$ENDIF CLR}
|
|
FormatDateTime(FDateFormat, FMinDate)])
|
|
else
|
|
if (FMaxDate <> NullDate) and (Value > FMaxDate) then
|
|
{$IFDEF CLR}
|
|
raise EJVCLException.CreateFmt(RsEDateOutOfMax, [FormatDateTime(FDateFormat, Value),
|
|
{$ELSE}
|
|
raise EJVCLException.CreateResFmt(@RsEDateOutOfMax, [FormatDateTime(FDateFormat, Value),
|
|
{$ENDIF CLR}
|
|
FormatDateTime(FDateFormat, FMaxDate)]);
|
|
end;
|
|
inherited SetDate(Value);
|
|
end;
|
|
|
|
//=== { TJvDirectoryEdit } ===================================================
|
|
|
|
constructor TJvDirectoryEdit.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
{$IFDEF VCL}
|
|
FOptions := [sdAllowCreate];
|
|
FAutoCompleteFileOptions := [acfFileSystem, acfFileSysDirs];
|
|
{$ENDIF VCL}
|
|
FDialogKind := dkWin32;
|
|
end;
|
|
|
|
class function TJvDirectoryEdit.DefaultImageIndex: TImageIndex;
|
|
var
|
|
Bmp: TBitmap;
|
|
begin
|
|
{$IFDEF JVCLThemesEnabled}
|
|
if ThemeServices.ThemesEnabled then
|
|
begin
|
|
if GDirImageIndexXP < 0 then
|
|
begin
|
|
Bmp := TBitmap.Create;
|
|
try
|
|
Bmp.LoadFromResourceName(HInstance, sDirXPBmp);
|
|
GDirImageIndexXP := DefaultImages.AddMasked(Bmp, clFuchsia);
|
|
finally
|
|
Bmp.Free;
|
|
end;
|
|
end;
|
|
Result := GDirImageIndexXP;
|
|
Exit;
|
|
end;
|
|
{$ENDIF JVCLThemesEnabled}
|
|
|
|
if GDirImageIndex < 0 then
|
|
begin
|
|
Bmp := TBitmap.Create;
|
|
try
|
|
Bmp.LoadFromResourceName(HInstance, sDirBmp);
|
|
GDirImageIndex := DefaultImages.AddMasked(Bmp, clFuchsia);
|
|
finally
|
|
Bmp.Free;
|
|
end;
|
|
end;
|
|
Result := GDirImageIndex;
|
|
end;
|
|
|
|
function TJvDirectoryEdit.GetLongName: string;
|
|
var
|
|
Temp: string;
|
|
Pos: Integer;
|
|
begin
|
|
if not MultipleDirs then
|
|
Result := ShortToLongPath(Text)
|
|
else
|
|
begin
|
|
Result := '';
|
|
Pos := 1;
|
|
while Pos <= Length(Text) do
|
|
begin
|
|
Temp := ShortToLongPath(ExtractSubstr(Text, Pos, [PathSep]));
|
|
if (Result <> '') and (Temp <> '') then
|
|
Result := Result + PathSep;
|
|
Result := Result + Temp;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TJvDirectoryEdit.GetShortName: string;
|
|
var
|
|
Temp: string;
|
|
Pos: Integer;
|
|
begin
|
|
if not MultipleDirs then
|
|
Result := LongToShortPath(Text)
|
|
else
|
|
begin
|
|
Result := '';
|
|
Pos := 1;
|
|
while Pos <= Length(Text) do
|
|
begin
|
|
Temp := LongToShortPath(ExtractSubstr(Text, Pos, [PathSep]));
|
|
if (Result <> '') and (Temp <> '') then
|
|
Result := Result + PathSep;
|
|
Result := Result + Temp;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDirectoryEdit.PopupDropDown(DisableEdit: Boolean);
|
|
var
|
|
Temp: string;
|
|
{$IFDEF VisualCLX}
|
|
TempW: WideString;
|
|
{$ENDIF VisualCLX}
|
|
Action: Boolean;
|
|
begin
|
|
Temp := Text;
|
|
Action := True;
|
|
DoBeforeDialog(Temp, Action);
|
|
if not Action then
|
|
Exit;
|
|
if Temp = '' then
|
|
begin
|
|
if InitialDir <> '' then
|
|
Temp := InitialDir
|
|
else
|
|
Temp := PathDelim;
|
|
end;
|
|
if not DirectoryExists(Temp) then
|
|
Temp := PathDelim;
|
|
DisableSysErrors;
|
|
try
|
|
{$IFDEF VCL}
|
|
{$IFNDEF CLR}
|
|
if NewStyleControls and (DialogKind = dkWin32) then
|
|
Action := BrowseForFolder(FDialogText, sdAllowCreate in DialogOptions, Temp, Self.HelpContext)
|
|
else
|
|
{$ENDIF !CLR}
|
|
Action := SelectDirectory(Temp, FOptions, Self.HelpContext);
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
begin
|
|
Action := SelectDirectory(FDialogText, Temp, TempW);
|
|
Temp := TempW;
|
|
end;
|
|
{$ENDIF VisualCLX}
|
|
finally
|
|
EnableSysErrors;
|
|
end;
|
|
if CanFocus then
|
|
SetFocus;
|
|
DoAfterDialog(Temp, Action);
|
|
if Action then
|
|
begin
|
|
SelText := '';
|
|
if (Text = '') or not MultipleDirs then
|
|
Text := Temp
|
|
else
|
|
Text := Text + PathSep + Temp;
|
|
if (Temp <> '') and DirectoryExists(Temp) then
|
|
InitialDir := Temp;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDirectoryEdit.ReceptFileDir(const AFileName: string);
|
|
var
|
|
Temp: string;
|
|
begin
|
|
if FileExists(AFileName) then
|
|
Temp := ExtractFilePath(AFileName)
|
|
else
|
|
Temp := AFileName;
|
|
if (Text = '') or not MultipleDirs then
|
|
Text := Temp
|
|
else
|
|
Text := Text + PathSep + Temp;
|
|
end;
|
|
|
|
//=== { TJvEditButton } ======================================================
|
|
|
|
constructor TJvEditButton.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FStandard := True; // Polaris
|
|
ControlStyle := ControlStyle + [csReplicatable];
|
|
ParentShowHint := True;
|
|
end;
|
|
|
|
procedure TJvEditButton.Click;
|
|
begin
|
|
if not FNoAction then
|
|
inherited Click
|
|
else
|
|
FNoAction := False;
|
|
end;
|
|
|
|
function TJvEditButton.GetGlyph: TBitmap;
|
|
begin
|
|
Result := ButtonGlyph.Glyph;
|
|
end;
|
|
|
|
function TJvEditButton.GetNumGlyphs: TJvNumGlyphs;
|
|
begin
|
|
Result := ButtonGlyph.NumGlyphs;
|
|
end;
|
|
|
|
function TJvEditButton.GetUseGlyph: Boolean;
|
|
begin
|
|
Result := not Assigned(Images) or (ImageIndex < 0);
|
|
end;
|
|
|
|
procedure TJvEditButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
if (Button = mbLeft) and (Owner <> nil) then
|
|
with TJvCustomComboEdit(Owner) do
|
|
begin
|
|
FNoAction := (FPopup <> nil) and FPopupVisible;
|
|
if not FPopupVisible then
|
|
begin
|
|
if TabStop and CanFocus and (GetFocus <> Handle) then
|
|
SetFocus;
|
|
end
|
|
else
|
|
PopupCloseUp(FPopup, FStandard); // Polaris
|
|
end;
|
|
end;
|
|
|
|
procedure TJvEditButton.Paint;
|
|
{$IFDEF JVCLThemesEnabled}
|
|
var
|
|
ThemedState: TThemedComboBox;
|
|
Details: TThemedElementDetails;
|
|
R: TRect;
|
|
{$ENDIF JVCLThemesEnabled}
|
|
begin
|
|
{$IFDEF JVCLThemesEnabled}
|
|
if ThemeServices.ThemesEnabled then
|
|
begin
|
|
if FDrawThemedDropDownBtn then
|
|
begin
|
|
if not Enabled then
|
|
ThemedState := tcDropDownButtonDisabled
|
|
else
|
|
if FState in [rbsDown, rbsExclusive] then
|
|
ThemedState := tcDropDownButtonPressed
|
|
else
|
|
if MouseOver or IsDragging then
|
|
ThemedState := tcDropDownButtonHot
|
|
else
|
|
ThemedState := tcDropDownButtonNormal;
|
|
R := ClientRect;
|
|
Details := ThemeServices.GetElementDetails(ThemedState);
|
|
ThemeServices.DrawElement(Canvas.Handle, Details, R);
|
|
end
|
|
else
|
|
inherited Paint;
|
|
end
|
|
else
|
|
{$ENDIF JVCLThemesEnabled}
|
|
begin
|
|
inherited Paint;
|
|
if FState <> rbsDown then
|
|
with Canvas do
|
|
begin
|
|
if NewStyleControls then
|
|
Pen.Color := clBtnFace
|
|
else
|
|
Pen.Color := clBtnShadow;
|
|
MoveTo(0, 0);
|
|
LineTo(0, Self.Height - 1);
|
|
Pen.Color := clBtnHighlight;
|
|
MoveTo(1, 1);
|
|
LineTo(1, Self.Height - 2);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvEditButton.PaintImage(Canvas: TCanvas; ARect: TRect;
|
|
const Offset: TPoint; AState: TJvButtonState; DrawMark: Boolean);
|
|
begin
|
|
if UseGlyph then
|
|
ButtonGlyph.Draw(Canvas, ARect, Offset, '', Layout,
|
|
Margin, Spacing, False, AState, 0)
|
|
else
|
|
inherited PaintImage(Canvas, ARect, Offset, AState, DrawMark);
|
|
end;
|
|
|
|
procedure TJvEditButton.SetGlyph(const Value: TBitmap);
|
|
begin
|
|
ButtonGlyph.Glyph := Value;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TJvEditButton.SetNumGlyphs(Value: TJvNumGlyphs);
|
|
begin
|
|
if Value < 0 then
|
|
Value := 1
|
|
else
|
|
if Value > Ord(High(TJvButtonState)) + 1 then
|
|
Value := Ord(High(TJvButtonState)) + 1;
|
|
if Value <> ButtonGlyph.NumGlyphs then
|
|
begin
|
|
ButtonGlyph.NumGlyphs := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
procedure TJvEditButton.WMContextMenu(var Msg: TWMContextMenu);
|
|
begin
|
|
{ (rb) Without this, we get 2 context menu's (1 from the form, another from
|
|
the combo edit; don't know exactly what is causing this. (I guess
|
|
it's related to FBtnControl being a TWinControl) }
|
|
Msg.Result := 1;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
//=== { TJvFileDirEdit } =====================================================
|
|
|
|
constructor TJvFileDirEdit.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
{$IFDEF VCL}
|
|
OEMConvert := True;
|
|
FAcceptFiles := True;
|
|
FAutoCompleteOptions := [acoAutoSuggest];
|
|
{$ENDIF VCL}
|
|
ControlState := ControlState + [csCreating];
|
|
try
|
|
ImageKind := ikDefault; { force update }
|
|
finally
|
|
ControlState := ControlState - [csCreating];
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFileDirEdit.Change;
|
|
var
|
|
Ps: Integer;
|
|
begin
|
|
// The control becomes confused when the Text property has a #10 or #13 in it.
|
|
Ps := Pos(#10, Text);
|
|
if Ps = 0 then
|
|
Ps := Pos(#13, Text);
|
|
if Ps > 0 then
|
|
Text := Copy(Text, 1, Ps - 1)
|
|
else
|
|
inherited Change;
|
|
end;
|
|
|
|
procedure TJvFileDirEdit.ClearFileList;
|
|
begin
|
|
end;
|
|
|
|
{$IFDEF JVCLThemesEnabled}
|
|
procedure TJvFileDirEdit.CMSysColorChange(var Msg: TMessage);
|
|
begin
|
|
inherited;
|
|
// We use this event to respond to theme changes (no WM_THEMECHANGED are broadcasted
|
|
// to the components)
|
|
// Note that there is a bug in TApplication.WndProc, so the application will not
|
|
// change from non-themed to themed.
|
|
if ImageKind = ikDefault then
|
|
Button.ImageIndex := DefaultImageIndex;
|
|
end;
|
|
{$ENDIF JVCLThemesEnabled}
|
|
|
|
{$IFDEF VCL}
|
|
|
|
procedure TJvFileDirEdit.CreateHandle;
|
|
begin
|
|
inherited CreateHandle;
|
|
|
|
if FAcceptFiles then
|
|
SetDragAccept(True);
|
|
end;
|
|
|
|
procedure TJvFileDirEdit.DestroyWindowHandle;
|
|
begin
|
|
SetDragAccept(False);
|
|
inherited DestroyWindowHandle;
|
|
end;
|
|
|
|
{$ENDIF VCL}
|
|
|
|
procedure TJvFileDirEdit.DisableSysErrors;
|
|
begin
|
|
{$IFDEF MSWINDOWS}
|
|
FErrMode := SetErrorMode(SEM_NOOPENFILEERRORBOX or SEM_FAILCRITICALERRORS);
|
|
{$ENDIF MSWINDOWS}
|
|
end;
|
|
|
|
procedure TJvFileDirEdit.DoAfterDialog(var FileName: string; var Action: Boolean);
|
|
begin
|
|
if Assigned(FOnAfterDialog) then
|
|
FOnAfterDialog(Self, FileName, Action);
|
|
end;
|
|
|
|
procedure TJvFileDirEdit.DoBeforeDialog(var FileName: string; var Action: Boolean);
|
|
begin
|
|
if Assigned(FOnBeforeDialog) then
|
|
FOnBeforeDialog(Self, FileName, Action);
|
|
end;
|
|
|
|
procedure TJvFileDirEdit.EnableSysErrors;
|
|
begin
|
|
{$IFDEF MSWINDOWS}
|
|
SetErrorMode(FErrMode);
|
|
{$ENDIF MSWINDOWS}
|
|
FErrMode := 0;
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
|
|
function TJvFileDirEdit.GetAutoCompleteSource: IEnumString;
|
|
begin
|
|
{$IFDEF CLR}
|
|
FAutoCompleteSourceIntf :=
|
|
Activator.CreateInstance(System.Type.GetTypeFromCLSID(Guid.Create(CLSID_ACLMulti))) as IEnumString;
|
|
{$ELSE}
|
|
if Failed(CoCreateInstance(CLSID_ACLMulti, nil, CLSCTX_INPROC_SERVER, IEnumString, FAutoCompleteSourceIntf)) then
|
|
FAutoCompleteSourceIntf := nil;
|
|
{$ENDIF CLR}
|
|
Result := FAutoCompleteSourceIntf;
|
|
end;
|
|
|
|
procedure TJvFileDirEdit.SetAcceptFiles(Value: Boolean);
|
|
begin
|
|
if FAcceptFiles <> Value then
|
|
begin
|
|
SetDragAccept(Value);
|
|
FAcceptFiles := Value;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFileDirEdit.SetAutoCompleteFileOptions(const Value: TJvAutoCompleteFileOptions);
|
|
begin
|
|
if FAutoCompleteFileOptions <> Value then
|
|
begin
|
|
FAutoCompleteFileOptions := Value;
|
|
if not (csDesigning in ComponentState) then
|
|
UpdateAutoComplete;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFileDirEdit.SetDragAccept(Value: Boolean);
|
|
begin
|
|
if not (csDesigning in ComponentState) and (Handle <> 0) then
|
|
DragAcceptFiles(Handle, Value);
|
|
end;
|
|
|
|
procedure TJvFileDirEdit.DestroyAutoComplete;
|
|
begin
|
|
// Mantis 3112: We drop the references we get to the various interfaces
|
|
// thus avoiding accesses to them triggered by the ancestor(s) destructor(s)
|
|
FMRUList := nil;
|
|
FHistoryList := nil;
|
|
FFileSystemList:= nil;
|
|
FAutoCompleteSourceIntf := nil;
|
|
|
|
inherited DestroyAutoComplete;
|
|
end;
|
|
|
|
procedure TJvFileDirEdit.UpdateAutoComplete;
|
|
var
|
|
ObjMgr: IObjMgr;
|
|
List2: IACList2;
|
|
Options: DWORD;
|
|
begin
|
|
if Supports(FAutoCompleteSourceIntf, IObjMgr, ObjMgr) then
|
|
begin
|
|
if acfURLMRU in AutoCompleteFileOptions then
|
|
begin
|
|
if not Assigned(FMRUList) and
|
|
{$IFDEF CLR}
|
|
SucceededCom(FMRUList,
|
|
Activator.CreateInstance(System.Type.GetTypeFromCLSID(Guid.Create(CLSID_ACLMRU)))) then
|
|
{$ELSE}
|
|
Succeeded(CoCreateInstance(CLSID_ACLMRU, nil, CLSCTX_INPROC_SERVER, IUnknown, FMRUList)) then
|
|
{$ENDIF CLR}
|
|
begin
|
|
ObjMgr.Append(FMRUList);
|
|
end
|
|
end
|
|
else
|
|
if Assigned(FMRUList) then
|
|
begin
|
|
ObjMgr.Remove(FMRUList);
|
|
FMRUList := nil;
|
|
end;
|
|
|
|
if acfURLHistory in AutoCompleteFileOptions then
|
|
begin
|
|
if not Assigned(FHistoryList) and
|
|
{$IFDEF CLR}
|
|
SucceededCom(FHistoryList,
|
|
Activator.CreateInstance(System.Type.GetTypeFromCLSID(Guid.Create(CLSID_ACLHistory)))) then
|
|
{$ELSE}
|
|
Succeeded(CoCreateInstance(CLSID_ACLHistory, nil, CLSCTX_INPROC_SERVER, IUnknown, FHistoryList)) then
|
|
{$ENDIF CLR}
|
|
begin
|
|
ObjMgr.Append(FHistoryList);
|
|
end;
|
|
end
|
|
else
|
|
if Assigned(FHistoryList) then
|
|
begin
|
|
ObjMgr.Remove(FHistoryList);
|
|
FHistoryList := nil;
|
|
end;
|
|
|
|
if [acfFileSystem, acfFileSysDirs] * AutoCompleteFileOptions <> [] then
|
|
begin
|
|
if not Assigned(FFileSystemList) and
|
|
{$IFDEF CLR}
|
|
SucceededCom(FFileSystemList,
|
|
Activator.CreateInstance(System.Type.GetTypeFromCLSID(Guid.Create(CLSID_ACListISF)))) then
|
|
{$ELSE}
|
|
Succeeded(CoCreateInstance(CLSID_ACListISF, nil, CLSCTX_INPROC_SERVER, IUnknown, FFileSystemList)) then
|
|
{$ENDIF CLR}
|
|
begin
|
|
ObjMgr.Append(FFileSystemList);
|
|
end;
|
|
|
|
Options := ACLO_FILESYSONLY;
|
|
if acfFileSysDirs in AutoCompleteFileOptions then
|
|
Options := Options or ACLO_FILESYSDIRS;
|
|
|
|
if Supports(FFileSystemList, IACList2, List2) then
|
|
List2.SetOptions(Options);
|
|
end
|
|
else
|
|
if Assigned(FFileSystemList) then
|
|
begin
|
|
ObjMgr.Remove(FFileSystemList);
|
|
FFileSystemList := nil;
|
|
end;
|
|
end;
|
|
|
|
inherited UpdateAutoComplete;
|
|
end;
|
|
|
|
procedure TJvFileDirEdit.WMDropFiles(var Msg: TWMDropFiles);
|
|
var
|
|
{$IFDEF CLR}
|
|
AFileName: StringBuilder;
|
|
{$ELSE}
|
|
AFileName: array [0..255] of Char;
|
|
{$ENDIF CLR}
|
|
I, Num: Cardinal;
|
|
begin
|
|
Msg.Result := 0;
|
|
try
|
|
Num := DragQueryFile(Msg.Drop, $FFFFFFFF, nil, 0);
|
|
if Num > 0 then
|
|
begin
|
|
ClearFileList;
|
|
for I := 0 to Num - 1 do
|
|
begin
|
|
{$IFDEF CLR}
|
|
AFileName := StringBuilder.Create(256);
|
|
DragQueryFile(Msg.Drop, I, AFileName, 255);
|
|
ReceptFileDir(AFileName.ToString());
|
|
{$ELSE}
|
|
DragQueryFile(Msg.Drop, I, PChar(@AFileName), Pred(SizeOf(AFileName)));
|
|
ReceptFileDir(StrPas(AFileName));
|
|
{$ENDIF CLR}
|
|
if not FMultipleDirs then
|
|
Break;
|
|
end;
|
|
if Assigned(FOnDropFiles) then
|
|
FOnDropFiles(Self);
|
|
end;
|
|
finally
|
|
DragFinish(Msg.Drop);
|
|
end;
|
|
end;
|
|
|
|
{$ENDIF VCL}
|
|
|
|
//=== { TJvFilenameEdit } ====================================================
|
|
|
|
constructor TJvFilenameEdit.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FAddQuotes := True;
|
|
{$IFDEF VCL}
|
|
FAutoCompleteFileOptions := [acfFileSystem];
|
|
{$ENDIF VCL}
|
|
CreateEditDialog;
|
|
end;
|
|
|
|
procedure TJvFilenameEdit.ClearFileList;
|
|
begin
|
|
FDialog.Files.Clear;
|
|
end;
|
|
|
|
procedure TJvFilenameEdit.CreateEditDialog;
|
|
var
|
|
NewDialog: TOpenDialog;
|
|
begin
|
|
case FDialogKind of
|
|
dkOpen:
|
|
NewDialog := TOpenDialog.Create(Self);
|
|
dkOpenPicture:
|
|
NewDialog := TOpenPictureDialog.Create(Self);
|
|
dkSavePicture:
|
|
NewDialog := TSavePictureDialog.Create(Self);
|
|
else { dkSave }
|
|
NewDialog := TSaveDialog.Create(Self);
|
|
end;
|
|
try
|
|
if FDialog <> nil then
|
|
begin
|
|
with NewDialog do
|
|
begin
|
|
DefaultExt := FDialog.DefaultExt;
|
|
{$IFDEF VCL}
|
|
FileEditStyle := FDialog.FileEditStyle;
|
|
{$ENDIF VCL}
|
|
FileName := FDialog.FileName;
|
|
Filter := FDialog.Filter;
|
|
FilterIndex := FDialog.FilterIndex;
|
|
InitialDir := FDialog.InitialDir;
|
|
HistoryList := FDialog.HistoryList;
|
|
Files.Assign(FDialog.Files);
|
|
Options := FDialog.Options;
|
|
Title := FDialog.Title;
|
|
end;
|
|
FDialog.Free;
|
|
end
|
|
else
|
|
begin
|
|
NewDialog.Title := RsBrowseCaption;
|
|
NewDialog.Filter := RsDefaultFilter;
|
|
NewDialog.Options := [ofHideReadOnly];
|
|
end;
|
|
finally
|
|
FDialog := NewDialog;
|
|
end;
|
|
end;
|
|
|
|
class function TJvFilenameEdit.DefaultImageIndex: TImageIndex;
|
|
var
|
|
Bmp: TBitmap;
|
|
begin
|
|
{$IFDEF JVCLThemesEnabled}
|
|
if ThemeServices.ThemesEnabled then
|
|
begin
|
|
if GFileImageIndexXP < 0 then
|
|
begin
|
|
Bmp := TBitmap.Create;
|
|
try
|
|
Bmp.LoadFromResourceName(HInstance, sFileXPBmp);
|
|
GFileImageIndexXP := DefaultImages.AddMasked(Bmp, clFuchsia);
|
|
finally
|
|
Bmp.Free;
|
|
end;
|
|
end;
|
|
Result := GFileImageIndexXP;
|
|
Exit;
|
|
end;
|
|
{$ENDIF JVCLThemesEnabled}
|
|
|
|
if GFileImageIndex < 0 then
|
|
begin
|
|
Bmp := TBitmap.Create;
|
|
try
|
|
Bmp.LoadFromResourceName(HInstance, sFileBmp);
|
|
GFileImageIndex := DefaultImages.AddMasked(Bmp, clFuchsia);
|
|
finally
|
|
Bmp.Free;
|
|
end;
|
|
end;
|
|
Result := GFileImageIndex;
|
|
end;
|
|
|
|
function TJvFilenameEdit.GetDefaultExt: TFileExt;
|
|
begin
|
|
Result := FDialog.DefaultExt;
|
|
end;
|
|
|
|
function TJvFilenameEdit.GetDialogFiles: TStrings;
|
|
begin
|
|
Result := FDialog.Files;
|
|
end;
|
|
|
|
function TJvFilenameEdit.GetDialogTitle: string;
|
|
begin
|
|
Result := FDialog.Title;
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
function TJvFilenameEdit.GetFileEditStyle: TFileEditStyle;
|
|
begin
|
|
Result := FDialog.FileEditStyle;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
function TJvFilenameEdit.GetFileName: TFileName;
|
|
begin
|
|
Result := ClipFilename(inherited Text, AddQuotes);
|
|
end;
|
|
|
|
function TJvFilenameEdit.GetFilter: string;
|
|
begin
|
|
Result := FDialog.Filter;
|
|
end;
|
|
|
|
function TJvFilenameEdit.GetFilterIndex: Integer;
|
|
begin
|
|
Result := FDialog.FilterIndex;
|
|
end;
|
|
|
|
function TJvFilenameEdit.GetHistoryList: TStrings;
|
|
begin
|
|
Result := FDialog.HistoryList;
|
|
end;
|
|
|
|
function TJvFilenameEdit.GetInitialDir: string;
|
|
begin
|
|
Result := FDialog.InitialDir;
|
|
end;
|
|
|
|
function TJvFilenameEdit.GetLongName: string;
|
|
begin
|
|
Result := ShortToLongFileName(FileName);
|
|
end;
|
|
|
|
function TJvFilenameEdit.GetOptions: TOpenOptions;
|
|
begin
|
|
Result := FDialog.Options;
|
|
end;
|
|
|
|
function TJvFilenameEdit.GetShortName: string;
|
|
begin
|
|
Result := LongToShortFileName(FileName);
|
|
end;
|
|
|
|
function TJvFilenameEdit.IsCustomFilter: Boolean;
|
|
begin
|
|
{$IFDEF CLR}
|
|
Result := CompareStr(RsDefaultFilter, FDialog.Filter) <> 0;
|
|
{$ELSE}
|
|
Result := AnsiCompareStr(RsDefaultFilter, FDialog.Filter) <> 0;
|
|
{$ENDIF CLR}
|
|
end;
|
|
|
|
function TJvFilenameEdit.IsCustomTitle: Boolean;
|
|
begin
|
|
{$IFDEF CLR}
|
|
Result := CompareStr(RsBrowseCaption, FDialog.Title) <> 0;
|
|
{$ELSE}
|
|
Result := AnsiCompareStr(RsBrowseCaption, FDialog.Title) <> 0;
|
|
{$ENDIF CLR}
|
|
end;
|
|
|
|
procedure TJvFilenameEdit.PopupDropDown(DisableEdit: Boolean);
|
|
var
|
|
Temp: string;
|
|
Action: Boolean;
|
|
begin
|
|
Action := True;
|
|
Temp := FileName;
|
|
DoBeforeDialog(Temp, Action);
|
|
if not Action then
|
|
Exit;
|
|
if ValidFileName(Temp) then
|
|
try
|
|
if DirectoryExists(ExtractFilePath(Temp)) then
|
|
SetInitialDir(ExtractFilePath(Temp));
|
|
if (ExtractFileName(Temp) = '') or
|
|
not ValidFileName(ExtractFileName(Temp)) then
|
|
Temp := '';
|
|
FDialog.FileName := Temp;
|
|
except
|
|
{ ignore any exceptions }
|
|
end;
|
|
FDialog.HelpContext := Self.HelpContext;
|
|
DisableSysErrors;
|
|
try
|
|
Action := FDialog.Execute;
|
|
finally
|
|
EnableSysErrors;
|
|
end;
|
|
if Action then
|
|
Temp := FDialog.FileName;
|
|
if CanFocus then
|
|
SetFocus;
|
|
DoAfterDialog(Temp, Action);
|
|
if Action then
|
|
begin
|
|
if AddQuotes then
|
|
inherited Text := ExtFilename(Temp)
|
|
else
|
|
inherited Text := Temp;
|
|
SetInitialDir(ExtractFilePath(FDialog.FileName));
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFilenameEdit.ReceptFileDir(const AFileName: string);
|
|
begin
|
|
if FMultipleDirs then
|
|
begin
|
|
if FDialog.Files.Count = 0 then
|
|
SetFileName(AFileName);
|
|
FDialog.Files.Add(AFileName);
|
|
end
|
|
else
|
|
SetFileName(AFileName);
|
|
end;
|
|
|
|
procedure TJvFilenameEdit.SetDefaultExt(Value: TFileExt);
|
|
begin
|
|
FDialog.DefaultExt := Value;
|
|
end;
|
|
|
|
procedure TJvFilenameEdit.SetDialogKind(Value: TFileDialogKind);
|
|
begin
|
|
if FDialogKind <> Value then
|
|
begin
|
|
FDialogKind := Value;
|
|
CreateEditDialog;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFilenameEdit.SetDialogTitle(const Value: string);
|
|
begin
|
|
FDialog.Title := Value;
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
procedure TJvFilenameEdit.SetFileEditStyle(Value: TFileEditStyle);
|
|
begin
|
|
FDialog.FileEditStyle := Value;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
procedure TJvFilenameEdit.SetFileName(const Value: TFileName);
|
|
begin
|
|
if (Value = '') or ValidFileName(ClipFilename(Value, AddQuotes)) then
|
|
begin
|
|
if AddQuotes then
|
|
inherited Text := ExtFilename(Value)
|
|
else
|
|
inherited Text := Value;
|
|
ClearFileList;
|
|
end
|
|
else
|
|
{$IFDEF CLR}
|
|
raise EComboEditError.CreateFmt(SInvalidFilename, [Value]);
|
|
{$ELSE}
|
|
raise EComboEditError.CreateResFmt(@SInvalidFilename, [Value]);
|
|
{$ENDIF CLR}
|
|
end;
|
|
|
|
procedure TJvFilenameEdit.SetFilter(const Value: string);
|
|
begin
|
|
FDialog.Filter := Value;
|
|
end;
|
|
|
|
procedure TJvFilenameEdit.SetFilterIndex(Value: Integer);
|
|
begin
|
|
FDialog.FilterIndex := Value;
|
|
end;
|
|
|
|
procedure TJvFilenameEdit.SetHistoryList(Value: TStrings);
|
|
begin
|
|
FDialog.HistoryList := Value;
|
|
end;
|
|
|
|
procedure TJvFilenameEdit.SetInitialDir(const Value: string);
|
|
begin
|
|
FDialog.InitialDir := Value;
|
|
end;
|
|
|
|
procedure TJvFilenameEdit.SetOptions(Value: TOpenOptions);
|
|
begin
|
|
if Value <> FDialog.Options then
|
|
begin
|
|
FDialog.Options := Value;
|
|
FMultipleDirs := ofAllowMultiSelect in FDialog.Options;
|
|
if not FMultipleDirs then
|
|
ClearFileList;
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvPopupWindow } =====================================================
|
|
|
|
constructor TJvPopupWindow.Create(AOwner: TComponent);
|
|
begin
|
|
{$IFDEF VisualCLX}
|
|
// (p3) have to use CreateNew for VCL as well since there is no dfm
|
|
inherited CreateNew(AOwner);
|
|
{$ELSE}
|
|
inherited Create(AOwner);
|
|
{$ENDIF VisualCLX}
|
|
|
|
FEditor := AOwner as TWinControl;
|
|
ControlStyle := ControlStyle + [csNoDesignVisible, csReplicatable];
|
|
|
|
// If we were to add csAcceptsControls at design time, any attempt
|
|
// to paste a component while a component using TJvPopupWindow is active
|
|
// would lead to the parent of the pasted component being set to the
|
|
// TJvPopupWindow instead of the parent of the selected component.
|
|
// This was reported in issue 3042 and was seen in TJvCustomDateEdit
|
|
// descendents
|
|
if not (csDesigning in ComponentState) then
|
|
ControlStyle := ControlStyle + [csAcceptsControls];
|
|
Visible := False;
|
|
{$IFDEF VCL}
|
|
Ctl3D := False;
|
|
ParentCtl3D := False;
|
|
Parent := FEditor;
|
|
// use same size on small and large font:
|
|
//Scaled := False;
|
|
{$ENDIF VCL}
|
|
end;
|
|
|
|
procedure TJvPopupWindow.CloseUp(Accept: Boolean);
|
|
begin
|
|
if Assigned(FCloseUp) then
|
|
FCloseUp(Self, Accept);
|
|
end;
|
|
|
|
{$IFDEF CLR}
|
|
|
|
{ Allow this unit to access protected members of anchestors. }
|
|
procedure TJvPopupWindow.KeyDown(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
inherited KeyDown(Key, Shift);
|
|
end;
|
|
|
|
procedure TJvPopupWindow.KeyPress(var Key: Char);
|
|
begin
|
|
inherited KeyPress(Key);
|
|
end;
|
|
|
|
{$ENDIF CLR}
|
|
|
|
{$IFDEF VCL}
|
|
procedure TJvPopupWindow.CreateParams(var Params: TCreateParams);
|
|
begin
|
|
inherited CreateParams(Params);
|
|
with Params do
|
|
begin
|
|
Style := WS_POPUP or WS_BORDER or WS_CLIPCHILDREN;
|
|
ExStyle := WS_EX_TOOLWINDOW;
|
|
WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
|
|
end;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
function TJvPopupWindow.GetPopupText: string;
|
|
begin
|
|
Result := '';
|
|
end;
|
|
|
|
procedure TJvPopupWindow.Hide;
|
|
begin
|
|
{$IFDEF VCL}
|
|
SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_NOZORDER or
|
|
SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_HIDEWINDOW);
|
|
{$ENDIF VCL}
|
|
Visible := False;
|
|
end;
|
|
|
|
procedure TJvPopupWindow.InvalidateEditor;
|
|
var
|
|
R: TRect;
|
|
begin
|
|
if FEditor is TJvCustomComboEdit then
|
|
with TJvCustomComboEdit(FEditor) do
|
|
SetRect(R, 0, 0, ClientWidth - FBtnControl.Width {Polaris - 2}, ClientHeight + 1)
|
|
else
|
|
R := FEditor.ClientRect;
|
|
{$IFDEF CLR}
|
|
InvalidateRect(FEditor.Handle, R, False);
|
|
{$ELSE}
|
|
{$IFDEF VCL}
|
|
InvalidateRect(FEditor.Handle, @R, False);
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
FEditor.InvalidateRect(R, False);
|
|
{$ENDIF VisualCLX}
|
|
{$ENDIF CLR}
|
|
UpdateWindow(FEditor.Handle);
|
|
end;
|
|
|
|
procedure TJvPopupWindow.MouseUp(Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
if Button = mbLeft then
|
|
CloseUp(PtInRect(ClientRect, Point(X, Y)));
|
|
end;
|
|
|
|
{$IFDEF VisualCLX}
|
|
procedure TJvPopupWindow.SetParent(const Value: TWidgetControl);
|
|
var
|
|
Pt: TPoint;
|
|
R: TRect;
|
|
begin
|
|
Pt := Point(Left, Top);
|
|
R := BoundsRect;
|
|
inherited SetParent(Value);
|
|
if not (csDestroying in ComponentState) then
|
|
begin
|
|
QWidget_reparent(Handle, nil, 0, @Pt, Showing);
|
|
BoundsRect := R;
|
|
end;
|
|
end;
|
|
{$ENDIF VisualCLX}
|
|
|
|
procedure TJvPopupWindow.Show(Origin: TPoint);
|
|
begin
|
|
SetBounds(Origin.X, Origin.Y, Width, Height);
|
|
{$IFDEF VCL}
|
|
SetWindowPos(Handle, HWND_TOP, Origin.X, Origin.Y, 0, 0,
|
|
SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOSIZE);
|
|
{$ENDIF VCL}
|
|
Visible := True;
|
|
end;
|
|
|
|
{$IFDEF VisualCLX}
|
|
function TJvPopupWindow.WidgetFlags: Integer;
|
|
begin
|
|
Result := Integer(WidgetFlags_WType_Popup) or // WS_POPUP
|
|
Integer(WidgetFlags_WStyle_NormalBorder) or // WS_BORDER
|
|
Integer(WidgetFlags_WStyle_Tool); // WS_EX_TOOLWINDOW
|
|
end;
|
|
{$ENDIF VisualCLX}
|
|
|
|
{$IFDEF VCL}
|
|
procedure TJvPopupWindow.WMActivate(var Msg: TWMActivate);
|
|
begin
|
|
inherited;
|
|
if Msg.Active = WA_INACTIVE then
|
|
begin
|
|
if FEditor is TJvCustomComboEdit then
|
|
TJvCustomComboEdit(FEditor).AsyncPopupCloseUp(False)
|
|
else
|
|
CloseUp(False);
|
|
end;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
{$IFDEF VCL}
|
|
procedure TJvPopupWindow.WMMouseActivate(var Msg: TMessage);
|
|
begin
|
|
if FIsFocusable then
|
|
inherited
|
|
else
|
|
Msg.Result := MA_NOACTIVATE;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
initialization
|
|
{$IFDEF UNITVERSIONING}
|
|
RegisterUnitVersion(HInstance, UnitVersioning);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
finalization
|
|
{$IFNDEF CLR}
|
|
{$IFDEF VCL}
|
|
FreeAndNil(GDateHook);
|
|
{$ENDIF VCL}
|
|
FreeAndNil(GDefaultComboEditImagesList);
|
|
{$ENDIF !CLR}
|
|
{$IFDEF UNITVERSIONING}
|
|
UnregisterUnitVersion(HInstance);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
end.
|