diff --git a/components/jvcllaz/devtools/JvExVCL/Readme.txt b/components/jvcllaz/devtools/JvExVCL/Readme.txt new file mode 100644 index 000000000..133c51400 --- /dev/null +++ b/components/jvcllaz/devtools/JvExVCL/Readme.txt @@ -0,0 +1,16 @@ +Directory structure +------------------- +.\ preprocessed files +source\ source files that must be preprocessed + + +Files +----- +.\jpp.exe JCL pascal preprocessor +.\preprocess.bat preprocess the source\JvExXxx files +.\Readme.txt this file +source\dpp.exe Delphi language preprocessor (http://www.sf.net/projects/dpp32) +source\build.pas used for preprocessing +source\JvExControls.pas base system and interfaces +source\JvExXxx extended VCL classes for the VCL controls +source\JvExControls.macros macros used by the preprocessor diff --git a/components/jvcllaz/devtools/JvExVCL/preprocess.bat b/components/jvcllaz/devtools/JvExVCL/preprocess.bat new file mode 100644 index 000000000..28b9d975f --- /dev/null +++ b/components/jvcllaz/devtools/JvExVCL/preprocess.bat @@ -0,0 +1,37 @@ +@echo off + +SET OUTDIR=..\..\..\run + +cd src + + +SET FILE=.\build +if NOT "-%1" == "-" SET FILE=%1 +echo Preprocessing template: %FILE%.pas +dpp.exe .\%FILE%.pas -I..\..\..\common >NUL + +if "%FILE%" == ".\build" GOTO ALL + +move %FILE%.i.pas %OUTDIR%\%FILE%.pas + + +goto LEAVE +:ALL + +move JvExButtons.i.pas %OUTDIR%\JvExButtons.pas +move JvExCheckLst.i.pas %OUTDIR%\JvExCheckLst.pas +move JvExComCtrls.i.pas %OUTDIR%\JvExComCtrls.pas +move JvExControls.i.pas %OUTDIR%\JvExControls.pas +REM move JvExDBCtrls.i.pas %OUTDIR%\JvExDBCtrls.pas +move JvExDBGrids.i.pas %OUTDIR%\JvExDBGrids.pas +move JvExExtCtrls.i.pas %OUTDIR%\JvExExtCtrls.pas +move JvExForms.i.pas %OUTDIR%\JvExForms.pas +move JvExGrids.i.pas %OUTDIR%\JvExGrids.pas +move JvExMask.i.pas %OUTDIR%\JvExMask.pas +move JvExStdCtrls.i.pas %OUTDIR%\JvExStdCtrls.pas + +cd .. + +:LEAVE +SET FILE= +SET OUTDIR= diff --git a/components/jvcllaz/devtools/JvExVCL/src/JvExControls.macros b/components/jvcllaz/devtools/JvExVCL/src/JvExControls.macros new file mode 100644 index 000000000..b338ab4ce --- /dev/null +++ b/components/jvcllaz/devtools/JvExVCL/src/JvExControls.macros @@ -0,0 +1,594 @@ + +// This comment is inserted into every JvExXxx.pas file +(*$DEFINE WARNINGHEADER +{***************************************************************************** + * WARNING: Do not edit this file. + * This file is autogenerated from the source in devtools/JvExVCL/src. + * If you do it despite this warning your changes will be discarded by the next + * update of this file. Do your changes in the template files. + ****************************************************************************} +{$D-} // do not step into this unit +*) + +// ************************************************************************* +// *************************** INTERFACE MACROS **************************** +// ************************************************************************* + +(*$DEFINE COMMON_PUBLISHED + published + property BiDiMode; + property DragCursor; + property DragKind; + property DragMode; + property ParentBiDiMode; + property OnEndDock; + property OnStartDock; +*) + +// ****************** Control ************************ +(*$DEFINE CONTROL_DECL + private + // TODO: + // FAboutJVCL: TJVCLAboutInfo; + FHintColor: TColor; + FMouseOver: Boolean; + FHintWindowClass: THintWindowClass; + FOnMouseEnter: TNotifyEvent; + FOnMouseLeave: TNotifyEvent; + FOnParentColorChanged: TNotifyEvent; + function BaseWndProc(Msg: Integer; WParam: Integer = 0; LParam: Longint = 0): Integer; overload; + function BaseWndProc(Msg: Integer; WParam: Integer; LParam: TControl): Integer; overload; + function BaseWndProcEx(Msg: Integer; WParam: Integer; var LParam): Integer; + protected + procedure WndProc(var Msg: TLMessage); override; + procedure FocusChanged(AControl: TWinControl); dynamic; + procedure VisibleChanged; reintroduce; dynamic; + procedure EnabledChanged; reintroduce; dynamic; + procedure TextChanged; reintroduce; virtual; + procedure ColorChanged; reintroduce; dynamic; + procedure FontChanged; reintroduce; dynamic; + procedure ParentFontChanged; reintroduce; dynamic; + procedure ParentColorChanged; reintroduce; dynamic; + procedure ParentShowHintChanged; reintroduce; dynamic; + function WantKey(Key: Integer; Shift: TShiftState; const KeyText: WideString): Boolean; reintroduce; virtual; + function HintShow(var HintInfo: THintInfo): Boolean; reintroduce; dynamic; + function HitTest(X, Y: Integer): Boolean; reintroduce; virtual; + procedure MouseEnter(AControl: TControl); reintroduce; dynamic; + procedure MouseLeave(AControl: TControl); reintroduce; dynamic; + property MouseOver: Boolean read FMouseOver write FMouseOver; + property HintColor: TColor read FHintColor write FHintColor default clDefault; + property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter; + property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave; + property OnParentColorChange: TNotifyEvent read FOnParentColorChanged write FOnParentColorChanged; + function GetCaption: TCaption; virtual; + procedure SetCaption(Value: TCaption); virtual; + public + constructor Create(AOwner: TComponent); override; + property Caption: TCaption read GetCaption write SetCaption; + property HintWindowClass: THintWindowClass read FHintWindowClass write FHintWindowClass; + published + // TODO: + // property AboutJVCL: TJVCLAboutInfo read FAboutJVCL write FAboutJVCL stored False; +*) + +// ****************** WinControl ********************* +((*$DEFINE WINCONTROL_DECL + CONTROL_DECL + private + FDotNetHighlighting: Boolean; + protected + procedure BoundsChanged; reintroduce; virtual; + procedure CursorChanged; reintroduce; dynamic; + procedure ShowingChanged; reintroduce; dynamic; + procedure ShowHintChanged; reintroduce; dynamic; + procedure ControlsListChanging(Control: TControl; Inserting: Boolean); reintroduce; dynamic; + procedure ControlsListChanged(Control: TControl; Inserting: Boolean); reintroduce; dynamic; + procedure GetDlgCode(var Code: TDlgCodes); virtual; + procedure FocusSet(PrevWnd: THandle); virtual; + procedure FocusKilled(NextWnd: THandle); virtual; + function DoEraseBackground(ACanvas: TCanvas; Param: Integer): Boolean; virtual; + published + property DotNetHighlighting: Boolean read FDotNetHighlighting write FDotNetHighlighting default False; +*) + +// ****************** EditControl ******************** +(*$DEFINE EDITCONTROL_DECL + WINCONTROL_DECL + private + FClipboardCommands: TJvClipboardCommands; + protected + procedure SetClipboardCommands(const Value: TJvClipboardCommands); virtual; + property ClipboardCommands: TJvClipboardCommands read FClipboardCommands write SetClipboardCommands default [caCopy..caUndo]; +*) + +// ************************************************************************* +// ************************************************************************* + +// ****************** Default-Helpers ******************** + +// TJvEx##ClassName = class(T##ClassName, IJvExControl) +(*$DEFINE CONTROL_DECL_DEFAULT(ClassName) + TJvEx##ClassName = class(T##ClassName) + CONTROL_DECL + end; +*) + +// TJvEx##ClassName = class(T##ClassName, IJvExControl) +(*$DEFINE WINCONTROL_DECL_DEFAULT(ClassName) + TJvEx##ClassName = class(T##ClassName) + WINCONTROL_DECL + end; +*) + +// TJvEx##ClassName = class(T##ClassName, IJvExControl) +(*$DEFINE EDITCONTROL_DECL_DEFAULT(ClassName) + TJvEx##ClassName = class(T##ClassName) + EDITCONTROL_DECL + end; +*) + +// ************************************************************************* +// ************************ IMPLEMENTATION MACROS ************************** +// ************************************************************************* + +// ****************** Constructors ******************* +(*$DEFINE BEGIN_CONTROL_CONSTRUCTOR(ClassName) +constructor TJvEx##ClassName.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FHintColor := clDefault; +*) + +(*$DEFINE BEGIN_WINCONTROL_CONSTRUCTOR(ClassName) +BEGIN_CONTROL_CONSTRUCTOR(ClassName) +*) + +(*$DEFINE BEGIN_EDITCONTROL_CONSTRUCTOR(ClassName) +BEGIN_WINCONTROL_CONSTRUCTOR(ClassName) + FClipboardCommands := [caCopy..caUndo]; +*) + +(*$DEFINE END_CONSTRUCTOR +end; +*) + +// ****************** Control implementation ******************* +(*$DEFINE CONTROL_IMPL(ClassName) +function TJvEx##ClassName.BaseWndProc(Msg: Integer; WParam: Integer = 0; LParam: Longint = 0): Integer; +var + Mesg: TLMessage; +begin + Mesg := CreateWMMessage(Msg, WParam, LParam); + inherited WndProc(Mesg); + Result := Mesg.Result; +end; + +function TJvEx##ClassName.BaseWndProc(Msg: Integer; WParam: Integer; LParam: TControl): Integer; +var + Mesg: TLMessage; +begin + Mesg := CreateWMMessage(Msg, WParam, LParam); + inherited WndProc(Mesg); + Result := Mesg.Result; +end; + +function TJvEx##ClassName.BaseWndProcEx(Msg: Integer; WParam: Integer; var LParam): Integer; +var + Mesg: TStructPtrMessage; +begin + Mesg := TStructPtrMessage.Create(Msg, WParam, LParam); + try + inherited WndProc(Mesg.Msg); + finally + Result := Mesg.Msg.Result; + Mesg.Free; + end; +end; + +procedure TJvEx##ClassName.VisibleChanged; +begin + BaseWndProc(CM_VISIBLECHANGED); +end; + +procedure TJvEx##ClassName.EnabledChanged; +begin + BaseWndProc(CM_ENABLEDCHANGED); +end; + +procedure TJvEx##ClassName.TextChanged; +begin + BaseWndProc(CM_TEXTCHANGED); +end; + +procedure TJvEx##ClassName.FontChanged; +begin + BaseWndProc(CM_FONTCHANGED); +end; + +procedure TJvEx##ClassName.ColorChanged; +begin + BaseWndProc(CM_COLORCHANGED); +end; + +procedure TJvEx##ClassName.ParentFontChanged; +begin + // LCL doesn't send this message but left it in case + //BaseWndProc(CM_PARENTFONTCHANGED); +end; + +procedure TJvEx##ClassName.ParentColorChanged; +begin + BaseWndProc(CM_PARENTCOLORCHANGED); + if Assigned(OnParentColorChange) then + OnParentColorChange(Self); +end; + +procedure TJvEx##ClassName.ParentShowHintChanged; +begin + BaseWndProc(CM_PARENTSHOWHINTCHANGED); +end; + +function TJvEx##ClassName.WantKey(Key: Integer; Shift: TShiftState; const KeyText: WideString): Boolean; +begin + Result := BaseWndProc(CM_DIALOGCHAR, Word(Key), ShiftStateToKeyData(Shift)) <> 0; +end; + +function TJvEx##ClassName.HitTest(X, Y: Integer): Boolean; +begin + Result := BaseWndProc(CM_HITTEST, 0, SmallPointToLong(PointToSmallPoint(Point(X, Y)))) <> 0; +end; + +function TJvEx##ClassName.HintShow(var HintInfo: THintInfo): Boolean; +begin + GetHintColor(HintInfo, Self, FHintColor); + if FHintWindowClass <> nil then + HintInfo.HintWindowClass := FHintWindowClass; + Result := BaseWndProcEx(CM_HINTSHOW, 0, HintInfo) <> 0; +end; + +procedure TJvEx##ClassName.MouseEnter(AControl: TControl); +begin + FMouseOver := True; + if Assigned(FOnMouseEnter) then + FOnMouseEnter(Self); + BaseWndProc(CM_MOUSEENTER, 0, AControl); +end; + +procedure TJvEx##ClassName.MouseLeave(AControl: TControl); +begin + FMouseOver := False; + BaseWndProc(CM_MOUSELEAVE, 0, AControl); + if Assigned(FOnMouseLeave) then + FOnMouseLeave(Self); +end; + +procedure TJvEx##ClassName.FocusChanged(AControl: TWinControl); +begin + BaseWndProc(CM_FOCUSCHANGED, 0, AControl); +end; + +function TJvEx##ClassName.GetCaption: TCaption; +begin + Result := inherited Caption; +end; + +// 25.09.2007 - SESS: +// I have done this because TextChanged wasn't fired as expected. +// I still don't shure if this problem is only for this reintroduced +// method because the way LCL treats Caption or will have the same +// problem with other reintroduced methods. So far, I tested some +// other events and seems not. +procedure TJvEx##ClassName.SetCaption(Value: TCaption); +begin + inherited Caption := Value; + TextChanged; +end; +*) + +// ****************** WinControl implementation ******************* +((*$DEFINE WINCONTROL_IMPL(ClassName) +CONTROL_IMPL(ClassName) + +procedure TJvEx##ClassName.BoundsChanged; +begin +end; + +procedure TJvEx##ClassName.CursorChanged; +begin + BaseWndProc(CM_CURSORCHANGED); +end; + +procedure TJvEx##ClassName.ShowingChanged; +begin + BaseWndProc(CM_SHOWINGCHANGED); +end; + +procedure TJvEx##ClassName.ShowHintChanged; +begin + BaseWndProc(CM_SHOWHINTCHANGED); +end; + +{ VCL sends CM_CONTROLLISTCHANGE and CM_CONTROLCHANGE in a different order than + the CLX methods are used. So we must correct it by evaluating "Inserting". } +procedure TJvEx##ClassName.ControlsListChanging(Control: TControl; Inserting: Boolean); +begin + if Inserting then + BaseWndProc(CM_CONTROLLISTCHANGE, Integer(Control), Integer(Inserting)) + else + BaseWndProc(CM_CONTROLCHANGE, Integer(Control), Integer(Inserting)); +end; + +procedure TJvEx##ClassName.ControlsListChanged(Control: TControl; Inserting: Boolean); +begin + if not Inserting then + BaseWndProc(CM_CONTROLLISTCHANGE, Integer(Control), Integer(Inserting)) + else + BaseWndProc(CM_CONTROLCHANGE, Integer(Control), Integer(Inserting)); +end; + +procedure TJvEx##ClassName.GetDlgCode(var Code: TDlgCodes); +begin +end; + +procedure TJvEx##ClassName.FocusSet(PrevWnd: THandle); +begin + BaseWndProc(LM_SETFOCUS, Integer(PrevWnd), 0); +end; + +procedure TJvEx##ClassName.FocusKilled(NextWnd: THandle); +begin + BaseWndProc(LM_KILLFOCUS, Integer(NextWnd), 0); +end; + +function TJvEx##ClassName.DoEraseBackground(ACanvas: TCanvas; Param: Integer): Boolean; +begin + Result := BaseWndProc(LM_ERASEBKGND, ACanvas.Handle, Param) <> 0; +end; +*) + + +// ****************** EditControl implementation ******************* +(*$DEFINE EDITCONTROL_IMPL(ClassName) +WINCONTROL_IMPL(ClassName) + +procedure TJvEx##ClassName.SetClipboardCommands(const Value: TJvClipboardCommands); +begin + FClipboardCommands := Value; +end; +*) + +// ********************************************************************* +// ********************************************************************* + +// ****************** Control WndProc implementation ******************* +(*$DEFINE CONTROL_WNDPROC_CASES + { + // TODO: do we need this? I think not... + CM_DENYSUBCLASSING: + Msg.Result := Ord(GetInterfaceEntry(IJvDenySubClassing) <> nil); + } + CM_DIALOGCHAR: + with TCMDialogChar(Msg) do + Result := Ord(WantKey(CharCode, KeyDataToShiftState(KeyData), WideChar(CharCode))); + CM_HINTSHOW: + with TCMHintShow(Msg) do + Result := Integer(HintShow(HintInfo^)); + CM_HITTEST: + with TCMHitTest(Msg) do + Result := Integer(HitTest(XPos, YPos)); + CM_MOUSEENTER: + MouseEnter(TControl(Msg.LParam)); + CM_MOUSELEAVE: + MouseLeave(TControl(Msg.LParam)); + CM_VISIBLECHANGED: + VisibleChanged; + CM_ENABLEDCHANGED: + EnabledChanged; + // LCL doesn't send this message but left it in case + CM_TEXTCHANGED: + TextChanged; + CM_FONTCHANGED: + FontChanged; + CM_COLORCHANGED: + ColorChanged; + CM_FOCUSCHANGED: + FocusChanged(TWinControl(Msg.LParam)); + // LCL doesn't send this message but left it in case + //CM_PARENTFONTCHANGED: + // ParentFontChanged; + CM_PARENTCOLORCHANGED: + ParentColorChanged; + CM_PARENTSHOWHINTCHANGED: + ParentShowHintChanged; +*) + +(*$DEFINE CONTROL_WNDPROC(ClassName) +procedure TJvEx##ClassName.WndProc(var Msg: TLMessage); +begin + if not DispatchIsDesignMsg(Self, Msg) then + case Msg.Msg of + CONTROL_WNDPROC_CASES + else + inherited WndProc(Msg); + end; +end; +*) + +// ****************** WinControl WndProc implementation ******************* +(*$DEFINE WINCONTROL_WNDPROC_CASES + CONTROL_WNDPROC_CASES + CM_CURSORCHANGED: + CursorChanged; + CM_SHOWINGCHANGED: + ShowingChanged; + CM_SHOWHINTCHANGED: + ShowHintChanged; + CM_CONTROLLISTCHANGE: + if Msg.LParam <> 0 then + ControlsListChanging(TControl(Msg.WParam), True) + else + ControlsListChanged(TControl(Msg.WParam), False); + CM_CONTROLCHANGE: + if Msg.LParam = 0 then + ControlsListChanging(TControl(Msg.WParam), False) + else + ControlsListChanged(TControl(Msg.WParam), True); + LM_SETFOCUS: + FocusSet(THandle(Msg.WParam)); + LM_KILLFOCUS: + FocusKilled(THandle(Msg.WParam)); + LM_SIZE: + begin + inherited WndProc(Msg); + BoundsChanged; + end; + LM_ERASEBKGND: + if Msg.WParam <> 0 then + begin + IdSaveDC := SaveDC(HDC(Msg.WParam)); // protect DC against Stock-Objects from Canvas + WCanvas := TCanvas.Create; + try + WCanvas.Handle := HDC(Msg.WParam); + Msg.Result := Ord(DoEraseBackground(WCanvas, Msg.LParam)); + finally + WCanvas.Handle := 0; + WCanvas.Free; + RestoreDC(HDC(Msg.WParam), IdSaveDC); + end; + end + else + inherited WndProc(Msg); + LM_GETDLGCODE: + begin + inherited WndProc(Msg); + DlgCodes := [dcNative] + DlgcToDlgCodes(Msg.Result); + GetDlgCode(DlgCodes); + if not (dcNative in DlgCodes) then + Msg.Result := DlgCodesToDlgc(DlgCodes); + end; +*) + +(*$DEFINE WINCONTROL_WNDPROC(ClassName) +procedure TJvEx##ClassName.WndProc(var Msg: TLMessage); +var + IdSaveDC: Integer; + DlgCodes: TDlgCodes; + WCanvas: TCanvas; +begin + if not DispatchIsDesignMsg(Self, Msg) then + begin + case Msg.Msg of + WINCONTROL_WNDPROC_CASES + else + inherited WndProc(Msg); + end; + // TODO: + // LM_NCPAINT isn't send by LCL, may be .Net highlighting can't be implemented. + case Msg.Msg of // precheck message to prevent access violations on released controls + CM_MOUSEENTER, CM_MOUSELEAVE, LM_KILLFOCUS, LM_SETFOCUS, LM_NCPAINT: + if DotNetHighlighting then + HandleDotNetHighlighting(Self, Msg, MouseOver, Color); + end; + end; +end; +*) + +// ****************** EditControl WndProc implementation ******************* +(*$DEFINE EDITCONTROL_WNDPROC_CASES + WINCONTROL_WNDPROC_CASES + { + // TODO: convert to LCL messages + WM_CLEAR: + if caClear in ClipboardCommands then + inherited WndProc(Msg) + else + Msg.Result := 1; + WM_UNDO, EM_UNDO: + if caUndo in ClipboardCommands then + inherited WndProc(Msg) + else + Msg.Result := 1; + WM_COPY: + if caCopy in ClipboardCommands then + inherited WndProc(Msg) + else + Msg.Result := 1; + WM_CUT: + if caCut in ClipboardCommands then + inherited WndProc(Msg) + else + Msg.Result := 1; + WM_PASTE: + if caPaste in ClipboardCommands then + inherited WndProc(Msg) + else + Msg.Result := 1; + } +*) + +(*$DEFINE EDITCONTROL_WNDPROC(ClassName) +procedure TJvEx##ClassName.WndProc(var Msg: TLMessage); +var + IdSaveDC: Integer; + DlgCodes: TDlgCodes; + WCanvas: TCanvas; +begin + if not DispatchIsDesignMsg(Self, Msg) then + begin + case Msg.Msg of + EDITCONTROL_WNDPROC_CASES + else + inherited WndProc(Msg); + end; + // TODO: + // LM_NCPAINT isn't send by LCL, may be .Net highlighting can't be implemented. + case Msg.Msg of // precheck message to prevent access violations on released controls + CM_MOUSEENTER, CM_MOUSELEAVE, LM_KILLFOCUS, LM_SETFOCUS, LM_NCPAINT: + if DotNetHighlighting then + HandleDotNetHighlighting(Self, Msg, MouseOver, Color); + end; + end; +end; +*) + +// ************************************************************************* +// ************************************************************************* + +// ****************** Default-Helpers ******************** + +(*$DEFINE CONTROL_IMPL_DEFAULT(ClassName) +BEGIN_CONTROL_CONSTRUCTOR(ClassName) +END_CONSTRUCTOR + +CONTROL_IMPL(ClassName) + +CONTROL_WNDPROC(ClassName) + +//============================================================================ + +*) + +(*$DEFINE WINCONTROL_IMPL_DEFAULT(ClassName) +BEGIN_WINCONTROL_CONSTRUCTOR(ClassName) +END_CONSTRUCTOR + +WINCONTROL_IMPL(ClassName) + +WINCONTROL_WNDPROC(ClassName) + +//============================================================================ + +*) + +(*$DEFINE EDITCONTROL_IMPL_DEFAULT(ClassName) +BEGIN_EDITCONTROL_CONSTRUCTOR(ClassName) +END_CONSTRUCTOR + +EDITCONTROL_IMPL(ClassName) + +EDITCONTROL_WNDPROC(ClassName) + +//============================================================================ + +*) + diff --git a/components/jvcllaz/devtools/JvExVCL/src/JvExControls.pas b/components/jvcllaz/devtools/JvExVCL/src/JvExControls.pas new file mode 100644 index 000000000..602b0c46b --- /dev/null +++ b/components/jvcllaz/devtools/JvExVCL/src/JvExControls.pas @@ -0,0 +1,479 @@ +{----------------------------------------------------------------------------- +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: JvExControls.pas, released on 2004-01-04 + +The Initial Developer of the Original Code is Andreas Hausladen [Andreas dott Hausladen att gmx dott de] +Portions created by Andreas Hausladen are Copyright (C) 2004 Andreas Hausladen. +All Rights Reserved. + +Contributor(s): - + dejoy. + +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: +-----------------------------------------------------------------------------} +// $Id: JvExControls.pas 11400 2007-06-28 21:24:06Z ahuser $ +// Initial port to Lazarus by Sergio Samayoa - september 2007. +// Conversion is done in incremental way: as types / classes / routines +// are needed they are converted. +// TODO: Make this unit generated by template as JVCL's. + +{$mode objfpc}{$H+} + +unit JvExControls; +{MACROINCLUDE JvExControls.macros} + +{***************************************************************************** + * WARNING: Do not edit this file. + * This file is autogenerated from the source in devtools/JvExVCL/src. + * If you do it despite this warning your changes will be discarded by the next + * update of this file. Do your changes in the template files. + ****************************************************************************} +{$D-} // do not step into this unit + +interface + +uses + Classes, Controls, Graphics, LCLIntf, LCLType, LMessages, Forms; + +type + TDlgCode = + (dcWantAllKeys, dcWantArrows, dcWantChars, dcButton, dcHasSetSel, dcWantTab, + dcNative); // if dcNative is in the set the native allowed keys are used and GetDlgCode is ignored + TDlgCodes = set of TDlgCode; + +(******************** NOT CONVERTED +const + dcWantMessage = dcWantAllKeys; + +const + CM_DENYSUBCLASSING = JvThemes.CM_DENYSUBCLASSING; + CM_PERFORM = CM_BASE + $500 + 0; // LParam: "Msg: ^TMessage" + CM_SETAUTOSIZE = CM_BASE + $500 + 1; // WParam: "Value: Boolean" + +type + TJvHotTrackOptions = class; + + { IJvExControl is used for the identification of an JvExXxx control. } + IJvExControl = interface + ['{8E6579C3-D683-4562-AFAB-D23C8526E386}'] + end; + + { Add IJvDenySubClassing to the base class list if the control should not + be themed by the ThemeManager (http://www.soft-gems.net Mike Lischke). + This only works with JvExVCL derived classes. } + IJvDenySubClassing = interface + ['{76942BC0-2A6E-4DC4-BFC9-8E110DB7F601}'] + end; + + + { IJvHotTrack is Specifies whether Control are highlighted when the mouse passes over them} + IJvHotTrack = interface + ['{8F1B40FB-D8E3-46FE-A7A3-21CE4B199A8F}'] + + function GetHotTrack:Boolean; + function GetHotTrackFont:TFont; + function GetHotTrackFontOptions:TJvTrackFontOptions; + function GetHotTrackOptions:TJvHotTrackOptions; + + procedure SetHotTrack(Value: Boolean); + procedure SetHotTrackFont(Value: TFont); + procedure SetHotTrackFontOptions(Value: TJvTrackFontOptions); + procedure SetHotTrackOptions(Value: TJvHotTrackOptions); + + property HotTrack: Boolean read GetHotTrack write SetHotTrack; + property HotTrackFont: TFont read GetHotTrackFont write SetHotTrackFont; + property HotTrackFontOptions: TJvTrackFontOptions read GetHotTrackFontOptions write SetHotTrackFontOptions; + property HotTrackOptions: TJvHotTrackOptions read GetHotTrackOptions write SetHotTrackOptions; + end; + + TJvHotTrackOptions = class(TJvPersistentProperty) + private + FEnabled: Boolean; + FFrameVisible: Boolean; + FColor: TColor; + FFrameColor: TColor; + procedure SetColor(Value: TColor); + procedure SetEnabled(Value: Boolean); + procedure SetFrameColor(Value: TColor); + procedure SetFrameVisible(Value: Boolean); + public + constructor Create; virtual; + procedure Assign(Source: TPersistent); override; + published + property Enabled: Boolean read FEnabled write SetEnabled default False; + property Color: TColor read FColor write SetColor default $00D2BDB6; + property FrameVisible: Boolean read FFrameVisible write SetFrameVisible default False; + property FrameColor: TColor read FFrameColor write SetFrameColor default $006A240A; + end; +******************** NOT CONVERTED *) + +type + TStructPtrMessage = class(TObject) + private + public + Msg: TLMessage; + constructor Create(AMsg: Integer; WParam: Integer; var LParam); + end; + +//******************** NOT CONVERTED +//procedure SetDotNetFrameColors(FocusedColor, UnfocusedColor: TColor); + +procedure DrawDotNetControl(Control: TWinControl; AColor: TColor; InControl: Boolean); +procedure HandleDotNetHighlighting(Control: TWinControl; const Msg: TLMessage; + MouseOver: Boolean; Color: TColor); +function CreateWMMessage(Msg: Integer; WParam: Integer; LParam: Longint): TLMessage; overload; {$IFDEF SUPPORTS_INLINE} inline {$ENDIF} +function CreateWMMessage(Msg: Integer; WParam: Integer; LParam: TControl): TLMessage; overload; {$IFDEF SUPPORTS_INLINE} inline {$ENDIF} +function SmallPointToLong(const Pt: TSmallPoint): Longint; {$IFDEF SUPPORTS_INLINE} inline {$ENDIF} +function ShiftStateToKeyData(Shift: TShiftState): Longint; + +//******************** NOT CONVERTED +//function GetFocusedControl(AControl: TControl): TWinControl; + +function DlgcToDlgCodes(Value: Longint): TDlgCodes; +function DlgCodesToDlgc(Value: TDlgCodes): Longint; +procedure GetHintColor(var HintInfo: THintInfo; AControl: TControl; HintColor: TColor); +function DispatchIsDesignMsg(Control: TControl; var Msg: TLMessage): Boolean; + +type + //******************** NOT CONVERTED + //CONTROL_DECL_DEFAULT(Control) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(WinControl) + + WINCONTROL_DECL_DEFAULT(CustomControl) + + CONTROL_DECL_DEFAULT(GraphicControl) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(HintWindow) + +(******************** NOT CONVERTED + TJvExPubGraphicControl = class(TJvExGraphicControl) + COMMON_PUBLISHED + end; +******************** NOT CONVERTED *) + +implementation + +(******************** NOT CONVERTED +uses + TypInfo; + +var + InternalFocusedColor: TColor = TColor($00733800); + InternalUnfocusedColor: TColor = clGray; + +procedure SetDotNetFrameColors(FocusedColor, UnfocusedColor: TColor); +begin + InternalFocusedColor := FocusedColor; + InternalUnfocusedColor := UnfocusedColor; +end; +******************** NOT CONVERTED *) + +procedure DrawDotNetControl(Control: TWinControl; AColor: TColor; InControl: Boolean); +(******************** NOT CONVERTED +var + DC: HDC; + R: TRect; + Canvas: TCanvas; +begin + DC := GetWindowDC(Control.Handle); + try + GetWindowRect(Control.Handle, R); + OffsetRect(R, -R.Left, -R.Top); + Canvas := TCanvas.Create; + with Canvas do + try + Handle := DC; + Brush.Color := InternalUnfocusedColor; + if Control.Focused or InControl then + Brush.Color := InternalFocusedColor; + FrameRect(R); + InflateRect(R, -1, -1); + if not (Control.Focused or InControl) then + Brush.Color := AColor; + FrameRect(R); + finally + Free; + end; + finally + ReleaseDC(Control.Handle, DC); + end; +end; +******************** NOT CONVERTED *) +begin +end; + +procedure HandleDotNetHighlighting(Control: TWinControl; const Msg: TLMessage; + MouseOver: Boolean; Color: TColor); +(******************** NOT CONVERTED +var + Rgn, SubRgn: HRGN; +begin + if not (csDesigning in Control.ComponentState) then + case Msg.Msg of + CM_MOUSEENTER, CM_MOUSELEAVE, WM_KILLFOCUS, WM_SETFOCUS, WM_NCPAINT: + begin + DrawDotNetControl(Control, Color, MouseOver); + if Msg.Msg = CM_MOUSELEAVE then + begin + Rgn := CreateRectRgn(0, 0, Control.Width - 1, Control.Height - 1); + SubRgn := CreateRectRgn(2, 2, Control.Width - 3, Control.Height - 3); + try + CombineRgn(Rgn, Rgn, SubRgn, RGN_DIFF); + InvalidateRgn(Control.Handle, Rgn, False); // redraw 3D border + finally + DeleteObject(SubRgn); + DeleteObject(Rgn); + end; + end; + end; + end; +end; +******************** NOT CONVERTED *) +begin +end; + +function CreateWMMessage(Msg: Integer; WParam: Integer; LParam: Longint): TLMessage; +begin + Result.Msg := Msg; + Result.WParam := WParam; + Result.LParam := LParam; + Result.Result := 0; +end; + +function CreateWMMessage(Msg: Integer; WParam: Integer; LParam: TControl): TLMessage; +begin + Result := CreateWMMessage(Msg, WParam, Integer(LParam)); +end; + +{ TStructPtrMessage } +constructor TStructPtrMessage.Create(AMsg: Integer; WParam: Integer; var LParam); +begin + inherited Create; + Self.Msg.Msg := AMsg; + Self.Msg.WParam := WParam; + Self.Msg.LParam := Longint(@LParam); + Self.Msg.Result := 0; +end; + +function SmallPointToLong(const Pt: TSmallPoint): Longint; +begin + Result := Longint(Pt); +end; + +function ShiftStateToKeyData(Shift: TShiftState): Longint; +const + AltMask = $20000000; + CtrlMask = $10000000; + ShiftMask = $08000000; +begin + Result := 0; + if ssAlt in Shift then + Result := Result or AltMask; + if ssCtrl in Shift then + Result := Result or CtrlMask; + if ssShift in Shift then + Result := Result or ShiftMask; +end; + +(******************** NOT CONVERTED +function GetFocusedControl(AControl: TControl): TWinControl; +var + Form: TCustomForm; +begin + Result := nil; + Form := GetParentForm(AControl); + if Assigned(Form) then + Result := Form.ActiveControl; +end; +******************** NOT CONVERTED *) + +function DlgcToDlgCodes(Value: Longint): TDlgCodes; +begin + Result := []; +(******************** NOT CONVERTED + if (Value and DLGC_WANTARROWS) <> 0 then + Include(Result, dcWantArrows); + if (Value and DLGC_WANTTAB) <> 0 then + Include(Result, dcWantTab); + if (Value and DLGC_WANTALLKEYS) <> 0 then + Include(Result, dcWantAllKeys); + if (Value and DLGC_WANTCHARS) <> 0 then + Include(Result, dcWantChars); + if (Value and DLGC_BUTTON) <> 0 then + Include(Result, dcButton); + if (Value and DLGC_HASSETSEL) <> 0 then + Include(Result, dcHasSetSel); +******************** NOT CONVERTED *) +end; + +function DlgCodesToDlgc(Value: TDlgCodes): Longint; +begin + Result := 0; +(******************** NOT CONVERTED + if dcWantAllKeys in Value then + Result := Result or DLGC_WANTALLKEYS; + if dcWantArrows in Value then + Result := Result or DLGC_WANTARROWS; + if dcWantTab in Value then + Result := Result or DLGC_WANTTAB; + if dcWantChars in Value then + Result := Result or DLGC_WANTCHARS; + if dcButton in Value then + Result := Result or DLGC_BUTTON; + if dcHasSetSel in Value then + Result := Result or DLGC_HASSETSEL; +******************** NOT CONVERTED *) +end; + +procedure GetHintColor(var HintInfo: THintInfo; AControl: TControl; HintColor: TColor); +var + AHintInfo: THintInfo; +begin + case HintColor of + clNone: + HintInfo.HintColor := Application.HintColor; + clDefault: + begin + if Assigned(AControl) and Assigned(AControl.Parent) then + begin + AHintInfo := HintInfo; + AControl.Parent.Perform(CM_HINTSHOW, 0, Integer(@AHintInfo)); + HintInfo.HintColor := AHintInfo.HintColor; + end; + end; + else + HintInfo.HintColor := HintColor; + end; +end; + +function DispatchIsDesignMsg(Control: TControl; var Msg: TLMessage): Boolean; +var + Form: TCustomForm; +begin + Result := False; + case Msg.Msg of + LM_SETFOCUS, LM_KILLFOCUS, LM_NCHITTEST, + LM_MOUSEFIRST..LM_MOUSELAST, + LM_KEYFIRST..LM_KEYLAST, + LM_CANCELMODE: + Exit; // These messages are handled in TWinControl.WndProc before IsDesignMsg() is called + end; + if (Control <> nil) and (csDesigning in Control.ComponentState) then + begin + Form := GetParentForm(Control); + if (Form <> nil) and (Form.Designer <> nil) and + Form.Designer.IsDesignMsg(Control, Msg) then + Result := True; + end; +end; + +(******************** NOT CONVERTED +//=== { TJvHotTrackOptions } ====================================== + +constructor TJvHotTrackOptions.Create; +begin + inherited Create; + FEnabled := False; + FFrameVisible := False; + FColor := $00D2BDB6; + FFrameColor := $006A240A; +end; + +procedure TJvHotTrackOptions.Assign(Source: TPersistent); +begin + if Source is TJvHotTrackOptions then + begin + BeginUpdate; + try + Enabled := TJvHotTrackOptions(Source).Enabled; + Color := TJvHotTrackOptions(Source).Color; + FrameVisible := TJvHotTrackOptions(Source).FrameVisible; + FrameColor := TJvHotTrackOptions(Source).FrameColor; + finally + EndUpdate; + end; + end + else + inherited Assign(Source); +end; + +procedure TJvHotTrackOptions.SetColor(Value: TColor); +begin + if FColor <> Value then + begin + Changing; + ChangingProperty('Color'); + FColor := Value; + ChangedProperty('Color'); + Changed; + end; +end; + +procedure TJvHotTrackOptions.SetEnabled(Value: Boolean); +begin + if FEnabled <> Value then + begin + Changing; + ChangingProperty('Enabled'); + FEnabled := Value; + ChangedProperty('Enabled'); + Changed; + end; +end; + +procedure TJvHotTrackOptions.SetFrameVisible(Value: Boolean); +begin + if FFrameVisible <> Value then + begin + Changing; + ChangingProperty('FrameVisible'); + FFrameVisible := Value; + ChangedProperty('FrameVisible'); + Changed; + end; +end; + +procedure TJvHotTrackOptions.SetFrameColor(Value: TColor); +begin + if FFrameColor <> Value then + begin + Changing; + ChangingProperty('FrameColor'); + FFrameColor := Value; + ChangedProperty('FrameColor'); + Changed; + end; +end; +******************** NOT CONVERTED *) + +//============================================================================ + +//******************** NOT CONVERTED +//CONTROL_IMPL_DEFAULT(Control) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(WinControl) + +CONTROL_IMPL_DEFAULT(GraphicControl) + +WINCONTROL_IMPL_DEFAULT(CustomControl) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(HintWindow) + +end. + diff --git a/components/jvcllaz/devtools/JvExVCL/src/JvExExtCtrls.pas b/components/jvcllaz/devtools/JvExVCL/src/JvExExtCtrls.pas new file mode 100644 index 000000000..e93ca879d --- /dev/null +++ b/components/jvcllaz/devtools/JvExVCL/src/JvExExtCtrls.pas @@ -0,0 +1,163 @@ +{----------------------------------------------------------------------------- +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: JvExExtCtrls.pas, released on 2004-01-04 + +The Initial Developer of the Original Code is Andreas Hausladen [Andreas dott Hausladen att gmx dott de] +Portions created by Andreas Hausladen are Copyright (C) 2004 Andreas Hausladen. +All Rights Reserved. + +Contributor(s): - + +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: +-----------------------------------------------------------------------------} +// $Id: JvExExtCtrls.pas 10613 2006-05-19 19:21:43Z jfudickar $ + +// Initial port to Lazarus by Sergio Samayoa - september 2007. +// Conversion is done in incremental way: as types / classes / routines +// are needed they are converted. + +unit JvExExtCtrls; + +{MACROINCLUDE JvExControls.macros} + +WARNINGHEADER + +interface + +uses + Classes, Controls, ExtCtrls, Forms, Graphics, JvExControls, LCLIntf, LMessages; + +type + //******************** NOT CONVERTED + //CONTROL_DECL_DEFAULT(Shape) + + //******************** NOT CONVERTED + //CONTROL_DECL_DEFAULT(PaintBox) + + //******************** NOT CONVERTED + //CONTROL_DECL_DEFAULT(Image) + + //******************** NOT CONVERTED + //CONTROL_DECL_DEFAULT(Bevel) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(CustomPanel) + + (******************** NOT CONVERTED + TJvExPubCustomPanel = class(TJvExCustomPanel) + COMMON_PUBLISHED + end; + ******************** NOT CONVERTED *) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(CustomRadioGroup) + + CONTROL_DECL_DEFAULT(Splitter) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(CustomControlBar) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(ControlBar) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(Panel) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(RadioGroup) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(Page) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(Notebook) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(Header) + + + //******************** NOT CONVERTED + //CONTROL_DECL_DEFAULT(BoundLabel) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(CustomLabeledEdit) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(LabeledEdit) + + //******************** NOT CONVERTED - Exists in LCL? + //WINCONTROL_DECL_DEFAULT(CustomColorBox) + + //******************** NOT CONVERTED - Exists in LCL? + //WINCONTROL_DECL_DEFAULT(ColorBox) + +implementation + +//******************** NOT CONVERTED +//CONTROL_IMPL_DEFAULT(Shape) + +//******************** NOT CONVERTED +//CONTROL_IMPL_DEFAULT(PaintBox) + +//******************** NOT CONVERTED +//CONTROL_IMPL_DEFAULT(Image) + +//******************** NOT CONVERTED +//CONTROL_IMPL_DEFAULT(Bevel) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(CustomPanel) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(CustomRadioGroup) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(CustomControlBar) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(ControlBar) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(Panel) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(RadioGroup) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(Page) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(Notebook) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(Header) + +//******************** NOT CONVERTED +//CONTROL_IMPL_DEFAULT(BoundLabel) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(CustomLabeledEdit) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(LabeledEdit) + +//******************** NOT CONVERTED - Exists in LCL? +//WINCONTROL_IMPL_DEFAULT(CustomColorBox) + +//******************** NOT CONVERTED - Exists in LCL? +//WINCONTROL_IMPL_DEFAULT(ColorBox) + +CONTROL_IMPL_DEFAULT(Splitter) + +end. diff --git a/components/jvcllaz/devtools/JvExVCL/src/build.pas b/components/jvcllaz/devtools/JvExVCL/src/build.pas new file mode 100644 index 000000000..5eea37346 --- /dev/null +++ b/components/jvcllaz/devtools/JvExVCL/src/build.pas @@ -0,0 +1,19 @@ +unit build; +interface +uses + JvExControls + // ,JvExButtons + // ,JvExCheckLst + // ,JvExComCtrls + // ,JvExExtCtrls + // ,JvExForms + // ,JvExGrids, + // ,JvExMask, + // {,JvExDBCtrls} + // ,JvExDBGrids, + // ,JvExStdCtrls + ; + +implementation + +end. diff --git a/components/jvcllaz/dist/readme.txt b/components/jvcllaz/dist/readme.txt new file mode 100644 index 000000000..7db7ca556 --- /dev/null +++ b/components/jvcllaz/dist/readme.txt @@ -0,0 +1 @@ +Output directory for distribution packaging. \ No newline at end of file diff --git a/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemo.lpi b/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemo.lpi new file mode 100644 index 000000000..ce959d9ed --- /dev/null +++ b/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemo.lpi @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemo.lpr b/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemo.lpr new file mode 100644 index 000000000..d3ff7b73e --- /dev/null +++ b/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemo.lpr @@ -0,0 +1,18 @@ +program JvNavPaneDemo; + +{$mode objfpc}{$H+} + +uses + {$IFDEF UNIX}{$IFDEF UseCThreads} + cthreads, + {$ENDIF}{$ENDIF} + Interfaces, // this includes the LCL widgetset + Forms + { add your units here }, JvNavPaneDemoMainForm; + +begin + Application.Initialize; + Application.CreateForm(TJvNavPaneDemoMainFrm, JvNavPaneDemoMainFrm); + Application.Run; +end. + diff --git a/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemoMainForm.lfm b/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemoMainForm.lfm new file mode 100644 index 000000000..2f935786b --- /dev/null +++ b/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemoMainForm.lfm @@ -0,0 +1,776 @@ +object JvNavPaneDemoMainFrm: TJvNavPaneDemoMainFrm + Left = 105 + Height = 468 + Top = 109 + Width = 518 + HorzScrollBar.Page = 517 + VertScrollBar.Page = 467 + Caption = 'JvNavigationPane Demo' + DockSite = True + Font.Height = -11 + Font.Name = 'Tahoma' + OnCreate = FormCreate + object PopupMenu1: TPopupMenu + OnPopup = PopupMenu1Popup + left = 92 + top = 64 + object HideAll1: TMenuItem + Caption = 'Hide All' + OnClick = HideAll1Click + end + object ShowAll1: TMenuItem + Caption = 'Show All' + OnClick = ShowAll1Click + end + object N1: TMenuItem + Caption = '-' + end + object ChangeFont1: TMenuItem + Caption = 'Font...' + OnClick = ChangeFont1Click + end + object Colors1: TMenuItem + Caption = 'Colors' + object Standard1: TMenuItem + Caption = 'Standard' + Checked = True + GroupIndex = 1 + RadioItem = True + OnClick = SchemaClick + end + object Blue1: TMenuItem + Tag = 1 + Caption = 'Blue' + GroupIndex = 1 + RadioItem = True + OnClick = SchemaClick + end + object Silver1: TMenuItem + Tag = 2 + Caption = 'Silver' + GroupIndex = 1 + RadioItem = True + OnClick = SchemaClick + end + object Olive1: TMenuItem + Tag = 3 + Caption = 'Olive' + GroupIndex = 1 + RadioItem = True + OnClick = SchemaClick + end + end + object BackgroundImage1: TMenuItem + Caption = 'Background Image...' + OnClick = BackgroundImage1Click + end + object N2: TMenuItem + Caption = '-' + end + object Dontallowresize1: TMenuItem + Caption = 'Don''t allow resize' + OnClick = Dontallowresize1Click + end + object N3: TMenuItem + Caption = '-' + end + object ShowToolPanel1: TMenuItem + Caption = 'Show Tool Panel' + OnClick = ShowToolPanel1Click + end + object ShowCloseButton1: TMenuItem + Caption = 'Show Close Button' + OnClick = ShowCloseButton1Click + end + end + object LargeImages: TImageList + Height = 20 + Width = 24 + left = 92 + top = 16 + Bitmap = { + 4C69060000001800000014000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000CEB59CFFC6AD9CFFCEAD + 9CFFCEAD9CFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000BDBDBDFFE7C6B5FFC6F7FFFFC6F7FFFFADE7 + F7FFC6AD9CFFCEAD9CFF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000CEAD9CFFDED6CEFFC6EFFFFFC6EFFFFFC6F7FFFFADE7 + F7FF7BD6F7FF8CC6D6FFAD9484FF000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000BDBDBDFFCEBDB5FFC6F7FFFFC6EFFFFFC6F7FFFFC6F7FFFFC6EFFFFF8CE7 + FFFF7BDEF7FF6BC6F7FF6BCEF7FFAD9484FF0000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000CEAD + 9CFFDED6CEFFC6EFFFFFC6F7FFFFC6EFFFFFC6F7FFFFC6EFFFFFADE7F7FF8CE7 + F7FF84D6F7FF63CEF7FF6BC6F7FF4ABDF7FFBDBDBDFF849CA5FF000000000000 + 0000000000000000000000000000000000000000000000000000CEAD9CFFC6F7 + FFFFC6F7FFFFC6EFFFFFC6F7FFFFA5E7F7FF94E7FFFF7BD6F7FF7BD6F7FF84D6 + F7FF7BD6F7FF6BC6F7FF6BCEF7FF4AB5EFFF52B5F7FF4ABDF7FFAD9484FF0000 + 00000000000000000000000000000000000000000000C6AD9CFFC6F7FFFFADE7 + F7FFA5E7F7FF94E7F7FF7BD6F7FF6BC6F7FF63CEF7FF52B5EFFF4ABDF7FF4AB5 + F7FF52BDF7FF31B5DEFF39ADF7FF31A5EFFF21A5EFFF39A5EFFF39ADF7FFA57B + 6BFF0000000000000000000000000000000000000000CEAD9CFF63C6F7FFF7EF + EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F7 + E7FFF7EFEFFFF7F7EFFFF7EFEFFFADE7F7FFADE7EFFF94C6D6FF31ADEFFF9C7B + 6BFF0000000000000000000000000000000000000000D6AD84FF7BD6F7FFF7F7 + EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7EF + EFFFEFEFEFFFF7EFE7FFEFEFEFFFF7F7EFFFF7EFEFFFDEC6ADFF31A5F7FF9C7B + 6BFF4A4231FF00000000000000000000000000000000CEADA5FFC6AD9CFFFFDE + C6FFFFFFFFFFF7DECEFFFFDEC6FFF7F7EFFFFFDECEFFFFDEC6FFFFDECEFFF7DE + C6FFF7F7EFFFF7EFEFFFEFF7EFFFF7EFEFFFEFEFEFFFD6BDADFFA57B6BFF9C7B + 6BFF4A4231FF00000000000000000000000000000000D6AD84FFFFDECEFFC6AD + 9CFFFFFFFFFFF7F7EFFFD6CECEFFDED6CEFFD6D6CEFFD6D6CEFFDED6CEFFD6D6 + CEFFDEBDADFFDEC6ADFFE7C6ADFFD6CECEFFF7F7EFFF9C7B6BFFE7AD8CFF9C7B + 6BFF4A4231FF00000000000000000000000000000000D6A58CFFFFFFFFFFFFE7 + CEFFC6AD9CFFFFFFFFFFFFFFFFFFCEA584FFD6A58CFFD6A584FFAD948CFFAD94 + 8CFFAD948CFFAD948CFFF7EFEFFFF7F7EFFF9C736BFFE7BD94FFFFCEA5FF9C7B + 6BFF4A4231FF00000000000000000000000000000000CE9C7BFFFFFFFFFFEFEF + EFFFF7F7EFFFC6AD9CFFD6A58CFFFFE7CEFFEFEFEFFFF7F7EFFFF7EFEFFFF7F7 + EFFFEFEFEFFFF7D6B5FF9C7B6BFFAD948CFFEFB594FFF7D6BDFFFFCE9CFF9C7B + 6BFF4A4231FF00000000000000000000000000000000AD9484FFF7EFEFFFEFF7 + EFFFF7EFEFFFD6A584FFEFF7EFFFF7EFEFFFEFEFEFFFF7EFEFFFEFEFEFFFEFEF + EFFFFFE7C6FFFFDECEFFFFCEA5FF9C7B6BFFFFCE9CFFFFCE9CFFF7C68CFF9C7B + 6BFF4A4231FF00000000000000000000000000000000AD948CFFF7F7EFFFF7EF + EFFFCEA584FFF7F7EFFFF7EFEFFFEFEFEFFFF7F7E7FFEFEFEFFFF7F7EFFFFFDE + C6FFF7D6C6FFF7DEBDFFF7D6B5FFF7C68CFF9C7B6BFFF7B58CFFF7A573FF9C7B + 6BFF4A4231FF00000000000000000000000000000000AD9484FFF7EFEFFFC6AD + 9CFFEFEFEFFFF7EFEFFFEFEFEFFFF7F7EFFFF7DEC6FFFFDECEFFF7DEC6FFF7D6 + C6FFF7D6B5FFF7D6BDFFFFCE9CFFF7C68CFFFFAD8CFF9C7B6BFFE7946BFF9C7B + 6BFF4A4231FF00000000000000000000000000000000AD9484FFC6B59CFFF7F7 + EFFFF7EFEFFFEFF7EFFFFFDEC6FFF7D6BDFFF7D6BDFFF7D6B5FFF7D6BDFFF7CE + ADFFFFCE9CFFFFCEA5FFF7BD8CFFE7B594FFF7A573FFE7946BFF9C7B6BFF9C7B + 6BFF4A4231FF00000000000000000000000000000000C69C7BFFFFDEC6FFEFEF + EFFFFFDEC6FFF7D6BDFFFFCE9CFFF7C68CFFE7B594FFF7AD8CFFF7B58CFFF7A5 + 73FFEFA57BFFF7A573FFE79C63FFE79463FFE79C6BFFE79463FFCE7B4AFF9C7B + 6BFF4A4231FF00000000000000000000000000000000CE9C7BFF9C7B6BFF9C7B + 6BFF9C7B6BFF9C7B6BFF9C7B6BFF9C7B6BFF9C7B6BFF9C7B6BFF9C7B6BFF9C7B + 6BFF9C7B6BFF9C7B6BFF9C7B6BFF9C7B6BFF9C7B6BFF9C7B6BFF9C7B6BFF9C7B + 6BFF4A4231FF00000000000000000000000000000000000000004A4231FF4A42 + 31FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A42 + 31FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A42 + 31FF4A4231FF0000000000000000000000004A3931FF000000004A3929FF0000 + 00004A3931FF000000004A3931FF000000004A3931FF000000004A3929FF0000 + 00004A3931FF000000004A3931FF000000004A3931FF000000004A3931FF0000 + 00004A3931FF0000000000000000AD948CFF00000000AD948CFF00000000AD94 + 8CFF00000000AD948CFF00000000A57B6BFF000000009C7B6BFF00000000A57B + 6BFF00000000A57B6BFF000000006B6352FF00000000735A52FF000000006B5A + 52FF000000000000000000000000E7AD8CFFE7B58CFFE7B58CFFF7A573FFDEA5 + 7BFFDEAD84FFDEA57BFFE79C63FFE7946BFFE79463FFEF9C6BFFE79463FFD684 + 5AFFD68452FFD6845AFFDE7B4AFFE77B4AFFDE7B4AFFDE7B4AFFE77B4AFFDE7B + 4AFF4A4231FF0000000000000000E7B58CFFFFDECEFFF7DECEFFFFDECEFFF7DE + C6FFFFD6BDFFF7D6BDFFF7CEB5FFF7CEB5FFF7CEB5FFF7BD9CFFF7BDA5FFF7BD + 9CFFF7B58CFFF7B58CFFF7B58CFFF7A57BFFF7A573FFF7A57BFFF7A573FFE794 + 6BFF4A4231FF0000000000000000E7AD8CFFF7DEC6FFFFDEBDFFF7DEC6FFF7CE + ADFFEFCEB5FFF7CEADFFFFCE9CFFF7BD9CFFEFBD9CFFF7B58CFFF7B58CFFF7B5 + 8CFFF7A573FFF7A573FFF7A573FFEFA573FFF7A57BFFE79C63FFE7946BFFE79C + 63FF4A4231FF0000000000000000F7A573FFF7A573FFF7A57BFFDEA57BFFDEA5 + 7BFFDEA57BFFE79463FFE7946BFFE79463FFE79C6BFFE79463FFD68452FFCE84 + 52FFD68452FFDE7B4AFFDE7B4AFFDE7B4AFFDE7B4AFFDE7B4AFF4A4231FF4A42 + 31FF4A4231FF0000000000000000CEBDB5FFFFFFFFFFFFFFFFFFFFFFFFFFEFBD + 9CFFFFFFFFFFFFFFFFFFFFFFFFFFEFC69CFFFFFFFFFFF7EFEFFFF7F7F7FFEFBD + 9CFFFFFFFFFFEFEFF7FFF7F7EFFFEFBD9CFFF7EFEFFFF7F7EFFFFFDECEFFE7BD + 9CFF4A4231FF0000000000000000CEBDADFFFFFFFFFFEFF7EFFFF7EFEFFFE7BD + 9CFFFFFFFFFFF7EFEFFFF7F7EFFFCEA58CFFF7EFEFFFEFF7EFFFF7DECEFFD6A5 + 84FFEFEFEFFFF7EFEFFFF7DEC6FFD6A584FFEFEFEFFFF7DECEFFF7CEB5FFCE9C + 7BFF4A4231FF0000000000000000CEBDADFFFFFFFFFFF7EFEFFFEFEFEFFFD6A5 + 84FFFFFFFFFFEFF7EFFFFFDECEFFC69C7BFFF7EFEFFFFFDEC6FFF7DECEFFC69C + 7BFFF7F7EFFFF7D6BDFFF7CEADFFC69C7BFFFFDECEFFF7CEADFFFFCE9CFFC69C + 7BFF4A4231FF0000000000000000CEAD9CFFE7BD9CFFEFBD94FFCEA584FFD6AD + 8CFFE7B594FFE7AD8CFFCE9C7BFFC69C7BFFE7BD94FFD6A584FFCE9C7BFF398C + D6FF428CD6FF398CD6FF1842CEFF1842CEFFE7BD94FFD6A58CFFC69C7BFFA57B + 73FF4A4231FF0000000000000000C6B59CFFFFFFFFFFFFFFFFFFF7EFEFFFE7B5 + 94FFFFFFFFFFF7F7EFFFEFEFEFFFEFB594FFEFEFEFFFF7F7EFFFEFEFEFFF428C + D6FFF7F7EFFFF7EFEFFFFFE7CEFF1839CEFFFFE7CEFFF7DEC6FFFFE7CEFFE7B5 + 94FF4A4231FF0000000000000000C6ADA5FFFFFFFFFFF7EFEFFFEFF7EFFFD6A5 + 8CFFFFFFFFFFF7EFEFFFF7E7CEFFD6A58CFFEFEFEFFFF7EFEFFFFFE7C6FF398C + D6FFFFDECEFFF7D6BDFFFFDEBDFF1042CEFFFFDECEFFF7D6BDFFF7CEB5FFCE9C + 7BFF4A4231FF0000000000000000C6AD9CFFFFFFFFFFF7F7EFFFF7DECEFFCE9C + 7BFFEFF7EFFFFFDEC6FFF7D6BDFFCE9C7BFFEFF7EFFFFFDECEFFF7D6B5FF1839 + CEFFFFDEBDFFF7D6BDFFF7CEADFF1842CEFFFFDEBDFFEFC6A5FFEFBD9CFFC69C + 7BFF4A3931FF0000000000000000CEB59CFFE7B594FFD6A584FFC69C7BFFCE9C + 7BFFE7B594FFCEA58CFFCE9C7BFFC69C7BFFEFB594FFCEA58CFFCE9C7BFF1842 + CEFF1042CEFF1842CEFF1842CEFF1042D6FFE7AD8CFFC69C7BFFAD948CFFA57B + 6BFF4A4231FF0000000000000000C6ADA5FFFFFFFFFFF7F7EFFFF7EFEFFFE7B5 + 94FFF7F7EFFFF7F7EFFFEFEFEFFFE7BD94FFF7EFEFFFFFE7CEFFF7DECEFFEFBD + 94FFFFDECEFFFFE7CEFFFFDEBDFFEFB594FFF7DEC6FFFFDEC6FFF7CEADFFE7B5 + 9CFF4A4231FF0000000000000000C6B59CFFF7EFEFFFEFEFEFFFF7F7EFFFCEA5 + 8CFFF7EFEFFFF7DEC6FFFFDECEFFD6A584FFF7DECEFFF7D6BDFFFFDEBDFFC69C + 7BFFFFDECEFFF7D6BDFFF7CEB5FFC69C7BFFFFD6BDFFEFCEB5FFFFCE9CFFCE9C + 7BFF4A3931FF0000000000000000D6A58CFFF7F7EFFFEFEFEFFFF7DEBDFFCE9C + 7BFFEFF7EFFFF7D6C6FFF7CEADFFC69C7BFFFFE7CEFFF7D6BDFFFFCEA5FFC69C + 7BFFF7DEBDFFF7CEB5FFF7BD9CFFC69C7BFFF7CEB5FFF7BD9CFFE7BD94FFCE9C + 7BFF4A4231FF0000000000000000CEA58CFFF7D6B5FFE7B594FFD6A58CFFC69C + 7BFFE7AD8CFFCE9C7BFFAD948CFF9C7B6BFFE7AD8CFFCE9C7BFFAD948CFF9C7B + 6BFFE7AD8CFFC69C7BFFAD948CFF9C7B6BFFE7B58CFFC69C7BFFAD948CFFA57B + 73FF4A3931FF0000000000000000D6A58CFF4A4231FF4A4231FF4A4231FF4A42 + 31FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A42 + 31FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A42 + 31FF4A4231FF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000CEBDADFFCEBDB5FFD6BD + ADFFCEBDADFFCEBDADFFCEBDADFFD6BDB5FFCEBDADFFCEAD9CFFC6B5A5FFCEAD + 9CFFC6B59CFFC6AD9CFFC6B59CFFCEAD9CFFC6B59CFFD6A58CFFCEA584FFD6A5 + 8CFFAD948CFFAD9484FFAD948CFF0000000000000000D6BDADFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFEFEFEFFFF7F7EFFF4A4231FF0000000000000000CEBDADFFFFFFFFFFFFFF + FFFFF7EFEFFFB5BDBDFFAD948CFF6B7B8CFF6B848CFFBDBDBDFFF7EFEFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F7EFFFF7EF + EFFFEFF7EFFFFFD6C6FF4A4231FF0000000000000000CEBDB5FFFFFFFFFFFFFF + FFFFBDBDBDFF6B848CFF6B7B8CFF8C9CA5FFAD948CFF6B5A52FFB5BDBDFFFFFF + FFFFFFFFFFFFF7AD8CFFF7B58CFFF7B58CFFF7A573FFF7A57BFFEFA573FFF7A5 + 73FFEFEFEFFFFFDEC6FF4A4231FF0000000000000000CEBDADFFFFFFFFFFFFFF + FFFF6B7B8CFF6B5A52FF736352FF6B848CFF6B5A52FFBDBDBDFF6B7B8CFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFEFEFFFF7F7EFFFEFEFEFFFF7F7 + EFFFEFEFEFFFF7D6B5FF4A4231FF0000000000000000D6BDADFFFFFFFFFFFFFF + FFFF736352FF4A3931FFBDBDBDFFDED6D6FFBDBDBDFF8C9CA5FF6B848CFFFFFF + FFFFFFFFFFFFFFB58CFFF7AD8CFFF7B58CFFF7A573FFEFA573FFF7A573FFF7A5 + 73FFF7EFEFFFF7CEADFF4A4231FF0000000000000000CEBDADFFFFFFFFFFFFFF + FFFF4A3931FF4A4231FFDED6D6FFB5B5BDFF849CA5FF6B7B8CFF6B6352FFFFFF + FFFFFFFFFFFFEFF7EFFFF7EFEFFFF7F7EFFFEFEFEFFFF7EFEFFFEFEFEFFFF7F7 + EFFFEFEFEFFFF7BD9CFF4A4231FF0000000000000000CEADA5FFFFFFFFFFFFFF + FFFFBDBDBDFF000000FFBDBDBDFF8C9CA5FF6B848CFF735A52FF849CA5FFF7EF + EFFFF7F7EFFFF7EFEFFFF7EFEFFFEFEFEFFFF7EFEFFFEFF7EFFFF7EFEFFFEFEF + EFFFFFE7CEFFF7BDA5FF4A4231FF0000000000000000C6AD9CFFFFFFFFFFFFFF + FFFFF7F7EFFFDECECEFF6B5A52FF6B6352FF735A52FF1842D6FFBDBDBDFFF7F7 + EFFFEFEFEFFFEFEFE7FFF7F7EFFFEFEFEFFFF7F7EFFFF7EFEFFFF7DEC6FFFFDE + C6FFF7DECEFFEFB594FF4A4231FF0000000000000000CEAD9CFFFFFFFFFFFFFF + FFFFB5CEDEFF1842CEFF1842CEFFDED6D6FFF7F7EFFF1842CEFF1839CEFFD6D6 + CEFFF7EFEFFFC69C7BFFCE9C7BFF9C7B6BFF9C736BFF9C7B6BFF9C7B6BFF9C7B + 6BFFF7E7C6FFFFB58CFF4A4231FF0000000000000000C6AD9CFFFFFFFFFFFFFF + FFFF1842CEFF84ADC6FF398CD6FF1842CEFF1884BDFF1842CEFF188CC6FF1842 + CEFFF7F7EFFFF7EFEFFFEFEFEFFFF7F7EFFFFFDEC6FFFFE7CEFFFFDECEFFFFD6 + C6FFF7DEC6FFF7A573FF4A4231FF0000000000000000CEB5A5FFFFFFFFFFFFFF + FFFF1842CEFF39ADEFFF428CD6FF428CD6FF1842CEFF188CBDFF1842CEFF315A + 73FFF7EFEFFFC69C7BFFA57B6BFF9C7B6BFF9C7B6BFF9C7B6BFF9C7B6BFF9C73 + 6BFFF7DEC6FFF7A573FF4A4231FF0000000000000000C6AD9CFFFFFFFFFFFFFF + FFFF1842CEFF188CBDFF428CD6FF428CD6FF1842CEFF188CC6FF2142CEFF3963 + 7BFFF7F7EFFFFFDECEFFF7DEC6FFFFDECEFFFFDECEFFFFDEC6FFF7DEBDFFFFDE + C6FFF7D6B5FFF7A57BFF4A4231FF0000000000000000C6AD9CFFFFFFFFFFF7F7 + EFFFDED6CEFF1842CEFF1842CEFF1842CEFF1842CEFF396373FF39637BFFCEBD + ADFFFFDECEFF9C7B6BFFA57B6BFF9C7B6BFF9C7B6BFF9C736BFF9C7B6BFF9C73 + 6BFFF7CEB5FFE79463FF4A4231FF0000000000000000D6A58CFFF7F7EFFFF7EF + EFFFF7EFEFFFF7F7EFFFF7F7EFFFF7F7EFFFF7F7EFFFF7EFEFFFFFDECEFFFFE7 + C6FFF7DECEFFFFDECEFFF7DEBDFFFFDEC6FFF7DEC6FFFFD6BDFFF7CEADFFF7CE + B5FFF7CEADFFE79463FF4A4231FF0000000000000000CEA584FFF7EFEFFFF7DE + C6FFF7D6C6FFF7DEC6FFF7CEBDFFF7D6B5FFF7C6ADFFEFC6ADFFF7BD9CFFEFBD + 9CFFE7B594FFE7B58CFFF7AD8CFFF7A573FFF7A573FFEFA573FFF7A57BFFE794 + 63FFE79463FFEF9C6BFF4A4231FF0000000000000000D6A58CFF4A4231FF4A42 + 31FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A42 + 31FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A4231FF4A42 + 31FF4A4231FF4A4231FF4A4231FF000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000849CA5FF849CA5FF849CA5FF8C9C + A5FF6B7B8CFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000DEC6B5FFCEBD + ADFFD6BDADFFCEBDB5FFCEBDADFF8C9CA5FF8CC6D6FFC6EFFFFFC6F7FFFFADE7 + F7FF8CC6D6FF6B7B8CFFCEAD9CFFC6B5A5FFCEAD9CFFC6AD9CFFC6ADA5FF0000 + 00000000000000000000000000000000000000000000CEBDADFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFF7EFEFFF849CA5FFC6F7FFFF6B7B8CFF6B7B8CFF8C9C + A5FF8CC6CEFF31637BFFCEAD9CFFF7F7EFFFEFEFEFFFF7F7EFFFF7EFEFFF849C + A5FF0000000000000000000000000000000000000000D6BDADFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF8C9CA5FF8CBDD6FFADF7FFFF6B848CFF84ADC6FF8CC6 + D6FF6BCEF7FF6B7B8CFF31637BFFFFDEC6FFEFEFEFFFF7F7EFFFB5CED6FF395A + 7BFF0000000000000000000000000000000000000000CEBDADFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF849CA5FFADE7F7FFADE7EFFF8CBDD6FF8CC6CEFF8CC6 + CEFF84ADC6FF84ADC6FF6B848CFFFFDEC6FFEFEFEFFFB5CED6FF1842CEFF428C + D6FF0000000000000000000000000000000000000000D6BDB5FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF6B848CFF6B7B8CFF6B7B8CFF396373FF39637BFF395A + 7BFF396373FF6B7B8CFFAD948CFFFFDEBDFFA5ADF7FF1842CEFF428CD6FFCEA5 + 8CFF0000000000000000000000000000000000000000CEBDADFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F7EFFFF7F7EFFFFFDECEFFF7DEC6FFFFD6 + B5FFEFC6ADFFF7D6BDFFFFDEC6FFA5ADF7FF398CD6FF428CD6FFFFE7C6FF9C7B + 6BFF0000000000000000000000000000000000000000CEBDB5FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFEF + EFFFF7F7EFFFF7EFEFFFB5CED6FF1842CEFF1842CEFFB5CED6FFFFDECEFF9C7B + 6BFF0000000000000000000000000000000000000000D6BDADFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7EFEFFFF7EF + EFFFEFEFEFFFA5ADF7FF398CD6FF1842CEFFBDBDBDFFFFDECEFFF7D6BDFF6B5A + 52FF0000000000000000000000000000000000000000CEBDADFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7EFEFFFEFEFEFFFF7F7 + EFFFA5B5F7FF428CD6FF1842CEFF84ADBDFFFFDECEFFFFE7C6FFF7C6ADFF6B63 + 52FF0000000000000000000000000000000000000000CEBDADFFFFFFFFFFFFFF + FFFFA5ADFFFFB5CED6FFFFFFFFFFFFFFFFFFFFFFFFFFEFEFEFFFF7F7E7FFA5AD + F7FF398CD6FF1842CEFF8C9CA5FFDED6CEFFF7DECEFFF7DEBDFFF7BD9CFF6B5A + 52FF0000000000000000000000000000000000000000CEBDB5FFF7F7EFFFA5AD + F7FF428CD6FF398CD6FFA5ADF7FFFFFFFFFFF7EFEFFFF7F7EFFFA5ADF7FF428C + D6FF1842CEFF398CD6FFFFDEC6FFF7E7CEFFFFD6BDFFF7DEC6FFEFBD9CFF6B63 + 52FF0000000000000000000000000000000000000000E7BDADFFA5E7F7FF1842 + CEFF1842CEFF1842CEFFADB5F7FFA5ADF7FFEFF7EFFFA5ADF7FF398CD6FF1842 + CEFF1842CEFFE7D6CEFFFFDECEFFF7D6BDFFF7DEC6FFF7CEADFFE7AD8CFF6B5A + 52FF0000000000000000000000000000000000000000CEAD9CFFFFFFFFFFADB5 + F7FF1842CEFF1842CEFF1842CEFFA5ADF7FFA5ADF7FF428CD6FF1842CEFF1842 + CEFFBDBDBDFFFFE7C6FFF7D6C6FFF7DEBDFFF7D6C6FFF7C6ADFFE7B58CFF4A42 + 31FF0000000000000000000000000000000000000000C6B59CFFFFFFFFFFFFFF + FFFFBDCED6FF1842CEFF1842CEFF1842CEFF428CD6FF1842CEFF1842CEFF428C + D6FFFFDECEFFF7DECEFFF7DEBDFFFFD6C6FFF7D6B5FFEFC6ADFFF7B58CFF4A39 + 31FF0000000000000000000000000000000000000000CEAD9CFFFFFFFFFFFFFF + FFFFF7EFEFFFBDD6DEFF1842CEFF2142CEFF1842CEFF1842CEFF1842CEFFDED6 + CEFFF7DEC6FFFFDEBDFFF7D6C6FFF7D6B5FFF7CEB5FFEFC6A5FFF7A573FF4A39 + 31FF0000000000000000000000000000000000000000C6AD9CFFFFFFFFFFF7F7 + EFFFEFEFEFFFF7EFEFFFB5CED6FF1842CEFF1842CEFF2142CEFFD6C6ADFFF7D6 + BDFFF7D6BDFFF7CEADFFEFC6ADFFF7C6ADFFF7BD9CFFE7BD94FFF7A57BFF4A42 + 31FF0000000000000000000000000000000000000000CEAD9CFFEFF7EFFFFFD6 + C6FFF7D6BDFFEFC6A5FFF7CEADFF8C9CA5FF1842CEFFAD9C8CFFE7B594FFE7AD + 8CFFE7AD8CFFE7AD8CFFF7B58CFFF7B58CFFEFA573FFF7A57BFFEF9463FF4A42 + 31FF0000000000000000000000000000000000000000CEAD8CFF9C736BFF6B5A + 52FF6B6352FF735A52FF6B5A52FF6B6352FFA57B6BFF6B5A52FF736352FF6B5A + 52FF4A4231FF4A4231FF4A3931FF4A4231FF4A3931FF4A4231FF4A4231FF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000000000008CC6D6FF8CBD + D6FF8CC6D6FF8CC6CEFF8CBDD6FF8CC6CEFF8CC6D6FF8CBDD6FF8CC6CEFF94BD + D6FF7BADC6FF84ADC6FF7BADC6FF84ADC6FF7BADBDFF84ADC6FF7BADC6FF84AD + BDFF7BADC6FF00000000000000000000000000000000000000008CC6CEFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFF395A7BFF000000000000000000000000000000000000000094BDD6FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFF39637BFF00000000000000000000000000000000000000008CC6D6FFFFFF + FFFFCEF7FFFFC6EFFFFFC6F7FFFFCEF7FFFFC6EFFFFFC6F7FFFFC6F7FFFFC6F7 + FFFFC6F7FFFFC6F7FFFFC6F7FFFFC6F7FFFFC6F7FFFFC6F7FFFFC6F7FFFFC6F7 + FFFF395A7BFF00000000000000000000000000000000000000008CC6CEFFC6EF + FFFFA5F7FFFFA5F7FFFFADEFFFFFA5F7FFFFA5F7FFFFADF7FFFFA5EFFFFFADF7 + FFFFA5EFFFFFADF7FFFFA5EFFFFFADF7FFFFA5EFFFFFADF7FFFFA5EFFFFFADF7 + FFFF396373FF00000000000000000000000000000000000000008CC6D6FFC6F7 + FFFFADF7FFFFA5F7F7FFADF7FFFFA5F7F7FFADEFFFFFA5F7F7FFADF7FFFFA5F7 + F7FFADF7FFFFA5F7F7FFADF7FFFFA5F7F7FFADF7FFFFA5F7FFFFADF7FFFFA5F7 + FFFF315A73FF00000000000000000000000000000000000000008CC6CEFFC6EF + FFFFA5EFFFFFADF7FFFFA5EFFFFFADF7FFFFA5F7FFFFA5F7FFFFADF7FFFFA5EF + FFFFA5F7FFFFADF7FFFFA5EFFFFFA5F7FFFFADF7FFFFA5EFFFFFA5F7F7FFADF7 + FFFF39637BFF00000000000000000000000000000000000000007BADBDFF94E7 + FFFF8CE7F7FFA5F7FFFFADF7F7FFA5F7FFFFADEFF7FFA5F7FFFFADF7F7FFA5F7 + FFFFADF7F7FFA5EFFFFFADF7F7FFA5F7FFFFADF7F7FFA5F7FFFFADF7FFFFA5F7 + FFFF395A73FF000000000000000000000000000000000000000084ADBDFF8CE7 + FFFF94E7F7FFA5F7FFFFADEFFFFFA5F7FFFFA5F7FFFFADF7FFFFA5F7FFFFA5EF + FFFFADF7FFFFA5F7FFFFA5F7FFFFADF7FFFFA5EFFFFFADF7F7FFA5EFFFFFADF7 + FFFF31637BFF00000000000000000000000000000000000000007BADC6FF84D6 + F7FF8CE7FFFF8CE7F7FF8CE7F7FF94E7F7FF8CDEFFFF8CE7F7FF94E7F7FF8CE7 + F7FF8CE7FFFF94DEF7FF8CE7F7FF8CE7FFFF8CE7F7FF8CE7FFFF94E7F7FF8CE7 + FFFF395A73FF000000000000000000000000000000000000000084ADBDFF63C6 + F7FF94E7F7FF8CE7FFFF94E7FFFF8CE7F7FF8CE7FFFF94E7F7FF8CDEFFFF94E7 + FFFF8CE7F7FF94E7FFFF8CE7F7FF94DEFFFF8CE7F7FF94E7FFFF8CE7F7FF94E7 + FFFF31637BFF00000000000000000000000000000000000000007BADC6FF52BD + F7FF7BD6F7FF94E7F7FF8CDEFFFF94E7F7FF8CE7FFFF8CE7F7FF94E7FFFF8CE7 + F7FF8CE7FFFF8CE7F7FF94E7FFFF8CE7F7FF94E7FFFF8CDEF7FF8CE7FFFF94E7 + F7FF395A73FF000000000000000000000000000000000000000084ADBDFF319C + CEFF39B5E7FF4ABDEFFF4AB5F7FF39B5DEFF39B5E7FF84D6F7FF8CE7F7FF8CDE + FFFF94E7F7FF8CE7FFFF94DEF7FF8CE7FFFF8CE7F7FF94E7FFFF8CE7F7FF94E7 + FFFF31637BFF000000000000000000000000000000000000000084ADC6FF39B5 + E7FF39B5DEFF39B5E7FF39B5E7FF39B5DEFF00A5DEFF6BCEF7FF7BD6F7FF84D6 + F7FF7BD6F7FF84D6F7FF7BD6F7FF7BD6F7FF84D6F7FF7BD6F7FF7BD6F7FF84D6 + F7FF315A7BFF000000000000000000000000000000000000000084ADBDFF6BCE + F7FF00A5DEFF39B5E7FF39B5DEFF39B5E7FF00A5DEFF39B5E7FF84D6F7FF7BD6 + FFFF84DEF7FF7BD6F7FF84DEF7FF7BD6FFFF84DEF7FF7BD6F7FF84D6FFFF7BDE + F7FF39637BFF00000000000000000000000000000000000000007BADC6FF6BCE + F7FF39B5DEFF1884BDFF39B5E7FF39B5DEFF39ADEFFF00A5DEFF6BCEF7FF7BD6 + F7FF7BD6F7FF84D6F7FF7BD6F7FF84D6F7FF7BD6F7FF84DEF7FF7BD6F7FF84D6 + F7FF31637BFF000000000000000000000000000000000000000084ADBDFF63C6 + F7FF6BCEF7FF52BDF7FF00A5DEFF1884BDFF08A5DEFF00A5DEFF219CEFFF6BCE + F7FF63C6F7FF84DEF7FF7BD6FFFF7BDEF7FF84D6F7FF7BD6FFFF7BD6F7FF84D6 + F7FF39637BFF00000000000000000000000000000000000000007BADC6FF6BCE + F7FF63C6F7FF6BCEF7FF6BCEF7FF4ABDF7FF299CEFFF319CCEFF08A5DEFF319C + CEFF39ADEFFF39B5E7FF4AB5EFFF52BDF7FF63C6F7FF6BCEF7FF6BCEF7FF63CE + F7FF395A73FF000000000000000000000000000000000000000084ADC6FF3963 + 73FF395A7BFF396373FF395A7BFF395A73FF39637BFF396373FF39637BFF3963 + 73FF39637BFF39637BFF395A73FF39637BFF396373FF395A7BFF396373FF395A + 7BFF39637BFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000000000008494A5FF849C + A5FF849CA5FF8C9CA5FF849CADFF849CA5FF8C9CA5FF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000008C9CA5FFB5CEDEFFCEF7 + FFFFC6F7FFFFC6EFFFFFADF7FFFFADE7F7FFB5CED6FF849CA5FF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000008494A5FF84ADC6FFB5CED6FFB5CE + D6FFB5CEDEFFB5CED6FF8CBDCEFF8CC6D6FF8CBDCEFF84ADC6FF849CA5FF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000008C9CA5FF849CA5FF8C9CADFF849C + A5FF8C9CA5FF849CA5FF8C9CA5FF8C9CA5FF6B848CFF6B7B8CFF6B848CFF6B7B + 8CFF6B848CFF6B7B8CFF6B7B8CFF6B7B8CFF6B7B8CFF6B7B8CFF6B7B8CFF6B7B + 8CFF6B7B8CFF000000000000000000000000849CADFFCEF7FFFFC6EFFFFFC6F7 + FFFFC6EFFFFFC6F7FFFFC6F7FFFFADE7F7FFADE7F7FFADE7F7FFADE7F7FF7BD6 + F7FF84DEF7FF7BD6F7FF84DEF7FF7BDEF7FF6BCEF7FF6BCEF7FF63CEF7FF6BCE + F7FF84ADC6FF6B7B8CFF0000000000000000849CA5FFC6EFFFFFC6F7FFFFC6EF + FFFFADE7F7FFADE7F7FFADDEF7FFADE7F7FF8CE7F7FF7BD6F7FF7BDEF7FF6BC6 + F7FF63CEF7FF6BC6F7FF63CEF7FF52B5F7FF4AB5F7FF4AB5F7FF39B5DEFF39B5 + E7FF319CCEFF39637BFF0000000000000000849CA5FFC6F7FFFFC6EFFFFFADF7 + FFFFA5E7EFFFADE7F7FFA5E7EFFF8CE7F7FF84D6F7FF7BD6F7FF6BC6F7FF6BCE + F7FF6BC6F7FF6BCEF7FF4AB5EFFF52BDF7FF4ABDEFFF39B5DEFF39B5E7FF319C + CEFF31A5CEFF735A52FF00000000000000008C9CA5FFC6EFFFFFA5F7FFFFADE7 + EFFFADE7F7FFA5E7EFFF94E7FFFF7BD6F7FF84D6FFFF7BD6F7FF6BCEF7FF63C6 + F7FF6BCEF7FF4AB5EFFF52BDF7FF4AB5EFFF39B5E7FF39B5E7FF39B5E7FF399C + CEFF319CCEFF39637BFF0000000000000000849CA5FFC6F7FFFFADE7F7FFADDE + F7FFA5E7EFFFADE7F7FF8CE7F7FF84D6F7FF7BDEF7FF6BC6F7FF6BCEF7FF63CE + F7FF6BC6F7FF4ABDF7FF52B5EFFF4ABDF7FF39B5DEFF39B5E7FF39ADEFFF319C + CEFF188CC6FF523931FF00000000000000008C9CA5FFC6EFFFFFADE7EFFFA5E7 + F7FFADE7EFFF94E7FFFF7BD6F7FF84D6F7FF63C6F7FF6BCEF7FF63C6F7FF6BCE + F7FF4AB5EFFF52BDF7FF4AB5EFFF39B5E7FF39B5DEFF39B5E7FF31ADEFFF399C + CEFF188CC6FF4A4231FF0000000000000000849CA5FFC6F7FFFFADE7F7FFADDE + EFFF8CE7FFFF7BD6F7FF7BD6F7FF84DEF7FF63C6F7FF6BCEF7FF6BC6F7FF4ABD + EFFF52B5F7FF4ABDEFFF39B5E7FF39B5E7FF39B5DEFF39A5F7FF39ADEFFF319C + CEFF1884BDFF524231FF00000000000000008C9CA5FFC6EFFFFFADE7F7FFA5E7 + EFFF94E7FFFF7BD6F7FF84D6F7FF63C6F7FF6BCEF7FF6BCEF7FF4AB5EFFF52BD + F7FF4AB5F7FF39B5DEFF39B5E7FF39B5DEFF31ADF7FF39ADEFFF319CCEFF399C + CEFF188CC6FF4A4231FF0000000000000000849CA5FFADE7F7FFA5E7EFFF94E7 + FFFF7BD6F7FF84D6F7FF63CEF7FF6BCEF7FF6BC6F7FF63CEF7FF52B5F7FF4ABD + EFFF39B5E7FF39B5DEFF39B5E7FF39A5EFFF39ADEFFF319CCEFF39A5CEFF1884 + C6FF188CBDFF4A3931FF00000000000000008494A5FFADE7F7FF8CE7FFFF7BD6 + F7FF84D6F7FF63CEF7FF6BC6F7FF6BCEF7FF63C6F7FF52BDF7FF4AB5EFFF39B5 + E7FF39B5DEFF39B5E7FF31ADEFFF39ADF7FF319CCEFF399CD6FF319CCEFF188C + BDFF1884C6FF4A4231FF0000000000000000849CA5FFADE7F7FF7BD6F7FF84D6 + F7FF7BDEF7FF6BC6F7FF63CEF7FF6BC6F7FF4ABDEFFF52B5EFFF4ABDF7FF39B5 + DEFF39B5E7FF39A5EFFF39ADEFFF319CCEFF39A5CEFF319CCEFF39A5CEFF1884 + C6FF188CBDFF000000FF0000000000000000849CA5FFADE7F7FF84D6F7FF7BDE + F7FF6BC6F7FF6BCEF7FF63C6F7FF6BCEF7FF52BDF7FF4AB5F7FF39B5DEFF39B5 + E7FF39B5E7FF39ADEFFF31ADF7FF399CCEFF319CCEFF399CCEFF31A5CEFF1884 + BDFF188CC6FF000000FF0000000000000000849CADFFADE7EFFF7BD6F7FF6BC6 + F7FF4ABDF7FF4AB5EFFF52BDEFFF4AB5F7FF39B5DEFF39ADEFFF319CCEFF399C + CEFF319CCEFF319CCEFF399CCEFF31A5CEFF1884C6FF188CC6FF1884BDFF188C + C6FF1884BDFF000000FF00000000000000008C9CA5FFADE7F7FF4AB5F7FF4ABD + F7FF84ADBDFF39B5E7FF319CCEFF399CCEFF319CCEFF319CCEFF1884BDFF188C + C6FF1884BDFF188CC6FF188CBDFF1884C6FF188CBDFF1884BDFF188CC6FF1884 + BDFF188CC6FF000000FF00000000000000006B7B8CFF396373FF39637BFF5239 + 29FF4A4231FF524231FF4A4231FF524231FF4A4231FF524231FF000000FF0000 + 00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000 + 00FF000000FF000000FF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000 + } + end + object SmallImages: TImageList + left = 40 + top = 16 + Bitmap = { + 4C69060000001000000010000000000000000000000000000000000000000000 + 000000000000CEBDADFFC6ADA5FFC6AD9CFFC6ADA5FF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000008CBD + CEFFC6ADA5FFEFE7DEFFC6F7FFFFC6F7FFFFBDC6CEFFCEBDADFF000000000000 + 0000000000000000000000000000000000000000000000000000CEBDB5FFCEBD + ADFFC6EFFFFFC6F7FFFFC6EFFFFFADE7EFFF8CE7FFFF63CEF7FFC6AD9CFF8C9C + A5FF0000000000000000000000000000000000000000CEBDADFFC6D6DEFFC6F7 + FFFFC6F7FFFFC6EFFFFFADEFFFFFA5E7EFFF7BD6F7FF6BC6F7FF63CEF7FF8CBD + D6FFC6AD9CFF84ADC6FF00000000C6AD9CFFCEB5ADFFC6F7FFFFC6EFFFFFC6EF + FFFFC6F7FFFFA5EFFFFFADE7EFFF7BD6F7FF63C6F7FF6BCEF7FF6BC6EFFF6BCE + F7FF4AB5EFFF8CADC6FF8C9CA5FFC6AD9CFFADF7FFFFA5E7F7FFADE7EFFFADE7 + EFFF7BD6F7FF6BC6F7FF63CEF7FF6BCEF7FF6BCEEFFF4AADEFFF42B5EFFF4AAD + E7FF42B5EFFF29BDEFFFBD9C8CFFC6ADA5FFADE7EFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7EFE7FFFFF7EFFFFFEFE7FFFFF7 + EFFFEFDEDEFF42B5EFFF94847BFFC6AD9CFFCEBDB5FFF7EFEFFFFFEFE7FFE7E7 + DEFFFFEFEFFFFFEFE7FFF7F7EFFFFFEFE7FFF7EFEFFFFFEFE7FFF7DECEFFF7F7 + E7FFFFD6C6FF94847BFF94847BFFC6ADA5FFF7CEB5FFDEC6ADFFF7EFEFFFFFEF + EFFFE7BD94FFE7B594FFC6ADA5FFC6AD9CFFC6ADA5FFC6AD9CFFE7E7DEFFFFDE + C6FFB59C8CFFE7AD84FF94847BFFC6A58CFFFFFFFFFFFFDEC6FFDEC6ADFFDEC6 + ADFFDEBDADFFDECEC6FFDEC6ADFFDEC6B5FFDEC6ADFFC6ADA5FFC6AD9CFFB59C + 8CFFE7AD8CFFFFD69CFF8C8484FFBDA594FFFFFFFFFFFFFFFFFFBDA58CFFDECE + C6FFFFF7EFFFF7EFEFFFFFF7EFFFF7EFEFFFFFDECEFFFFDEC6FFDEA57BFFB58C + 73FFFFD69CFFFFCE94FF94847BFFC6A58CFFFFFFFFFFC6ADA5FFDECEC6FFF7EF + EFFFF7EFE7FFFFEFEFFFF7EFE7FFFFF7E7FFF7DEC6FFF7DEC6FFFFD6ADFFE7AD + 84FFB58473FFFFB57BFFCE734AFFB59C8CFFC6ADA5FFDECEC6FFFFFFFFFFF7F7 + E7FFFFDECEFFF7E7C6FFFFDECEFFF7DEC6FFFFD6ADFFFFDEB5FFFFD69CFFFFCE + 94FFE79463FFC67B4AFFCE7342FFBD9C84FFF7D6BDFFFFFFFFFFFFDECEFFFFDE + ADFFFFD69CFFFFC68CFFFFC68CFFFFC694FFFFB57BFFFFB57BFFF7A57BFFEFA5 + 7BFFE79463FFD6845AFFB56331FFB59C8CFFB59C8CFFB58C73FFB58473FFB58C + 73FF8C8484FFCE734AFFC6734AFFC67B42FFC6734AFFC6734AFFC6734AFFB563 + 31FFBD6331FFB56331FFBD6331FF000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF4A3931FFFF00FFFF4A4231FFFF00 + FFFF4A4231FFFF00FFFF4A4231FFFF00FFFF523931FFFF00FFFF4A4231FFFF00 + FFFF524231FFFF00FFFF524231FFB59C8CFFFFFFFFFF94847BFFFFFFFFFF9484 + 84FFFFFFFFFF94847BFFFFFFFFFF948484FFFFFFFFFF52636BFFFFFFFFFF525A + 6BFFFFFFFFFF52636BFFFF00FFFFF7A58CFFF7AD94FFF7A57BFFDEA57BFFDEA5 + 7BFFE7946BFFE79463FFE7946BFFD68452FFDE7B4AFFD68452FFCE7B4AFFCE73 + 4AFFC67B42FFCE734AFF524231FFEFAD94FFF7EFEFFFFFF7EFFFF7EFEFFFFFF7 + EFFFF7F7EFFFF7EFEFFFF7AD8CFFF7A57BFFF7A57BFFF7A57BFFEFA57BFFF7A5 + 7BFFF7A57BFFF7A57BFF524231FFF7AD8CFFF7A58CFFEFA573FFF7A57BFFEFA5 + 73FFF7A57BFFE79463FFE79463FFDE946BFFD68452FFDE7B4AFFDE7B4AFFDE7B + 4AFFDE7B4AFFDE7B4AFF524231FFBDADA5FFFFFFFFFFFFFFFFFFDEA57BFFFFFF + FFFFFFFFFFFFDEA57BFFFFFFFFFFFFFFFFFFDEA57BFFFFFFFFFFFFFFFFFFDEA5 + 7BFFFFF7EFFFF7EFEFFF4A4231FFC6ADA5FFFFFFFFFFFFFFFFFFB59C8CFFFFFF + FFFFFFFFFFFFB59C8CFFFFFFFFFFFFFFFFFFB59C8CFFFFFFFFFFFFF7EFFFB594 + 8CFFFFF7EFFFDECEC6FF4A4239FFC6AD9CFFD6AD94FFB59C8CFFBD8473FFDEA5 + 7BFFB59C8CFFB58C73FFDEA57BFFB59C8CFF42B5EFFF2994DEFF1842CEFF184A + CEFFDEA57BFF00000000524239FFC6ADA5FFFFFFFFFFFFFFFFFFDEA57BFFFFFF + FFFFFFFFFFFFDEA57BFFFFFFFFFFFFFFFFFF299CDEFFFFFFFFFFFFF7EFFF1842 + C6FFFFF7EFFFDECECEFF4A4231FFC6AD9CFFFFFFFFFFFFFFFFFFB59C8CFFFFFF + FFFFFFFFFFFFB59C8CFFFFFFFFFFFFEFEFFF1842CEFFFFF7EFFFFFEFE7FF1842 + CEFFFFF7EFFFCEBDADFF4A4231FFC6ADA5FFD6AD94FF00000000BD8C73FFDEA5 + 7BFFB59C8CFFBD8473FFDEA57BFF00000000214AC6FF1842CEFF184ACEFF1842 + CEFFDEA57BFFBD9C8CFF4A4231FFC6B5A5FFFFFFFFFFFFFFFFFFCEAD94FFFFFF + FFFFFFFFFFFFDEA57BFFFFF7EFFFFFEFEFFFDEA57BFFFFF7EFFFFFEFE7FFDEA5 + 7BFFFFE7CEFFC6B5ADFF524239FFC6AD9CFFFFFFFFFFFFFFFFFFB59484FFFFFF + FFFFFFF7EFFF00000000F7EFEFFFF7EFEFFF00000000F7EFEFFFF7F7EFFF0000 + 0000FFDECEFFCEBDB5FF4A4231FFC6ADA5FFC6ADA5FF00000000BD8C73FFE7B5 + 94FFD6AD94FFB58473FFEFBD94FF00000000BD8473FFC6AD9CFFB59C8CFFBD84 + 73FFCEAD8CFFB59C8CFF524231FF000000004A4239FF524231FF4A4239FF5242 + 39FF4A4231FF524239FF4A4231FF4A4239FF524231FF4A4239FF524231FF4A42 + 39FF524231FF524239FF4A4231FF000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000CEBDADFFCEBDB5FFCEBDADFFCEBDB5FFCEBD + ADFFCEBDB5FFC6ADA5FFC6AD9CFFC6ADA5FFC6AD9CFFC6ADA5FFC6A58CFFB59C + 8CFFB59C84FFB5948CFFB59C8CFFCEBDB5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF526363FFC6BDADFFFFFFFFFFEFDEDEFF5A7B8CFF9484 + 7BFF5A7B8CFFBDC6CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7 + EFFFFFEFEFFFDED6CEFF4A3931FFCEBDB5FFFFFFFFFF4A6363FF637B8CFF8C9C + ADFF849CA5FF94847BFFEFE7DEFFFFFFFFFFF7F7EFFFFFFFFFFFF7EFEFFFF7EF + E7FFFFEFE7FFDECEC6FF4A4231FFCEBDADFFFFFFFFFF524239FF4A3931FFEFE7 + DEFFBDC6CEFF94847BFFE7DEDEFFF7F7EFFFF7BDA5FFF7BD9CFFFFB57BFFF7A5 + 7BFFF7A57BFFCEBDB5FF4A4231FFC6ADA5FFFFFFFFFF52636BFF524239FFCEBD + B5FF94847BFF52636BFFFFFFFFFFFFEFEFFFF7F7E7FFF7EFEFFFFFF7EFFFF7EF + EFFFF7E7C6FFCEBDB5FF524231FFC6ADA5FFFFFFFFFFEFE7DEFF52636BFFB59C + 84FF8C9CADFF525A63FFC6D6DEFFF7F7E7FFF7CEBDFFC6A58CFFB59C84FFB59C + 84FFB58473FFCEBDB5FF4A4231FFBDAD9CFFFFF7EFFF107BBDFF8CADC6FF1842 + CEFF1884BDFF184ACEFF1842CEFFFFF7EFFFFFDEC6FFF7DECEFFFFDECEFFF7D6 + BDFFFFD6BDFFE7BD94FF4A3939FFC6AD9CFFEFE7DEFF1842C6FF4AB5EFFF299C + DEFF214ACEFF1884BDFF1842C6FFFFEFEFFFDEC6ADFFC6A594FFB59C84FFB59C + 8CFFB58473FFEFBD9CFF4A4231FFC6A594FFF7F7EFFFBDC6CEFF1842CEFF214A + C6FF1842CEFF214ACEFFC6A58CFFFFE7CEFFF7DEC6FFF7D6BDFFF7D6C6FFFFDE + BDFFF7D6BDFFE7B58CFF4A4239FFB59C8CFFFFDEC6FFFFDEC6FFDECEC6FFE7C6 + ADFFDEC6ADFFE7C6B5FFDEC6ADFFEFC6A5FFE7B59CFFE7BD94FFE7B594FFE7AD + 8CFFE7B58CFFE7AD8CFF524231FFB59C84FF52636BFF4A4231FF4A4231FF5242 + 39FF4A4231FF4A4231FF524239FF4A4231FF524231FF4A4239FF524239FF4A42 + 31FF4A4239FF524239FF4A4239FF000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000084ADC6FF8C9CA5FF849CADFF0000000000000000000000000000 + 000000000000000000000000000000000000DEC6ADFFCEBDB5FFCEBDADFFCEBD + B5FF8C9CA5FFADE7EFFFADE7F7FF8CC6D6FF526363FFC6ADA5FFC6AD9CFFC6A5 + 94FF00000000000000000000000000000000CEBDADFFFFFFFFFFFFFFFFFFFFFF + FFFF849CA5FF849CADFF94847BFF8CBDD6FF637B8CFFFFF7EFFFE7DEDEFFEFE7 + DEFF525A63FF000000000000000000000000CEBDB5FFFFFFFFFFFFFFFFFF8C9C + ADFF7BD6F7FF8CE7FFFF7BD6F7FF63CEF7FF8C9CA5FF5A738CFFE7E7DEFFDECE + C6FFB59C84FF000000000000000000000000CEBDB5FFFFFFFFFFFFFFFFFF849C + A5FF637B8CFF637B8CFF637B8CFF637B8CFF5A7B8CFF8C9CADFF84ADBDFF1842 + CEFFB59C8CFF000000000000000000000000CEBDADFFFFFFFFFFFFFFFFFFFFFF + FFFFF7EFEFFFFFEFEFFFF7F7EFFFEFDEDEFFEFE7DEFF8CADC6FF1842CEFF8C9C + A5FF948484FF000000000000000000000000C6AD9CFFFFFFFFFFFFFFFFFFFFEF + EFFFF7F7E7FFFFEFEFFFF7EFE7FFE7E7DEFF2994DEFF184ACEFF8C9CA5FFDED6 + C6FF525A6BFF000000000000000000000000C6ADA5FFFFFFFFFFC6F7FFFFC6D6 + D6FFFFEFE7FFF7EFEFFFEFE7DEFF8CADBDFF1842CEFF5A7B8CFFFFDECEFFE7C6 + B5FF4A4231FF000000000000000000000000C6AD9CFFF7EFEFFF42ADEFFF4AB5 + EFFF84ADC6FFC6D6D6FF84ADC6FF1842CEFF214ACEFFFFDEC6FFF7DEBDFFC6AD + A5FF4A4231FF000000000000000000000000C6AD9CFFFFF7EFFF2142C6FF1842 + CEFF299CDEFF2994DEFF184AC6FF1842CEFFCEBDADFFFFDEC6FFDECEC6FFC6AD + A5FF4A4239FF000000000000000000000000C6ADA5FFF7F7EFFFC6D6D6FF1842 + CEFF214ACEFF2142CEFF184ACEFF8C9CA5FFF7D6B5FFF7CEBDFFDEC6ADFFD6AD + 8CFF524231FF000000000000000000000000C6AD9CFFFFEFE7FFFFF7EFFFEFE7 + DEFF2142CEFF184ACEFF637B8CFFDECEC6FFF7CEB5FFDECEC6FFDEC6B5FFD6AD + 94FF4A4239FF000000000000000000000000C6ADA5FFF7F7EFFFDECEC6FFDECE + C6FFDECEC6FF8C9CA5FFCEBDB5FFE7BD94FFC6ADA5FFC6AD9CFFD6AD8CFFBDA5 + 94FF524231FF000000000000000000000000D6AD94FF523931FF4A4231FF4A42 + 31FF4A4231FF52636BFF524231FF4A4239FF524231FF4A4239FF524231FF4A42 + 39FF000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000008CBDD6FF8CC6CEFF94C6D6FF8CBD + D6FF8CC6D6FF94C6D6FF8CBDD6FF8CC6CEFF94BDD6FF8CC6D6FF84ADBDFF84AD + C6FF84ADC6FF84ADC6FF000000000000000094BDCEFFC6F7FFFFC6EFFFFFC6F7 + FFFFC6F7FFFFC6EFFFFFC6F7FFFFC6F7FFFFC6F7FFFFC6F7FFFFCEEFFFFFC6F7 + FFFFCEF7FFFF5A7B8CFF00000000000000008CC6D6FFC6F7FFFFADEFFFFFADEF + F7FFADEFFFFFADEFF7FFADEFFFFFADEFFFFFADEFFFFFA5EFFFFFADEFFFFFA5EF + F7FFADEFFFFF5A7B8CFF000000000000000084ADBDFFADEFFFFFADEFFFFFA5EF + FFFFADEFFFFFA5EFFFFFADEFFFFFA5EFF7FFADEFFFFFA5EFF7FFADEFFFFFADEF + FFFFADF7FFFF525A6BFF000000000000000084ADC6FFADE7EFFFA5EFFFFFADF7 + F7FFADEFFFFFADF7FFFFA5EFFFFFADEFFFFFADF7FFFFADEFFFFFA5EFF7FFADEF + FFFFA5EFFFFF526363FF000000000000000084ADC6FF8CE7F7FF8CE7FFFF8CE7 + FFFF8CE7F7FF8CE7FFFF8CE7F7FF8CE7F7FF8CE7FFFF8CE7F7FF8CE7FFFF8CE7 + FFFF8CE7FFFF526363FF000000000000000084ADC6FF6BC6F7FF8CE7F7FF8CE7 + FFFF8CDEFFFF8CE7F7FF8CE7FFFF8CE7FFFF8CDEF7FF8CE7FFFF8CE7F7FF8CE7 + FFFF8CE7F7FF525A6BFF00000000000000008CADBDFF42B5EFFF7BD6F7FF8CE7 + FFFF8CE7F7FF8CE7FFFF8CDEFFFF8CE7F7FF8CE7FFFF8CE7FFFF8CE7FFFF8CE7 + FFFF8CE7FFFF526363FF000000000000000084ADC6FF4AADEFFF29BDEFFF4AB5 + EFFF42ADEFFF299CDEFF6BCEEFFF8CE7FFFF8CE7F7FF8CDEFFFF8CE7F7FF8CE7 + FFFF8CE7FFFF525A63FF000000000000000084ADBDFF6BCEF7FF299CDEFF29BD + EFFF29BDEFFF299CDEFF29BDEFFF8CDEFFFF8CE7FFFF8CE7F7FF8CE7FFFF8CE7 + F7FF8CE7FFFF52636BFF000000000000000084ADC6FF6BCEF7FF4AADEFFF299C + DEFF31BDF7FF29BDEFFF299CDEFF7BD6F7FF7BD6F7FF7BD6FFFF7BD6F7FF7BD6 + F7FF7BD6F7FF526363FF00000000000000008CADC6FF7BD6F7FF6BCEEFFF4AB5 + EFFF299CDEFF319CE7FF299CDEFF4AB5EFFF7BD6F7FF6BCEF7FF7BD6F7FF7BD6 + F7FF7BDEFFFF52636BFF000000000000000084ADBDFF6BCEF7FF7BD6F7FF6BC6 + F7FF4AB5E7FF2994DEFF299CDEFF1884BDFF299CDEFF4AADEFFF4AB5EFFF4AB5 + EFFF4AADEFFF526363FF00000000000000008CADC6FF5A738CFF637B8CFF5A7B + 8CFF637B8CFF637B8CFF5A636BFF525A63FF5A636BFF526363FF525A6BFF5263 + 63FF526363FF52636BFF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000008C9CA5FF849CA5FF8C9CADFF849C + A5FF8C9CA5FF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000849CADFFADE7F7FFADEFFFFFADEFFFFFADF7 + FFFF8CE7FFFF849CADFF00000000000000000000000000000000000000000000 + 00000000000000000000000000008C9CA5FF849CA5FF8C9CA5FF849CA5FF849C + A5FF8C9CA5FF8C9CA5FF849CA5FF8C9CA5FF849CADFF849CA5FF8C9CADFF849C + A5FF849CA5FF0000000000000000849CADFFCEF7FFFFC6F7FFFFC6EFFFFFC6F7 + FFFFADEFFFFFADEFFFFFADEFFFFF8CE7FFFF8CE7FFFF7BD6F7FF6BCEF7FF63C6 + F7FF6BCEF7FF5A738CFF00000000849CA5FFC6EFFFFFADEFFFFFADEFFFFFADEF + FFFFA5EFFFFF8CE7FFFF8CE7FFFF8CE7FFFF63C6EFFF6BCEF7FF4AADEFFF4AB5 + EFFF299CDEFF5A7B8CFF00000000849CADFFC6F7FFFFADEFFFFFA5EFFFFFADEF + FFFF8CE7F7FF8CE7FFFF8CE7F7FF7BD6F7FF6BCEF7FF63C6F7FF4AB5E7FF2994 + DEFF1884BDFF5A636BFF000000008C9CA5FFC6F7FFFFA5EFF7FFADF7FFFFADEF + F7FF8CE7FFFF8CE7FFFF7BD6F7FF63CEF7FF6BC6EFFF4AB5EFFF4AB5EFFF319C + DEFF1884BDFF526363FF00000000849CA5FFADEFFFFFADEFFFFFA5EFFFFF8CE7 + FFFF8CE7F7FF7BD6F7FF6BC6F7FF6BCEF7FF4AADEFFF4AB5E7FF4AADEFFF299C + DEFF1884BDFF524231FF000000008C9CADFFA5E7EFFFADEFFFFF8CE7F7FF8CE7 + FFFF7BD6F7FF63CEF7FF6BCEF7FF42ADE7FF4AB5EFFF4AB5EFFF2994DEFF299C + DEFF1884BDFF4A4239FF0000000094847BFFADE7F7FF8CE7FFFF8CE7FFFF7BD6 + F7FF6BC6F7FF6BCEEFFF4AADEFFF4AB5EFFF4AB5E7FF2994DEFF299CE7FF2184 + BDFF1884BDFF524231FF000000005A7B8CFFADE7EFFF63CEF7FF4AADE7FF4AB5 + EFFF299CDEFF2994E7FF1884B5FF1884BDFF1884BDFF1884BDFF1884B5FF1884 + BDFF1884BDFF000000FF000000005A7B8CFF63738CFF526363FF52636BFF5242 + 31FF524231FF524231FF000000FF000000FF000000FF000000FF000000FF0000 + 00FF000000FF000000FF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000 + } + end + object ToolImages: TImageList + Height = 12 + Width = 12 + left = 144 + top = 16 + Bitmap = { + 4C69060000000C0000000C000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000008484 + 84FF848484FF848484FF848484FF848484FF848484FF848484FF848484FF8484 + 84FF848484FF848484FF000000FF848484FF000000FF00FFFFFFFFFFFFFF00FF + FFFFFFFFFFFF00FFFFFFFFFFFFFF00FFFFFFFFFFFFFF000000FF000000FF8484 + 84FFC6C6C6FF000000FF00FFFFFFFFFFFFFF00FFFFFFFFFFFFFF00FFFFFFFFFF + FFFF000000FF008484FF000000FF848484FF00FFFFFFC6C6C6FF000000FF00FF + FFFFFFFFFFFF00FFFFFFFFFFFFFF000000FF008484FFC6C6C6FF000000FF8484 + 84FFFFFFFFFFFFFFFFFF008484FF000000FF00FFFFFFFFFFFFFF000000FF0084 + 84FFC6C6C6FFC6C6C6FF000000FF848484FF00FFFFFF008484FFC6C6C6FF0084 + 84FF000000FF000000FF008484FFC6C6C6FF008484FFC6C6C6FF000000FF8484 + 84FF008484FFC6C6C6FFC6C6C6FFC6C6C6FF008484FF008484FFC6C6C6FFC6C6 + C6FFC6C6C6FF008484FF000000FF848484FFC6C6C6FFC6C6C6FFC6C6C6FFC6C6 + C6FFC6C6C6FFC6C6C6FFC6C6C6FFC6C6C6FFC6C6C6FFC6C6C6FF000000FF8484 + 84FF848484FF848484FF848484FF848484FF848484FF848484FF848484FF8484 + 84FF848484FF848484FF000000FF000000FF000000FF000000FF000000FF0000 + 00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000008484 + 84FF848484FF848484FF848484FF848484FF848484FF848484FF848484FF8484 + 84FF848484FF848484FF000000FF848484FF000000FF00FFFFFFFFFFFFFF00FF + FFFFFFFFFFFF00FFFFFFFFFFFFFF00FFFFFFFFFFFFFF000000FF000000FF8484 + 84FFC6C6C6FF000000FF00FFFFFFFFFFFFFF00FFFFFFFFFFFFFF00FFFFFFFFFF + FFFF000000FF000084FF000000FF848484FF00FFFFFFC6C6C6FF000000FF00FF + FFFFFFFFFFFF00FFFFFFFFFFFFFF000000FF000084FFC6C6C6FF000000FF8484 + 84FFFFFFFFFFFFFFFFFF000084FF000000FF0000FFFF0000FFFF000000FF0000 + 84FFC6C6C6FF0000FFFF0000FFFF848484FF00FFFFFF000084FFC6C6C6FF0000 + 84FF0000FFFF0000FFFF0000FFFFC6C6C6FF0000FFFF0000FFFF0000FFFF8484 + 84FF000084FFC6C6C6FFC6C6C6FFC6C6C6FF000084FF0000FFFF0000FFFF0000 + FFFF0000FFFF0000FFFF000000FF848484FFC6C6C6FFC6C6C6FFC6C6C6FFC6C6 + C6FFC6C6C6FFC6C6C6FF0000FFFF0000FFFF0000FFFFC6C6C6FF000000FF8484 + 84FF848484FF848484FF848484FF848484FF848484FF0000FFFF0000FFFF0000 + FFFF0000FFFF0000FFFF000000FF000000FF000000FF000000FF000000FF0000 + 00FF0000FFFF0000FFFF0000FFFF000000FF0000FFFF0000FFFF0000FFFF0000 + 0000000000000000000000000000000000000000FFFF0000FFFF000000000000 + 0000000000000000FFFF0000FFFF000000000000000000000000000000000000 + 0000848484FFC6C6C6FF848484FF848484FF848484FF00000000000000000000 + 0000000000000000000000000000848484FFFFFFFFFF848484FFC6C6C6FFFFFF + FFFFFFFFFFFF848484FF00000000000000000000000000000000848484FFFFFF + FFFFFFFFFFFFFFFFFFFF000000FFC6C6C6FF848484FFFFFFFFFF848484FF0000 + 00000000000000000000848484FFFFFFFFFFFFFFFFFF848484FF848400FF0000 + 00FF848400FFC6C6C6FF848484FF000000000000000000000000848484FFFFFF + FFFFFFFFFFFF848484FF000000FFFFFF00FF848484FF848484FF848484FF0000 + 0000C6C6C6FFC6C6C6FF848484FFFFFFFFFFFFFFFFFF848484FF000000FFFFFF + FFFF848484FFC6C6C6FF848484FFC6C6C6FF000000FF000000FF848484FFFFFF + FFFFFFFFFFFF848484FF848400FF000000FF848400FF848484FF848484FF0000 + 00FF848484FF0000000000000000000000FFFFFFFFFFFFFFFFFF848484FF8484 + 84FF848484FF000000FF00000000848484FF0000000000000000000000000000 + 0000000000FF000000FF000000FF000000FF000000FF00000000000000000000 + 000000000000000000000000000000000000848484FFC6C6C6FF848484FFC6C6 + C6FF000000FF0000000000000000000000000000000000000000000000008484 + 84FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6C6C6FF848484FF000000000000 + 00000000000000000000848484FFC6C6C6FF848484FFC6C6C6FF848484FFC6C6 + C6FF848484FF848484FF000000FF000000000000000000000000000000000000 + 0000848484FFC6C6C6FF848484FF848484FF848484FF00000000000000000000 + 0000000000000000000000000000848484FFFFFFFFFF848484FFC6C6C6FFFFFF + FFFFFFFFFFFF848484FF00000000000000000000000000000000848484FFFFFF + FFFFFFFFFFFFFFFFFFFF000000FFC6C6C6FF848484FFFFFFFFFF848484FF0000 + 00000000000000000000848484FFFFFFFFFFFFFFFFFF848484FF848400FF0000 + 00FF848400FFC6C6C6FF848484FF000000000000000000000000848484FFFFFF + FFFFFFFFFFFF848484FF000000FFFFFF00FF848484FF848484FF848484FF0000 + 0000C6C6C6FFC6C6C6FF848484FFFFFFFFFFFFFFFFFF848484FF0000FFFF0000 + FFFF0000FFFF0000FFFF848484FFC6C6C6FF000000FF000000FF848484FFFFFF + FFFFFFFFFFFF0000FFFFFFFFFFFF0000FFFF0000FFFFFFFFFFFF0000FFFF0000 + 00FF848484FF0000000000000000000000FFFFFFFFFF0000FFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF0000FFFF848484FF0000000000000000000000000000 + 0000000000FF0000FFFF0000FFFFFFFFFFFFFFFFFFFF0000FFFF0000FFFF0000 + 000000000000000000000000000000000000848484FF0000FFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF0000FFFF000000000000000000000000000000008484 + 84FFFFFFFFFF0000FFFFFFFFFFFF0000FFFF0000FFFFFFFFFFFF0000FFFF0000 + 00000000000000000000848484FFC6C6C6FF848484FFC6C6C6FF0000FFFF0000 + FFFF0000FFFF0000FFFF000000FF000000000000000000000000000000000084 + 84FF848484FF848484FF848484FF000000000000000000000000000000000000 + 00000000000000000000008484FFFFFFFFFFFFFFFFFFFFFFFFFFC6C6C6FF8484 + 84FF000000000000000000000000000000000000000000000000000000FF0000 + 00FF848484FFC6C6C6FF008484FF000000FF0000000000000000000000000000 + 00000000000000000000848484FFC6C6C6FFFFFFFFFFFFFFFFFF008484FF0000 + 00FF00000000000000000000000000000000000000FF00000000000000FF0000 + 00FF848484FFC6C6C6FF000000FF000000FF00000000000000FF00000000C6C6 + C6FF000000FF000000FF848484FFC6C6C6FFFFFFFFFFFFFFFFFF848484FF0000 + 00FF000000FF000000FFC6C6C6FF00000000000000FFFFFFFFFF000000FF0000 + 00FF848484FFC6C6C6FF000000FF000000FFFFFFFFFF000000FF000000000000 + 0000000000FFFFFFFFFF848484FFC6C6C6FFC6C6C6FF848484FF848484FF0000 + 00FFFFFFFFFF000000FF000000000000000000000000000000FFFFFFFFFF0000 + 00FF000000FF000000FF000000FFFFFFFFFF000000FF00000000000000000000 + 00000000000000000000848484FF848484FF848484FF848484FF848484FF0000 + 00FF000000000000000000000000000000000000000000000000000000000000 + 0000000000FF000000FF00000000000000000000000000000000000000000000 + 000000000000C6C6C6FF848484FF000000FF000000FF000000FF000000FF0000 + 00FF848484FF0000000000000000000000000000000000000000000000000084 + 84FF848484FF848484FF848484FF000000000000000000000000000000000000 + 00000000000000000000008484FFFFFFFFFFFFFFFFFFFFFFFFFFC6C6C6FF8484 + 84FF000000000000000000000000000000000000000000000000000000FF0000 + 00FF848484FFC6C6C6FF008484FF000000FF0000000000000000000000000000 + 00000000000000000000848484FFC6C6C6FFFFFFFFFFFFFFFFFF008484FF0000 + 00FF00000000000000000000000000000000000000FF00000000000000FF0000 + 00FF848484FFC6C6C6FF000000FF000000FF00000000000000FF00000000C6C6 + C6FF000000FF000000FF848484FFC6C6C6FFFFFFFFFFFFFFFFFF0000FFFF0000 + FFFF0000FFFF0000FFFFC6C6C6FF00000000000000FFFFFFFFFF000000FF0000 + 00FF848484FF0000FFFFFFFFFFFF0000FFFF0000FFFFFFFFFFFF0000FFFF0000 + 0000000000FFFFFFFFFF848484FFC6C6C6FFC6C6C6FF0000FFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF0000FFFF0000000000000000000000FFFFFFFFFF0000 + 00FF000000FF0000FFFF0000FFFFFFFFFFFFFFFFFFFF0000FFFF0000FFFF0000 + 00000000000000000000848484FF848484FF848484FF0000FFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF0000FFFF000000000000000000000000000000000000 + 0000000000FF0000FFFFFFFFFFFF0000FFFF0000FFFFFFFFFFFF0000FFFF0000 + 000000000000C6C6C6FF848484FF000000FF000000FF000000FF0000FFFF0000 + FFFF0000FFFF0000FFFF00000000 + } + end + object OpenPictureDialog1: TOpenPictureDialog + Title = 'Open existing file' + left = 136 + top = 64 + end +end diff --git a/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemoMainForm.lrs b/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemoMainForm.lrs new file mode 100644 index 000000000..584222def --- /dev/null +++ b/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemoMainForm.lrs @@ -0,0 +1,941 @@ +LazarusResources.Add('TJvNavPaneDemoMainFrm','FORMDATA',[ + 'TPF0'#21'TJvNavPaneDemoMainFrm'#20'JvNavPaneDemoMainFrm'#4'Left'#2'i'#6'Heig' + +'ht'#3#212#1#3'Top'#2'm'#5'Width'#3#6#2#18'HorzScrollBar.Page'#3#5#2#18'Vert' + +'ScrollBar.Page'#3#211#1#7'Caption'#6#21'JvNavigationPane Demo'#8'DockSite'#9 + +#11'Font.Height'#2#245#9'Font.Name'#6#6'Tahoma'#8'OnCreate'#7#10'FormCreate' + +#0#10'TPopupMenu'#10'PopupMenu1'#7'OnPopup'#7#15'PopupMenu1Popup'#4'left'#2 + +'\'#3'top'#2'@'#0#9'TMenuItem'#8'HideAll1'#7'Caption'#6#8'Hide All'#7'OnClic' + +'k'#7#13'HideAll1Click'#0#0#9'TMenuItem'#8'ShowAll1'#7'Caption'#6#8'Show All' + +#7'OnClick'#7#13'ShowAll1Click'#0#0#9'TMenuItem'#2'N1'#7'Caption'#6#1'-'#0#0 + +#9'TMenuItem'#11'ChangeFont1'#7'Caption'#6#7'Font...'#7'OnClick'#7#16'Change' + +'Font1Click'#0#0#9'TMenuItem'#7'Colors1'#7'Caption'#6#6'Colors'#0#9'TMenuIte' + +'m'#9'Standard1'#7'Caption'#6#8'Standard'#7'Checked'#9#10'GroupIndex'#2#1#9 + +'RadioItem'#9#7'OnClick'#7#11'SchemaClick'#0#0#9'TMenuItem'#5'Blue1'#3'Tag'#2 + +#1#7'Caption'#6#4'Blue'#10'GroupIndex'#2#1#9'RadioItem'#9#7'OnClick'#7#11'Sc' + +'hemaClick'#0#0#9'TMenuItem'#7'Silver1'#3'Tag'#2#2#7'Caption'#6#6'Silver'#10 + +'GroupIndex'#2#1#9'RadioItem'#9#7'OnClick'#7#11'SchemaClick'#0#0#9'TMenuItem' + +#6'Olive1'#3'Tag'#2#3#7'Caption'#6#5'Olive'#10'GroupIndex'#2#1#9'RadioItem'#9 + +#7'OnClick'#7#11'SchemaClick'#0#0#0#9'TMenuItem'#16'BackgroundImage1'#7'Capt' + +'ion'#6#19'Background Image...'#7'OnClick'#7#21'BackgroundImage1Click'#0#0#9 + +'TMenuItem'#2'N2'#7'Caption'#6#1'-'#0#0#9'TMenuItem'#16'Dontallowresize1'#7 + +'Caption'#6#18'Don''t allow resize'#7'OnClick'#7#21'Dontallowresize1Click'#0 + +#0#9'TMenuItem'#2'N3'#7'Caption'#6#1'-'#0#0#9'TMenuItem'#14'ShowToolPanel1'#7 + +'Caption'#6#15'Show Tool Panel'#7'OnClick'#7#19'ShowToolPanel1Click'#0#0#9'T' + +'MenuItem'#16'ShowCloseButton1'#7'Caption'#6#17'Show Close Button'#7'OnClick' + +#7#21'ShowCloseButton1Click'#0#0#0#10'TImageList'#11'LargeImages'#6'Height'#2 + +#20#5'Width'#2#24#4'left'#2'\'#3'top'#2#16#6'Bitmap'#10#14'-'#0#0'Li'#6#0#0#0 + +#24#0#0#0#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#206#181#156#255#198#173#156#255#206#173#156#255#206 + +#173#156#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#189#189#189#255#231#198#181#255#198#247#255#255#198#247#255#255#173#231 + +#247#255#198#173#156#255#206#173#156#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#206#173#156#255#222#214#206#255#198#239#255#255#198#239#255 + +#255#198#247#255#255#173#231#247#255'{'#214#247#255#140#198#214#255#173#148 + +#132#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#189#189#189#255#206#189#181#255#198#247 + +#255#255#198#239#255#255#198#247#255#255#198#247#255#255#198#239#255#255#140 + +#231#255#255'{'#222#247#255'k'#198#247#255'k'#206#247#255#173#148#132#255#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#206#173#156#255#222#214#206#255#198#239#255#255#198#247#255#255#198 + +#239#255#255#198#247#255#255#198#239#255#255#173#231#247#255#140#231#247#255 + +#132#214#247#255'c'#206#247#255'k'#198#247#255'J'#189#247#255#189#189#189#255 + +#132#156#165#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#206#173#156#255#198#247#255#255#198#247#255#255#198#239#255#255#198#247 + +#255#255#165#231#247#255#148#231#255#255'{'#214#247#255'{'#214#247#255#132 + +#214#247#255'{'#214#247#255'k'#198#247#255'k'#206#247#255'J'#181#239#255'R' + +#181#247#255'J'#189#247#255#173#148#132#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#198#173#156#255#198#247#255#255#173#231#247#255#165#231#247 + +#255#148#231#247#255'{'#214#247#255'k'#198#247#255'c'#206#247#255'R'#181#239 + +#255'J'#189#247#255'J'#181#247#255'R'#189#247#255'1'#181#222#255'9'#173#247 + +#255'1'#165#239#255'!'#165#239#255'9'#165#239#255'9'#173#247#255#165'{k'#255 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#173#156#255'c'#198#247#255#247 + +#239#239#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#247#247#231#255#247#239#239 + +#255#247#247#239#255#247#239#239#255#173#231#247#255#173#231#239#255#148#198 + +#214#255'1'#173#239#255#156'{k'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#214#173#132#255'{'#214#247#255#247#247#239#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#247#239#239#255#239#239#239#255#247#239#231#255#239#239#239#255#247 + +#247#239#255#247#239#239#255#222#198#173#255'1'#165#247#255#156'{k'#255'JB1' + +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#173#165#255#198#173#156#255#255#222 + +#198#255#255#255#255#255#247#222#206#255#255#222#198#255#247#247#239#255#255 + +#222#206#255#255#222#198#255#255#222#206#255#247#222#198#255#247#247#239#255 + +#247#239#239#255#239#247#239#255#247#239#239#255#239#239#239#255#214#189#173 + ,#255#165'{k'#255#156'{k'#255'JB1'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#173 + +#132#255#255#222#206#255#198#173#156#255#255#255#255#255#247#247#239#255#214 + +#206#206#255#222#214#206#255#214#214#206#255#214#214#206#255#222#214#206#255 + +#214#214#206#255#222#189#173#255#222#198#173#255#231#198#173#255#214#206#206 + +#255#247#247#239#255#156'{k'#255#231#173#140#255#156'{k'#255'JB1'#255#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#214#165#140#255#255#255#255#255#255#231#206#255#198 + +#173#156#255#255#255#255#255#255#255#255#255#206#165#132#255#214#165#140#255 + +#214#165#132#255#173#148#140#255#173#148#140#255#173#148#140#255#173#148#140 + +#255#247#239#239#255#247#247#239#255#156'sk'#255#231#189#148#255#255#206#165 + +#255#156'{k'#255'JB1'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#156'{'#255#255 + +#255#255#255#239#239#239#255#247#247#239#255#198#173#156#255#214#165#140#255 + +#255#231#206#255#239#239#239#255#247#247#239#255#247#239#239#255#247#247#239 + +#255#239#239#239#255#247#214#181#255#156'{k'#255#173#148#140#255#239#181#148 + +#255#247#214#189#255#255#206#156#255#156'{k'#255'JB1'#255#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#173#148#132#255#247#239#239#255#239#247#239#255#247#239#239#255 + +#214#165#132#255#239#247#239#255#247#239#239#255#239#239#239#255#247#239#239 + +#255#239#239#239#255#239#239#239#255#255#231#198#255#255#222#206#255#255#206 + +#165#255#156'{k'#255#255#206#156#255#255#206#156#255#247#198#140#255#156'{k' + +#255'JB1'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#173#148#140#255#247#247#239#255 + +#247#239#239#255#206#165#132#255#247#247#239#255#247#239#239#255#239#239#239 + +#255#247#247#231#255#239#239#239#255#247#247#239#255#255#222#198#255#247#214 + +#198#255#247#222#189#255#247#214#181#255#247#198#140#255#156'{k'#255#247#181 + +#140#255#247#165's'#255#156'{k'#255'JB1'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#173#148#132#255#247#239#239#255#198#173#156#255#239#239#239#255#247#239#239 + +#255#239#239#239#255#247#247#239#255#247#222#198#255#255#222#206#255#247#222 + +#198#255#247#214#198#255#247#214#181#255#247#214#189#255#255#206#156#255#247 + +#198#140#255#255#173#140#255#156'{k'#255#231#148'k'#255#156'{k'#255'JB1'#255 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#173#148#132#255#198#181#156#255#247#247#239 + +#255#247#239#239#255#239#247#239#255#255#222#198#255#247#214#189#255#247#214 + +#189#255#247#214#181#255#247#214#189#255#247#206#173#255#255#206#156#255#255 + +#206#165#255#247#189#140#255#231#181#148#255#247#165's'#255#231#148'k'#255 + +#156'{k'#255#156'{k'#255'JB1'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#198#156'{' + +#255#255#222#198#255#239#239#239#255#255#222#198#255#247#214#189#255#255#206 + +#156#255#247#198#140#255#231#181#148#255#247#173#140#255#247#181#140#255#247 + +#165's'#255#239#165'{'#255#247#165's'#255#231#156'c'#255#231#148'c'#255#231 + +#156'k'#255#231#148'c'#255#206'{J'#255#156'{k'#255'JB1'#255#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#206#156'{'#255#156'{k'#255#156'{k'#255#156'{k'#255#156'{k'#255 + +#156'{k'#255#156'{k'#255#156'{k'#255#156'{k'#255#156'{k'#255#156'{k'#255#156 + +'{k'#255#156'{k'#255#156'{k'#255#156'{k'#255#156'{k'#255#156'{k'#255#156'{k' + +#255#156'{k'#255'JB1'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'JB1'#255'J' + +'B1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1' + +#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255 + +'JB1'#255#0#0#0#0#0#0#0#0#0#0#0#0'J91'#255#0#0#0#0'J9)'#255#0#0#0#0'J91'#255 + +#0#0#0#0'J91'#255#0#0#0#0'J91'#255#0#0#0#0'J9)'#255#0#0#0#0'J91'#255#0#0#0#0 + +'J91'#255#0#0#0#0'J91'#255#0#0#0#0'J91'#255#0#0#0#0'J91'#255#0#0#0#0#0#0#0#0 + +#173#148#140#255#0#0#0#0#173#148#140#255#0#0#0#0#173#148#140#255#0#0#0#0#173 + +#148#140#255#0#0#0#0#165'{k'#255#0#0#0#0#156'{k'#255#0#0#0#0#165'{k'#255#0#0 + +#0#0#165'{k'#255#0#0#0#0'kcR'#255#0#0#0#0'sZR'#255#0#0#0#0'kZR'#255#0#0#0#0#0 + +#0#0#0#0#0#0#0#231#173#140#255#231#181#140#255#231#181#140#255#247#165's'#255 + +#222#165'{'#255#222#173#132#255#222#165'{'#255#231#156'c'#255#231#148'k'#255 + +#231#148'c'#255#239#156'k'#255#231#148'c'#255#214#132'Z'#255#214#132'R'#255 + +#214#132'Z'#255#222'{J'#255#231'{J'#255#222'{J'#255#222'{J'#255#231'{J'#255 + +#222'{J'#255'JB1'#255#0#0#0#0#0#0#0#0#231#181#140#255#255#222#206#255#247#222 + +#206#255#255#222#206#255#247#222#198#255#255#214#189#255#247#214#189#255#247 + +#206#181#255#247#206#181#255#247#206#181#255#247#189#156#255#247#189#165#255 + +#247#189#156#255#247#181#140#255#247#181#140#255#247#181#140#255#247#165'{' + +#255#247#165's'#255#247#165'{'#255#247#165's'#255#231#148'k'#255'JB1'#255#0#0 + +#0#0#0#0#0#0#231#173#140#255#247#222#198#255#255#222#189#255#247#222#198#255 + +#247#206#173#255#239#206#181#255#247#206#173#255#255#206#156#255#247#189#156 + +#255#239#189#156#255#247#181#140#255#247#181#140#255#247#181#140#255#247#165 + +'s'#255#247#165's'#255#247#165's'#255#239#165's'#255#247#165'{'#255#231#156 + +'c'#255#231#148'k'#255#231#156'c'#255'JB1'#255#0#0#0#0#0#0#0#0#247#165's'#255 + +#247#165's'#255#247#165'{'#255#222#165'{'#255#222#165'{'#255#222#165'{'#255 + +#231#148'c'#255#231#148'k'#255#231#148'c'#255#231#156'k'#255#231#148'c'#255 + ,#214#132'R'#255#206#132'R'#255#214#132'R'#255#222'{J'#255#222'{J'#255#222'{J' + +#255#222'{J'#255#222'{J'#255'JB1'#255'JB1'#255'JB1'#255#0#0#0#0#0#0#0#0#206 + +#189#181#255#255#255#255#255#255#255#255#255#255#255#255#255#239#189#156#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#239#198#156#255#255#255#255 + +#255#247#239#239#255#247#247#247#255#239#189#156#255#255#255#255#255#239#239 + +#247#255#247#247#239#255#239#189#156#255#247#239#239#255#247#247#239#255#255 + +#222#206#255#231#189#156#255'JB1'#255#0#0#0#0#0#0#0#0#206#189#173#255#255#255 + +#255#255#239#247#239#255#247#239#239#255#231#189#156#255#255#255#255#255#247 + +#239#239#255#247#247#239#255#206#165#140#255#247#239#239#255#239#247#239#255 + +#247#222#206#255#214#165#132#255#239#239#239#255#247#239#239#255#247#222#198 + +#255#214#165#132#255#239#239#239#255#247#222#206#255#247#206#181#255#206#156 + +'{'#255'JB1'#255#0#0#0#0#0#0#0#0#206#189#173#255#255#255#255#255#247#239#239 + +#255#239#239#239#255#214#165#132#255#255#255#255#255#239#247#239#255#255#222 + +#206#255#198#156'{'#255#247#239#239#255#255#222#198#255#247#222#206#255#198 + +#156'{'#255#247#247#239#255#247#214#189#255#247#206#173#255#198#156'{'#255 + +#255#222#206#255#247#206#173#255#255#206#156#255#198#156'{'#255'JB1'#255#0#0 + +#0#0#0#0#0#0#206#173#156#255#231#189#156#255#239#189#148#255#206#165#132#255 + +#214#173#140#255#231#181#148#255#231#173#140#255#206#156'{'#255#198#156'{' + +#255#231#189#148#255#214#165#132#255#206#156'{'#255'9'#140#214#255'B'#140#214 + +#255'9'#140#214#255#24'B'#206#255#24'B'#206#255#231#189#148#255#214#165#140 + +#255#198#156'{'#255#165'{s'#255'JB1'#255#0#0#0#0#0#0#0#0#198#181#156#255#255 + +#255#255#255#255#255#255#255#247#239#239#255#231#181#148#255#255#255#255#255 + +#247#247#239#255#239#239#239#255#239#181#148#255#239#239#239#255#247#247#239 + +#255#239#239#239#255'B'#140#214#255#247#247#239#255#247#239#239#255#255#231 + +#206#255#24'9'#206#255#255#231#206#255#247#222#198#255#255#231#206#255#231 + +#181#148#255'JB1'#255#0#0#0#0#0#0#0#0#198#173#165#255#255#255#255#255#247#239 + +#239#255#239#247#239#255#214#165#140#255#255#255#255#255#247#239#239#255#247 + +#231#206#255#214#165#140#255#239#239#239#255#247#239#239#255#255#231#198#255 + +'9'#140#214#255#255#222#206#255#247#214#189#255#255#222#189#255#16'B'#206#255 + +#255#222#206#255#247#214#189#255#247#206#181#255#206#156'{'#255'JB1'#255#0#0 + +#0#0#0#0#0#0#198#173#156#255#255#255#255#255#247#247#239#255#247#222#206#255 + +#206#156'{'#255#239#247#239#255#255#222#198#255#247#214#189#255#206#156'{' + +#255#239#247#239#255#255#222#206#255#247#214#181#255#24'9'#206#255#255#222 + +#189#255#247#214#189#255#247#206#173#255#24'B'#206#255#255#222#189#255#239 + +#198#165#255#239#189#156#255#198#156'{'#255'J91'#255#0#0#0#0#0#0#0#0#206#181 + +#156#255#231#181#148#255#214#165#132#255#198#156'{'#255#206#156'{'#255#231 + +#181#148#255#206#165#140#255#206#156'{'#255#198#156'{'#255#239#181#148#255 + +#206#165#140#255#206#156'{'#255#24'B'#206#255#16'B'#206#255#24'B'#206#255#24 + +'B'#206#255#16'B'#214#255#231#173#140#255#198#156'{'#255#173#148#140#255#165 + +'{k'#255'JB1'#255#0#0#0#0#0#0#0#0#198#173#165#255#255#255#255#255#247#247#239 + +#255#247#239#239#255#231#181#148#255#247#247#239#255#247#247#239#255#239#239 + +#239#255#231#189#148#255#247#239#239#255#255#231#206#255#247#222#206#255#239 + +#189#148#255#255#222#206#255#255#231#206#255#255#222#189#255#239#181#148#255 + +#247#222#198#255#255#222#198#255#247#206#173#255#231#181#156#255'JB1'#255#0#0 + +#0#0#0#0#0#0#198#181#156#255#247#239#239#255#239#239#239#255#247#247#239#255 + +#206#165#140#255#247#239#239#255#247#222#198#255#255#222#206#255#214#165#132 + +#255#247#222#206#255#247#214#189#255#255#222#189#255#198#156'{'#255#255#222 + +#206#255#247#214#189#255#247#206#181#255#198#156'{'#255#255#214#189#255#239 + +#206#181#255#255#206#156#255#206#156'{'#255'J91'#255#0#0#0#0#0#0#0#0#214#165 + +#140#255#247#247#239#255#239#239#239#255#247#222#189#255#206#156'{'#255#239 + +#247#239#255#247#214#198#255#247#206#173#255#198#156'{'#255#255#231#206#255 + +#247#214#189#255#255#206#165#255#198#156'{'#255#247#222#189#255#247#206#181 + +#255#247#189#156#255#198#156'{'#255#247#206#181#255#247#189#156#255#231#189 + +#148#255#206#156'{'#255'JB1'#255#0#0#0#0#0#0#0#0#206#165#140#255#247#214#181 + +#255#231#181#148#255#214#165#140#255#198#156'{'#255#231#173#140#255#206#156 + +'{'#255#173#148#140#255#156'{k'#255#231#173#140#255#206#156'{'#255#173#148 + +#140#255#156'{k'#255#231#173#140#255#198#156'{'#255#173#148#140#255#156'{k' + +#255#231#181#140#255#198#156'{'#255#173#148#140#255#165'{s'#255'J91'#255#0#0 + +#0#0#0#0#0#0#214#165#140#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB' + +'1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1' + +#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#206#189#173#255#206#189#181#255#214#189#173#255 + +#206#189#173#255#206#189#173#255#206#189#173#255#214#189#181#255#206#189#173 + +#255#206#173#156#255#198#181#165#255#206#173#156#255#198#181#156#255#198#173 + +#156#255#198#181#156#255#206#173#156#255#198#181#156#255#214#165#140#255#206 + +#165#132#255#214#165#140#255#173#148#140#255#173#148#132#255#173#148#140#255 + +#0#0#0#0#0#0#0#0#214#189#173#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#239#239#239#255#247#247#239#255'JB1'#255#0#0#0#0#0#0#0#0#206 + +#189#173#255#255#255#255#255#255#255#255#255#247#239#239#255#181#189#189#255 + +#173#148#140#255'k{'#140#255'k'#132#140#255#189#189#189#255#247#239#239#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#247#247#239#255#247#239#239#255#239#247 + +#239#255#255#214#198#255'JB1'#255#0#0#0#0#0#0#0#0#206#189#181#255#255#255#255 + +#255#255#255#255#255#189#189#189#255'k'#132#140#255'k{'#140#255#140#156#165 + +#255#173#148#140#255'kZR'#255#181#189#189#255#255#255#255#255#255#255#255#255 + +#247#173#140#255#247#181#140#255#247#181#140#255#247#165's'#255#247#165'{' + +#255#239#165's'#255#247#165's'#255#239#239#239#255#255#222#198#255'JB1'#255#0 + +#0#0#0#0#0#0#0#206#189#173#255#255#255#255#255#255#255#255#255'k{'#140#255'k' + +'ZR'#255'scR'#255'k'#132#140#255'kZR'#255#189#189#189#255'k{'#140#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#239 + +#239#239#255#247#247#239#255#239#239#239#255#247#247#239#255#239#239#239#255 + +#247#214#181#255'JB1'#255#0#0#0#0#0#0#0#0#214#189#173#255#255#255#255#255#255 + +#255#255#255'scR'#255'J91'#255#189#189#189#255#222#214#214#255#189#189#189 + +#255#140#156#165#255'k'#132#140#255#255#255#255#255#255#255#255#255#255#181 + +#140#255#247#173#140#255#247#181#140#255#247#165's'#255#239#165's'#255#247 + +#165's'#255#247#165's'#255#247#239#239#255#247#206#173#255'JB1'#255#0#0#0#0#0 + +#0#0#0#206#189#173#255#255#255#255#255#255#255#255#255'J91'#255'JB1'#255#222 + +#214#214#255#181#181#189#255#132#156#165#255'k{'#140#255'kcR'#255#255#255#255 + +#255#255#255#255#255#239#247#239#255#247#239#239#255#247#247#239#255#239#239 + +#239#255#247#239#239#255#239#239#239#255#247#247#239#255#239#239#239#255#247 + +#189#156#255'JB1'#255#0#0#0#0#0#0#0#0#206#173#165#255#255#255#255#255#255#255 + +#255#255#189#189#189#255#0#0#0#255#189#189#189#255#140#156#165#255'k'#132#140 + +#255'sZR'#255#132#156#165#255#247#239#239#255#247#247#239#255#247#239#239#255 + +#247#239#239#255#239#239#239#255#247#239#239#255#239#247#239#255#247#239#239 + +#255#239#239#239#255#255#231#206#255#247#189#165#255'JB1'#255#0#0#0#0#0#0#0#0 + +#198#173#156#255#255#255#255#255#255#255#255#255#247#247#239#255#222#206#206 + +#255'kZR'#255'kcR'#255'sZR'#255#24'B'#214#255#189#189#189#255#247#247#239#255 + +#239#239#239#255#239#239#231#255#247#247#239#255#239#239#239#255#247#247#239 + +#255#247#239#239#255#247#222#198#255#255#222#198#255#247#222#206#255#239#181 + +#148#255'JB1'#255#0#0#0#0#0#0#0#0#206#173#156#255#255#255#255#255#255#255#255 + +#255#181#206#222#255#24'B'#206#255#24'B'#206#255#222#214#214#255#247#247#239 + +#255#24'B'#206#255#24'9'#206#255#214#214#206#255#247#239#239#255#198#156'{' + +#255#206#156'{'#255#156'{k'#255#156'sk'#255#156'{k'#255#156'{k'#255#156'{k' + +#255#247#231#198#255#255#181#140#255'JB1'#255#0#0#0#0#0#0#0#0#198#173#156#255 + +#255#255#255#255#255#255#255#255#24'B'#206#255#132#173#198#255'9'#140#214#255 + +#24'B'#206#255#24#132#189#255#24'B'#206#255#24#140#198#255#24'B'#206#255#247 + +#247#239#255#247#239#239#255#239#239#239#255#247#247#239#255#255#222#198#255 + +#255#231#206#255#255#222#206#255#255#214#198#255#247#222#198#255#247#165's' + +#255'JB1'#255#0#0#0#0#0#0#0#0#206#181#165#255#255#255#255#255#255#255#255#255 + +#24'B'#206#255'9'#173#239#255'B'#140#214#255'B'#140#214#255#24'B'#206#255#24 + +#140#189#255#24'B'#206#255'1Zs'#255#247#239#239#255#198#156'{'#255#165'{k' + +#255#156'{k'#255#156'{k'#255#156'{k'#255#156'{k'#255#156'sk'#255#247#222#198 + +#255#247#165's'#255'JB1'#255#0#0#0#0#0#0#0#0#198#173#156#255#255#255#255#255 + +#255#255#255#255#24'B'#206#255#24#140#189#255'B'#140#214#255'B'#140#214#255 + +#24'B'#206#255#24#140#198#255'!B'#206#255'9c{'#255#247#247#239#255#255#222 + +#206#255#247#222#198#255#255#222#206#255#255#222#206#255#255#222#198#255#247 + +#222#189#255#255#222#198#255#247#214#181#255#247#165'{'#255'JB1'#255#0#0#0#0 + +#0#0#0#0#198#173#156#255#255#255#255#255#247#247#239#255#222#214#206#255#24 + +'B'#206#255#24'B'#206#255#24'B'#206#255#24'B'#206#255'9cs'#255'9c{'#255#206 + +#189#173#255#255#222#206#255#156'{k'#255#165'{k'#255#156'{k'#255#156'{k'#255 + ,#156'sk'#255#156'{k'#255#156'sk'#255#247#206#181#255#231#148'c'#255'JB1'#255 + +#0#0#0#0#0#0#0#0#214#165#140#255#247#247#239#255#247#239#239#255#247#239#239 + +#255#247#247#239#255#247#247#239#255#247#247#239#255#247#247#239#255#247#239 + +#239#255#255#222#206#255#255#231#198#255#247#222#206#255#255#222#206#255#247 + +#222#189#255#255#222#198#255#247#222#198#255#255#214#189#255#247#206#173#255 + +#247#206#181#255#247#206#173#255#231#148'c'#255'JB1'#255#0#0#0#0#0#0#0#0#206 + +#165#132#255#247#239#239#255#247#222#198#255#247#214#198#255#247#222#198#255 + +#247#206#189#255#247#214#181#255#247#198#173#255#239#198#173#255#247#189#156 + +#255#239#189#156#255#231#181#148#255#231#181#140#255#247#173#140#255#247#165 + +'s'#255#247#165's'#255#239#165's'#255#247#165'{'#255#231#148'c'#255#231#148 + +'c'#255#239#156'k'#255'JB1'#255#0#0#0#0#0#0#0#0#214#165#140#255'JB1'#255'JB1' + +#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255 + +'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1'#255'JB1' + +#255'JB1'#255'JB1'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#132#156#165#255#132#156#165#255#132#156#165#255#140 + +#156#165#255'k{'#140#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#222#198#181#255#206#189 + +#173#255#214#189#173#255#206#189#181#255#206#189#173#255#140#156#165#255#140 + +#198#214#255#198#239#255#255#198#247#255#255#173#231#247#255#140#198#214#255 + +'k{'#140#255#206#173#156#255#198#181#165#255#206#173#156#255#198#173#156#255 + +#198#173#165#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#189#173 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#247#239 + +#239#255#132#156#165#255#198#247#255#255'k{'#140#255'k{'#140#255#140#156#165 + +#255#140#198#206#255'1c{'#255#206#173#156#255#247#247#239#255#239#239#239#255 + +#247#247#239#255#247#239#239#255#132#156#165#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#214#189#173#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#140#156#165#255#140#189#214#255#173#247#255#255'k'#132#140 + +#255#132#173#198#255#140#198#214#255'k'#206#247#255'k{'#140#255'1c{'#255#255 + +#222#198#255#239#239#239#255#247#247#239#255#181#206#214#255'9Z{'#255#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#189#173#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#132#156#165#255#173#231#247#255#173#231 + +#239#255#140#189#214#255#140#198#206#255#140#198#206#255#132#173#198#255#132 + +#173#198#255'k'#132#140#255#255#222#198#255#239#239#239#255#181#206#214#255 + +#24'B'#206#255'B'#140#214#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#189 + +#181#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255'k' + +#132#140#255'k{'#140#255'k{'#140#255'9cs'#255'9c{'#255'9Z{'#255'9cs'#255'k{' + +#140#255#173#148#140#255#255#222#189#255#165#173#247#255#24'B'#206#255'B'#140 + +#214#255#206#165#140#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#189#173 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#247#247#239#255#247#247#239#255#255#222#206#255#247#222#198#255#255 + +#214#181#255#239#198#173#255#247#214#189#255#255#222#198#255#165#173#247#255 + +'9'#140#214#255'B'#140#214#255#255#231#198#255#156'{k'#255#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#206#189#181#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#239#239#239#255#247#247#239#255#247#239#239 + +#255#181#206#214#255#24'B'#206#255#24'B'#206#255#181#206#214#255#255#222#206 + +#255#156'{k'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#214#189#173#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#247#239#239#255#247#239#239 + +#255#239#239#239#255#165#173#247#255'9'#140#214#255#24'B'#206#255#189#189#189 + +#255#255#222#206#255#247#214#189#255'kZR'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#206#189#173#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#247#239#239#255 + +#239#239#239#255#247#247#239#255#165#181#247#255'B'#140#214#255#24'B'#206#255 + +#132#173#189#255#255#222#206#255#255#231#198#255#247#198#173#255'kcR'#255#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#189#173#255#255#255#255#255#255#255 + +#255#255#165#173#255#255#181#206#214#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#239#239#239#255#247#247#231#255#165#173#247#255'9'#140#214#255 + +#24'B'#206#255#140#156#165#255#222#214#206#255#247#222#206#255#247#222#189 + ,#255#247#189#156#255'kZR'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#189 + +#181#255#247#247#239#255#165#173#247#255'B'#140#214#255'9'#140#214#255#165 + +#173#247#255#255#255#255#255#247#239#239#255#247#247#239#255#165#173#247#255 + +'B'#140#214#255#24'B'#206#255'9'#140#214#255#255#222#198#255#247#231#206#255 + +#255#214#189#255#247#222#198#255#239#189#156#255'kcR'#255#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#231#189#173#255#165#231#247#255#24'B'#206#255#24'B'#206 + +#255#24'B'#206#255#173#181#247#255#165#173#247#255#239#247#239#255#165#173 + +#247#255'9'#140#214#255#24'B'#206#255#24'B'#206#255#231#214#206#255#255#222 + +#206#255#247#214#189#255#247#222#198#255#247#206#173#255#231#173#140#255'kZR' + +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#173#156#255#255#255#255#255 + +#173#181#247#255#24'B'#206#255#24'B'#206#255#24'B'#206#255#165#173#247#255 + +#165#173#247#255'B'#140#214#255#24'B'#206#255#24'B'#206#255#189#189#189#255 + +#255#231#198#255#247#214#198#255#247#222#189#255#247#214#198#255#247#198#173 + +#255#231#181#140#255'JB1'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#198#181 + +#156#255#255#255#255#255#255#255#255#255#189#206#214#255#24'B'#206#255#24'B' + +#206#255#24'B'#206#255'B'#140#214#255#24'B'#206#255#24'B'#206#255'B'#140#214 + +#255#255#222#206#255#247#222#206#255#247#222#189#255#255#214#198#255#247#214 + +#181#255#239#198#173#255#247#181#140#255'J91'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#206#173#156#255#255#255#255#255#255#255#255#255#247#239#239#255 + +#189#214#222#255#24'B'#206#255'!B'#206#255#24'B'#206#255#24'B'#206#255#24'B' + +#206#255#222#214#206#255#247#222#198#255#255#222#189#255#247#214#198#255#247 + +#214#181#255#247#206#181#255#239#198#165#255#247#165's'#255'J91'#255#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#198#173#156#255#255#255#255#255#247#247#239 + +#255#239#239#239#255#247#239#239#255#181#206#214#255#24'B'#206#255#24'B'#206 + +#255'!B'#206#255#214#198#173#255#247#214#189#255#247#214#189#255#247#206#173 + +#255#239#198#173#255#247#198#173#255#247#189#156#255#231#189#148#255#247#165 + +'{'#255'JB1'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#173#156#255#239 + +#247#239#255#255#214#198#255#247#214#189#255#239#198#165#255#247#206#173#255 + +#140#156#165#255#24'B'#206#255#173#156#140#255#231#181#148#255#231#173#140 + +#255#231#173#140#255#231#173#140#255#247#181#140#255#247#181#140#255#239#165 + +'s'#255#247#165'{'#255#239#148'c'#255'JB1'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#206#173#140#255#156'sk'#255'kZR'#255'kcR'#255'sZR'#255'kZR'#255'k' + +'cR'#255#165'{k'#255'kZR'#255'scR'#255'kZR'#255'JB1'#255'JB1'#255'J91'#255'J' + +'B1'#255'J91'#255'JB1'#255'JB1'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#198#214#255#140 + +#189#214#255#140#198#214#255#140#198#206#255#140#189#214#255#140#198#206#255 + +#140#198#214#255#140#189#214#255#140#198#206#255#148#189#214#255'{'#173#198 + +#255#132#173#198#255'{'#173#198#255#132#173#198#255'{'#173#189#255#132#173 + +#198#255'{'#173#198#255#132#173#189#255'{'#173#198#255#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#140#198#206#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255'9Z{'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#148#189#214#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255'9c{'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#140#198#214#255#255#255#255#255#206#247#255#255#198#239#255#255#198 + +#247#255#255#206#247#255#255#198#239#255#255#198#247#255#255#198#247#255#255 + +#198#247#255#255#198#247#255#255#198#247#255#255#198#247#255#255#198#247#255 + +#255#198#247#255#255#198#247#255#255#198#247#255#255#198#247#255#255'9Z{'#255 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#198#206#255#198#239#255#255#165 + +#247#255#255#165#247#255#255#173#239#255#255#165#247#255#255#165#247#255#255 + +#173#247#255#255#165#239#255#255#173#247#255#255#165#239#255#255#173#247#255 + +#255#165#239#255#255#173#247#255#255#165#239#255#255#173#247#255#255#165#239 + +#255#255#173#247#255#255'9cs'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140 + +#198#214#255#198#247#255#255#173#247#255#255#165#247#247#255#173#247#255#255 + +#165#247#247#255#173#239#255#255#165#247#247#255#173#247#255#255#165#247#247 + +#255#173#247#255#255#165#247#247#255#173#247#255#255#165#247#247#255#173#247 + +#255#255#165#247#255#255#173#247#255#255#165#247#255#255'1Zs'#255#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#198#206#255#198#239#255#255#165#239#255#255 + ,#173#247#255#255#165#239#255#255#173#247#255#255#165#247#255#255#165#247#255 + +#255#173#247#255#255#165#239#255#255#165#247#255#255#173#247#255#255#165#239 + +#255#255#165#247#255#255#173#247#255#255#165#239#255#255#165#247#247#255#173 + +#247#255#255'9c{'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'{'#173#189#255 + +#148#231#255#255#140#231#247#255#165#247#255#255#173#247#247#255#165#247#255 + +#255#173#239#247#255#165#247#255#255#173#247#247#255#165#247#255#255#173#247 + +#247#255#165#239#255#255#173#247#247#255#165#247#255#255#173#247#247#255#165 + +#247#255#255#173#247#255#255#165#247#255#255'9Zs'#255#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#132#173#189#255#140#231#255#255#148#231#247#255#165#247#255 + +#255#173#239#255#255#165#247#255#255#165#247#255#255#173#247#255#255#165#247 + +#255#255#165#239#255#255#173#247#255#255#165#247#255#255#165#247#255#255#173 + +#247#255#255#165#239#255#255#173#247#247#255#165#239#255#255#173#247#255#255 + +'1c{'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'{'#173#198#255#132#214#247 + +#255#140#231#255#255#140#231#247#255#140#231#247#255#148#231#247#255#140#222 + +#255#255#140#231#247#255#148#231#247#255#140#231#247#255#140#231#255#255#148 + +#222#247#255#140#231#247#255#140#231#255#255#140#231#247#255#140#231#255#255 + +#148#231#247#255#140#231#255#255'9Zs'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#132#173#189#255'c'#198#247#255#148#231#247#255#140#231#255#255#148#231 + +#255#255#140#231#247#255#140#231#255#255#148#231#247#255#140#222#255#255#148 + +#231#255#255#140#231#247#255#148#231#255#255#140#231#247#255#148#222#255#255 + +#140#231#247#255#148#231#255#255#140#231#247#255#148#231#255#255'1c{'#255#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'{'#173#198#255'R'#189#247#255'{'#214#247 + +#255#148#231#247#255#140#222#255#255#148#231#247#255#140#231#255#255#140#231 + +#247#255#148#231#255#255#140#231#247#255#140#231#255#255#140#231#247#255#148 + +#231#255#255#140#231#247#255#148#231#255#255#140#222#247#255#140#231#255#255 + +#148#231#247#255'9Zs'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#173#189 + +#255'1'#156#206#255'9'#181#231#255'J'#189#239#255'J'#181#247#255'9'#181#222 + +#255'9'#181#231#255#132#214#247#255#140#231#247#255#140#222#255#255#148#231 + +#247#255#140#231#255#255#148#222#247#255#140#231#255#255#140#231#247#255#148 + +#231#255#255#140#231#247#255#148#231#255#255'1c{'#255#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#132#173#198#255'9'#181#231#255'9'#181#222#255'9'#181#231#255 + +'9'#181#231#255'9'#181#222#255#0#165#222#255'k'#206#247#255'{'#214#247#255 + +#132#214#247#255'{'#214#247#255#132#214#247#255'{'#214#247#255'{'#214#247#255 + +#132#214#247#255'{'#214#247#255'{'#214#247#255#132#214#247#255'1Z{'#255#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#173#189#255'k'#206#247#255#0#165#222 + +#255'9'#181#231#255'9'#181#222#255'9'#181#231#255#0#165#222#255'9'#181#231 + +#255#132#214#247#255'{'#214#255#255#132#222#247#255'{'#214#247#255#132#222 + +#247#255'{'#214#255#255#132#222#247#255'{'#214#247#255#132#214#255#255'{'#222 + +#247#255'9c{'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'{'#173#198#255'k' + +#206#247#255'9'#181#222#255#24#132#189#255'9'#181#231#255'9'#181#222#255'9' + +#173#239#255#0#165#222#255'k'#206#247#255'{'#214#247#255'{'#214#247#255#132 + +#214#247#255'{'#214#247#255#132#214#247#255'{'#214#247#255#132#222#247#255'{' + +#214#247#255#132#214#247#255'1c{'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#132#173#189#255'c'#198#247#255'k'#206#247#255'R'#189#247#255#0#165#222#255 + +#24#132#189#255#8#165#222#255#0#165#222#255'!'#156#239#255'k'#206#247#255'c' + +#198#247#255#132#222#247#255'{'#214#255#255'{'#222#247#255#132#214#247#255'{' + +#214#255#255'{'#214#247#255#132#214#247#255'9c{'#255#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0'{'#173#198#255'k'#206#247#255'c'#198#247#255'k'#206#247#255 + +'k'#206#247#255'J'#189#247#255')'#156#239#255'1'#156#206#255#8#165#222#255'1' + +#156#206#255'9'#173#239#255'9'#181#231#255'J'#181#239#255'R'#189#247#255'c' + +#198#247#255'k'#206#247#255'k'#206#247#255'c'#206#247#255'9Zs'#255#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#173#198#255'9cs'#255'9Z{'#255'9cs'#255'9Z' + +'{'#255'9Zs'#255'9c{'#255'9cs'#255'9c{'#255'9cs'#255'9c{'#255'9c{'#255'9Zs' + +#255'9c{'#255'9cs'#255'9Z{'#255'9cs'#255'9Z{'#255'9c{'#255#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#148#165 + +#255#132#156#165#255#132#156#165#255#140#156#165#255#132#156#173#255#132#156 + +#165#255#140#156#165#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#140#156#165#255#181#206#222#255#206#247#255#255#198#247#255#255#198#239#255 + +#255#173#247#255#255#173#231#247#255#181#206#214#255#132#156#165#255#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#148#165#255#132#173#198#255#181#206#214#255 + ,#181#206#214#255#181#206#222#255#181#206#214#255#140#189#206#255#140#198#214 + +#255#140#189#206#255#132#173#198#255#132#156#165#255#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#140#156#165#255#132#156#165#255#140#156#173#255#132#156#165#255#140#156 + +#165#255#132#156#165#255#140#156#165#255#140#156#165#255'k'#132#140#255'k{' + +#140#255'k'#132#140#255'k{'#140#255'k'#132#140#255'k{'#140#255'k{'#140#255'k' + +'{'#140#255'k{'#140#255'k{'#140#255'k{'#140#255'k{'#140#255'k{'#140#255#0#0#0 + +#0#0#0#0#0#0#0#0#0#132#156#173#255#206#247#255#255#198#239#255#255#198#247 + +#255#255#198#239#255#255#198#247#255#255#198#247#255#255#173#231#247#255#173 + +#231#247#255#173#231#247#255#173#231#247#255'{'#214#247#255#132#222#247#255 + +'{'#214#247#255#132#222#247#255'{'#222#247#255'k'#206#247#255'k'#206#247#255 + +'c'#206#247#255'k'#206#247#255#132#173#198#255'k{'#140#255#0#0#0#0#0#0#0#0 + +#132#156#165#255#198#239#255#255#198#247#255#255#198#239#255#255#173#231#247 + +#255#173#231#247#255#173#222#247#255#173#231#247#255#140#231#247#255'{'#214 + +#247#255'{'#222#247#255'k'#198#247#255'c'#206#247#255'k'#198#247#255'c'#206 + +#247#255'R'#181#247#255'J'#181#247#255'J'#181#247#255'9'#181#222#255'9'#181 + +#231#255'1'#156#206#255'9c{'#255#0#0#0#0#0#0#0#0#132#156#165#255#198#247#255 + +#255#198#239#255#255#173#247#255#255#165#231#239#255#173#231#247#255#165#231 + +#239#255#140#231#247#255#132#214#247#255'{'#214#247#255'k'#198#247#255'k'#206 + +#247#255'k'#198#247#255'k'#206#247#255'J'#181#239#255'R'#189#247#255'J'#189 + +#239#255'9'#181#222#255'9'#181#231#255'1'#156#206#255'1'#165#206#255'sZR'#255 + +#0#0#0#0#0#0#0#0#140#156#165#255#198#239#255#255#165#247#255#255#173#231#239 + +#255#173#231#247#255#165#231#239#255#148#231#255#255'{'#214#247#255#132#214 + +#255#255'{'#214#247#255'k'#206#247#255'c'#198#247#255'k'#206#247#255'J'#181 + +#239#255'R'#189#247#255'J'#181#239#255'9'#181#231#255'9'#181#231#255'9'#181 + +#231#255'9'#156#206#255'1'#156#206#255'9c{'#255#0#0#0#0#0#0#0#0#132#156#165 + +#255#198#247#255#255#173#231#247#255#173#222#247#255#165#231#239#255#173#231 + +#247#255#140#231#247#255#132#214#247#255'{'#222#247#255'k'#198#247#255'k'#206 + +#247#255'c'#206#247#255'k'#198#247#255'J'#189#247#255'R'#181#239#255'J'#189 + +#247#255'9'#181#222#255'9'#181#231#255'9'#173#239#255'1'#156#206#255#24#140 + +#198#255'R91'#255#0#0#0#0#0#0#0#0#140#156#165#255#198#239#255#255#173#231#239 + +#255#165#231#247#255#173#231#239#255#148#231#255#255'{'#214#247#255#132#214 + +#247#255'c'#198#247#255'k'#206#247#255'c'#198#247#255'k'#206#247#255'J'#181 + +#239#255'R'#189#247#255'J'#181#239#255'9'#181#231#255'9'#181#222#255'9'#181 + +#231#255'1'#173#239#255'9'#156#206#255#24#140#198#255'JB1'#255#0#0#0#0#0#0#0 + +#0#132#156#165#255#198#247#255#255#173#231#247#255#173#222#239#255#140#231 + +#255#255'{'#214#247#255'{'#214#247#255#132#222#247#255'c'#198#247#255'k'#206 + +#247#255'k'#198#247#255'J'#189#239#255'R'#181#247#255'J'#189#239#255'9'#181 + +#231#255'9'#181#231#255'9'#181#222#255'9'#165#247#255'9'#173#239#255'1'#156 + +#206#255#24#132#189#255'RB1'#255#0#0#0#0#0#0#0#0#140#156#165#255#198#239#255 + +#255#173#231#247#255#165#231#239#255#148#231#255#255'{'#214#247#255#132#214 + +#247#255'c'#198#247#255'k'#206#247#255'k'#206#247#255'J'#181#239#255'R'#189 + +#247#255'J'#181#247#255'9'#181#222#255'9'#181#231#255'9'#181#222#255'1'#173 + +#247#255'9'#173#239#255'1'#156#206#255'9'#156#206#255#24#140#198#255'JB1'#255 + +#0#0#0#0#0#0#0#0#132#156#165#255#173#231#247#255#165#231#239#255#148#231#255 + +#255'{'#214#247#255#132#214#247#255'c'#206#247#255'k'#206#247#255'k'#198#247 + +#255'c'#206#247#255'R'#181#247#255'J'#189#239#255'9'#181#231#255'9'#181#222 + +#255'9'#181#231#255'9'#165#239#255'9'#173#239#255'1'#156#206#255'9'#165#206 + +#255#24#132#198#255#24#140#189#255'J91'#255#0#0#0#0#0#0#0#0#132#148#165#255 + +#173#231#247#255#140#231#255#255'{'#214#247#255#132#214#247#255'c'#206#247 + +#255'k'#198#247#255'k'#206#247#255'c'#198#247#255'R'#189#247#255'J'#181#239 + +#255'9'#181#231#255'9'#181#222#255'9'#181#231#255'1'#173#239#255'9'#173#247 + +#255'1'#156#206#255'9'#156#214#255'1'#156#206#255#24#140#189#255#24#132#198 + +#255'JB1'#255#0#0#0#0#0#0#0#0#132#156#165#255#173#231#247#255'{'#214#247#255 + +#132#214#247#255'{'#222#247#255'k'#198#247#255'c'#206#247#255'k'#198#247#255 + +'J'#189#239#255'R'#181#239#255'J'#189#247#255'9'#181#222#255'9'#181#231#255 + +'9'#165#239#255'9'#173#239#255'1'#156#206#255'9'#165#206#255'1'#156#206#255 + +'9'#165#206#255#24#132#198#255#24#140#189#255#0#0#0#255#0#0#0#0#0#0#0#0#132 + +#156#165#255#173#231#247#255#132#214#247#255'{'#222#247#255'k'#198#247#255'k' + +#206#247#255'c'#198#247#255'k'#206#247#255'R'#189#247#255'J'#181#247#255'9' + +#181#222#255'9'#181#231#255'9'#181#231#255'9'#173#239#255'1'#173#247#255'9' + +#156#206#255'1'#156#206#255'9'#156#206#255'1'#165#206#255#24#132#189#255#24 + +#140#198#255#0#0#0#255#0#0#0#0#0#0#0#0#132#156#173#255#173#231#239#255'{'#214 + +#247#255'k'#198#247#255'J'#189#247#255'J'#181#239#255'R'#189#239#255'J'#181 + ,#247#255'9'#181#222#255'9'#173#239#255'1'#156#206#255'9'#156#206#255'1'#156 + +#206#255'1'#156#206#255'9'#156#206#255'1'#165#206#255#24#132#198#255#24#140 + +#198#255#24#132#189#255#24#140#198#255#24#132#189#255#0#0#0#255#0#0#0#0#0#0#0 + +#0#140#156#165#255#173#231#247#255'J'#181#247#255'J'#189#247#255#132#173#189 + +#255'9'#181#231#255'1'#156#206#255'9'#156#206#255'1'#156#206#255'1'#156#206 + +#255#24#132#189#255#24#140#198#255#24#132#189#255#24#140#198#255#24#140#189 + +#255#24#132#198#255#24#140#189#255#24#132#189#255#24#140#198#255#24#132#189 + +#255#24#140#198#255#0#0#0#255#0#0#0#0#0#0#0#0'k{'#140#255'9cs'#255'9c{'#255 + +'R9)'#255'JB1'#255'RB1'#255'JB1'#255'RB1'#255'JB1'#255'RB1'#255#0#0#0#255#0#0 + +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255 + +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#10'TImageList'#11'SmallImages'#4'left'#2'('#3'top'#2#16#6'Bitmap'#10 + +#14#24#0#0'Li'#6#0#0#0#16#0#0#0#16#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#206#189#173#255#198#173#165#255#198#173#156#255#198#173#165#255 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#140#189#206#255#198#173#165#255#239#231#222#255#198#247#255#255#198#247 + +#255#255#189#198#206#255#206#189#173#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#189#181#255#206#189#173#255#198#239#255#255 + +#198#247#255#255#198#239#255#255#173#231#239#255#140#231#255#255'c'#206#247 + +#255#198#173#156#255#140#156#165#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#206#189#173#255#198#214#222#255#198#247#255#255#198#247#255#255#198#239#255 + +#255#173#239#255#255#165#231#239#255'{'#214#247#255'k'#198#247#255'c'#206#247 + +#255#140#189#214#255#198#173#156#255#132#173#198#255#0#0#0#0#198#173#156#255 + +#206#181#173#255#198#247#255#255#198#239#255#255#198#239#255#255#198#247#255 + +#255#165#239#255#255#173#231#239#255'{'#214#247#255'c'#198#247#255'k'#206#247 + +#255'k'#198#239#255'k'#206#247#255'J'#181#239#255#140#173#198#255#140#156#165 + +#255#198#173#156#255#173#247#255#255#165#231#247#255#173#231#239#255#173#231 + +#239#255'{'#214#247#255'k'#198#247#255'c'#206#247#255'k'#206#247#255'k'#206 + +#239#255'J'#173#239#255'B'#181#239#255'J'#173#231#255'B'#181#239#255')'#189 + +#239#255#189#156#140#255#198#173#165#255#173#231#239#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#247#239#231#255#255#247#239#255#255#239#231#255#255#247#239 + +#255#239#222#222#255'B'#181#239#255#148#132'{'#255#198#173#156#255#206#189 + +#181#255#247#239#239#255#255#239#231#255#231#231#222#255#255#239#239#255#255 + +#239#231#255#247#247#239#255#255#239#231#255#247#239#239#255#255#239#231#255 + +#247#222#206#255#247#247#231#255#255#214#198#255#148#132'{'#255#148#132'{' + +#255#198#173#165#255#247#206#181#255#222#198#173#255#247#239#239#255#255#239 + +#239#255#231#189#148#255#231#181#148#255#198#173#165#255#198#173#156#255#198 + +#173#165#255#198#173#156#255#231#231#222#255#255#222#198#255#181#156#140#255 + +#231#173#132#255#148#132'{'#255#198#165#140#255#255#255#255#255#255#222#198 + +#255#222#198#173#255#222#198#173#255#222#189#173#255#222#206#198#255#222#198 + +#173#255#222#198#181#255#222#198#173#255#198#173#165#255#198#173#156#255#181 + +#156#140#255#231#173#140#255#255#214#156#255#140#132#132#255#189#165#148#255 + +#255#255#255#255#255#255#255#255#189#165#140#255#222#206#198#255#255#247#239 + +#255#247#239#239#255#255#247#239#255#247#239#239#255#255#222#206#255#255#222 + +#198#255#222#165'{'#255#181#140's'#255#255#214#156#255#255#206#148#255#148 + +#132'{'#255#198#165#140#255#255#255#255#255#198#173#165#255#222#206#198#255 + +#247#239#239#255#247#239#231#255#255#239#239#255#247#239#231#255#255#247#231 + +#255#247#222#198#255#247#222#198#255#255#214#173#255#231#173#132#255#181#132 + +'s'#255#255#181'{'#255#206'sJ'#255#181#156#140#255#198#173#165#255#222#206 + +#198#255#255#255#255#255#247#247#231#255#255#222#206#255#247#231#198#255#255 + +#222#206#255#247#222#198#255#255#214#173#255#255#222#181#255#255#214#156#255 + +#255#206#148#255#231#148'c'#255#198'{J'#255#206'sB'#255#189#156#132#255#247 + +#214#189#255#255#255#255#255#255#222#206#255#255#222#173#255#255#214#156#255 + +#255#198#140#255#255#198#140#255#255#198#148#255#255#181'{'#255#255#181'{' + +#255#247#165'{'#255#239#165'{'#255#231#148'c'#255#214#132'Z'#255#181'c1'#255 + +#181#156#140#255#181#156#140#255#181#140's'#255#181#132's'#255#181#140's'#255 + +#140#132#132#255#206'sJ'#255#198'sJ'#255#198'{B'#255#198'sJ'#255#198'sJ'#255 + +#198'sJ'#255#181'c1'#255#189'c1'#255#181'c1'#255#189'c1'#255#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#255#255#255#0#255#255#255#0#255 + +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255 + ,#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0 + +#255#255#255#0#255#255#255#0#255#255#255#0#255#255'J91'#255#255#0#255#255'JB' + +'1'#255#255#0#255#255'JB1'#255#255#0#255#255'JB1'#255#255#0#255#255'R91'#255 + +#255#0#255#255'JB1'#255#255#0#255#255'RB1'#255#255#0#255#255'RB1'#255#181#156 + +#140#255#255#255#255#255#148#132'{'#255#255#255#255#255#148#132#132#255#255 + +#255#255#255#148#132'{'#255#255#255#255#255#148#132#132#255#255#255#255#255 + +'Rck'#255#255#255#255#255'RZk'#255#255#255#255#255'Rck'#255#255#0#255#255#247 + +#165#140#255#247#173#148#255#247#165'{'#255#222#165'{'#255#222#165'{'#255#231 + +#148'k'#255#231#148'c'#255#231#148'k'#255#214#132'R'#255#222'{J'#255#214#132 + +'R'#255#206'{J'#255#206'sJ'#255#198'{B'#255#206'sJ'#255'RB1'#255#239#173#148 + +#255#247#239#239#255#255#247#239#255#247#239#239#255#255#247#239#255#247#247 + +#239#255#247#239#239#255#247#173#140#255#247#165'{'#255#247#165'{'#255#247 + +#165'{'#255#239#165'{'#255#247#165'{'#255#247#165'{'#255#247#165'{'#255'RB1' + +#255#247#173#140#255#247#165#140#255#239#165's'#255#247#165'{'#255#239#165's' + +#255#247#165'{'#255#231#148'c'#255#231#148'c'#255#222#148'k'#255#214#132'R' + +#255#222'{J'#255#222'{J'#255#222'{J'#255#222'{J'#255#222'{J'#255'RB1'#255#189 + +#173#165#255#255#255#255#255#255#255#255#255#222#165'{'#255#255#255#255#255 + +#255#255#255#255#222#165'{'#255#255#255#255#255#255#255#255#255#222#165'{' + +#255#255#255#255#255#255#255#255#255#222#165'{'#255#255#247#239#255#247#239 + +#239#255'JB1'#255#198#173#165#255#255#255#255#255#255#255#255#255#181#156#140 + +#255#255#255#255#255#255#255#255#255#181#156#140#255#255#255#255#255#255#255 + +#255#255#181#156#140#255#255#255#255#255#255#247#239#255#181#148#140#255#255 + +#247#239#255#222#206#198#255'JB9'#255#198#173#156#255#214#173#148#255#181#156 + +#140#255#189#132's'#255#222#165'{'#255#181#156#140#255#181#140's'#255#222#165 + +'{'#255#181#156#140#255'B'#181#239#255')'#148#222#255#24'B'#206#255#24'J'#206 + +#255#222#165'{'#255#0#0#0#0'RB9'#255#198#173#165#255#255#255#255#255#255#255 + +#255#255#222#165'{'#255#255#255#255#255#255#255#255#255#222#165'{'#255#255 + +#255#255#255#255#255#255#255')'#156#222#255#255#255#255#255#255#247#239#255 + +#24'B'#198#255#255#247#239#255#222#206#206#255'JB1'#255#198#173#156#255#255 + +#255#255#255#255#255#255#255#181#156#140#255#255#255#255#255#255#255#255#255 + +#181#156#140#255#255#255#255#255#255#239#239#255#24'B'#206#255#255#247#239 + +#255#255#239#231#255#24'B'#206#255#255#247#239#255#206#189#173#255'JB1'#255 + +#198#173#165#255#214#173#148#255#0#0#0#0#189#140's'#255#222#165'{'#255#181 + +#156#140#255#189#132's'#255#222#165'{'#255#0#0#0#0'!J'#198#255#24'B'#206#255 + +#24'J'#206#255#24'B'#206#255#222#165'{'#255#189#156#140#255'JB1'#255#198#181 + +#165#255#255#255#255#255#255#255#255#255#206#173#148#255#255#255#255#255#255 + +#255#255#255#222#165'{'#255#255#247#239#255#255#239#239#255#222#165'{'#255 + +#255#247#239#255#255#239#231#255#222#165'{'#255#255#231#206#255#198#181#173 + +#255'RB9'#255#198#173#156#255#255#255#255#255#255#255#255#255#181#148#132#255 + +#255#255#255#255#255#247#239#255#0#0#0#0#247#239#239#255#247#239#239#255#0#0 + +#0#0#247#239#239#255#247#247#239#255#0#0#0#0#255#222#206#255#206#189#181#255 + +'JB1'#255#198#173#165#255#198#173#165#255#0#0#0#0#189#140's'#255#231#181#148 + +#255#214#173#148#255#181#132's'#255#239#189#148#255#0#0#0#0#189#132's'#255 + +#198#173#156#255#181#156#140#255#189#132's'#255#206#173#140#255#181#156#140 + +#255'RB1'#255#0#0#0#0'JB9'#255'RB1'#255'JB9'#255'RB9'#255'JB1'#255'RB9'#255 + +'JB1'#255'JB9'#255'RB1'#255'JB9'#255'RB1'#255'JB9'#255'RB1'#255'RB9'#255'JB1' + +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#189#173#255#206#189#181#255#206#189#173 + +#255#206#189#181#255#206#189#173#255#206#189#181#255#198#173#165#255#198#173 + +#156#255#198#173#165#255#198#173#156#255#198#173#165#255#198#165#140#255#181 + +#156#140#255#181#156#132#255#181#148#140#255#181#156#140#255#206#189#181#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255'Rcc' + +#255#198#189#173#255#255#255#255#255#239#222#222#255'Z{'#140#255#148#132'{' + +#255'Z{'#140#255#189#198#206#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#247#239#255#255#239#239#255#222#214 + +#206#255'J91'#255#206#189#181#255#255#255#255#255'Jcc'#255'c{'#140#255#140 + +#156#173#255#132#156#165#255#148#132'{'#255#239#231#222#255#255#255#255#255 + +#247#247#239#255#255#255#255#255#247#239#239#255#247#239#231#255#255#239#231 + +#255#222#206#198#255'JB1'#255#206#189#173#255#255#255#255#255'RB9'#255'J91' + +#255#239#231#222#255#189#198#206#255#148#132'{'#255#231#222#222#255#247#247 + ,#239#255#247#189#165#255#247#189#156#255#255#181'{'#255#247#165'{'#255#247 + +#165'{'#255#206#189#181#255'JB1'#255#198#173#165#255#255#255#255#255'Rck'#255 + +'RB9'#255#206#189#181#255#148#132'{'#255'Rck'#255#255#255#255#255#255#239#239 + +#255#247#247#231#255#247#239#239#255#255#247#239#255#247#239#239#255#247#231 + +#198#255#206#189#181#255'RB1'#255#198#173#165#255#255#255#255#255#239#231#222 + +#255'Rck'#255#181#156#132#255#140#156#173#255'RZc'#255#198#214#222#255#247 + +#247#231#255#247#206#189#255#198#165#140#255#181#156#132#255#181#156#132#255 + +#181#132's'#255#206#189#181#255'JB1'#255#189#173#156#255#255#247#239#255#16 + +'{'#189#255#140#173#198#255#24'B'#206#255#24#132#189#255#24'J'#206#255#24'B' + +#206#255#255#247#239#255#255#222#198#255#247#222#206#255#255#222#206#255#247 + +#214#189#255#255#214#189#255#231#189#148#255'J99'#255#198#173#156#255#239#231 + +#222#255#24'B'#198#255'J'#181#239#255')'#156#222#255'!J'#206#255#24#132#189 + +#255#24'B'#198#255#255#239#239#255#222#198#173#255#198#165#148#255#181#156 + +#132#255#181#156#140#255#181#132's'#255#239#189#156#255'JB1'#255#198#165#148 + +#255#247#247#239#255#189#198#206#255#24'B'#206#255'!J'#198#255#24'B'#206#255 + +'!J'#206#255#198#165#140#255#255#231#206#255#247#222#198#255#247#214#189#255 + +#247#214#198#255#255#222#189#255#247#214#189#255#231#181#140#255'JB9'#255#181 + +#156#140#255#255#222#198#255#255#222#198#255#222#206#198#255#231#198#173#255 + +#222#198#173#255#231#198#181#255#222#198#173#255#239#198#165#255#231#181#156 + +#255#231#189#148#255#231#181#148#255#231#173#140#255#231#181#140#255#231#173 + +#140#255'RB1'#255#181#156#132#255'Rck'#255'JB1'#255'JB1'#255'RB9'#255'JB1' + +#255'JB1'#255'RB9'#255'JB1'#255'RB1'#255'JB9'#255'RB9'#255'JB1'#255'JB9'#255 + +'RB9'#255'JB9'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#132#173#198#255#140#156#165#255#132#156#173#255#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#222#198#173#255#206 + +#189#181#255#206#189#173#255#206#189#181#255#140#156#165#255#173#231#239#255 + +#173#231#247#255#140#198#214#255'Rcc'#255#198#173#165#255#198#173#156#255#198 + +#165#148#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#206#189#173#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#132#156#165#255#132#156#173#255#148#132'{' + +#255#140#189#214#255'c{'#140#255#255#247#239#255#231#222#222#255#239#231#222 + +#255'RZc'#255#0#0#0#0#0#0#0#0#0#0#0#0#206#189#181#255#255#255#255#255#255#255 + +#255#255#140#156#173#255'{'#214#247#255#140#231#255#255'{'#214#247#255'c'#206 + +#247#255#140#156#165#255'Zs'#140#255#231#231#222#255#222#206#198#255#181#156 + +#132#255#0#0#0#0#0#0#0#0#0#0#0#0#206#189#181#255#255#255#255#255#255#255#255 + +#255#132#156#165#255'c{'#140#255'c{'#140#255'c{'#140#255'c{'#140#255'Z{'#140 + +#255#140#156#173#255#132#173#189#255#24'B'#206#255#181#156#140#255#0#0#0#0#0 + +#0#0#0#0#0#0#0#206#189#173#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#247#239#239#255#255#239#239#255#247#247#239#255#239#222#222#255#239#231 + +#222#255#140#173#198#255#24'B'#206#255#140#156#165#255#148#132#132#255#0#0#0 + +#0#0#0#0#0#0#0#0#0#198#173#156#255#255#255#255#255#255#255#255#255#255#239 + +#239#255#247#247#231#255#255#239#239#255#247#239#231#255#231#231#222#255')' + +#148#222#255#24'J'#206#255#140#156#165#255#222#214#198#255'RZk'#255#0#0#0#0#0 + +#0#0#0#0#0#0#0#198#173#165#255#255#255#255#255#198#247#255#255#198#214#214 + +#255#255#239#231#255#247#239#239#255#239#231#222#255#140#173#189#255#24'B' + +#206#255'Z{'#140#255#255#222#206#255#231#198#181#255'JB1'#255#0#0#0#0#0#0#0#0 + +#0#0#0#0#198#173#156#255#247#239#239#255'B'#173#239#255'J'#181#239#255#132 + +#173#198#255#198#214#214#255#132#173#198#255#24'B'#206#255'!J'#206#255#255 + +#222#198#255#247#222#189#255#198#173#165#255'JB1'#255#0#0#0#0#0#0#0#0#0#0#0#0 + +#198#173#156#255#255#247#239#255'!B'#198#255#24'B'#206#255')'#156#222#255')' + +#148#222#255#24'J'#198#255#24'B'#206#255#206#189#173#255#255#222#198#255#222 + +#206#198#255#198#173#165#255'JB9'#255#0#0#0#0#0#0#0#0#0#0#0#0#198#173#165#255 + +#247#247#239#255#198#214#214#255#24'B'#206#255'!J'#206#255'!B'#206#255#24'J' + +#206#255#140#156#165#255#247#214#181#255#247#206#189#255#222#198#173#255#214 + +#173#140#255'RB1'#255#0#0#0#0#0#0#0#0#0#0#0#0#198#173#156#255#255#239#231#255 + +#255#247#239#255#239#231#222#255'!B'#206#255#24'J'#206#255'c{'#140#255#222 + +#206#198#255#247#206#181#255#222#206#198#255#222#198#181#255#214#173#148#255 + +'JB9'#255#0#0#0#0#0#0#0#0#0#0#0#0#198#173#165#255#247#247#239#255#222#206#198 + +#255#222#206#198#255#222#206#198#255#140#156#165#255#206#189#181#255#231#189 + +#148#255#198#173#165#255#198#173#156#255#214#173#140#255#189#165#148#255'RB1' + +#255#0#0#0#0#0#0#0#0#0#0#0#0#214#173#148#255'R91'#255'JB1'#255'JB1'#255'JB1' + +#255'Rck'#255'RB1'#255'JB9'#255'RB1'#255'JB9'#255'RB1'#255'JB9'#255#0#0#0#0#0 + ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#140#189#214#255#140#198#206#255#148#198#214#255 + +#140#189#214#255#140#198#214#255#148#198#214#255#140#189#214#255#140#198#206 + +#255#148#189#214#255#140#198#214#255#132#173#189#255#132#173#198#255#132#173 + +#198#255#132#173#198#255#0#0#0#0#0#0#0#0#148#189#206#255#198#247#255#255#198 + +#239#255#255#198#247#255#255#198#247#255#255#198#239#255#255#198#247#255#255 + +#198#247#255#255#198#247#255#255#198#247#255#255#206#239#255#255#198#247#255 + +#255#206#247#255#255'Z{'#140#255#0#0#0#0#0#0#0#0#140#198#214#255#198#247#255 + +#255#173#239#255#255#173#239#247#255#173#239#255#255#173#239#247#255#173#239 + +#255#255#173#239#255#255#173#239#255#255#165#239#255#255#173#239#255#255#165 + +#239#247#255#173#239#255#255'Z{'#140#255#0#0#0#0#0#0#0#0#132#173#189#255#173 + +#239#255#255#173#239#255#255#165#239#255#255#173#239#255#255#165#239#255#255 + +#173#239#255#255#165#239#247#255#173#239#255#255#165#239#247#255#173#239#255 + +#255#173#239#255#255#173#247#255#255'RZk'#255#0#0#0#0#0#0#0#0#132#173#198#255 + +#173#231#239#255#165#239#255#255#173#247#247#255#173#239#255#255#173#247#255 + +#255#165#239#255#255#173#239#255#255#173#247#255#255#173#239#255#255#165#239 + +#247#255#173#239#255#255#165#239#255#255'Rcc'#255#0#0#0#0#0#0#0#0#132#173#198 + +#255#140#231#247#255#140#231#255#255#140#231#255#255#140#231#247#255#140#231 + +#255#255#140#231#247#255#140#231#247#255#140#231#255#255#140#231#247#255#140 + +#231#255#255#140#231#255#255#140#231#255#255'Rcc'#255#0#0#0#0#0#0#0#0#132#173 + +#198#255'k'#198#247#255#140#231#247#255#140#231#255#255#140#222#255#255#140 + +#231#247#255#140#231#255#255#140#231#255#255#140#222#247#255#140#231#255#255 + +#140#231#247#255#140#231#255#255#140#231#247#255'RZk'#255#0#0#0#0#0#0#0#0#140 + +#173#189#255'B'#181#239#255'{'#214#247#255#140#231#255#255#140#231#247#255 + +#140#231#255#255#140#222#255#255#140#231#247#255#140#231#255#255#140#231#255 + +#255#140#231#255#255#140#231#255#255#140#231#255#255'Rcc'#255#0#0#0#0#0#0#0#0 + +#132#173#198#255'J'#173#239#255')'#189#239#255'J'#181#239#255'B'#173#239#255 + +')'#156#222#255'k'#206#239#255#140#231#255#255#140#231#247#255#140#222#255 + +#255#140#231#247#255#140#231#255#255#140#231#255#255'RZc'#255#0#0#0#0#0#0#0#0 + +#132#173#189#255'k'#206#247#255')'#156#222#255')'#189#239#255')'#189#239#255 + +')'#156#222#255')'#189#239#255#140#222#255#255#140#231#255#255#140#231#247 + +#255#140#231#255#255#140#231#247#255#140#231#255#255'Rck'#255#0#0#0#0#0#0#0#0 + +#132#173#198#255'k'#206#247#255'J'#173#239#255')'#156#222#255'1'#189#247#255 + +')'#189#239#255')'#156#222#255'{'#214#247#255'{'#214#247#255'{'#214#255#255 + +'{'#214#247#255'{'#214#247#255'{'#214#247#255'Rcc'#255#0#0#0#0#0#0#0#0#140 + +#173#198#255'{'#214#247#255'k'#206#239#255'J'#181#239#255')'#156#222#255'1' + +#156#231#255')'#156#222#255'J'#181#239#255'{'#214#247#255'k'#206#247#255'{' + +#214#247#255'{'#214#247#255'{'#222#255#255'Rck'#255#0#0#0#0#0#0#0#0#132#173 + +#189#255'k'#206#247#255'{'#214#247#255'k'#198#247#255'J'#181#231#255')'#148 + +#222#255')'#156#222#255#24#132#189#255')'#156#222#255'J'#173#239#255'J'#181 + +#239#255'J'#181#239#255'J'#173#239#255'Rcc'#255#0#0#0#0#0#0#0#0#140#173#198 + +#255'Zs'#140#255'c{'#140#255'Z{'#140#255'c{'#140#255'c{'#140#255'Zck'#255'RZ' + +'c'#255'Zck'#255'Rcc'#255'RZk'#255'Rcc'#255'Rcc'#255'Rck'#255#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#156#165#255#132#156#165#255#140#156#173#255 + +#132#156#165#255#140#156#165#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#156#173#255#173#231#247#255#173#239 + +#255#255#173#239#255#255#173#247#255#255#140#231#255#255#132#156#173#255#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#156 + +#165#255#132#156#165#255#140#156#165#255#132#156#165#255#132#156#165#255#140 + +#156#165#255#140#156#165#255#132#156#165#255#140#156#165#255#132#156#173#255 + +#132#156#165#255#140#156#173#255#132#156#165#255#132#156#165#255#0#0#0#0#0#0 + +#0#0#132#156#173#255#206#247#255#255#198#247#255#255#198#239#255#255#198#247 + +#255#255#173#239#255#255#173#239#255#255#173#239#255#255#140#231#255#255#140 + +#231#255#255'{'#214#247#255'k'#206#247#255'c'#198#247#255'k'#206#247#255'Zs' + +#140#255#0#0#0#0#132#156#165#255#198#239#255#255#173#239#255#255#173#239#255 + +#255#173#239#255#255#165#239#255#255#140#231#255#255#140#231#255#255#140#231 + +#255#255'c'#198#239#255'k'#206#247#255'J'#173#239#255'J'#181#239#255')'#156 + ,#222#255'Z{'#140#255#0#0#0#0#132#156#173#255#198#247#255#255#173#239#255#255 + +#165#239#255#255#173#239#255#255#140#231#247#255#140#231#255#255#140#231#247 + +#255'{'#214#247#255'k'#206#247#255'c'#198#247#255'J'#181#231#255')'#148#222 + +#255#24#132#189#255'Zck'#255#0#0#0#0#140#156#165#255#198#247#255#255#165#239 + +#247#255#173#247#255#255#173#239#247#255#140#231#255#255#140#231#255#255'{' + +#214#247#255'c'#206#247#255'k'#198#239#255'J'#181#239#255'J'#181#239#255'1' + +#156#222#255#24#132#189#255'Rcc'#255#0#0#0#0#132#156#165#255#173#239#255#255 + +#173#239#255#255#165#239#255#255#140#231#255#255#140#231#247#255'{'#214#247 + +#255'k'#198#247#255'k'#206#247#255'J'#173#239#255'J'#181#231#255'J'#173#239 + +#255')'#156#222#255#24#132#189#255'RB1'#255#0#0#0#0#140#156#173#255#165#231 + +#239#255#173#239#255#255#140#231#247#255#140#231#255#255'{'#214#247#255'c' + +#206#247#255'k'#206#247#255'B'#173#231#255'J'#181#239#255'J'#181#239#255')' + +#148#222#255')'#156#222#255#24#132#189#255'JB9'#255#0#0#0#0#148#132'{'#255 + +#173#231#247#255#140#231#255#255#140#231#255#255'{'#214#247#255'k'#198#247 + +#255'k'#206#239#255'J'#173#239#255'J'#181#239#255'J'#181#231#255')'#148#222 + +#255')'#156#231#255'!'#132#189#255#24#132#189#255'RB1'#255#0#0#0#0'Z{'#140 + +#255#173#231#239#255'c'#206#247#255'J'#173#231#255'J'#181#239#255')'#156#222 + +#255')'#148#231#255#24#132#181#255#24#132#189#255#24#132#189#255#24#132#189 + +#255#24#132#181#255#24#132#189#255#24#132#189#255#0#0#0#255#0#0#0#0'Z{'#140 + +#255'cs'#140#255'Rcc'#255'Rck'#255'RB1'#255'RB1'#255'RB1'#255#0#0#0#255#0#0#0 + +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#10'TImageList'#10'ToolImages'#6'Height'#2#12#5'Width'#2#12#4'left'#3#144 + +#0#3'top'#2#16#6'Bitmap'#10#142#13#0#0'Li'#6#0#0#0#12#0#0#0#12#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#132#132#132#255#132#132#132#255#132#132#132#255#132#132#132#255 + +#132#132#132#255#132#132#132#255#132#132#132#255#132#132#132#255#132#132#132 + +#255#132#132#132#255#132#132#132#255#0#0#0#255#132#132#132#255#0#0#0#255#0 + +#255#255#255#255#255#255#255#0#255#255#255#255#255#255#255#0#255#255#255#255 + +#255#255#255#0#255#255#255#255#255#255#255#0#0#0#255#0#0#0#255#132#132#132 + +#255#198#198#198#255#0#0#0#255#0#255#255#255#255#255#255#255#0#255#255#255 + +#255#255#255#255#0#255#255#255#255#255#255#255#0#0#0#255#0#132#132#255#0#0#0 + +#255#132#132#132#255#0#255#255#255#198#198#198#255#0#0#0#255#0#255#255#255 + +#255#255#255#255#0#255#255#255#255#255#255#255#0#0#0#255#0#132#132#255#198 + +#198#198#255#0#0#0#255#132#132#132#255#255#255#255#255#255#255#255#255#0#132 + +#132#255#0#0#0#255#0#255#255#255#255#255#255#255#0#0#0#255#0#132#132#255#198 + +#198#198#255#198#198#198#255#0#0#0#255#132#132#132#255#0#255#255#255#0#132 + +#132#255#198#198#198#255#0#132#132#255#0#0#0#255#0#0#0#255#0#132#132#255#198 + +#198#198#255#0#132#132#255#198#198#198#255#0#0#0#255#132#132#132#255#0#132 + +#132#255#198#198#198#255#198#198#198#255#198#198#198#255#0#132#132#255#0#132 + +#132#255#198#198#198#255#198#198#198#255#198#198#198#255#0#132#132#255#0#0#0 + +#255#132#132#132#255#198#198#198#255#198#198#198#255#198#198#198#255#198#198 + +#198#255#198#198#198#255#198#198#198#255#198#198#198#255#198#198#198#255#198 + +#198#198#255#198#198#198#255#0#0#0#255#132#132#132#255#132#132#132#255#132 + +#132#132#255#132#132#132#255#132#132#132#255#132#132#132#255#132#132#132#255 + +#132#132#132#255#132#132#132#255#132#132#132#255#132#132#132#255#0#0#0#255#0 + +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0 + +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#132#132#132#255#132#132#132#255#132#132#132#255#132#132#132#255#132 + +#132#132#255#132#132#132#255#132#132#132#255#132#132#132#255#132#132#132#255 + +#132#132#132#255#132#132#132#255#0#0#0#255#132#132#132#255#0#0#0#255#0#255 + +#255#255#255#255#255#255#0#255#255#255#255#255#255#255#0#255#255#255#255#255 + +#255#255#0#255#255#255#255#255#255#255#0#0#0#255#0#0#0#255#132#132#132#255 + +#198#198#198#255#0#0#0#255#0#255#255#255#255#255#255#255#0#255#255#255#255 + +#255#255#255#0#255#255#255#255#255#255#255#0#0#0#255#0#0#132#255#0#0#0#255 + +#132#132#132#255#0#255#255#255#198#198#198#255#0#0#0#255#0#255#255#255#255 + +#255#255#255#0#255#255#255#255#255#255#255#0#0#0#255#0#0#132#255#198#198#198 + +#255#0#0#0#255#132#132#132#255#255#255#255#255#255#255#255#255#0#0#132#255#0 + ,#0#0#255#0#0#255#255#0#0#255#255#0#0#0#255#0#0#132#255#198#198#198#255#0#0 + +#255#255#0#0#255#255#132#132#132#255#0#255#255#255#0#0#132#255#198#198#198 + +#255#0#0#132#255#0#0#255#255#0#0#255#255#0#0#255#255#198#198#198#255#0#0#255 + +#255#0#0#255#255#0#0#255#255#132#132#132#255#0#0#132#255#198#198#198#255#198 + +#198#198#255#198#198#198#255#0#0#132#255#0#0#255#255#0#0#255#255#0#0#255#255 + +#0#0#255#255#0#0#255#255#0#0#0#255#132#132#132#255#198#198#198#255#198#198 + +#198#255#198#198#198#255#198#198#198#255#198#198#198#255#198#198#198#255#0#0 + +#255#255#0#0#255#255#0#0#255#255#198#198#198#255#0#0#0#255#132#132#132#255 + +#132#132#132#255#132#132#132#255#132#132#132#255#132#132#132#255#132#132#132 + +#255#0#0#255#255#0#0#255#255#0#0#255#255#0#0#255#255#0#0#255#255#0#0#0#255#0 + +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#255#255#0#0#255#255#0#0 + +#255#255#0#0#0#255#0#0#255#255#0#0#255#255#0#0#255#255#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#255#255#0#0#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255 + +#255#0#0#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#132#132#255#198 + +#198#198#255#132#132#132#255#132#132#132#255#132#132#132#255#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#132#132#255#255#255#255#255#132#132#132 + +#255#198#198#198#255#255#255#255#255#255#255#255#255#132#132#132#255#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#132#132#132#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#0#0#0#255#198#198#198#255#132#132#132#255#255#255#255#255#132 + +#132#132#255#0#0#0#0#0#0#0#0#0#0#0#0#132#132#132#255#255#255#255#255#255#255 + +#255#255#132#132#132#255#132#132#0#255#0#0#0#255#132#132#0#255#198#198#198 + +#255#132#132#132#255#0#0#0#0#0#0#0#0#0#0#0#0#132#132#132#255#255#255#255#255 + +#255#255#255#255#132#132#132#255#0#0#0#255#255#255#0#255#132#132#132#255#132 + +#132#132#255#132#132#132#255#0#0#0#0#198#198#198#255#198#198#198#255#132#132 + +#132#255#255#255#255#255#255#255#255#255#132#132#132#255#0#0#0#255#255#255 + +#255#255#132#132#132#255#198#198#198#255#132#132#132#255#198#198#198#255#0#0 + +#0#255#0#0#0#255#132#132#132#255#255#255#255#255#255#255#255#255#132#132#132 + +#255#132#132#0#255#0#0#0#255#132#132#0#255#132#132#132#255#132#132#132#255#0 + +#0#0#255#132#132#132#255#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#255#255#255 + +#255#255#132#132#132#255#132#132#132#255#132#132#132#255#0#0#0#255#0#0#0#0 + +#132#132#132#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#255#0#0#0 + +#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#132#132#132#255#198#198#198#255#132#132#132#255#198#198#198#255#0#0#0 + +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#132#132#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#198#198#198#255#132 + +#132#132#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#132#132#255#198#198#198#255 + +#132#132#132#255#198#198#198#255#132#132#132#255#198#198#198#255#132#132#132 + +#255#132#132#132#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132 + +#132#132#255#198#198#198#255#132#132#132#255#132#132#132#255#132#132#132#255 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#132#132#255#255#255#255 + +#255#132#132#132#255#198#198#198#255#255#255#255#255#255#255#255#255#132#132 + +#132#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#132#132#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#0#0#0#255#198#198#198#255#132#132#132#255#255 + +#255#255#255#132#132#132#255#0#0#0#0#0#0#0#0#0#0#0#0#132#132#132#255#255#255 + +#255#255#255#255#255#255#132#132#132#255#132#132#0#255#0#0#0#255#132#132#0 + +#255#198#198#198#255#132#132#132#255#0#0#0#0#0#0#0#0#0#0#0#0#132#132#132#255 + +#255#255#255#255#255#255#255#255#132#132#132#255#0#0#0#255#255#255#0#255#132 + +#132#132#255#132#132#132#255#132#132#132#255#0#0#0#0#198#198#198#255#198#198 + +#198#255#132#132#132#255#255#255#255#255#255#255#255#255#132#132#132#255#0#0 + +#255#255#0#0#255#255#0#0#255#255#0#0#255#255#132#132#132#255#198#198#198#255 + +#0#0#0#255#0#0#0#255#132#132#132#255#255#255#255#255#255#255#255#255#0#0#255 + +#255#255#255#255#255#0#0#255#255#0#0#255#255#255#255#255#255#0#0#255#255#0#0 + +#0#255#132#132#132#255#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#255#0#0#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#0#0#255#255 + +#132#132#132#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#255#255#0#0 + +#255#255#255#255#255#255#255#255#255#255#0#0#255#255#0#0#255#255#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#132#132#255#0#0#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#0#0#255#255#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#132#132#132#255#255#255#255#255#0#0#255#255#255#255#255#255#0#0 + +#255#255#0#0#255#255#255#255#255#255#0#0#255#255#0#0#0#0#0#0#0#0#0#0#0#0#132 + +#132#132#255#198#198#198#255#132#132#132#255#198#198#198#255#0#0#255#255#0#0 + +#255#255#0#0#255#255#0#0#255#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#132#132#255#132#132#132#255#132#132#132#255#132#132#132#255#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#132#255#255#255#255#255#255 + ,#255#255#255#255#255#255#255#198#198#198#255#132#132#132#255#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#255#132#132#132#255#198#198 + +#198#255#0#132#132#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#132#132#132#255#198#198#198#255#255#255#255#255#255#255#255#255#0#132 + +#132#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#0#0#0#0 + +#255#0#0#0#255#132#132#132#255#198#198#198#255#0#0#0#255#0#0#0#255#0#0#0#0#0 + +#0#0#255#0#0#0#0#198#198#198#255#0#0#0#255#0#0#0#255#132#132#132#255#198#198 + +#198#255#255#255#255#255#255#255#255#255#132#132#132#255#0#0#0#255#0#0#0#255 + +#0#0#0#255#198#198#198#255#0#0#0#0#0#0#0#255#255#255#255#255#0#0#0#255#0#0#0 + +#255#132#132#132#255#198#198#198#255#0#0#0#255#0#0#0#255#255#255#255#255#0#0 + +#0#255#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#255#132#132#132#255#198#198#198 + +#255#198#198#198#255#132#132#132#255#132#132#132#255#0#0#0#255#255#255#255 + +#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#255#0#0#0#255#0 + +#0#0#255#0#0#0#255#0#0#0#255#255#255#255#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#132#132#132#255#132#132#132#255#132#132#132#255#132#132 + +#132#255#132#132#132#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#198#198#198#255#132#132#132#255#0#0#0#255#0#0#0#255#0 + +#0#0#255#0#0#0#255#0#0#0#255#132#132#132#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#132#132#255#132#132#132#255#132#132#132#255#132#132#132 + +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#132#132#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#198#198#198#255#132#132#132 + +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#255#132 + +#132#132#255#198#198#198#255#0#132#132#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#132#132#132#255#198#198#198#255#255#255#255#255#255 + +#255#255#255#0#132#132#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#255#0#0#0#0#0#0#0#255#0#0#0#255#132#132#132#255#198#198#198#255#0#0#0#255#0 + +#0#0#255#0#0#0#0#0#0#0#255#0#0#0#0#198#198#198#255#0#0#0#255#0#0#0#255#132 + +#132#132#255#198#198#198#255#255#255#255#255#255#255#255#255#0#0#255#255#0#0 + +#255#255#0#0#255#255#0#0#255#255#198#198#198#255#0#0#0#0#0#0#0#255#255#255 + +#255#255#0#0#0#255#0#0#0#255#132#132#132#255#0#0#255#255#255#255#255#255#0#0 + +#255#255#0#0#255#255#255#255#255#255#0#0#255#255#0#0#0#0#0#0#0#255#255#255 + +#255#255#132#132#132#255#198#198#198#255#198#198#198#255#0#0#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#0#0#255#255#0#0#0#0 + +#0#0#0#0#0#0#0#255#255#255#255#255#0#0#0#255#0#0#0#255#0#0#255#255#0#0#255 + +#255#255#255#255#255#255#255#255#255#0#0#255#255#0#0#255#255#0#0#0#0#0#0#0#0 + +#0#0#0#0#132#132#132#255#132#132#132#255#132#132#132#255#0#0#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#0#0#255#255#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#255#255#255#255#255#255#0#0 + +#255#255#0#0#255#255#255#255#255#255#0#0#255#255#0#0#0#0#0#0#0#0#198#198#198 + +#255#132#132#132#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#255#255#0#0#255#255#0 + +#0#255#255#0#0#255#255#0#0#0#0#0#0#18'TOpenPictureDialog'#18'OpenPictureDial' + +'og1'#5'Title'#6#18'Open existing file'#4'left'#3#136#0#3'top'#2'@'#0#0#0 +]); diff --git a/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemoMainForm.pas b/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemoMainForm.pas new file mode 100644 index 000000000..3d8b0da5f --- /dev/null +++ b/components/jvcllaz/examples/JvNavigationPane/JvNavPaneDemoMainForm.pas @@ -0,0 +1,482 @@ +// $Id: JvNavPaneDemoMainForm.pas 10610 2006-05-19 13:35:08Z elahn $ +unit JvNavPaneDemoMainForm; + +{$mode objfpc}{$H+} + +interface + +uses + LCLIntf, LMessages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, {JvOutlookBar,} ComCtrls, CheckLst, //JvComponent, + JvNavigationPane, ImgList, Menus, {JvPageList, JclWin32, JvExControls,} ExtCtrls, + {JvExExtCtrls,} ExtDlgs, LResources; + +type + TJvNavPaneDemoMainFrm = class(TForm) + PopupMenu1: TPopupMenu; + LargeImages: TImageList; + HideAll1: TMenuItem; + ShowAll1: TMenuItem; + N1: TMenuItem; + Dontallowresize1: TMenuItem; + ChangeFont1: TMenuItem; + SmallImages: TImageList; + Colors1: TMenuItem; + Standard1: TMenuItem; + Blue1: TMenuItem; + Silver1: TMenuItem; + Olive1: TMenuItem; + N2: TMenuItem; + ShowToolPanel1: TMenuItem; + ToolImages: TImageList; + ShowCloseButton1: TMenuItem; + N3: TMenuItem; + BackgroundImage1: TMenuItem; + OpenPictureDialog1: TOpenPictureDialog; + procedure FormCreate(Sender: TObject); + procedure Dontallowresize1Click(Sender: TObject); + procedure HideAll1Click(Sender: TObject); + procedure ShowAll1Click(Sender: TObject); + procedure ChangeFont1Click(Sender: TObject); + procedure SchemaClick(Sender: TObject); + procedure PopupMenu1Popup(Sender: TObject); + procedure ShowToolPanel1Click(Sender: TObject); + procedure ShowCloseButton1Click(Sender: TObject); + procedure BackgroundImage1Click(Sender: TObject); + private + JvNavPaneStyleManager1: TJvNavPaneStyleManager; + JvOutlookSplitter1: TJvOutlookSplitter; + { Private declarations } + procedure DoToolMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer); + procedure DoToolMouseMove(Sender: TObject; Shift: TShiftState; X, Y: integer); + procedure DoToolPanelClose(Sender: TObject); + procedure DoToolButtonClick(Sender: TObject; Index: integer); + procedure DoToolEndDock(Sender, Target: TObject; X, Y: Integer); + public + { Public declarations } + NP: TJvNavigationPane; + NT: TJvNavPaneToolPanel; + end; + +var + JvNavPaneDemoMainFrm: TJvNavPaneDemoMainFrm; + +implementation +uses + CommCtrl; + +procedure TJvNavPaneDemoMainFrm.FormCreate(Sender: TObject); +var + Page: TJvNavPanelPage; + N: TTreeNode; + R: TRect; + i: integer; + + tv: TTreeView; + + dummy: integer; +begin + //Self.Height := 600; + //Self.Width := 800; + (* + object JvNavPaneStyleManager1: TJvNavPaneStyleManager + Theme = nptXPOlive + Left = 32 + Top = 50 + end + object JvOutlookSplitter1: TJvOutlookSplitter + Left = 0 + Top = 0 + Width = 7 + Height = 434 + Cursor = crSizeWE + Align = alLeft + ColorFrom = 7703937 + ColorTo = 3823693 + StyleManager = JvNavPaneStyleManager1 + ParentStyleManager = False + end + *) + JvNavPaneStyleManager1 := TJvNavPaneStyleManager.Create(Self); + JvNavPaneStyleManager1.Theme := nptXPOlive; + + JvOutlookSplitter1 := TJvOutlookSplitter.Create(Self); + JvOutlookSplitter1.Parent := Self; + JvOutlookSplitter1.Align := alLeft; + JvOutlookSplitter1.ColorFrom := TColor(7703937); + JvOutlookSplitter1.ColorTo := TColor(3823693); + JvOutlookSplitter1.StyleManager := JvNavPaneStyleManager1; + JvOutlookSplitter1.ParentStyleManager := False; + + JvNavPaneStyleManager1.Theme := nptCustom; + // this is how to create a NavPane at run-time + // also shows how to create and insert pages as well as controls on pages + NP := TJvNavigationPane.Create(Self); + + NP.Parent := Self; + NP.Cursor := crHandPoint; + NP.Width := 220; + // NP.BorderWidth := 2; + NP.Align := alLeft; + JvOutlookSplitter1.Left := 225; + JvOutlookSplitter1.MinSize := 220; + NP.DropDownMenu := PopupMenu1; + NP.SmallImages := SmallImages; + NP.LargeImages := LargeImages; + NP.AutoHeaders := True; + NP.StyleManager := JvNavPaneStyleManager1; + + Page := TJvNavPanelPage.Create(Self); + Page.Caption := '&Mail'; + Page.ImageIndex := 0; + Page.PageList := NP; + + with TJvNavPanelDivider.Create(Self) do + begin + Caption := 'Favorite Folders'; + Parent := Page; + Top := 100; + Align := alTop; + Enabled := false; + Cursor := crDefault; + StyleManager := JvNavPaneStyleManager1; + end; + + tv := TTreeView.Create(Self); + with tv do + begin + Parent := Page; + Top := 200; + Align := alTop; + Font.Style := []; + BorderStyle := bsNone; + Items.Add(nil, 'Inbox'); + Items.Add(nil, 'Unread Mail'); + Items.Add(nil, 'For Follow Up [4]'); + Items.Add(nil, 'Sent Items'); + Height := 100; + end; + + with TJvNavPanelDivider.Create(Self) do + begin + Caption := 'All Mail Folders'; + Parent := Page; + Top := tv.Top + tv.Height; // 201; // old = 100 + Align := alTop; + Cursor := crSizeNS; + StyleManager := JvNavPaneStyleManager1; + end; + + with TTreeView.Create(Self) do + begin + Parent := Page; + Align := alClient; + BorderStyle := bsNone; + Font.Style := []; + N := Items.Add(nil, 'Mailbox - Chris Gray'); + Items.AddChild(N, 'Deleted Items'); + Items.AddChild(N, 'Drafts'); + Items.AddChild(N, 'Inbox'); + Items.AddChild(N, 'Junk E-mail'); + Items.AddChild(N, 'Outbox'); + Items.AddChild(N, 'Sent Items'); + N := Items.AddChild(N, 'Search Folders'); + Items.AddChild(N, 'For Follow Up [4]'); + Items.AddChild(N, 'Large Mail'); + Items.AddChild(N, 'Unread Mail'); + FullExpand; + end; + + Page := TJvNavPanelPage.Create(Self); + Page.Caption := '&Calendar'; + Page.ImageIndex := 1; + Page.PageList := NP; + //TODO: replace + (* + // NB! TMonthCalendar messes up the form when you size the form smaller than one calendar width + with TMonthCalendar.Create(Self) do + begin + Parent := Page; + Align := alTop; + AutoSize := true; + AutoSize := false; + Date := SysUtils.Date; + MonthCal_GetMinReqRect(Handle, R); + end; + Constraints.MinHeight := R.Bottom - R.Top + 12; + Constraints.MinWidth := R.Right - R.Left + 12; + *) + + with TJvNavPanelDivider.Create(Self) do + begin + Caption := 'My Calendars'; + Parent := Page; + Top := 1500; + Align := alTop; + Cursor := crDefault; + Enabled := false; + StyleManager := JvNavPaneStyleManager1; + end; + with TCheckListBox.Create(Self) do + begin + Parent := Page; + Checked[Items.Add('Calendar')] := true; + Items.Add('Project Schedule'); + Top := 1500; + Height := 32; + Align := alTop; + end; + with TJvNavPanelDivider.Create(Self) do + begin + Caption := 'Other Calendars'; + Parent := Page; + Top := 1500; + Align := alTop; + Cursor := crSizeNS; + StyleManager := JvNavPaneStyleManager1; + end; + with TCheckListBox.Create(Self) do + begin + Parent := Page; + Checked[Items.Add('Alan Chong')] := Random(4) = 1; + Checked[Items.Add('Andreas Hausladen')] := Random(4) = 1; + Checked[Items.Add('André Snepvangers')] := Random(4) = 1; + Checked[Items.Add('Michael Beck')] := Random(4) = 1; + Checked[Items.Add('Leroy Casterline')] := Random(4) = 1; + Checked[Items.Add('Chris Latta')] := Random(4) = 1; + Checked[Items.Add('Erwin Molendijk')] := Random(4) = 1; + Checked[Items.Add('James Lan')] := Random(4) = 1; + Checked[Items.Add('Ignacio Vazquez')] := Random(4) = 1; + Checked[Items.Add('Marcel Bestebroer')] := Random(4) = 1; + Checked[Items.Add('Jens Fudickar')] := Random(4) = 1; + Checked[Items.Add('Jose Perez')] := Random(4) = 1; + Checked[Items.Add('Marc Hoffmann')] := Random(4) = 1; + Checked[Items.Add('Fernando Silva')] := Random(4) = 1; + Checked[Items.Add('Robert Marquardt')] := Random(4) = 1; + Checked[Items.Add('Matthias Thoma')] := Random(4) = 1; + Checked[Items.Add('Olivier Sannier')] := Random(4) = 1; + Checked[Items.Add('Oliver Giesen')] := Random(4) = 1; + Checked[Items.Add('Dmitry Osinovsky')] := Random(4) = 1; + Checked[Items.Add('Peter Thornqvist')] := Random(4) = 1; + Checked[Items.Add('henri gourvest')] := Random(4) = 1; + Checked[Items.Add('Rob den Braasem')] := Random(4) = 1; + Checked[Items.Add('Remko Bonte')] := Random(4) = 1; + Checked[Items.Add('Christian Vogt')] := Random(4) = 1; + Checked[Items.Add('Warren Postma')] := Random(4) = 1; + Top := 1500; + Align := alClient; + end; + + Page := TJvNavPanelPage.Create(Self); + Page.Caption := 'C&ontacts'; + Page.ImageIndex := 2; + Page.PageList := NP; + + with TListBox.Create(Self) do + begin + Parent := Page; + Align := alClient; + Items.Add('Alan Chong'); + Items.Add('Andreas Hausladen'); + Items.Add('André Snepvangers'); + Items.Add('Michael Beck'); + Items.Add('Leroy Casterline'); + Items.Add('Chris Latta'); + Items.Add('Erwin Molendijk'); + Items.Add('James Lan'); + Items.Add('Ignacio Vazquez'); + Items.Add('Marcel Bestebroer'); + Items.Add('Jens Fudickar'); + Items.Add('Jose Perez'); + Items.Add('Marc Hoffmann'); + Items.Add('Fernando Silva'); + Items.Add('Robert Marquardt'); + Items.Add('Matthias Thoma'); + Items.Add('Olivier Sannier'); + Items.Add('Oliver Giesen'); + Items.Add('Dmitry Osinovsky'); + Items.Add('Peter Thornqvist'); + Items.Add('henri gourvest'); + Items.Add('Rob den Braasem'); + Items.Add('Remko Bonte'); + Items.Add('Christian Vogt'); + Items.Add('Warren Postma'); + end; + + Page := TJvNavPanelPage.Create(Self); + Page.Caption := '&Tasks'; + Page.ImageIndex := 3; + Page.PageList := NP; + + Page := TJvNavPanelPage.Create(Self); + Page.Caption := '&Notes'; + Page.ImageIndex := 4; + Page.PageList := NP; + + Page := TJvNavPanelPage.Create(Self); + Page.Caption := '&Folder List'; + Page.ImageIndex := 5; + Page.PageList := NP; + + { with TJvOutlookSplitter.Create(Self) do + begin + Align := alNone; + Parent := Self; + Left := NP.Width + 100; + Align := alLeft; + Width := 7; + Cursor := crSizeWE; + end; + } + NP.ActivePageIndex := 0; + + NT := TJvNavPaneToolPanel.Create(Self); + NT.DragKind := dkDock; + // NT.DragMode := dmAutomatic; + NT.Parent := Self; + NT.Align := alClient; + NT.Caption := 'Sample Tool Panel'; + NT.StyleManager := JvNavPaneStyleManager1; + NT.Images := ToolImages; + NT.DropDownMenu := PopupMenu1; + for i := 0 to ToolImages.Count - 1 do + NT.Buttons.Add.ImageIndex := i; + NT.OnButtonClick := @DoToolButtonClick; + NT.OnMouseDown := @DoToolMouseDown; + NT.OnMouseMove := @DoToolMouseMove; + NT.OnEndDock := @DoToolEndDock; + + NT.CloseButton := false; + NT.OnClose := @DoToolPanelClose; + // now, set the real start theme: + JvNavPaneStyleManager1.Theme := nptStandard; + + // SESS + NT.ShowHint := true; + NT.Hint := 'Hello world !!'; + +end; + +procedure TJvNavPaneDemoMainFrm.Dontallowresize1Click(Sender: TObject); +begin + Dontallowresize1.Checked := not Dontallowresize1.Checked; + NP.Resizable := not Dontallowresize1.Checked; +end; + +procedure TJvNavPaneDemoMainFrm.HideAll1Click(Sender: TObject); +begin + NP.MaximizedCount := 0; +end; + +procedure TJvNavPaneDemoMainFrm.ShowAll1Click(Sender: TObject); +begin + NP.MaximizedCount := NP.PageCount; +end; + +procedure TJvNavPaneDemoMainFrm.ChangeFont1Click(Sender: TObject); +var + FD: TFontDialog; +begin + FD := TFontDialog.Create(nil); + try + FD.Font := NP.NavPanelFont; + if FD.Execute then + NP.NavPanelFont := FD.Font; + finally + FD.Free; + end; +end; + +procedure TJvNavPaneDemoMainFrm.SchemaClick(Sender: TObject); +begin + JvNavPaneStyleManager1.Theme := TJvNavPanelTheme((Sender as TMenuItem).Tag); + (Sender as TMenuItem).Checked := true; +end; + +procedure TJvNavPaneDemoMainFrm.DoToolPanelClose(Sender: TObject); +begin + if MessageDlg('Close this window?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then + begin + JvOutlookSplitter1.Visible := False; + NT.Visible := False; + NP.Align := alClient; + end; +end; + +procedure TJvNavPaneDemoMainFrm.PopupMenu1Popup(Sender: TObject); +begin + ShowToolPanel1.Enabled := not NT.Visible; + ShowCloseButton1.Checked := NT.CloseButton; +end; + +procedure TJvNavPaneDemoMainFrm.ShowToolPanel1Click(Sender: TObject); +begin + NP.Align := alLeft; + NP.Width := 220; + JvOutlookSplitter1.Visible := True; + JvOutlookSplitter1.Left := 225; + NT.Visible := True; +end; + +procedure TJvNavPaneDemoMainFrm.DoToolButtonClick(Sender: TObject; Index: integer); +begin + ShowMessageFmt('You clicked button %d ', [Index]); +end; + +procedure TJvNavPaneDemoMainFrm.ShowCloseButton1Click(Sender: TObject); +begin + ShowCloseButton1.Checked := not ShowCloseButton1.Checked; + NT.CloseButton := ShowCloseButton1.Checked; +end; + +type + THackForm = class(TCustomForm); + +procedure TJvNavPaneDemoMainFrm.DoToolEndDock(Sender, Target: TObject; X, Y: Integer); +begin + if (Target is TCustomForm) and (Target <> Self) then + begin + TCustomForm(Target).BorderStyle := bsSizeable; + //TODO: + //SetWindowLong(TCustomForm(Target).Handle, GWL_STYLE, GetWindowLong(TCustomForm(Target).Handle, GWL_STYLE) and not WS_CAPTION); + TCustomForm(Target).Width := TCustomForm(Target).Width + 1; + TCustomForm(Target).Width := TCustomForm(Target).Width - 1; + end + else + NT.Align := alClient; +end; + +procedure TJvNavPaneDemoMainFrm.DoToolMouseDown(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: integer); +begin + if phtGrabber in NT.GetHitTestInfoAt(X, Y) then + NT.BeginDrag(false); +end; + +procedure TJvNavPaneDemoMainFrm.DoToolMouseMove(Sender: TObject; Shift: TShiftState; X, + Y: integer); +begin + if phtGrabber in NT.GetHitTestInfoAt(X, Y) then + NT.Cursor := crSize + else + NT.Cursor := crDefault; +end; + +procedure TJvNavPaneDemoMainFrm.BackgroundImage1Click(Sender: TObject); +begin + if OpenPictureDialog1.Execute then + begin + NP.Background.Picture.LoadFromFile(OpenPictureDialog1.Filename); + NP.Background.Tile := True; + NT.Background.Picture.LoadFromFile(OpenPictureDialog1.Filename); + NT.Background.Tile := True; + end; +end; + +initialization + {$i JvNavPaneDemoMainForm.lrs} + {$i JvNavPaneDemoMainForm.lrs} + {$i JvNavPaneDemoMainForm.lrs} + +end. + diff --git a/components/jvcllaz/examples/JvNavigationPane/LargeImages.bmp b/components/jvcllaz/examples/JvNavigationPane/LargeImages.bmp new file mode 100644 index 000000000..986df990d Binary files /dev/null and b/components/jvcllaz/examples/JvNavigationPane/LargeImages.bmp differ diff --git a/components/jvcllaz/examples/JvNavigationPane/SmallImages.bmp b/components/jvcllaz/examples/JvNavigationPane/SmallImages.bmp new file mode 100644 index 000000000..9eef73e37 Binary files /dev/null and b/components/jvcllaz/examples/JvNavigationPane/SmallImages.bmp differ diff --git a/components/jvcllaz/packages/JvCoreLaz.lpk b/components/jvcllaz/packages/JvCoreLaz.lpk new file mode 100644 index 000000000..bf0c366fd --- /dev/null +++ b/components/jvcllaz/packages/JvCoreLaz.lpk @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/jvcllaz/packages/JvCoreLaz.pas b/components/jvcllaz/packages/JvCoreLaz.pas new file mode 100644 index 000000000..09b63fc3f --- /dev/null +++ b/components/jvcllaz/packages/JvCoreLaz.pas @@ -0,0 +1,15 @@ +{ This file was automatically created by Lazarus. Do not edit! +This source is only used to compile and install the package. + } + +unit JvCoreLaz; + +interface + +uses + JvTypes, JvComponent, JvConsts, JvExControls, JvExExtCtrls, JvJCLUtils, + JvJVCLUtils; + +implementation + +end. diff --git a/components/jvcllaz/packages/JvXPBarLaz.lpk b/components/jvcllaz/packages/JvXPBarLaz.lpk new file mode 100644 index 000000000..ef80e5236 --- /dev/null +++ b/components/jvcllaz/packages/JvXPBarLaz.lpk @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/jvcllaz/packages/JvXPBarLaz.lrs b/components/jvcllaz/packages/JvXPBarLaz.lrs new file mode 100644 index 000000000..5bb5082e8 --- /dev/null +++ b/components/jvcllaz/packages/JvXPBarLaz.lrs @@ -0,0 +1,79 @@ +LazarusResources.Add('TJVXPBAR','BMP',[ + 'BM'#246#6#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#24#0#0#0#24#0#0#0#1#0#24#0#0#0#0#0 + +#192#6#0#0#18#11#0#0#18#11#0#0#0#0#0#0#0#0#0#0#192#0#224#0#224#192#0#224#192 + +#0#224#192#0#224#192#0#224#192#0#224#192#0#224#192#0#224#192#0#224#192#0#224 + +#192#0#224#192#0#224#192#0#224#160#0#224#160#0#224#160#255#255#0#255#0#0#255 + +#0#0#255#0#0#255#0#0#255#0#0#255#0#0#255#0#0#0#224#192#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#224#192#0#0#0#0#0#0#0#0#0#0#224#192#0#224#160#0 + +#0#0#255#255#0#255#0#0#255#0#0#0#255#255#0#255#255#255#0#0#255#0#0#255#0#0#0 + +#224#192#192#192#192#192#192#192#192#192#192#192#192#192#192#192#192#192#192 + +#192#192#192#192#192#192#192#0#224#192#0#0#0#0#224#192#0#224#192#0#0#0#0#224 + +#192#0#224#160#255#255#0#255#0#0#0#255#255#255#0#0#255#0#0#0#255#255#255#0#0 + +#255#0#0#0#224#224#128#128#128#128#128#128#128#128#128#128#128#128#128#128 + +#128#128#128#128#128#128#128#128#128#128#0#224#192#0#0#0#0#224#192#0#224#192 + +#0#0#0#0#224#192#0#224#192#255#255#0#255#0#0#0#255#255#255#0#0#255#0#0#0#255 + +#255#255#0#0#255#0#0#0#224#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#224#192#0#0#0#0#0#0#0#0#0#0#224#192#0#224#192#0#0#0#255#255#0#255#0#0 + +#255#0#0#255#0#0#255#0#0#0#255#255#255#0#0#255#0#0#0#224#224#0#224#224#0#224 + +#224#0#224#192#0#224#192#0#224#192#0#224#192#0#224#192#0#224#192#0#224#192#0 + +#224#192#0#224#192#0#224#192#0#224#192#0#224#192#0#224#192#255#255#0#255#0#0 + +#255#0#0#255#0#0#255#0#0#0#255#255#255#0#0#255#0#0#0#224#224#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#255#255#0#255#0#0#255#0#0#255#0#0#255#0#0#0#255#255#255#0#0#255#0#0#0#224 + +#224#0#0#0#255#255#255#128#128#128#128#128#128#128#128#128#128#128#128#128 + +#128#128#128#128#128#128#128#128#128#128#128#128#128#128#128#128#128#128#128 + +#128#128#128#128#128#128#128#255#255#0#255#0#0#255#0#0#255#0#0#255#0#0#255#0 + +#0#255#0#0#255#0#0#0#224#224#0#0#0#255#255#255#247#223#214#247#223#214#247 + +#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223 + +#214#247#223#214#247#223#214#247#223#214#247#223#214#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#0#224#224#0#0#0#255 + +#255#255#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223 + +#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214 + +#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#128 + +#128#128#0#0#0#0#224#160#0#224#224#0#0#0#255#255#255#247#223#214#247#223#214 + +#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247 + +#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223 + +#214#247#223#214#247#223#214#247#223#214#128#128#128#0#0#0#0#224#160#0#224 + +#224#0#0#0#255#255#255#247#223#214#247#223#214#247#223#214#247#223#214#247 + +#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223 + +#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214 + +#247#223#214#128#128#128#0#0#0#0#224#160#0#224#224#0#0#0#255#255#255#247#223 + +#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214 + +#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247 + +#223#214#247#223#214#247#223#214#247#223#214#247#223#214#128#128#128#0#0#0#0 + +#224#192#0#224#224#0#0#0#255#255#255#247#223#214#247#223#214#247#223#214#247 + +#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223 + +#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214 + +#247#223#214#247#223#214#128#128#128#0#0#0#0#224#192#0#224#224#0#0#0#255#255 + +#255#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214 + +#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247 + +#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#128#128 + +#128#0#0#0#0#224#192#0#224#224#0#0#0#255#255#255#247#223#214#247#223#214#247 + +#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223 + +#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214#247#223#214 + +#247#223#214#247#223#214#247#223#214#128#128#128#0#0#0#0#224#192#0#224#224#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#224#192#0#224#224#0 + +#0#0#255#255#255#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228 + +#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228 + +#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#128#128#128#0 + +#0#0#0#224#192#0#224#224#0#0#0#255#255#255#228#167'~'#228#167'~'#228#167'~' + +#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~' + +#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#0#0#0#228#167'~'#228 + +#167'~'#128#128#128#0#0#0#0#224#192#0#224#224#0#0#0#255#255#255#228#167'~' + +#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~' + +#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#0#0#0#0#0 + ,#0#0#0#0#228#167'~'#128#128#128#0#0#0#0#224#192#0#224#224#0#0#0#255#255#255 + +#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~' + +#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~'#228#167'~' + +#228#167'~'#228#167'~'#228#167'~'#228#167'~'#128#128#128#0#0#0#0#224#192#0 + +#192#224#0#224#224#0#0#0#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255 + +#255#255#255#0#0#0#0#224#192#0#224#192#0#192#224#0#192#224#0#224#224#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#224#192#0#224#192#0#224#192#0#192#224#0#192#224#0 + +#192#224#0#224#224#0#224#224#0#224#224#0#224#224#0#224#224#0#224#224#0#224 + +#224#0#224#224#0#224#224#0#224#224#0#224#224#0#224#224#0#224#224#0#224#224#0 + +#224#224#0#224#224#0#224#224#0#224#224#0#224#192#0#224#192#0#224#192 +]); diff --git a/components/jvcllaz/packages/JvXPBarLaz.pas b/components/jvcllaz/packages/JvXPBarLaz.pas new file mode 100644 index 000000000..9fb9e07bb --- /dev/null +++ b/components/jvcllaz/packages/JvXPBarLaz.pas @@ -0,0 +1,21 @@ +{ This file was automatically created by Lazarus. Do not edit! +This source is only used to compile and install the package. + } + +unit JvXPBarLaz; + +interface + +uses + JvXPCoreUtils, JvXPBar, JvXPCore, JvXPBarReg, LazarusPackageIntf; + +implementation + +procedure Register; +begin + RegisterUnit('JvXPBarReg', @JvXPBarReg.Register); +end; + +initialization + RegisterPackage('JvXPBarLaz', @Register); +end. diff --git a/components/jvcllaz/packages/JvXPBarReg.pp b/components/jvcllaz/packages/JvXPBarReg.pp new file mode 100644 index 000000000..6b9df86b0 --- /dev/null +++ b/components/jvcllaz/packages/JvXPBarReg.pp @@ -0,0 +1,24 @@ +unit JvXPBarReg; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, LResources, SysUtils; + +procedure Register; + +implementation +uses JvXPBar; + +procedure Register; +begin + RegisterComponents('JvXP',[TJvXPBar]); +end; + +initialization + {$I JvXPBarLaz.lrs} + +end. + diff --git a/components/jvcllaz/resource/JvXPBar.lrs b/components/jvcllaz/resource/JvXPBar.lrs new file mode 100644 index 000000000..99599805c --- /dev/null +++ b/components/jvcllaz/resource/JvXPBar.lrs @@ -0,0 +1,254 @@ +LazarusResources.Add('JVXPCUSTOMWINXPBARCOLLAPSE0','BMP',[ + 'BM&'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#18#0#0#0#18#0#0#0#1#0#24#0#0#0#0#0#240#3 + +#0#0#195#14#0#0#195#14#0#0#0#0#0#0#0#0#0#0#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#0#165'8'#0#255#0#255#255#0 + +#255#255#0#255#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#165'8'#0#165'8'#0#255#0#255#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#0#165'8'#0#165'8'#0#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0 + +#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255 + +#0#255#165'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255#165'8'#0#165'8'#0 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#0#165'8'#0#255#0 + +#255#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#165'8'#0#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#0#255#0#255#255 + +#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#0#0 +]); +LazarusResources.Add('JVXPCUSTOMWINXPBARCOLLAPSE1','BMP',[ + 'BM&'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#18#0#0#0#18#0#0#0#1#0#24#0#0#0#0#0#240#3 + +#0#0#195#14#0#0#195#14#0#0#0#0#0#0#0#0#0#0#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#0#165'8'#0#255#0#255#255#0 + +#255#255#0#255#165'8'#0#165'8'#1#255#0#255#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#165'8'#0#165'8'#0#255#0#255#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#0#165'8'#0#165'8'#0#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0 + +#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255 + +#0#255#165'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255#165'8'#0#165'8'#0 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#0#165'8'#0#255#0 + +#255#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#165'8'#0#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#0#255#0#255#255 + +#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#0#0 +]); +LazarusResources.Add('JVXPCUSTOMWINXPBARCOLLAPSE2','BMP',[ + 'BM&'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#18#0#0#0#18#0#0#0#1#0#24#0#0#0#0#0#240#3 + +#0#0#195#14#0#0#195#14#0#0#0#0#0#0#0#0#0#0#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255#165'8'#0#165 + +'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#0#165'8'#0#255 + +#0#255#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#165'8'#0#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#0#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0 + +#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#0#165 + +'8'#0#255#0#255#255#0#255#255#0#255#165'8'#0#165'8'#0#255#0#255#255#0#255#255 + +#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#165'8'#0#165'8'#0#255#0#255#165'8'#0#165'8'#0#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#0#165 + +'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#165'8'#0#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0 + +#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#0#0 +]); +LazarusResources.Add('JVXPCUSTOMWINXPBAREXPAND0','BMP',[ + 'BM&'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#18#0#0#0#18#0#0#0#1#0#24#0#0#0#0#0#240#3 + +#0#0#195#14#0#0#195#14#0#0#0#0#0#0#0#0#0#0#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#168'6'#8#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#0#165'8'#0#165 + +'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#165'8'#0#165'8'#0#255#0#255#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#173'3'#24#166'8'#2#255#0#255#255#0#255#255#0#255#165'8' + +#0#165'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#165'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#165'8'#0#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#166'7'#3#165'8'#0#255#0#255#165 + +'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#0#182 + +'./'#255#0#255#255#0#255#255#0#255#169'6'#11#169'5'#12#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0 + +#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#0#0 +]); +LazarusResources.Add('JVXPCUSTOMWINXPBAREXPAND1','BMP',[ + 'BM&'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#18#0#0#0#18#0#0#0#1#0#24#0#0#0#0#0#240#3 + +#0#0#195#14#0#0#195#14#0#0#0#0#0#0#0#0#0#0#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#167'6'#7#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#166'8'#2#165'8'#0#165 + +'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#165'8'#0#165'8'#0#255#0#255#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255#165'8'#0 + +#165'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255 + +#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#165'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#165'8'#0#165'8'#0#165'8'#0#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#1#165'8'#1#255#0#255#165 + +'8'#0#165'8'#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#165'8'#1#171 + +'4'#18#255#0#255#255#0#255#255#0#255#166'7'#4#165'8'#1#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0 + +#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255 + +#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#0#0#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#0#0#255#0#255 + +#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0 + +#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255#255#0#255 + +#255#0#255#255#0#255#0#0 +]); +LazarusResources.Add('JVXPCUSTOMWINXPBAREXPAND2','BMP',[ + 'BM'#174#1#0#0#0#0#0#0'F'#0#0#0'('#0#0#0#18#0#0#0#18#0#0#0#1#0#8#0#0#0#0#0'h' + +#1#0#0#195#14#0#0#195#14#0#0#4#0#0#0#4#0#0#0#255#0#255#0#165'8'#0#0#255#255 + +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#1#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#1#1#0#1#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#1#0#0#0#1#1#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#1#1#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#1#1#0#1#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#1#0#0#0#1#1#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 + +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0 +]); diff --git a/components/jvcllaz/run/JvButton.pas b/components/jvcllaz/run/JvButton.pas new file mode 100644 index 000000000..7f14b12ec --- /dev/null +++ b/components/jvcllaz/run/JvButton.pas @@ -0,0 +1,923 @@ +{----------------------------------------------------------------------------- +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: JvButton.PAS, released on 2001-02-28. + +The Initial Developer of the Original Code is Sébastien Buysse [sbuysse att buypin dott com] +Portions created by Sébastien Buysse are Copyright (C) 2001 Sébastien Buysse. +All Rights Reserved. + +Contributor(s): Michael Beck [mbeck att bigfoot dott com]. + +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: +-----------------------------------------------------------------------------} +// $Id: JvButton.pas 11400 2007-06-28 21:24:06Z ahuser $ + +// Initial port to Lazarus by Sergio Samayoa - september 2007. +// Conversion is done in incremental way: as types / classes / routines +// are needed they are converted. + +{$mode objfpc}{$H+} + +unit JvButton; + +interface + +uses + Classes, Controls, Graphics, JvComponent, JvConsts, JvTypes, LMessages, Menus; + +type + TJvButtonMouseState = (bsMouseInside, bsMouseDown); + TJvButtonMouseStates = set of TJvButtonMouseState; + + TJvCustomGraphicButton = class(TJvGraphicControl) + private + FStates: TJvButtonMouseStates; + FBuffer: TBitmap; + FFlat: Boolean; + FDropDownMenu: TPopupMenu; + FDown: Boolean; + FForceSameSize: Boolean; + FAllowAllUp: Boolean; + FGroupIndex: Integer; + FHotTrack: Boolean; + FHotFont: TFont; + FHotTrackFontOptions: TJvTrackFontOptions; + FOnDropDownMenu: TContextPopupEvent; + FDropArrow: Boolean; + FOnDropDownClose: TNotifyEvent; + function GetPattern: TBitmap; + procedure SetFlat(const Value: Boolean); + procedure SetDown(Value: Boolean); + procedure CMButtonPressed(var Msg: TCMButtonPressed); message CM_JVBUTTONPRESSED; + procedure CMForceSize(var Msg: TCMForceSize); message CM_FORCESIZE; + procedure CMSysColorChange(var Msg: TLMessage); message CM_SYSCOLORCHANGE; + procedure SetForceSameSize(const Value: Boolean); + procedure SetAllowAllUp(const Value: Boolean); + procedure SetGroupIndex(const Value: Integer); + procedure SetHotFont(const Value: TFont); + procedure SetHotTrackFontOptions(const Value: TJvTrackFontOptions); + procedure SetDropArrow(const Value: Boolean); + procedure SetDropDownMenu(const Value: TPopupMenu); + protected + procedure ButtonPressed(Sender: TJvCustomGraphicButton; AGroupIndex: Integer); virtual; + procedure ForceSize(Sender: TControl; AWidth, AHeight: Integer); + function DoDropDownMenu(Button: TMouseButton; Shift: TShiftState; X, Y: Integer): Boolean; virtual; + procedure DropDownClose; + procedure UpdateExclusive; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; + procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseEnter(Control: TControl); override; + procedure MouseLeave(Control: TControl); override; + procedure Paint; override; + procedure PaintButton(ACanvas: TCanvas); virtual; + procedure PaintFrame(ACanvas: TCanvas); virtual; + function InsideBtn(X, Y: Integer): Boolean; virtual; + function WantKey(Key: Integer; Shift: TShiftState; + const KeyText: WideString): Boolean; override; + procedure EnabledChanged; override; + procedure FontChanged; override; + procedure RepaintBackground; virtual; + procedure TextChanged; override; + property AllowAllUp: Boolean read FAllowAllUp write SetAllowAllUp default False; + property GroupIndex: Integer read FGroupIndex write SetGroupIndex default 0; + property MouseStates: TJvButtonMouseStates read FStates write FStates default []; + property ForceSameSize: Boolean read FForceSameSize write SetForceSameSize default False; + property Pattern: TBitmap read GetPattern; + property Flat: Boolean read FFlat write SetFlat default False; + property HotTrack: Boolean read FHotTrack write FHotTrack default False; + property HotTrackFont: TFont read FHotFont write SetHotFont; + property HotTrackFontOptions: TJvTrackFontOptions read FHotTrackFontOptions write SetHotTrackFontOptions default + DefaultTrackFontOptions; + property Down: Boolean read FDown write SetDown default False; + property DropDownMenu: TPopupMenu read FDropDownMenu write SetDropDownMenu; + property DropArrow: Boolean read FDropArrow write SetDropArrow default False; + property OnDropDownMenu: TContextPopupEvent read FOnDropDownMenu write FOnDropDownMenu; + property OnDropDownClose: TNotifyEvent read FOnDropDownClose write FOnDropDownClose; + public + procedure Click; override; + procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure DrawDropArrow(ACanvas: TCanvas; ArrowRect: TRect); virtual; + end; + +(******************** NOT CONVERTED + TJvCustomButton = class(TJvExButton) + private + FDropDownMenu: TPopupMenu; + FHotTrack: Boolean; + FHotFont: TFont; + FFontSave: TFont; + FWordWrap: Boolean; + FForceSameSize: Boolean; + FHotTrackFontOptions: TJvTrackFontOptions; + FOnDropDownMenu: TContextPopupEvent; + FDropArrow: Boolean; + procedure SetHotFont(const Value: TFont); + procedure SetWordWrap(const Value: Boolean); + procedure SetForceSameSize(const Value: Boolean); + procedure CMForceSize(var Msg: TCMForceSize); message CM_FORCESIZE; + procedure SetHotTrackFontOptions(const Value: TJvTrackFontOptions); + procedure SetDropArrow(const Value: Boolean); + procedure SetDropDownMenu(const Value: TPopupMenu); + protected + function DoDropDownMenu(X, Y: Integer): Boolean; virtual; + procedure ForceSize(Sender: TControl; AWidth, AHeight: Integer); + procedure MouseEnter(Control: TControl); override; + procedure MouseLeave(Control: TControl); override; + procedure FontChanged; override; + procedure CreateParams(var Params: TCreateParams); override; + function GetRealCaption: string; dynamic; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + property WordWrap: Boolean read FWordWrap write SetWordWrap default True; + property ForceSameSize: Boolean read FForceSameSize write SetForceSameSize default False; + property DropArrow: Boolean read FDropArrow write SetDropArrow default False; + property DropDownMenu: TPopupMenu read FDropDownMenu write SetDropDownMenu; + property HotTrack: Boolean read FHotTrack write FHotTrack default False; + property HotTrackFont: TFont read FHotFont write SetHotFont; + property HotTrackFontOptions: TJvTrackFontOptions read FHotTrackFontOptions write SetHotTrackFontOptions default + DefaultTrackFontOptions; + property HintColor; + property OnParentColorChange; + property OnDropDownMenu: TContextPopupEvent read FOnDropDownMenu write FOnDropDownMenu; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Click;override; + procedure DrawDropArrow(Canvas: TCanvas; ArrowRect: TRect); virtual; + procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer; AHeight: Integer); override; + end; + + // TJvDropDownButton draws a DropDown button with the DropDown glyph + // (also themed). It ignores the properties Glyph and Flat + TJvDropDownButton = class(TSpeedButton) + protected + procedure Paint; override; + public + constructor Create(AOwner: TComponent); override; + end; +******************** NOT CONVERTED *) + +implementation + +uses + Forms, JvJVCLUtils, LCLIntf, LCLType, SysUtils; + +(******************** NOT CONVERTED +const + JvBtnLineSeparator = '|'; +******************** NOT CONVERTED *) + +var + GlobalPattern: TBitmap = nil; + +function CreateBrushPattern: TBitmap; +var + X, Y: Integer; +begin + if GlobalPattern = nil then + begin + GlobalPattern := TBitmap.Create; + try + GlobalPattern.Width := 8; { must have this size } + GlobalPattern.Height := 8; + with GlobalPattern.Canvas do + begin + Brush.Style := bsSolid; + Brush.Color := clBtnFace; + FillRect(Rect(0, 0, GlobalPattern.Width, GlobalPattern.Height)); + for Y := 0 to 7 do + for X := 0 to 7 do + if (Y mod 2) = (X mod 2) then { toggles between even/odd pixels } + Pixels[X, Y] := clWhite; { on even/odd rows } + end; + except + FreeAndNil(GlobalPattern); + end; + end; + Result := GlobalPattern; +end; + +//=== { TJvCustomGraphicButton } ============================================= + +constructor TJvCustomGraphicButton.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + ControlStyle := ControlStyle - + [csOpaque, csDoubleClicks ]; + FStates := []; + SetBounds(0, 0, 40, 40); + FBuffer := TBitmap.Create; + FFlat := False; + FDropArrow := False; + FForceSameSize := False; + FHotFont := TFont.Create; + FHotTrackFontOptions := DefaultTrackFontOptions; +end; + +destructor TJvCustomGraphicButton.Destroy; +begin + FBuffer.Free; + FHotFont.Free; + inherited Destroy; +end; + +procedure TJvCustomGraphicButton.DrawDropArrow(ACanvas: TCanvas; ArrowRect: TRect); +var + I: Integer; +begin + if not Enabled then + ACanvas.Pen.Color := clInactiveCaption + else + ACanvas.Pen.Color := clWindowText; + for I := 0 to 3 do + begin + if ArrowRect.Left + I <= ArrowRect.Right - I then + begin + ACanvas.MoveTo(ArrowRect.Left + I, ArrowRect.Top + I); + ACanvas.LineTo(ArrowRect.Right - I, ArrowRect.Top + I); + end; + end; +end; + +{ Handle speedkeys (Alt + key) } + +function TJvCustomGraphicButton.WantKey(Key: Integer; Shift: TShiftState; + const KeyText: WideString): Boolean; +begin + Result := IsAccel(Key, Caption) and Enabled and (Shift * KeyboardShiftStates = [ssAlt]); + if Result then + Click + else + Result := inherited WantKey(Key, Shift, KeyText); +end; + +procedure TJvCustomGraphicButton.EnabledChanged; +begin + inherited EnabledChanged; + if not Enabled then + FStates := []; + RepaintBackground; +end; + +procedure TJvCustomGraphicButton.MouseEnter(Control: TControl); +begin + if csDesigning in ComponentState then + Exit; + if Enabled and not MouseOver then + begin + Include(FStates, bsMouseInside); + inherited MouseEnter(Control); + if Flat then + RepaintBackground; + if HotTrack then + Repaint; + end; +end; + +procedure TJvCustomGraphicButton.MouseLeave(Control: TControl); +begin + if Enabled and MouseOver then + begin + Exclude(FStates, bsMouseInside); + inherited MouseLeave(Control); + if Flat then + RepaintBackground; + if HotTrack then + Repaint; + end; +end; + +procedure TJvCustomGraphicButton.Paint; +var + ArrowRect: TRect; +begin +// FBuffer.Width := Width; +// FBuffer.Height := Height; + PaintFrame(Canvas); + PaintButton(Canvas); + if DropArrow and Assigned(DropDownMenu) then + begin + ArrowRect := Rect(Width - 16, Height div 2, Width - 9, Height div 2 + 9); + if bsMouseDown in FStates then + OffsetRect(ArrowRect, 1, 1); + DrawDropArrow(Canvas, ArrowRect); + end; +// BitBlt(Canvas.Handle, 0, 0, Width,Height, FBuffer.Canvas.Handle, 0, 0, SRCCOPY); +end; + +procedure TJvCustomGraphicButton.PaintFrame(ACanvas: TCanvas); +begin + // do nothing +end; + +procedure TJvCustomGraphicButton.PaintButton(ACanvas: TCanvas); +begin + if (bsMouseInside in FStates) and HotTrack then + ACanvas.Font := FHotFont + else + ACanvas.Font := Font; +end; + +function TJvCustomGraphicButton.InsideBtn(X, Y: Integer): Boolean; +begin + Result := PtInRect(Rect(0, 0, Width, Height), Point(X, Y)); +end; + +procedure TJvCustomGraphicButton.MouseDown(Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +var + Tmp: TPoint; +begin + if not Enabled then + Exit; + + inherited MouseDown(Button, Shift, X, Y); + + if InsideBtn(X, Y) then + begin + FStates := [bsMouseDown, bsMouseInside]; + RepaintBackground; + end; + SetCaptureControl(Self); + Tmp := ClientToScreen(Point(0, Height)); + DoDropDownMenu(Button, Shift, Tmp.X, Tmp.Y); +end; + +procedure TJvCustomGraphicButton.MouseMove(Shift: TShiftState; + X, Y: Integer); +begin + inherited MouseMove(Shift, X, Y); + if MouseCapture then + begin + if not InsideBtn(X, Y) then + begin + if bsMouseInside in FStates then + begin + Exclude(FStates, bsMouseInside); + RepaintBackground; + end; + end + else + begin + if not (bsMouseInside in FStates) then + begin + Include(FStates, bsMouseInside); + RepaintBackground; + end; + end; + end; +end; + +procedure TJvCustomGraphicButton.MouseUp(Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +begin + if GetCaptureControl = Self then + ReleaseCapture; + if not Enabled then + Exit; + inherited MouseUp(Button, Shift, X, Y); + Exclude(FStates, bsMouseDown); + + // 26.09.2007 - SESS: + // Update bsMouseInside flag also. + if not InsideBtn(X, Y) and (bsMouseInside in FStates) then + Exclude(FStates, bsMouseInside); + + RepaintBackground; +end; + +function TJvCustomGraphicButton.DoDropDownMenu(Button: TMouseButton; Shift: TShiftState; X, Y: Integer): Boolean; +var + Msg: TMsg; + Handled: Boolean; +begin + Result := (Button = mbLeft) and (DropDownMenu <> nil); + if Result then + begin + DropDownMenu.PopupComponent := Self; + Handled := False; + if Assigned(FOnDropDownMenu) then + FOnDropDownMenu(Self, Point(X, Y), Handled); + if not Handled then + DropDownMenu.Popup(X, Y) + else + Exit; + { wait 'til menu is done } + while PeekMessage(Msg, 0, LM_MOUSEFIRST, LM_MOUSELAST, PM_REMOVE) do + {nothing}; + { release button } + MouseUp(Button, Shift, X, Y); + DropDownClose; + end; +end; + +procedure TJvCustomGraphicButton.SetFlat(const Value: Boolean); +begin + if FFlat <> Value then + begin + FFlat := Value; + if FFlat then + ControlStyle := ControlStyle - [csOpaque] + else + ControlStyle := ControlStyle + [csOpaque]; + RepaintBackground; + end; +end; + +procedure TJvCustomGraphicButton.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if (Operation = opRemove) and (AComponent = DropDownMenu) then + DropDownMenu := nil; +end; + +procedure TJvCustomGraphicButton.SetDown(Value: Boolean); +begin + if GroupIndex = 0 then + Value := False; + if FDown <> Value then + begin + if FDown and not AllowAllUp then + Exit; + FDown := Value; + UpdateExclusive; + Invalidate; + end; +end; + +procedure TJvCustomGraphicButton.SetForceSameSize(const Value: Boolean); +begin + if FForceSameSize <> Value then + begin + FForceSameSize := Value; + if FForceSameSize then + SetBounds(Left, Top, Width, Height); + end; +end; + +procedure TJvCustomGraphicButton.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); +var + Form: TCustomForm; + Msg: TCMForceSize; +begin + inherited SetBounds(ALeft, ATop, AWidth, AHeight); + if ForceSameSize then + begin + Form := GetParentForm(Self); + if Assigned(Form) then + begin + Msg.Msg := CM_FORCESIZE; + Msg.Sender := Self; + Msg.NewSize.X := AWidth; + Msg.NewSize.Y := AHeight; + Form.Broadcast(Msg); + end; + end; +end; + +procedure TJvCustomGraphicButton.CMForceSize(var Msg: TCMForceSize); +begin + with Msg do + ForceSize(Sender, NewSize.x, NewSize.y); +end; + +function TJvCustomGraphicButton.GetPattern: TBitmap; +begin + Result := CreateBrushPattern; +end; + +procedure TJvCustomGraphicButton.SetAllowAllUp(const Value: Boolean); +begin + if FAllowAllUp <> Value then + begin + FAllowAllUp := Value; + UpdateExclusive; + end; +end; + +procedure TJvCustomGraphicButton.SetGroupIndex(const Value: Integer); +begin + if FGroupIndex <> Value then + begin + FGroupIndex := Value; + UpdateExclusive; + end; +end; + +procedure TJvCustomGraphicButton.UpdateExclusive; +var + Msg: TCMButtonPressed; +begin + if (GroupIndex <> 0) and (Parent <> nil) then + begin + Msg.Msg := CM_JVBUTTONPRESSED; + Msg.Index := GroupIndex; + Msg.Control := Self; + Msg.Result := 0; + Parent.Broadcast(Msg); + end; +end; + +procedure TJvCustomGraphicButton.CMButtonPressed(var Msg: TCMButtonPressed); +begin + ButtonPressed(TJvCustomGraphicButton(Msg.Control), Msg.Index); +end; + +procedure TJvCustomGraphicButton.SetHotFont(const Value: TFont); +begin + FHotFont.Assign(Value); +end; + +procedure TJvCustomGraphicButton.SetHotTrackFontOptions(const Value: TJvTrackFontOptions); +begin + if FHotTrackFontOptions <> Value then + begin + FHotTrackFontOptions := Value; + UpdateTrackFont(HotTrackFont, Font, HotTrackFontOptions); + end; +end; + +procedure TJvCustomGraphicButton.SetDropArrow(const Value: Boolean); +begin + if FDropArrow <> Value then + begin + FDropArrow := Value; + Invalidate; + end; +end; + +procedure TJvCustomGraphicButton.SetDropDownMenu(const Value: TPopupMenu); +begin + if FDropDownMenu <> Value then + begin + FDropDownMenu := Value; + if DropArrow then + Invalidate; + end; +end; + +procedure TJvCustomGraphicButton.CMSysColorChange(var Msg: TLMessage); +begin + inherited; + RepaintBackground; +end; + +procedure TJvCustomGraphicButton.FontChanged; +begin + inherited FontChanged; + UpdateTrackFont(HotTrackFont, Font, HotTrackFontOptions); +end; + +procedure TJvCustomGraphicButton.TextChanged; +begin + inherited TextChanged; + RepaintBackground; +end; + +procedure TJvCustomGraphicButton.Click; +begin + if GroupIndex <> 0 then + begin + if AllowAllUp then + Down := not Down + else + Down := True; + end; + try + inherited Click; + except + // Mantis 3097: In case there is an exception, we ensure here that the + // button is not left "down", and we reraise the exception as we can't + // handle it and don't want to ignore it. + Exclude(FStates, bsMouseDown); + RepaintBackground; + raise; + end; +end; + +procedure TJvCustomGraphicButton.ButtonPressed(Sender: TJvCustomGraphicButton; + AGroupIndex: Integer); +begin + if AGroupIndex = GroupIndex then + if Sender <> Self then + begin + if Sender.Down and Down then + begin + FDown := False; + Exclude(FStates, bsMouseDown); + RepaintBackground; + end; + FAllowAllUp := Sender.AllowAllUp; + end; +end; + +procedure TJvCustomGraphicButton.ForceSize(Sender: TControl; AWidth, AHeight: Integer); +begin + if Sender <> Self then + inherited SetBounds(Left, Top, AWidth, AHeight); +end; + +(******************** NOT CONVERTED +//=== { TJvCustomButton } ==================================================== + +constructor TJvCustomButton.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FDropArrow := False; + FHotTrack := False; + FHotFont := TFont.Create; + FFontSave := TFont.Create; + // ControlStyle := ControlStyle + [csAcceptsControls]; + FWordWrap := True; + FForceSameSize := False; + FHotTrackFontOptions := DefaultTrackFontOptions; +end; + +destructor TJvCustomButton.Destroy; +begin + FHotFont.Free; + FFontSave.Free; + inherited Destroy; +end; + +procedure TJvCustomButton.Click; +var + Tmp: TPoint; +begin + // Call ClientToScreen before the inherited Click as the OnClick handler might + // reset the parent, which is needed by ClientToScreen. + Tmp := ClientToScreen(Point(0, Height)); + inherited Click; + DoDropDownMenu(Tmp.X, Tmp.Y); +end; + +procedure TJvCustomButton.DrawDropArrow(Canvas: TCanvas; ArrowRect: TRect); +var + I: Integer; +begin + if not Enabled then + Canvas.Pen.Color := clInactiveCaption + else + Canvas.Pen.Color := clWindowText; + for I := 0 to (ArrowRect.Bottom - ArrowRect.Top) do + begin + if ArrowRect.Left + I <= ArrowRect.Right - I then + begin + Canvas.MoveTo(ArrowRect.Left + I, ArrowRect.Top + I); + Canvas.LineTo(ArrowRect.Right - I, ArrowRect.Top + I); + end; + end; +end; + +procedure TJvCustomButton.CreateParams(var Params: TCreateParams); +begin + inherited CreateParams(Params); + Params.Style := Params.Style or BS_MULTILINE; +end; + +procedure TJvCustomButton.SetHotTrackFontOptions(const Value: TJvTrackFontOptions); +begin + if FHotTrackFontOptions <> Value then + begin + FHotTrackFontOptions := Value; + UpdateTrackFont(HotTrackFont, Font, HotTrackFontOptions); + end; +end; + +procedure TJvCustomButton.SetDropArrow(const Value: Boolean); +begin + if FDropArrow <> Value then + begin + FDropArrow := Value; + Invalidate; + end; +end; + +procedure TJvCustomButton.SetHotFont(const Value: TFont); +begin + FHotFont.Assign(Value); +end; + +procedure TJvCustomButton.SetDropDownMenu(const Value: TPopupMenu); +begin + if FDropDownMenu <> Value then + begin + FDropDownMenu := Value; + if DropArrow then + Invalidate; + end; +end; + +procedure TJvCustomButton.MouseEnter(Control: TControl); +begin + if not MouseOver then + begin + if FHotTrack then + begin + FFontSave.Assign(Font); + Font.Assign(FHotFont); + end; + inherited MouseEnter(Control); + end; +end; + +procedure TJvCustomButton.MouseLeave(Control: TControl); +begin + if MouseOver then + begin + if FHotTrack then + Font.Assign(FFontSave); + inherited MouseLeave(Control); + end; +end; + +procedure TJvCustomButton.FontChanged; +begin + inherited FontChanged; + UpdateTrackFont(HotTrackFont, Font, HotTrackFontOptions); +end; + +function TJvCustomButton.GetRealCaption: string; +begin + if WordWrap then + Result := StringReplace(Caption, JvBtnLineSeparator, Lf, [rfReplaceAll]) + else + Result := Caption; +end; + +procedure TJvCustomButton.SetWordWrap(const Value: Boolean); +begin + if FWordWrap <> Value then + begin + FWordWrap := Value; + Invalidate; + end; +end; + +procedure TJvCustomButton.SetForceSameSize(const Value: Boolean); +begin + if FForceSameSize <> Value then + begin + FForceSameSize := Value; + if FForceSameSize then + SetBounds(Left, Top, Width, Height); + end; +end; + +procedure TJvCustomButton.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); +var + Form: TCustomForm; + Msg: TCMForceSize; +begin + inherited SetBounds(ALeft, ATop, AWidth, AHeight); + if ForceSameSize then + begin + Form := GetParentForm(Self); + if Assigned(Form) then + begin + Msg.Msg := CM_FORCESIZE; + Msg.Sender := Self; + Msg.NewSize.X := AWidth; + Msg.NewSize.Y := AHeight; + Form.Broadcast(Msg); + end; + end; +end; + +procedure TJvCustomButton.CMForceSize(var Msg: TCMForceSize); +begin + with Msg do + ForceSize(Sender, NewSize.x, NewSize.y); +end; + +procedure TJvCustomButton.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if (Operation = opRemove) and (AComponent = FDropDownMenu) then + DropDownMenu := nil; +end; +******************** NOT CONVERTED *) + +procedure TJvCustomGraphicButton.RepaintBackground; +var + R: TRect; +begin + if (Parent <> nil) and Parent.HandleAllocated then + begin + R := BoundsRect; + InvalidateRect(Parent.Handle, @R, True); + end; + Repaint; +end; + +(******************** NOT CONVERTED +procedure TJvCustomButton.ForceSize(Sender: TControl; AWidth, AHeight: Integer); +begin + if Sender <> Self then + inherited SetBounds(Left, Top, AWidth, AHeight); +end; + +function TJvCustomButton.DoDropDownMenu(X, Y: Integer): Boolean; +var + Msg: TMsg; + Handled: Boolean; +begin + Result := (DropDownMenu <> nil); + if Result then + begin + DropDownMenu.PopupComponent := Self; + case DropDownMenu.Alignment of + paRight: + Inc(X, Width); + paCenter: + Inc(X, Width div 2); + end; + Handled := False; + if Assigned(FOnDropDownMenu) then + FOnDropDownMenu(Self, Point(X, Y), Handled); + if not Handled then + DropDownMenu.Popup(X, Y) + else + Exit; + { wait 'til menu is done } + while PeekMessage(Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) do + {nothing}; + end; +end; + +//=== { TJvDropDownButton } ================================================== + +constructor TJvDropDownButton.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + Width := 16; + Height := 16; +end; + +procedure TJvDropDownButton.Paint; +var + PaintRect: TRect; + DrawFlags: Integer; + DC: HDC; + Bmp: TBitmap; +begin + // adjust FState and FDragging + DC := Canvas.Handle; + Bmp := TBitmap.Create; + try + Bmp.Width := 1; + Bmp.Height := 1; + Canvas.Handle := Bmp.Canvas.Handle; + try + inherited Paint; + finally + Canvas.Handle := DC; + end; + finally + Bmp.Free; + end; + + PaintRect := Rect(0, 0, Width, Height); + DrawFlags := DFCS_SCROLLCOMBOBOX or DFCS_ADJUSTRECT; + if FState in [bsDown, bsExclusive] then + DrawFlags := DrawFlags or DFCS_PUSHED; + + {$IFDEF JVCLThemesEnabled} + if ThemeServices.ThemesEnabled then + DrawThemedFrameControl(Self, Canvas.Handle, PaintRect, DFC_SCROLL, DrawFlags) + else + {$ENDIF JVCLThemesEnabled} + begin + DrawFrameControl(Canvas.Handle, PaintRect, DFC_SCROLL, DrawFlags); + + end; +end; +******************** NOT CONVERTED *) + +procedure TJvCustomGraphicButton.DropDownClose; +begin + if Assigned(FOnDropDownClose) then + FOnDropDownClose(Self); +end; + +finalization + FreeAndNil(GlobalPattern); + +end. + diff --git a/components/jvcllaz/run/JvComponent.pas b/components/jvcllaz/run/JvComponent.pas new file mode 100644 index 000000000..0bd2eddc4 --- /dev/null +++ b/components/jvcllaz/run/JvComponent.pas @@ -0,0 +1,267 @@ +{----------------------------------------------------------------------------- +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: JvComponent.PAS, released on 2000-09-22. + +The Initial Developer of the Original Code is Joe Doe . +Portions created by Joe Doe are Copyright (C) 1999 Joe Doe. +Portions created by XXXX Corp. are Copyright (C) 1998, 1999 XXXX Corp. +All Rights Reserved. + +Contributor(s): - + +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: +-----------------------------------------------------------------------------} +// $Id: JvComponent.pas 11400 2007-06-28 21:24:06Z ahuser $ + +// Initial port to Lazarus by Sergio Samayoa - september 2007. +// Conversion is done in incremental way: as types / classes / routines +// are needed they are converted. + +{$mode objfpc}{$H+} + +unit JvComponent; + +interface + +uses + Classes, Controls, Forms, LMessages, JvExControls; + +type + TJvGraphicControl = TJvExGraphicControl; + + //******************** NOT CONVERTED + //TJvPubGraphicControl = TJvExPubGraphicControl; + + TJvCustomControl = TJvExCustomControl; + + //******************** NOT CONVERTED + //TJvWinControl = TJvExWinControl; + +(******************** NOT CONVERTED + TJvForm = class(TJvExForm) + private + FIsFocusable: Boolean; + procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED; + procedure WMMouseActivate(var Msg: TMessage); message WM_MOUSEACTIVATE; + protected + public + constructor Create(AOwner: TComponent); override; + constructor CreateNew(AOwner: TComponent; Dummy: Integer = 0); override; + {$IFDEF USE_DXGETTEXT} + procedure RefreshTranslation; virtual; + {$ENDIF USE_DXGETTEXT} + + function ShowModal: Integer; override; + { ShowNoActivate() shows the form but does not activate it. } + procedure ShowNoActivate(CallActivate: Boolean = False); + published + property IsFocusable: Boolean read FIsFocusable write FIsFocusable default True; + end; + +//=== { TJvPopupListBox } ==================================================== + +type + TJvPopupListBox = class(TJvExCustomListBox) + private + FSearchText: string; + FSearchTickCount: Longint; + protected + procedure CreateParams(var Params: TCreateParams); override; + procedure CreateWnd; override; + procedure KeyPress(var Key: Char); override; + end; +******************** NOT CONVERTED *) + +implementation + +(******************** NOT CONVERTED +{$IFDEF COMPILER6_UP} +uses + RTLConsts; +{$ELSE} +uses + Consts; +{$ENDIF COMPILER6_UP} + +//=== { TJvForm } ============================================================ + +constructor TJvForm.Create(AOwner: TComponent); +begin +// inherited Create(AOwner); + {$IFDEF CLR} + GlobalNameSpace.AcquireWriterLock(MaxInt); + {$ELSE} + GlobalNameSpace.BeginWrite; + {$ENDIF CLR} + try + CreateNew(AOwner, 0); + if (ClassType <> TJvForm) and not (csDesigning in ComponentState) then + begin + Include(FFormState, fsCreating); + try + if not InitInheritedComponent(Self, TJvForm) then + {$IFDEF CLR} + raise EResNotFound.CreateFmt(SResNotFound, [ClassName]); + {$ELSE} + raise EResNotFound.CreateResFmt(@SResNotFound, [ClassName]); + {$ENDIF CLR} + + {$IFDEF USE_DXGETTEXT} + TranslateComponent(Self, cDomainName); + {$ENDIF USE_DXGETTEXT} + finally + Exclude(FFormState, fsCreating); + end; + {$IFNDEF CLR} + if OldCreateOrder then + {$ENDIF !CLR} + DoCreate; + end; + finally + {$IFDEF CLR} + GlobalNameSpace.ReleaseWriterLock; + {$ELSE} + GlobalNameSpace.EndWrite; + {$ENDIF CLR} + end; +end; + +constructor TJvForm.CreateNew(AOwner: TComponent; Dummy: Integer); +begin + inherited CreateNew(AOwner, Dummy); + FIsFocusable := True; +end; + +{$IFDEF USE_DXGETTEXT} + +procedure TJvForm.RefreshTranslation; +begin + ReTranslateComponent(Self, cDomainName); +end; + +{$ENDIF USE_DXGETTEXT} + +procedure TJvForm.CMShowingChanged(var Message: TMessage); +var + NewParent: HWND; +begin + if Showing and (FormStyle <> fsMDIChild) then + begin + if FormStyle = fsStayOnTop then + begin + // restore StayOnTop + NewParent := Application.Handle; + if GetWindowLong(Handle, GWL_HWNDPARENT) <> Longint(NewParent) then + SetWindowLong(Handle, GWL_HWNDPARENT, Longint(NewParent)); + SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or SWP_NOACTIVATE); + end + else + begin + // Fixing the Window Ghosting "bug", only for forms that don't have a parent assigned (Mantis 4032) + if not Assigned(Parent) then + begin + NewParent := 0; + if Assigned(Screen.ActiveForm) and (Screen.ActiveForm <> Self) then + begin + if fsModal in Screen.ActiveForm.FormState then + NewParent := Screen.ActiveForm.Handle; + end; + if (NewParent = 0) and Assigned(Application.MainForm) and (Application.MainForm <> Self) then + NewParent := Application.MainForm.Handle; + if NewParent = 0 then + NewParent := Application.Handle; + if GetWindowLong(Handle, GWL_HWNDPARENT) <> Longint(NewParent) then + SetWindowLong(Handle, GWL_HWNDPARENT, Longint(NewParent)); + end; + end; + end; + inherited; +end; + +function TJvForm.ShowModal: Integer; +var + Msg: TMsg; +begin + while PeekMessage(Msg, 0, WM_ENABLE, WM_ENABLE, PM_REMOVE) do + DispatchMessage(Msg); + Result := inherited ShowModal; +end; + +procedure TJvForm.WMMouseActivate(var Msg: TMessage); +begin + if IsFocusable then + inherited + else + Msg.Result := MA_NOACTIVATE; +end; + +procedure TJvForm.ShowNoActivate(CallActivate: Boolean); +begin + if CallActivate then + Activate; + SetWindowPos(Handle, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_SHOWWINDOW or SWP_NOACTIVATE); + Visible := True; +end; + +//=== { TJvPopupListBox } ==================================================== + +procedure TJvPopupListBox.CreateParams(var Params: TCreateParams); +begin + inherited CreateParams(Params); + with Params do + begin + Style := Style or WS_BORDER; + ExStyle := WS_EX_TOOLWINDOW or WS_EX_TOPMOST; + AddBiDiModeExStyle(ExStyle); + WindowClass.Style := CS_SAVEBITS; + end; +end; + +procedure TJvPopupListBox.CreateWnd; +begin + inherited CreateWnd; + Windows.SetParent(Handle, 0); + CallWindowProc(DefWndProc, Handle, WM_SETFOCUS, 0, 0); +end; + +procedure TJvPopupListBox.KeyPress(var Key: Char); +var + TickCount: Int64; +begin + case Key of + BackSpace, Esc: + FSearchText := ''; + #32..#255: + begin + TickCount := GetTickCount; + if TickCount < FSearchTickCount then + Inc(TickCount, $100000000); // (ahuser) reduces the overflow + if TickCount - FSearchTickCount >= 4000 then + FSearchText := ''; + FSearchTickCount := TickCount; + if Length(FSearchText) < 32 then + FSearchText := FSearchText + Key; + {$IFNDEF CLR} + SendMessage(Handle, LB_SELECTSTRING, WPARAM(-1), LPARAM(PChar(FSearchText))); + {$ELSE} + SendTextMessage(Handle, LB_SELECTSTRING, WPARAM(-1), FSearchText); + {$ENDIF !CLR} + Key := #0; + end; + end; + inherited KeyPress(Key); +end; +******************** NOT CONVERTED *) + +end. diff --git a/components/jvcllaz/run/JvConsts.pas b/components/jvcllaz/run/JvConsts.pas new file mode 100644 index 000000000..fece89303 --- /dev/null +++ b/components/jvcllaz/run/JvConsts.pas @@ -0,0 +1,215 @@ +{----------------------------------------------------------------------------- +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: JvConst.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. + +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: +-----------------------------------------------------------------------------} +// $Id: JvConsts.pas 11414 2007-07-11 21:15:58Z ahuser $ + +// Initial port to Lazarus by Sergio Samayoa - september 2007. +// Conversion is done in incremental way: as types / classes / routines +// are needed they are converted. + +{$mode objfpc}{$H+} + +unit JvConsts; + +interface + +uses + Controls, Classes, LMessages, SysUtils; + //, Forms, Graphics, Windows, + +const + { JvEditor } + JvEditorCompletionChars = #8'0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'; + + { Various units } + DigitSymbols = ['0'..'9']; + SignSymbols = ['+', '-']; + IdentifierUppercaseLetters = ['A'..'Z']; + IdentifierLowercaseLetters = ['a'..'z']; + HexadecimalUppercaseLetters = ['A'..'F']; + HexadecimalLowercaseLetters = ['a'..'f']; + IdentifierLetters = IdentifierUppercaseLetters + IdentifierLowercaseLetters; + IdentifierFirstSymbols = ['_'] + IdentifierLetters; + IdentifierSymbols = IdentifierFirstSymbols + DigitSymbols; + HexadecimalSymbols = DigitSymbols + HexadecimalUppercaseLetters + HexadecimalLowercaseLetters; + + {$IFDEF DELPHI5} + SDelphiKey = 'Software\Borland\Delphi\5.0'; + {$ENDIF DELPHI5} + {$IFDEF BCB5} + SDelphiKey = 'Software\Borland\C++Builder\5.0'; + {$ENDIF BCB5} + {$IFDEF DELPHI6} + SDelphiKey = 'Software\Borland\Delphi\6.0'; + {$ENDIF DELPHI6} + {$IFDEF BCB6} + SDelphiKey = 'Software\Borland\C++Builder\6.0'; + {$ENDIF BCB6} + {$IFDEF DELPHI7} + SDelphiKey = 'Software\Borland\Delphi\7.0'; + {$ENDIF DELPHI7} + {$IFDEF DELPHI8} + SDelphiKey = 'Software\Borland\BDS\2.0'; + {$ENDIF DELPHI8} + {$IFDEF DELPHI9} + SDelphiKey = 'Software\Borland\BDS\3.0'; + {$ENDIF DELPHI9} + {$IFDEF DELPHI10} + SDelphiKey = 'Software\Borland\BDS\4.0'; + {$ENDIF DELPHI10} + {$IFDEF DELPHI11} + SDelphiKey = 'Software\Borland\BDS\5.0'; + {$ENDIF DELPHI11} + { JvDataProvider constants } + { Consumer attributes } + DPA_RenderDisabledAsGrayed = 1; + DPA_RendersSingleItem = 2; + DPA_ConsumerDisplaysList = 3; + + CM_JVBASE = CM_BASE + 80; // warning VCL improves and comes nearer + { Command message for JvSpeedbar editor } + CM_SPEEDBARCHANGED = CM_JVBASE + 0; + { Command message for TJvSpeedButton } + CM_JVBUTTONPRESSED = CM_JVBASE + 1; + // (rom) disabled unused + { Command messages for TJvWindowHook } + //CM_RECREATEWINDOW = CM_JVBASE + 2; + //CM_DESTROYHOOK = CM_JVBASE + 3; + { Notify message for TJvxTrayIcon } + //CM_TRAYICON = CM_JVBASE + 4; + CM_FORCESIZE = CM_JVBASE + 5; // used in JvButton + + { Values for WParam for CM_SPEEDBARCHANGED message } + SBR_CHANGED = 0; { change buttons properties } + SBR_DESTROYED = 1; { destroy SpeedBar } + SBR_BTNSELECT = 2; { select button in SpeedBar } + SBR_BTNSIZECHANGED = 3; { button size changed } + + { TBitmap.GetTransparentColor from GRAPHICS.PAS use this value } + PaletteMask = $02000000; + + // (outchy) now used + {$IFDEF COMPILER7_UP} + // (outchy) it was defined as $000000FF + DEFAULT_SYSCOLOR_MASK = clSystemColor; // $FF000000 + {$ELSE} + DEFAULT_SYSCOLOR_MASK = $80000000; + {$ENDIF COMPILER7_UP} + + {$IFDEF COMPILER5} + // Delphi colors not defined in Delphi 5 + clMoneyGreen = TColor($C0DCC0); + clSkyBlue = TColor($F0CAA6); + clCream = TColor($F0FBFF); + clMedGray = TColor($A4A0A0); + // (outchy) = TColor(COLOR_XXXXXXXXXXX or $80000000); + clGradientActiveCaption = TColor(COLOR_GRADIENTACTIVECAPTION or DEFAULT_SYSCOLOR_MASK); + clGradientInactiveCaption = TColor(COLOR_GRADIENTINACTIVECAPTION or DEFAULT_SYSCOLOR_MASK); + clHotLight = TColor(COLOR_HOTLIGHT or DEFAULT_SYSCOLOR_MASK); + clMenuHighlight = TColor(COLOR_MENUHILIGHT or DEFAULT_SYSCOLOR_MASK); + clMenuBar = TColor(COLOR_MENUBAR or DEFAULT_SYSCOLOR_MASK); + {$ENDIF COMPILER5} + + {$IFDEF COMPILER5} + {$IFDEF MSWINDOWS} + sLineBreak = #13#10; + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + sLineBreak = #10; + {$ENDIF UNIX} + {$ENDIF COMPILER5} + sLineBreakLen = Length(sLineBreak); + + CrLf = #13#10; + Cr = #13; + Lf = #10; + Backspace = #8; + Tab = #9; + Esc = #27; + Del = #127; + CtrlC = ^C; + CtrlH = ^H; + CtrlI = ^I; + CtrlJ = ^J; + CtrlM = ^M; + CtrlV = ^V; + CtrlX = ^X; + {$IFDEF MSWINDOWS} + RegPathDelim = '\'; + PathDelim = '\'; + DriveDelim = ':'; + PathSep = ';'; + AllFilePattern = '*.*'; + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + RegPathDelim = '_'; + PathDelim = '/'; + AllFilePattern = '*'; + {$ENDIF UNIX} + + (******************** NOT CONVERTED + //TODO: SESS - 25.09.2007 This doesnt compile in fpc + {const Separators is used in GetWordOnPos, JvUtils.ReplaceStrings and SubWord} + Separators: TSysCharSet = [#00, ' ', '-', #13, #10, '.', ',', '/', '\', '#', '"', '''', + ':', '+', '%', '*', '(', ')', ';', '=', '{', '}', '[', ']', '{', '}', '<', '>']; + ******************** NOT CONVERTED *) + + DigitChars = ['0'..'9']; + +var + crJVCLFirst: TCursor = 100; + crMultiDragLink: TCursor = 100; + crDragAlt: TCursor = 101; + crMultiDragAlt: TCursor = 102; + crMultiDragLinkAlt: TCursor = 103; + crHand: TCursor = 104; + crDragHand: TCursor = 105; + // this should be incremented to always contain the last default JVCL cursor index + crJVCLLast: TCursor = 105; + +const + ROP_DSPDxax = $00E20746; + +const + FOURCC_ACON = 'ACON'; + FOURCC_IART = 'IART'; + FOURCC_INAM = 'INAM'; + FOURCC_INFO = 'INFO'; + FOURCC_LIST = 'LIST'; + FOURCC_RIFF = 'RIFF'; + FOURCC_anih = 'anih'; + FOURCC_fram = 'fram'; + FOURCC_icon = 'icon'; + FOURCC_rate = 'rate'; + FOURCC_seq = 'seq '; + + AF_ICON = $00000001; + AF_SEQUENCE = $00000002; + +const + KeyboardShiftStates = [ssShift, ssAlt, ssCtrl]; + MouseShiftStates = [ssLeft, ssRight, ssMiddle, ssDouble]; + +implementation + +end. + diff --git a/components/jvcllaz/run/JvExControls.pas b/components/jvcllaz/run/JvExControls.pas new file mode 100644 index 000000000..2264df838 --- /dev/null +++ b/components/jvcllaz/run/JvExControls.pas @@ -0,0 +1,1064 @@ +{----------------------------------------------------------------------------- +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: JvExControls.pas, released on 2004-01-04 + +The Initial Developer of the Original Code is Andreas Hausladen [Andreas dott Hausladen att gmx dott de] +Portions created by Andreas Hausladen are Copyright (C) 2004 Andreas Hausladen. +All Rights Reserved. + +Contributor(s): - + dejoy. + +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: +-----------------------------------------------------------------------------} +// $Id: JvExControls.pas 11400 2007-06-28 21:24:06Z ahuser $ +// Initial port to Lazarus by Sergio Samayoa - september 2007. +// Conversion is done in incremental way: as types / classes / routines +// are needed they are converted. +// TODO: Make this unit generated by template as JVCL's. + +{$mode objfpc}{$H+} + +unit JvExControls; +{MACROINCLUDE JvExControls.macros} + +{***************************************************************************** + * WARNING: Do not edit this file. + * This file is autogenerated from the source in devtools/JvExVCL/src. + * If you do it despite this warning your changes will be discarded by the next + * update of this file. Do your changes in the template files. + ****************************************************************************} +{$D-} // do not step into this unit + +interface + +uses + Classes, Controls, Graphics, LCLIntf, LCLType, LMessages, Forms; + +type + TDlgCode = + (dcWantAllKeys, dcWantArrows, dcWantChars, dcButton, dcHasSetSel, dcWantTab, + dcNative); // if dcNative is in the set the native allowed keys are used and GetDlgCode is ignored + TDlgCodes = set of TDlgCode; + +(******************** NOT CONVERTED +const + dcWantMessage = dcWantAllKeys; + +const + CM_DENYSUBCLASSING = JvThemes.CM_DENYSUBCLASSING; + CM_PERFORM = CM_BASE + $500 + 0; // LParam: "Msg: ^TMessage" + CM_SETAUTOSIZE = CM_BASE + $500 + 1; // WParam: "Value: Boolean" + +type + TJvHotTrackOptions = class; + + { IJvExControl is used for the identification of an JvExXxx control. } + IJvExControl = interface + ['{8E6579C3-D683-4562-AFAB-D23C8526E386}'] + end; + + { Add IJvDenySubClassing to the base class list if the control should not + be themed by the ThemeManager (http://www.soft-gems.net Mike Lischke). + This only works with JvExVCL derived classes. } + IJvDenySubClassing = interface + ['{76942BC0-2A6E-4DC4-BFC9-8E110DB7F601}'] + end; + + + { IJvHotTrack is Specifies whether Control are highlighted when the mouse passes over them} + IJvHotTrack = interface + ['{8F1B40FB-D8E3-46FE-A7A3-21CE4B199A8F}'] + + function GetHotTrack:Boolean; + function GetHotTrackFont:TFont; + function GetHotTrackFontOptions:TJvTrackFontOptions; + function GetHotTrackOptions:TJvHotTrackOptions; + + procedure SetHotTrack(Value: Boolean); + procedure SetHotTrackFont(Value: TFont); + procedure SetHotTrackFontOptions(Value: TJvTrackFontOptions); + procedure SetHotTrackOptions(Value: TJvHotTrackOptions); + + property HotTrack: Boolean read GetHotTrack write SetHotTrack; + property HotTrackFont: TFont read GetHotTrackFont write SetHotTrackFont; + property HotTrackFontOptions: TJvTrackFontOptions read GetHotTrackFontOptions write SetHotTrackFontOptions; + property HotTrackOptions: TJvHotTrackOptions read GetHotTrackOptions write SetHotTrackOptions; + end; + + TJvHotTrackOptions = class(TJvPersistentProperty) + private + FEnabled: Boolean; + FFrameVisible: Boolean; + FColor: TColor; + FFrameColor: TColor; + procedure SetColor(Value: TColor); + procedure SetEnabled(Value: Boolean); + procedure SetFrameColor(Value: TColor); + procedure SetFrameVisible(Value: Boolean); + public + constructor Create; virtual; + procedure Assign(Source: TPersistent); override; + published + property Enabled: Boolean read FEnabled write SetEnabled default False; + property Color: TColor read FColor write SetColor default $00D2BDB6; + property FrameVisible: Boolean read FFrameVisible write SetFrameVisible default False; + property FrameColor: TColor read FFrameColor write SetFrameColor default $006A240A; + end; +******************** NOT CONVERTED *) + +type + TStructPtrMessage = class(TObject) + private + public + Msg: TLMessage; + constructor Create(AMsg: Integer; WParam: Integer; var LParam); + end; + +//******************** NOT CONVERTED +//procedure SetDotNetFrameColors(FocusedColor, UnfocusedColor: TColor); + +procedure DrawDotNetControl(Control: TWinControl; AColor: TColor; InControl: Boolean); +procedure HandleDotNetHighlighting(Control: TWinControl; const Msg: TLMessage; + MouseOver: Boolean; Color: TColor); +function CreateWMMessage(Msg: Integer; WParam: Integer; LParam: Longint): TLMessage; overload; {$IFDEF SUPPORTS_INLINE} inline {$ENDIF} +function CreateWMMessage(Msg: Integer; WParam: Integer; LParam: TControl): TLMessage; overload; {$IFDEF SUPPORTS_INLINE} inline {$ENDIF} +function SmallPointToLong(const Pt: TSmallPoint): Longint; {$IFDEF SUPPORTS_INLINE} inline {$ENDIF} +function ShiftStateToKeyData(Shift: TShiftState): Longint; + +//******************** NOT CONVERTED +//function GetFocusedControl(AControl: TControl): TWinControl; + +function DlgcToDlgCodes(Value: Longint): TDlgCodes; +function DlgCodesToDlgc(Value: TDlgCodes): Longint; +procedure GetHintColor(var HintInfo: THintInfo; AControl: TControl; HintColor: TColor); +function DispatchIsDesignMsg(Control: TControl; var Msg: TLMessage): Boolean; + +type + //******************** NOT CONVERTED + //CONTROL_DECL_DEFAULT(Control) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(WinControl) + + TJvExCustomControl = class(TCustomControl) + private + // TODO: + // FAboutJVCL: TJVCLAboutInfo; + FHintColor: TColor; + FMouseOver: Boolean; + FHintWindowClass: THintWindowClass; + FOnMouseEnter: TNotifyEvent; + FOnMouseLeave: TNotifyEvent; + FOnParentColorChanged: TNotifyEvent; + function BaseWndProc(Msg: Integer; WParam: Integer = 0; LParam: Longint = 0): Integer; overload; + function BaseWndProc(Msg: Integer; WParam: Integer; LParam: TControl): Integer; overload; + function BaseWndProcEx(Msg: Integer; WParam: Integer; var LParam): Integer; + protected + procedure WndProc(var Msg: TLMessage); override; + procedure FocusChanged(AControl: TWinControl); dynamic; + procedure VisibleChanged; reintroduce; dynamic; + procedure EnabledChanged; reintroduce; dynamic; + procedure TextChanged; reintroduce; virtual; + procedure ColorChanged; reintroduce; dynamic; + procedure FontChanged; reintroduce; dynamic; + procedure ParentFontChanged; reintroduce; dynamic; + procedure ParentColorChanged; reintroduce; dynamic; + procedure ParentShowHintChanged; reintroduce; dynamic; + function WantKey(Key: Integer; Shift: TShiftState; const KeyText: WideString): Boolean; reintroduce; virtual; + function HintShow(var HintInfo: THintInfo): Boolean; reintroduce; dynamic; + function HitTest(X, Y: Integer): Boolean; reintroduce; virtual; + procedure MouseEnter(AControl: TControl); reintroduce; dynamic; + procedure MouseLeave(AControl: TControl); reintroduce; dynamic; + property MouseOver: Boolean read FMouseOver write FMouseOver; + property HintColor: TColor read FHintColor write FHintColor default clDefault; + property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter; + property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave; + property OnParentColorChange: TNotifyEvent read FOnParentColorChanged write FOnParentColorChanged; + function GetCaption: TCaption; virtual; + procedure SetCaption(Value: TCaption); virtual; + public + constructor Create(AOwner: TComponent); override; + property Caption: TCaption read GetCaption write SetCaption; + property HintWindowClass: THintWindowClass read FHintWindowClass write FHintWindowClass; + published + // TODO: + // property AboutJVCL: TJVCLAboutInfo read FAboutJVCL write FAboutJVCL stored False; + private + FDotNetHighlighting: Boolean; + protected + procedure BoundsChanged; reintroduce; virtual; + procedure CursorChanged; reintroduce; dynamic; + procedure ShowingChanged; reintroduce; dynamic; + procedure ShowHintChanged; reintroduce; dynamic; + procedure ControlsListChanging(Control: TControl; Inserting: Boolean); reintroduce; dynamic; + procedure ControlsListChanged(Control: TControl; Inserting: Boolean); reintroduce; dynamic; + procedure GetDlgCode(var Code: TDlgCodes); virtual; + procedure FocusSet(PrevWnd: THandle); virtual; + procedure FocusKilled(NextWnd: THandle); virtual; + function DoEraseBackground(ACanvas: TCanvas; Param: Integer): Boolean; virtual; + published + property DotNetHighlighting: Boolean read FDotNetHighlighting write FDotNetHighlighting default False; + end; + + TJvExGraphicControl = class(TGraphicControl) + private + // TODO: + // FAboutJVCL: TJVCLAboutInfo; + FHintColor: TColor; + FMouseOver: Boolean; + FHintWindowClass: THintWindowClass; + FOnMouseEnter: TNotifyEvent; + FOnMouseLeave: TNotifyEvent; + FOnParentColorChanged: TNotifyEvent; + function BaseWndProc(Msg: Integer; WParam: Integer = 0; LParam: Longint = 0): Integer; overload; + function BaseWndProc(Msg: Integer; WParam: Integer; LParam: TControl): Integer; overload; + function BaseWndProcEx(Msg: Integer; WParam: Integer; var LParam): Integer; + protected + procedure WndProc(var Msg: TLMessage); override; + procedure FocusChanged(AControl: TWinControl); dynamic; + procedure VisibleChanged; reintroduce; dynamic; + procedure EnabledChanged; reintroduce; dynamic; + procedure TextChanged; reintroduce; virtual; + procedure ColorChanged; reintroduce; dynamic; + procedure FontChanged; reintroduce; dynamic; + procedure ParentFontChanged; reintroduce; dynamic; + procedure ParentColorChanged; reintroduce; dynamic; + procedure ParentShowHintChanged; reintroduce; dynamic; + function WantKey(Key: Integer; Shift: TShiftState; const KeyText: WideString): Boolean; reintroduce; virtual; + function HintShow(var HintInfo: THintInfo): Boolean; reintroduce; dynamic; + function HitTest(X, Y: Integer): Boolean; reintroduce; virtual; + procedure MouseEnter(AControl: TControl); reintroduce; dynamic; + procedure MouseLeave(AControl: TControl); reintroduce; dynamic; + property MouseOver: Boolean read FMouseOver write FMouseOver; + property HintColor: TColor read FHintColor write FHintColor default clDefault; + property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter; + property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave; + property OnParentColorChange: TNotifyEvent read FOnParentColorChanged write FOnParentColorChanged; + function GetCaption: TCaption; virtual; + procedure SetCaption(Value: TCaption); virtual; + public + constructor Create(AOwner: TComponent); override; + property Caption: TCaption read GetCaption write SetCaption; + property HintWindowClass: THintWindowClass read FHintWindowClass write FHintWindowClass; + published + // TODO: + // property AboutJVCL: TJVCLAboutInfo read FAboutJVCL write FAboutJVCL stored False; + end; + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(HintWindow) + +(******************** NOT CONVERTED + TJvExPubGraphicControl = class(TJvExGraphicControl) + COMMON_PUBLISHED + end; +******************** NOT CONVERTED *) + +implementation + +(******************** NOT CONVERTED +uses + TypInfo; + +var + InternalFocusedColor: TColor = TColor($00733800); + InternalUnfocusedColor: TColor = clGray; + +procedure SetDotNetFrameColors(FocusedColor, UnfocusedColor: TColor); +begin + InternalFocusedColor := FocusedColor; + InternalUnfocusedColor := UnfocusedColor; +end; +******************** NOT CONVERTED *) + +procedure DrawDotNetControl(Control: TWinControl; AColor: TColor; InControl: Boolean); +(******************** NOT CONVERTED +var + DC: HDC; + R: TRect; + Canvas: TCanvas; +begin + DC := GetWindowDC(Control.Handle); + try + GetWindowRect(Control.Handle, R); + OffsetRect(R, -R.Left, -R.Top); + Canvas := TCanvas.Create; + with Canvas do + try + Handle := DC; + Brush.Color := InternalUnfocusedColor; + if Control.Focused or InControl then + Brush.Color := InternalFocusedColor; + FrameRect(R); + InflateRect(R, -1, -1); + if not (Control.Focused or InControl) then + Brush.Color := AColor; + FrameRect(R); + finally + Free; + end; + finally + ReleaseDC(Control.Handle, DC); + end; +end; +******************** NOT CONVERTED *) +begin +end; + +procedure HandleDotNetHighlighting(Control: TWinControl; const Msg: TLMessage; + MouseOver: Boolean; Color: TColor); +(******************** NOT CONVERTED +var + Rgn, SubRgn: HRGN; +begin + if not (csDesigning in Control.ComponentState) then + case Msg.Msg of + CM_MOUSEENTER, CM_MOUSELEAVE, WM_KILLFOCUS, WM_SETFOCUS, WM_NCPAINT: + begin + DrawDotNetControl(Control, Color, MouseOver); + if Msg.Msg = CM_MOUSELEAVE then + begin + Rgn := CreateRectRgn(0, 0, Control.Width - 1, Control.Height - 1); + SubRgn := CreateRectRgn(2, 2, Control.Width - 3, Control.Height - 3); + try + CombineRgn(Rgn, Rgn, SubRgn, RGN_DIFF); + InvalidateRgn(Control.Handle, Rgn, False); // redraw 3D border + finally + DeleteObject(SubRgn); + DeleteObject(Rgn); + end; + end; + end; + end; +end; +******************** NOT CONVERTED *) +begin +end; + +function CreateWMMessage(Msg: Integer; WParam: Integer; LParam: Longint): TLMessage; +begin + Result.Msg := Msg; + Result.WParam := WParam; + Result.LParam := LParam; + Result.Result := 0; +end; + +function CreateWMMessage(Msg: Integer; WParam: Integer; LParam: TControl): TLMessage; +begin + Result := CreateWMMessage(Msg, WParam, Integer(LParam)); +end; + +{ TStructPtrMessage } +constructor TStructPtrMessage.Create(AMsg: Integer; WParam: Integer; var LParam); +begin + inherited Create; + Self.Msg.Msg := AMsg; + Self.Msg.WParam := WParam; + Self.Msg.LParam := Longint(@LParam); + Self.Msg.Result := 0; +end; + +function SmallPointToLong(const Pt: TSmallPoint): Longint; +begin + Result := Longint(Pt); +end; + +function ShiftStateToKeyData(Shift: TShiftState): Longint; +const + AltMask = $20000000; + CtrlMask = $10000000; + ShiftMask = $08000000; +begin + Result := 0; + if ssAlt in Shift then + Result := Result or AltMask; + if ssCtrl in Shift then + Result := Result or CtrlMask; + if ssShift in Shift then + Result := Result or ShiftMask; +end; + +(******************** NOT CONVERTED +function GetFocusedControl(AControl: TControl): TWinControl; +var + Form: TCustomForm; +begin + Result := nil; + Form := GetParentForm(AControl); + if Assigned(Form) then + Result := Form.ActiveControl; +end; +******************** NOT CONVERTED *) + +function DlgcToDlgCodes(Value: Longint): TDlgCodes; +begin + Result := []; +(******************** NOT CONVERTED + if (Value and DLGC_WANTARROWS) <> 0 then + Include(Result, dcWantArrows); + if (Value and DLGC_WANTTAB) <> 0 then + Include(Result, dcWantTab); + if (Value and DLGC_WANTALLKEYS) <> 0 then + Include(Result, dcWantAllKeys); + if (Value and DLGC_WANTCHARS) <> 0 then + Include(Result, dcWantChars); + if (Value and DLGC_BUTTON) <> 0 then + Include(Result, dcButton); + if (Value and DLGC_HASSETSEL) <> 0 then + Include(Result, dcHasSetSel); +******************** NOT CONVERTED *) +end; + +function DlgCodesToDlgc(Value: TDlgCodes): Longint; +begin + Result := 0; +(******************** NOT CONVERTED + if dcWantAllKeys in Value then + Result := Result or DLGC_WANTALLKEYS; + if dcWantArrows in Value then + Result := Result or DLGC_WANTARROWS; + if dcWantTab in Value then + Result := Result or DLGC_WANTTAB; + if dcWantChars in Value then + Result := Result or DLGC_WANTCHARS; + if dcButton in Value then + Result := Result or DLGC_BUTTON; + if dcHasSetSel in Value then + Result := Result or DLGC_HASSETSEL; +******************** NOT CONVERTED *) +end; + +procedure GetHintColor(var HintInfo: THintInfo; AControl: TControl; HintColor: TColor); +var + AHintInfo: THintInfo; +begin + case HintColor of + clNone: + HintInfo.HintColor := Application.HintColor; + clDefault: + begin + if Assigned(AControl) and Assigned(AControl.Parent) then + begin + AHintInfo := HintInfo; + AControl.Parent.Perform(CM_HINTSHOW, 0, Integer(@AHintInfo)); + HintInfo.HintColor := AHintInfo.HintColor; + end; + end; + else + HintInfo.HintColor := HintColor; + end; +end; + +function DispatchIsDesignMsg(Control: TControl; var Msg: TLMessage): Boolean; +var + Form: TCustomForm; +begin + Result := False; + case Msg.Msg of + LM_SETFOCUS, LM_KILLFOCUS, LM_NCHITTEST, + LM_MOUSEFIRST..LM_MOUSELAST, + LM_KEYFIRST..LM_KEYLAST, + LM_CANCELMODE: + Exit; // These messages are handled in TWinControl.WndProc before IsDesignMsg() is called + end; + if (Control <> nil) and (csDesigning in Control.ComponentState) then + begin + Form := GetParentForm(Control); + if (Form <> nil) and (Form.Designer <> nil) and + Form.Designer.IsDesignMsg(Control, Msg) then + Result := True; + end; +end; + +(******************** NOT CONVERTED +//=== { TJvHotTrackOptions } ====================================== + +constructor TJvHotTrackOptions.Create; +begin + inherited Create; + FEnabled := False; + FFrameVisible := False; + FColor := $00D2BDB6; + FFrameColor := $006A240A; +end; + +procedure TJvHotTrackOptions.Assign(Source: TPersistent); +begin + if Source is TJvHotTrackOptions then + begin + BeginUpdate; + try + Enabled := TJvHotTrackOptions(Source).Enabled; + Color := TJvHotTrackOptions(Source).Color; + FrameVisible := TJvHotTrackOptions(Source).FrameVisible; + FrameColor := TJvHotTrackOptions(Source).FrameColor; + finally + EndUpdate; + end; + end + else + inherited Assign(Source); +end; + +procedure TJvHotTrackOptions.SetColor(Value: TColor); +begin + if FColor <> Value then + begin + Changing; + ChangingProperty('Color'); + FColor := Value; + ChangedProperty('Color'); + Changed; + end; +end; + +procedure TJvHotTrackOptions.SetEnabled(Value: Boolean); +begin + if FEnabled <> Value then + begin + Changing; + ChangingProperty('Enabled'); + FEnabled := Value; + ChangedProperty('Enabled'); + Changed; + end; +end; + +procedure TJvHotTrackOptions.SetFrameVisible(Value: Boolean); +begin + if FFrameVisible <> Value then + begin + Changing; + ChangingProperty('FrameVisible'); + FFrameVisible := Value; + ChangedProperty('FrameVisible'); + Changed; + end; +end; + +procedure TJvHotTrackOptions.SetFrameColor(Value: TColor); +begin + if FFrameColor <> Value then + begin + Changing; + ChangingProperty('FrameColor'); + FFrameColor := Value; + ChangedProperty('FrameColor'); + Changed; + end; +end; +******************** NOT CONVERTED *) + +//============================================================================ + +//******************** NOT CONVERTED +//CONTROL_IMPL_DEFAULT(Control) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(WinControl) + +constructor TJvExGraphicControl.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FHintColor := clDefault; +end; + +function TJvExGraphicControl.BaseWndProc(Msg: Integer; WParam: Integer = 0; LParam: Longint = 0): Integer; +var + Mesg: TLMessage; +begin + Mesg := CreateWMMessage(Msg, WParam, LParam); + inherited WndProc(Mesg); + Result := Mesg.Result; +end; + +function TJvExGraphicControl.BaseWndProc(Msg: Integer; WParam: Integer; LParam: TControl): Integer; +var + Mesg: TLMessage; +begin + Mesg := CreateWMMessage(Msg, WParam, LParam); + inherited WndProc(Mesg); + Result := Mesg.Result; +end; + +function TJvExGraphicControl.BaseWndProcEx(Msg: Integer; WParam: Integer; var LParam): Integer; +var + Mesg: TStructPtrMessage; +begin + Mesg := TStructPtrMessage.Create(Msg, WParam, LParam); + try + inherited WndProc(Mesg.Msg); + finally + Result := Mesg.Msg.Result; + Mesg.Free; + end; +end; + +procedure TJvExGraphicControl.VisibleChanged; +begin + BaseWndProc(CM_VISIBLECHANGED); +end; + +procedure TJvExGraphicControl.EnabledChanged; +begin + BaseWndProc(CM_ENABLEDCHANGED); +end; + +procedure TJvExGraphicControl.TextChanged; +begin + BaseWndProc(CM_TEXTCHANGED); +end; + +procedure TJvExGraphicControl.FontChanged; +begin + BaseWndProc(CM_FONTCHANGED); +end; + +procedure TJvExGraphicControl.ColorChanged; +begin + BaseWndProc(CM_COLORCHANGED); +end; + +procedure TJvExGraphicControl.ParentFontChanged; +begin + // LCL doesn't send this message but left it in case + //BaseWndProc(CM_PARENTFONTCHANGED); +end; + +procedure TJvExGraphicControl.ParentColorChanged; +begin + BaseWndProc(CM_PARENTCOLORCHANGED); + if Assigned(OnParentColorChange) then + OnParentColorChange(Self); +end; + +procedure TJvExGraphicControl.ParentShowHintChanged; +begin + BaseWndProc(CM_PARENTSHOWHINTCHANGED); +end; + +function TJvExGraphicControl.WantKey(Key: Integer; Shift: TShiftState; const KeyText: WideString): Boolean; +begin + Result := BaseWndProc(CM_DIALOGCHAR, Word(Key), ShiftStateToKeyData(Shift)) <> 0; +end; + +function TJvExGraphicControl.HitTest(X, Y: Integer): Boolean; +begin + Result := BaseWndProc(CM_HITTEST, 0, SmallPointToLong(PointToSmallPoint(Point(X, Y)))) <> 0; +end; + +function TJvExGraphicControl.HintShow(var HintInfo: THintInfo): Boolean; +begin + GetHintColor(HintInfo, Self, FHintColor); + if FHintWindowClass <> nil then + HintInfo.HintWindowClass := FHintWindowClass; + Result := BaseWndProcEx(CM_HINTSHOW, 0, HintInfo) <> 0; +end; + +procedure TJvExGraphicControl.MouseEnter(AControl: TControl); +begin + FMouseOver := True; + if Assigned(FOnMouseEnter) then + FOnMouseEnter(Self); + BaseWndProc(CM_MOUSEENTER, 0, AControl); +end; + +procedure TJvExGraphicControl.MouseLeave(AControl: TControl); +begin + FMouseOver := False; + BaseWndProc(CM_MOUSELEAVE, 0, AControl); + if Assigned(FOnMouseLeave) then + FOnMouseLeave(Self); +end; + +procedure TJvExGraphicControl.FocusChanged(AControl: TWinControl); +begin + BaseWndProc(CM_FOCUSCHANGED, 0, AControl); +end; + +function TJvExGraphicControl.GetCaption: TCaption; +begin + Result := inherited Caption; +end; + +// 25.09.2007 - SESS: +// I have done this because TextChanged wasn't fired as expected. +// I still don't shure if this problem is only for this reintroduced +// method because the way LCL treats Caption or will have the same +// problem with other reintroduced methods. So far, I tested some +// other events and seems not. +procedure TJvExGraphicControl.SetCaption(Value: TCaption); +begin + inherited Caption := Value; + TextChanged; +end; + +procedure TJvExGraphicControl.WndProc(var Msg: TLMessage); +begin + if not DispatchIsDesignMsg(Self, Msg) then + case Msg.Msg of + { + // TODO: do we need this? I think not... + CM_DENYSUBCLASSING: + Msg.Result := Ord(GetInterfaceEntry(IJvDenySubClassing) <> nil); + } + CM_DIALOGCHAR: + with TCMDialogChar(Msg) do + Result := Ord(WantKey(CharCode, KeyDataToShiftState(KeyData), WideChar(CharCode))); + CM_HINTSHOW: + with TCMHintShow(Msg) do + Result := Integer(HintShow(HintInfo^)); + CM_HITTEST: + with TCMHitTest(Msg) do + Result := Integer(HitTest(XPos, YPos)); + CM_MOUSEENTER: + MouseEnter(TControl(Msg.LParam)); + CM_MOUSELEAVE: + MouseLeave(TControl(Msg.LParam)); + CM_VISIBLECHANGED: + VisibleChanged; + CM_ENABLEDCHANGED: + EnabledChanged; + // LCL doesn't send this message but left it in case + CM_TEXTCHANGED: + TextChanged; + CM_FONTCHANGED: + FontChanged; + CM_COLORCHANGED: + ColorChanged; + CM_FOCUSCHANGED: + FocusChanged(TWinControl(Msg.LParam)); + // LCL doesn't send this message but left it in case + //CM_PARENTFONTCHANGED: + // ParentFontChanged; + CM_PARENTCOLORCHANGED: + ParentColorChanged; + CM_PARENTSHOWHINTCHANGED: + ParentShowHintChanged; + else + inherited WndProc(Msg); + end; +end; + +//============================================================================ + +constructor TJvExCustomControl.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FHintColor := clDefault; +end; + +function TJvExCustomControl.BaseWndProc(Msg: Integer; WParam: Integer = 0; LParam: Longint = 0): Integer; +var + Mesg: TLMessage; +begin + Mesg := CreateWMMessage(Msg, WParam, LParam); + inherited WndProc(Mesg); + Result := Mesg.Result; +end; + +function TJvExCustomControl.BaseWndProc(Msg: Integer; WParam: Integer; LParam: TControl): Integer; +var + Mesg: TLMessage; +begin + Mesg := CreateWMMessage(Msg, WParam, LParam); + inherited WndProc(Mesg); + Result := Mesg.Result; +end; + +function TJvExCustomControl.BaseWndProcEx(Msg: Integer; WParam: Integer; var LParam): Integer; +var + Mesg: TStructPtrMessage; +begin + Mesg := TStructPtrMessage.Create(Msg, WParam, LParam); + try + inherited WndProc(Mesg.Msg); + finally + Result := Mesg.Msg.Result; + Mesg.Free; + end; +end; + +procedure TJvExCustomControl.VisibleChanged; +begin + BaseWndProc(CM_VISIBLECHANGED); +end; + +procedure TJvExCustomControl.EnabledChanged; +begin + BaseWndProc(CM_ENABLEDCHANGED); +end; + +procedure TJvExCustomControl.TextChanged; +begin + BaseWndProc(CM_TEXTCHANGED); +end; + +procedure TJvExCustomControl.FontChanged; +begin + BaseWndProc(CM_FONTCHANGED); +end; + +procedure TJvExCustomControl.ColorChanged; +begin + BaseWndProc(CM_COLORCHANGED); +end; + +procedure TJvExCustomControl.ParentFontChanged; +begin + // LCL doesn't send this message but left it in case + //BaseWndProc(CM_PARENTFONTCHANGED); +end; + +procedure TJvExCustomControl.ParentColorChanged; +begin + BaseWndProc(CM_PARENTCOLORCHANGED); + if Assigned(OnParentColorChange) then + OnParentColorChange(Self); +end; + +procedure TJvExCustomControl.ParentShowHintChanged; +begin + BaseWndProc(CM_PARENTSHOWHINTCHANGED); +end; + +function TJvExCustomControl.WantKey(Key: Integer; Shift: TShiftState; const KeyText: WideString): Boolean; +begin + Result := BaseWndProc(CM_DIALOGCHAR, Word(Key), ShiftStateToKeyData(Shift)) <> 0; +end; + +function TJvExCustomControl.HitTest(X, Y: Integer): Boolean; +begin + Result := BaseWndProc(CM_HITTEST, 0, SmallPointToLong(PointToSmallPoint(Point(X, Y)))) <> 0; +end; + +function TJvExCustomControl.HintShow(var HintInfo: THintInfo): Boolean; +begin + GetHintColor(HintInfo, Self, FHintColor); + if FHintWindowClass <> nil then + HintInfo.HintWindowClass := FHintWindowClass; + Result := BaseWndProcEx(CM_HINTSHOW, 0, HintInfo) <> 0; +end; + +procedure TJvExCustomControl.MouseEnter(AControl: TControl); +begin + FMouseOver := True; + if Assigned(FOnMouseEnter) then + FOnMouseEnter(Self); + BaseWndProc(CM_MOUSEENTER, 0, AControl); +end; + +procedure TJvExCustomControl.MouseLeave(AControl: TControl); +begin + FMouseOver := False; + BaseWndProc(CM_MOUSELEAVE, 0, AControl); + if Assigned(FOnMouseLeave) then + FOnMouseLeave(Self); +end; + +procedure TJvExCustomControl.FocusChanged(AControl: TWinControl); +begin + BaseWndProc(CM_FOCUSCHANGED, 0, AControl); +end; + +function TJvExCustomControl.GetCaption: TCaption; +begin + Result := inherited Caption; +end; + +// 25.09.2007 - SESS: +// I have done this because TextChanged wasn't fired as expected. +// I still don't shure if this problem is only for this reintroduced +// method because the way LCL treats Caption or will have the same +// problem with other reintroduced methods. So far, I tested some +// other events and seems not. +procedure TJvExCustomControl.SetCaption(Value: TCaption); +begin + inherited Caption := Value; + TextChanged; +end; + +procedure TJvExCustomControl.BoundsChanged; +begin +end; + +procedure TJvExCustomControl.CursorChanged; +begin + BaseWndProc(CM_CURSORCHANGED); +end; + +procedure TJvExCustomControl.ShowingChanged; +begin + BaseWndProc(CM_SHOWINGCHANGED); +end; + +procedure TJvExCustomControl.ShowHintChanged; +begin + BaseWndProc(CM_SHOWHINTCHANGED); +end; + +{ VCL sends CM_CONTROLLISTCHANGE and CM_CONTROLCHANGE in a different order than + the CLX methods are used. So we must correct it by evaluating "Inserting". } +procedure TJvExCustomControl.ControlsListChanging(Control: TControl; Inserting: Boolean); +begin + if Inserting then + BaseWndProc(CM_CONTROLLISTCHANGE, Integer(Control), Integer(Inserting)) + else + BaseWndProc(CM_CONTROLCHANGE, Integer(Control), Integer(Inserting)); +end; + +procedure TJvExCustomControl.ControlsListChanged(Control: TControl; Inserting: Boolean); +begin + if not Inserting then + BaseWndProc(CM_CONTROLLISTCHANGE, Integer(Control), Integer(Inserting)) + else + BaseWndProc(CM_CONTROLCHANGE, Integer(Control), Integer(Inserting)); +end; + +procedure TJvExCustomControl.GetDlgCode(var Code: TDlgCodes); +begin +end; + +procedure TJvExCustomControl.FocusSet(PrevWnd: THandle); +begin + BaseWndProc(LM_SETFOCUS, Integer(PrevWnd), 0); +end; + +procedure TJvExCustomControl.FocusKilled(NextWnd: THandle); +begin + BaseWndProc(LM_KILLFOCUS, Integer(NextWnd), 0); +end; + +function TJvExCustomControl.DoEraseBackground(ACanvas: TCanvas; Param: Integer): Boolean; +begin + Result := BaseWndProc(LM_ERASEBKGND, ACanvas.Handle, Param) <> 0; +end; + +procedure TJvExCustomControl.WndProc(var Msg: TLMessage); +var + IdSaveDC: Integer; + DlgCodes: TDlgCodes; + WCanvas: TCanvas; +begin + if not DispatchIsDesignMsg(Self, Msg) then + begin + case Msg.Msg of + { + // TODO: do we need this? I think not... + CM_DENYSUBCLASSING: + Msg.Result := Ord(GetInterfaceEntry(IJvDenySubClassing) <> nil); + } + CM_DIALOGCHAR: + with TCMDialogChar(Msg) do + Result := Ord(WantKey(CharCode, KeyDataToShiftState(KeyData), WideChar(CharCode))); + CM_HINTSHOW: + with TCMHintShow(Msg) do + Result := Integer(HintShow(HintInfo^)); + CM_HITTEST: + with TCMHitTest(Msg) do + Result := Integer(HitTest(XPos, YPos)); + CM_MOUSEENTER: + MouseEnter(TControl(Msg.LParam)); + CM_MOUSELEAVE: + MouseLeave(TControl(Msg.LParam)); + CM_VISIBLECHANGED: + VisibleChanged; + CM_ENABLEDCHANGED: + EnabledChanged; + // LCL doesn't send this message but left it in case + CM_TEXTCHANGED: + TextChanged; + CM_FONTCHANGED: + FontChanged; + CM_COLORCHANGED: + ColorChanged; + CM_FOCUSCHANGED: + FocusChanged(TWinControl(Msg.LParam)); + // LCL doesn't send this message but left it in case + //CM_PARENTFONTCHANGED: + // ParentFontChanged; + CM_PARENTCOLORCHANGED: + ParentColorChanged; + CM_PARENTSHOWHINTCHANGED: + ParentShowHintChanged; + CM_CURSORCHANGED: + CursorChanged; + CM_SHOWINGCHANGED: + ShowingChanged; + CM_SHOWHINTCHANGED: + ShowHintChanged; + CM_CONTROLLISTCHANGE: + if Msg.LParam <> 0 then + ControlsListChanging(TControl(Msg.WParam), True) + else + ControlsListChanged(TControl(Msg.WParam), False); + CM_CONTROLCHANGE: + if Msg.LParam = 0 then + ControlsListChanging(TControl(Msg.WParam), False) + else + ControlsListChanged(TControl(Msg.WParam), True); + LM_SETFOCUS: + FocusSet(THandle(Msg.WParam)); + LM_KILLFOCUS: + FocusKilled(THandle(Msg.WParam)); + LM_SIZE: + begin + inherited WndProc(Msg); + BoundsChanged; + end; + LM_ERASEBKGND: + if Msg.WParam <> 0 then + begin + IdSaveDC := SaveDC(HDC(Msg.WParam)); // protect DC against Stock-Objects from Canvas + WCanvas := TCanvas.Create; + try + WCanvas.Handle := HDC(Msg.WParam); + Msg.Result := Ord(DoEraseBackground(WCanvas, Msg.LParam)); + finally + WCanvas.Handle := 0; + WCanvas.Free; + RestoreDC(HDC(Msg.WParam), IdSaveDC); + end; + end + else + inherited WndProc(Msg); + LM_GETDLGCODE: + begin + inherited WndProc(Msg); + DlgCodes := [dcNative] + DlgcToDlgCodes(Msg.Result); + GetDlgCode(DlgCodes); + if not (dcNative in DlgCodes) then + Msg.Result := DlgCodesToDlgc(DlgCodes); + end; + else + inherited WndProc(Msg); + end; + // TODO: + // LM_NCPAINT isn't send by LCL, may be .Net highlighting can't be implemented. + case Msg.Msg of // precheck message to prevent access violations on released controls + CM_MOUSEENTER, CM_MOUSELEAVE, LM_KILLFOCUS, LM_SETFOCUS, LM_NCPAINT: + if DotNetHighlighting then + HandleDotNetHighlighting(Self, Msg, MouseOver, Color); + end; + end; +end; + +//============================================================================ + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(HintWindow) + +end. + diff --git a/components/jvcllaz/run/JvExExtCtrls.pas b/components/jvcllaz/run/JvExExtCtrls.pas new file mode 100644 index 000000000..b70f641f0 --- /dev/null +++ b/components/jvcllaz/run/JvExExtCtrls.pas @@ -0,0 +1,395 @@ +{----------------------------------------------------------------------------- +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: JvExExtCtrls.pas, released on 2004-01-04 + +The Initial Developer of the Original Code is Andreas Hausladen [Andreas dott Hausladen att gmx dott de] +Portions created by Andreas Hausladen are Copyright (C) 2004 Andreas Hausladen. +All Rights Reserved. + +Contributor(s): - + +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: +-----------------------------------------------------------------------------} +// $Id: JvExExtCtrls.pas 10613 2006-05-19 19:21:43Z jfudickar $ + +// Initial port to Lazarus by Sergio Samayoa - september 2007. +// Conversion is done in incremental way: as types / classes / routines +// are needed they are converted. + +unit JvExExtCtrls; + +{MACROINCLUDE JvExControls.macros} + +{***************************************************************************** + * WARNING: Do not edit this file. + * This file is autogenerated from the source in devtools/JvExVCL/src. + * If you do it despite this warning your changes will be discarded by the next + * update of this file. Do your changes in the template files. + ****************************************************************************} +{$D-} // do not step into this unit + +interface + +uses + Classes, Controls, ExtCtrls, Forms, Graphics, JvExControls, LCLIntf, LMessages; + +type + //******************** NOT CONVERTED + //CONTROL_DECL_DEFAULT(Shape) + + //******************** NOT CONVERTED + //CONTROL_DECL_DEFAULT(PaintBox) + + //******************** NOT CONVERTED + //CONTROL_DECL_DEFAULT(Image) + + //******************** NOT CONVERTED + //CONTROL_DECL_DEFAULT(Bevel) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(CustomPanel) + + (******************** NOT CONVERTED + TJvExPubCustomPanel = class(TJvExCustomPanel) + COMMON_PUBLISHED + end; + ******************** NOT CONVERTED *) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(CustomRadioGroup) + + TJvExSplitter = class(TSplitter) + private + // TODO: + // FAboutJVCL: TJVCLAboutInfo; + FHintColor: TColor; + FMouseOver: Boolean; + FHintWindowClass: THintWindowClass; + FOnMouseEnter: TNotifyEvent; + FOnMouseLeave: TNotifyEvent; + FOnParentColorChanged: TNotifyEvent; + function BaseWndProc(Msg: Integer; WParam: Integer = 0; LParam: Longint = 0): Integer; overload; + function BaseWndProc(Msg: Integer; WParam: Integer; LParam: TControl): Integer; overload; + function BaseWndProcEx(Msg: Integer; WParam: Integer; var LParam): Integer; + protected + procedure WndProc(var Msg: TLMessage); override; + procedure FocusChanged(AControl: TWinControl); dynamic; + procedure VisibleChanged; reintroduce; dynamic; + procedure EnabledChanged; reintroduce; dynamic; + procedure TextChanged; reintroduce; virtual; + procedure ColorChanged; reintroduce; dynamic; + procedure FontChanged; reintroduce; dynamic; + procedure ParentFontChanged; reintroduce; dynamic; + procedure ParentColorChanged; reintroduce; dynamic; + procedure ParentShowHintChanged; reintroduce; dynamic; + function WantKey(Key: Integer; Shift: TShiftState; const KeyText: WideString): Boolean; reintroduce; virtual; + function HintShow(var HintInfo: THintInfo): Boolean; reintroduce; dynamic; + function HitTest(X, Y: Integer): Boolean; reintroduce; virtual; + procedure MouseEnter(AControl: TControl); reintroduce; dynamic; + procedure MouseLeave(AControl: TControl); reintroduce; dynamic; + property MouseOver: Boolean read FMouseOver write FMouseOver; + property HintColor: TColor read FHintColor write FHintColor default clDefault; + property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter; + property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave; + property OnParentColorChange: TNotifyEvent read FOnParentColorChanged write FOnParentColorChanged; + function GetCaption: TCaption; virtual; + procedure SetCaption(Value: TCaption); virtual; + public + constructor Create(AOwner: TComponent); override; + property Caption: TCaption read GetCaption write SetCaption; + property HintWindowClass: THintWindowClass read FHintWindowClass write FHintWindowClass; + published + // TODO: + // property AboutJVCL: TJVCLAboutInfo read FAboutJVCL write FAboutJVCL stored False; + end; + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(CustomControlBar) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(ControlBar) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(Panel) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(RadioGroup) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(Page) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(Notebook) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(Header) + + + //******************** NOT CONVERTED + //CONTROL_DECL_DEFAULT(BoundLabel) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(CustomLabeledEdit) + + //******************** NOT CONVERTED + //WINCONTROL_DECL_DEFAULT(LabeledEdit) + + //******************** NOT CONVERTED - Exists in LCL? + //WINCONTROL_DECL_DEFAULT(CustomColorBox) + + //******************** NOT CONVERTED - Exists in LCL? + //WINCONTROL_DECL_DEFAULT(ColorBox) + +implementation + +//******************** NOT CONVERTED +//CONTROL_IMPL_DEFAULT(Shape) + +//******************** NOT CONVERTED +//CONTROL_IMPL_DEFAULT(PaintBox) + +//******************** NOT CONVERTED +//CONTROL_IMPL_DEFAULT(Image) + +//******************** NOT CONVERTED +//CONTROL_IMPL_DEFAULT(Bevel) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(CustomPanel) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(CustomRadioGroup) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(CustomControlBar) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(ControlBar) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(Panel) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(RadioGroup) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(Page) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(Notebook) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(Header) + +//******************** NOT CONVERTED +//CONTROL_IMPL_DEFAULT(BoundLabel) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(CustomLabeledEdit) + +//******************** NOT CONVERTED +//WINCONTROL_IMPL_DEFAULT(LabeledEdit) + +//******************** NOT CONVERTED - Exists in LCL? +//WINCONTROL_IMPL_DEFAULT(CustomColorBox) + +//******************** NOT CONVERTED - Exists in LCL? +//WINCONTROL_IMPL_DEFAULT(ColorBox) + +constructor TJvExSplitter.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FHintColor := clDefault; +end; + +function TJvExSplitter.BaseWndProc(Msg: Integer; WParam: Integer = 0; LParam: Longint = 0): Integer; +var + Mesg: TLMessage; +begin + Mesg := CreateWMMessage(Msg, WParam, LParam); + inherited WndProc(Mesg); + Result := Mesg.Result; +end; + +function TJvExSplitter.BaseWndProc(Msg: Integer; WParam: Integer; LParam: TControl): Integer; +var + Mesg: TLMessage; +begin + Mesg := CreateWMMessage(Msg, WParam, LParam); + inherited WndProc(Mesg); + Result := Mesg.Result; +end; + +function TJvExSplitter.BaseWndProcEx(Msg: Integer; WParam: Integer; var LParam): Integer; +var + Mesg: TStructPtrMessage; +begin + Mesg := TStructPtrMessage.Create(Msg, WParam, LParam); + try + inherited WndProc(Mesg.Msg); + finally + Result := Mesg.Msg.Result; + Mesg.Free; + end; +end; + +procedure TJvExSplitter.VisibleChanged; +begin + BaseWndProc(CM_VISIBLECHANGED); +end; + +procedure TJvExSplitter.EnabledChanged; +begin + BaseWndProc(CM_ENABLEDCHANGED); +end; + +procedure TJvExSplitter.TextChanged; +begin + BaseWndProc(CM_TEXTCHANGED); +end; + +procedure TJvExSplitter.FontChanged; +begin + BaseWndProc(CM_FONTCHANGED); +end; + +procedure TJvExSplitter.ColorChanged; +begin + BaseWndProc(CM_COLORCHANGED); +end; + +procedure TJvExSplitter.ParentFontChanged; +begin + // LCL doesn't send this message but left it in case + //BaseWndProc(CM_PARENTFONTCHANGED); +end; + +procedure TJvExSplitter.ParentColorChanged; +begin + BaseWndProc(CM_PARENTCOLORCHANGED); + if Assigned(OnParentColorChange) then + OnParentColorChange(Self); +end; + +procedure TJvExSplitter.ParentShowHintChanged; +begin + BaseWndProc(CM_PARENTSHOWHINTCHANGED); +end; + +function TJvExSplitter.WantKey(Key: Integer; Shift: TShiftState; const KeyText: WideString): Boolean; +begin + Result := BaseWndProc(CM_DIALOGCHAR, Word(Key), ShiftStateToKeyData(Shift)) <> 0; +end; + +function TJvExSplitter.HitTest(X, Y: Integer): Boolean; +begin + Result := BaseWndProc(CM_HITTEST, 0, SmallPointToLong(PointToSmallPoint(Point(X, Y)))) <> 0; +end; + +function TJvExSplitter.HintShow(var HintInfo: THintInfo): Boolean; +begin + GetHintColor(HintInfo, Self, FHintColor); + if FHintWindowClass <> nil then + HintInfo.HintWindowClass := FHintWindowClass; + Result := BaseWndProcEx(CM_HINTSHOW, 0, HintInfo) <> 0; +end; + +procedure TJvExSplitter.MouseEnter(AControl: TControl); +begin + FMouseOver := True; + if Assigned(FOnMouseEnter) then + FOnMouseEnter(Self); + BaseWndProc(CM_MOUSEENTER, 0, AControl); +end; + +procedure TJvExSplitter.MouseLeave(AControl: TControl); +begin + FMouseOver := False; + BaseWndProc(CM_MOUSELEAVE, 0, AControl); + if Assigned(FOnMouseLeave) then + FOnMouseLeave(Self); +end; + +procedure TJvExSplitter.FocusChanged(AControl: TWinControl); +begin + BaseWndProc(CM_FOCUSCHANGED, 0, AControl); +end; + +function TJvExSplitter.GetCaption: TCaption; +begin + Result := inherited Caption; +end; + +// 25.09.2007 - SESS: +// I have done this because TextChanged wasn't fired as expected. +// I still don't shure if this problem is only for this reintroduced +// method because the way LCL treats Caption or will have the same +// problem with other reintroduced methods. So far, I tested some +// other events and seems not. +procedure TJvExSplitter.SetCaption(Value: TCaption); +begin + inherited Caption := Value; + TextChanged; +end; + +procedure TJvExSplitter.WndProc(var Msg: TLMessage); +begin + if not DispatchIsDesignMsg(Self, Msg) then + case Msg.Msg of + { + // TODO: do we need this? I think not... + CM_DENYSUBCLASSING: + Msg.Result := Ord(GetInterfaceEntry(IJvDenySubClassing) <> nil); + } + CM_DIALOGCHAR: + with TCMDialogChar(Msg) do + Result := Ord(WantKey(CharCode, KeyDataToShiftState(KeyData), WideChar(CharCode))); + CM_HINTSHOW: + with TCMHintShow(Msg) do + Result := Integer(HintShow(HintInfo^)); + CM_HITTEST: + with TCMHitTest(Msg) do + Result := Integer(HitTest(XPos, YPos)); + CM_MOUSEENTER: + MouseEnter(TControl(Msg.LParam)); + CM_MOUSELEAVE: + MouseLeave(TControl(Msg.LParam)); + CM_VISIBLECHANGED: + VisibleChanged; + CM_ENABLEDCHANGED: + EnabledChanged; + // LCL doesn't send this message but left it in case + CM_TEXTCHANGED: + TextChanged; + CM_FONTCHANGED: + FontChanged; + CM_COLORCHANGED: + ColorChanged; + CM_FOCUSCHANGED: + FocusChanged(TWinControl(Msg.LParam)); + // LCL doesn't send this message but left it in case + //CM_PARENTFONTCHANGED: + // ParentFontChanged; + CM_PARENTCOLORCHANGED: + ParentColorChanged; + CM_PARENTSHOWHINTCHANGED: + ParentShowHintChanged; + else + inherited WndProc(Msg); + end; +end; + +//============================================================================ + +end. diff --git a/components/jvcllaz/run/JvJCLUtils.pas b/components/jvcllaz/run/JvJCLUtils.pas new file mode 100644 index 000000000..60344317f --- /dev/null +++ b/components/jvcllaz/run/JvJCLUtils.pas @@ -0,0 +1,9764 @@ +{----------------------------------------------------------------------------- +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: JvJCLUtils.pas, released on 2002-07-04. + +The Initial Developers of the Original Code are: Andrei Prygounkov +Copyright (c) 1999, 2002 Andrei Prygounkov +All Rights Reserved. + +Contributor(s): + Andreas Hausladen + Ralf Kaiser + Vladimir Gaitanoff + Dejoy den + +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: + +-----------------------------------------------------------------------------} +// $Id: JvJCLUtils.pas 11400 2007-06-28 21:24:06Z ahuser $ + +// (ahuser) No dependency on JCL units. Required functions are emulated. + +// Initial port to Lazarus by Sergio Samayoa - september 2007. +// Conversion is done in incremental way: as types / classes / routines +// are needed they are converted. + +{$mode objfpc}{$H+} + +unit JvJCLUtils; + +interface + +// (p3) note: this unit should only contain JCL compatible routines (no Forms etc) +// and no JVCL units! +// (ahuser) Unfortunately the QGraphics unit imports the QForms unit. Because +// the JCL has the same problem with CLX it should not make any difference. + +uses + Classes, Graphics, LCLIntf, LCLType; + +(******************** NOT CONVERTED +const + {$IFDEF MSWINDOWS} + PathDelim = '\'; + DriveDelim = ':'; + PathSep = ';'; + AllFilesMask = '*.*'; + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + PathDelim = '/'; + AllFilesMask = '*'; + {$ENDIF UNIX} + // Note: the else is on purpose, VCL is not defined for a console application + NullHandle = 0; + +{$IFDEF UNIX} +type + TFileTime = Integer; +{$ENDIF UNIX} + +function SendRectMessage(Handle: THandle; Msg: Integer; wParam: WPARAM; var R: TRect): Integer; +function SendStructMessage(Handle: THandle; Msg: Integer; wParam: WPARAM; var Data): Integer; + +function ReadCharsFromStream(Stream: TStream; var Buf: array of Char; BufSize: Integer): Integer; // ANSI-Stream +function WriteStringToStream(Stream: TStream; const Buf: string; BufSize: Integer): Integer; // ANSI-Stream + +const + DefaultDateOrder = doDMY; + CenturyOffset: Byte = 60; + NullDate: TDateTime = {-693594} 0; + +function USToLocalFloatStr(const Text: string): string; +function StrToFloatUS(const Text: string): Extended; +// StrToFloatUS uses US '.' as decimal seperator and ',' as thousand separator +function StrToFloatUSDef(const Text: string; Default: Extended): Extended; + +function VarIsInt(Value: Variant): Boolean; + // VarIsInt returns VarIsOrdinal-[varBoolean] + +{ PosIdx returns the index of the first appearance of SubStr in Str. The search + starts at index "Index". } +function PosIdx(const SubStr, S: string; Index: Integer = 0): Integer; +{$IFNDEF CLR} +function PosIdxW(const SubStr, S: WideString; Index: Integer = 0): Integer; +{$ENDIF !CLR} +function PosLastCharIdx(Ch: Char; const S: string; Index: Integer = 0): Integer; + +{ GetWordOnPos returns Word from string, S, on the cursor position, P} +function GetWordOnPos(const S: string; const P: Integer): string; +function GetWordOnPosW(const S: WideString; const P: Integer): WideString; +function GetWordOnPos2(const S: string; P: Integer; var iBeg, iEnd: Integer): string; +function GetWordOnPos2W(const S: WideString; P: Integer; var iBeg, iEnd: Integer): WideString; +{ GetWordOnPosEx working like GetWordOnPos function, but + also returns Word position in iBeg, iEnd variables } +function GetWordOnPosEx(const S: string; const P: Integer; var iBeg, iEnd: Integer): string; +function GetWordOnPosExW(const S: WideString; const P: Integer; var iBeg, iEnd: Integer): WideString; +function GetNextWordPosEx(const Text: string; StartIndex: Integer; + var iBeg, iEnd: Integer): string; +function GetNextWordPosExW(const Text: WideString; StartIndex: Integer; + var iBeg, iEnd: Integer): WideString; +procedure GetEndPosCaret(const Text: string; CaretX, CaretY: Integer; + var X, Y: Integer); +{ GetEndPosCaret returns the caret position of the last char. For the position + after the last char of Text you must add 1 to the returned X value. } +procedure GetEndPosCaretW(const Text: WideString; CaretX, CaretY: Integer; + var X, Y: Integer); +{ GetEndPosCaret returns the caret position of the last char. For the position + after the last char of Text you must add 1 to the returned X value. } + +{ SubStrBySeparator returns substring from string, S, separated with Separator string} +function SubStrBySeparator(const S: string; const Index: Integer; const Separator: string; StartIndex: Integer = 1): string; +{$IFNDEF CLR} +function SubStrBySeparatorW(const S: WideString; const Index: Integer; const Separator: WideString; StartIndex: Integer = 1): WideString; +{$ENDIF !CLR} +{ SubStrEnd same to previous function but Index numerated from the end of string } +//function SubStrEnd(const S: string; const Index: Integer; const Separator: string): string; +{ SubWord returns next Word from string, P, and offsets Pointer to the end of Word, P2 } +{$IFDEF CLR} +function SubWord(P: string; var P2: string): string; +{$ELSE} +function SubWord(P: PChar; var P2: PChar): string; +{$ENDIF CLR} +// function CurrencyByWord(Value: Currency): string; +{ GetLineByPos returns the Line number, there + the symbol Pos is pointed. Lines separated with #13 symbol } +function GetLineByPos(const S: string; const Pos: Integer): Integer; +{ GetXYByPos is same as GetLineByPos, but returns X position in line as well} +procedure GetXYByPos(const S: string; const Pos: Integer; var X, Y: Integer); +procedure GetXYByPosW(const S: WideString; const Pos: Integer; var X, Y: Integer); +{ ReplaceString searches for all substrings, OldPattern, + in a string, S, and replaces them with NewPattern } +function ReplaceString(S: string; const OldPattern, NewPattern: string; StartIndex: Integer = 1): string; +{$IFNDEF CLR} +function ReplaceStringW(S: WideString; const OldPattern, NewPattern: WideString; StartIndex: Integer = 1): WideString; +{$ENDIF !CLR} +{ ConcatSep concatenate S1 and S2 strings with Separator. + if S = '' then separator not included } +function ConcatSep(const S1, S2, Separator: string): string; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +{ ConcatLeftSep is same to previous function, but + strings concatenate right to left } +function ConcatLeftSep(const S1, S2, Separator: string): string; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} + +{ Next 4 function for russian chars transliterating. + This functions are needed because Oem2Ansi and Ansi2Oem functions + sometimes suck } +procedure Dos2Win(var S: string); +procedure Win2Dos(var S: string); +function Dos2WinRes(const S: string): string; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +function Win2DosRes(const S: string): string; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +function Win2Koi(const S: string): string; + +{ FillString fills the string Buffer with Count Chars } +procedure FillString(var Buffer: string; Count: Integer; const Value: Char); overload; +procedure FillString(var Buffer: string; StartIndex, Count: Integer; const Value: Char); overload; +{ MoveString copies Count Chars from Source to Dest } +procedure MoveString(const Source: string; var Dest: string; Count: Integer); {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} overload; +procedure MoveString(const Source: string; SrcStartIdx: Integer; var Dest: string; + DstStartIdx: Integer; Count: Integer); {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} overload; +{$IFNDEF CLR} +{ FillWideChar fills Buffer with Count WideChars (2 Bytes) } +procedure FillWideChar(var Buffer; Count: Integer; const Value: WideChar); +{ MoveWideChar copies Count WideChars from Source to Dest } +procedure MoveWideChar(const Source; var Dest; Count: Integer); {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +{$ENDIF !CLR} +{ IsSubString() compares the sub string to the string. Indices are 1th based. } +function IsSubString(const S: string; StartIndex: Integer; const SubStr: string): Boolean; + +{ Spaces returns string consists on N space chars } +function Spaces(const N: Integer): string; +{ AddSpaces adds spaces to string S, if its Length is smaller than N } +function AddSpaces(const S: string; const N: Integer): string; +{$IFNDEF CLR} +function SpacesW(const N: Integer): WideString; +function AddSpacesW(const S: WideString; const N: Integer): WideString; +{$ENDIF !CLR} +{ function LastDateRUS for russian users only } +{ returns date relative to current date: 'äâà äíÿ íàçàä' } +function LastDateRUS(const Dat: TDateTime): string; +{ CurrencyToStr format Currency, Cur, using ffCurrency float format} +function CurrencyToStr(const Cur: Currency): string; +{ HasChar returns True, if Char, Ch, contains in string, S } +function HasChar(const Ch: Char; const S: string): Boolean; +function HasCharW(const Ch: WideChar; const S: WideString): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +function HasAnyChar(const Chars: string; const S: string): Boolean; +function CharInSet(const Ch: Char; const SetOfChar: TSysCharSet): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +function CharInSetW(const Ch: WideChar; const SetOfChar: TSysCharSet): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +function CountOfChar(const Ch: Char; const S: string): Integer; +function DefStr(const S: string; Default: string): string; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} + +{$IFNDEF CLR} +{ StrLICompW2 is a faster replacement for JclUnicode.StrLICompW } +function StrLICompW2(S1, S2: PWideChar; MaxLen: Integer): Integer; +function StrPosW(S, SubStr: PWideChar): PWideChar; +function StrLenW(S: PWideChar): Integer; +{$ENDIF !CLR} +function TrimW(const S: WideString): WideString; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +function TrimLeftW(const S: WideString): WideString; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +function TrimRightW(const S: WideString): WideString; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +{**** files routines} +procedure SetDelimitedText(List: TStrings; const Text: string; Delimiter: Char); + +const + {$IFDEF MSWINDOWS} + DefaultCaseSensitivity = False; + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + DefaultCaseSensitivity = True; + {$ENDIF UNIX} + +{ GetTempDir returns Windows temporary folder name } +function GetTempDir: string; +{ GenTempFileName returns temporary file name on + drive, there FileName is placed } +function GenTempFileName(FileName: string): string; +{ GenTempFileNameExt same to previous function, but + returning filename has given extension, FileExt } +function GenTempFileNameExt(FileName: string; const FileExt: string): string; +{ ClearDir clears folder Dir } +function ClearDir(const Dir: string): Boolean; +{ DeleteDir clears and than delete folder Dir } +function DeleteDir(const Dir: string): Boolean; +{ FileEquMask returns True if file, FileName, + is compatible with given dos file mask, Mask } +function FileEquMask(FileName, Mask: TFileName; + CaseSensitive: Boolean = DefaultCaseSensitivity): Boolean; +{ FileEquMasks returns True if file, FileName, + is compatible with given Masks. + Masks must be separated with SepPath (MSW: ';' / UNIX: ':') } +function FileEquMasks(FileName, Masks: TFileName; + CaseSensitive: Boolean = DefaultCaseSensitivity): Boolean; +function DeleteFiles(const Folder: TFileName; const Masks: string): Boolean; + +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} +{ LZFileExpand expand file, FileSource, + into FileDest. Given file must be compressed, using MS Compress program } +function LZFileExpand(const FileSource, FileDest: string): Boolean; +{$ENDIF MSWINDOWS} +{$ENDIF !CLR} + +{ FileGetInfo fills SearchRec record for specified file attributes} +function FileGetInfo(FileName: TFileName; var SearchRec: TSearchRec): Boolean; +{ HasSubFolder returns True, if folder APath contains other folders } +function HasSubFolder(APath: TFileName): Boolean; +{ IsEmptyFolder returns True, if there are no files or + folders in given folder, APath} +function IsEmptyFolder(APath: TFileName): Boolean; +{ AddSlash returns string with added slash Char to Dir parameter, if needed } +function AddSlash(const Dir: TFileName): string; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +{ AddPath returns FileName with Path, if FileName not contain any path } +function AddPath(const FileName, Path: TFileName): TFileName; +function AddPaths(const PathList, Path: string): string; +function ParentPath(const Path: TFileName): TFileName; +function FindInPath(const FileName, PathList: string): TFileName; +{ DeleteReadOnlyFile clears R/O file attribute and delete file } +function DeleteReadOnlyFile(const FileName: TFileName): Boolean; +{ HasParam returns True, if program running with specified parameter, Param } +function HasParam(const Param: string): Boolean; +function HasSwitch(const Param: string): Boolean; +function Switch(const Param: string): string; +{ ExePath returns ExtractFilePath(ParamStr(0)) } +function ExePath: TFileName; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +function CopyDir(const SourceDir, DestDir: TFileName): Boolean; +//function FileTimeToDateTime(const FT: TFileTime): TDateTime; +procedure FileTimeToDosDateTimeDWord(const FT: TFileTime; out Dft: DWORD); +function MakeValidFileName(const FileName: TFileName; ReplaceBadChar: Char): TFileName; + +{**** Graphic routines } + +{ IsTTFontSelected returns True, if True Type font + is selected in specified device context } +function IsTTFontSelected(const DC: HDC): Boolean; +function KeyPressed(VK: Integer): Boolean; + +{ TrueInflateRect inflates rect in other method, than InflateRect API function } +function TrueInflateRect(const R: TRect; const I: Integer): TRect; + +{**** Color routines } +procedure RGBToHSV(R, G, B: Integer; var H, S, V: Integer); +function RGBToBGR(Value: Cardinal): Cardinal; +function ColorToPrettyName(Value: TColor): string; +function PrettyNameToColor(const Value: string): TColor; + +{**** other routines } +procedure SwapInt(var Int1, Int2: Integer); {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +function IntPower(Base, Exponent: Integer): Integer; +{$IFNDEF CLR} +function ChangeTopException(E: TObject): TObject; // Linux version writes error message to ErrOutput +{$ENDIF !CLR} +function StrToBool(const S: string): Boolean; + +function Var2Type(V: Variant; const DestVarType: Integer): Variant; +function VarToInt(V: Variant): Integer; +function VarToFloat(V: Variant): Double; + +{ following functions are not documented + because they do not work properly sometimes, so do not use them } +// (rom) ReplaceStrings1, GetSubStr removed + +function GetLongFileName(const FileName: string): string; +function FileNewExt(const FileName, NewExt: TFileName): TFileName; +{$IFNDEF CLR} +function GetParameter: string; +function GetComputerID: string; +{$ENDIF !CLR} +function GetComputerName: string; + +{**** string routines } + +{ ReplaceAllStrings searches for all substrings, Words, + in a string, S, and replaces them with Frases with the same Index. } +function ReplaceAllStrings(const S: string; Words, Frases: TStrings): string; +{ ReplaceStrings searches the Word in a string, S, on PosBeg position, + in the list, Words, and if founds, replaces this Word + with string from another list, Frases, with the same Index, + and then update NewSelStart variable } +function ReplaceStrings(const S: string; PosBeg, Len: Integer; Words, Frases: TStrings; var NewSelStart: Integer): string; +{ CountOfLines calculates the lines count in a string, S, + each line must be separated from another with CrLf sequence } +function CountOfLines(const S: string): Integer; +{ DeleteLines deletes all lines from strings which in the words, words. + The word of will be deleted from strings. } +procedure DeleteOfLines(Ss: TStrings; const Words: array of string); +{ DeleteEmptyLines deletes all empty lines from strings, Ss. + Lines contained only spaces also deletes. } +procedure DeleteEmptyLines(Ss: TStrings); +{ SQLAddWhere addes or modifies existing where-statement, where, + to the strings, SQL. + Note: If strings SQL allready contains where-statement, + it must be started on the begining of any line } +procedure SQLAddWhere(SQL: TStrings; const Where: string); + +{**** files routines - } + +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} +{ ResSaveToFile save resource named as Name with Typ type into file FileName. + Resource can be compressed using MS Compress program} +function ResSaveToFile(const Typ, Name: string; const Compressed: Boolean; const FileName: string): Boolean; +function ResSaveToFileEx(Instance: HINST; Typ, Name: PChar; + const Compressed: Boolean; const FileName: string): Boolean; +function ResSaveToString(Instance: HINST; const Typ, Name: string; + var S: string): Boolean; +{$ENDIF MSWINDOWS} +{$ENDIF !CLR} +{ IniReadSection read section, Section, from ini-file, + IniFileName, into strings, Ss. + This function reads ALL strings from specified section. + Note: TIninFile.ReadSection function reads only strings with '=' symbol.} +function IniReadSection(const IniFileName: TFileName; const Section: string; Ss: TStrings): Boolean; +{ LoadTextFile load text file, FileName, into string } +function LoadTextFile(const FileName: TFileName): string; +procedure SaveTextFile(const FileName: TFileName; const Source: string); +{ ReadFolder reads files list from disk folder, Folder, + that are equal to mask, Mask, into strings, FileList} +function ReadFolder(const Folder, Mask: TFileName; FileList: TStrings): Integer; +function ReadFolders(const Folder: TFileName; FolderList: TStrings): Integer; + +{ RATextOut same with TCanvas.TextOut procedure, but + can clipping drawing with rectangle, RClip. } +procedure RATextOut(Canvas: TCanvas; const R, RClip: TRect; const S: string); +{ RATextOutEx same with RATextOut function, but + can calculate needed height for correct output } +function RATextOutEx(Canvas: TCanvas; const R, RClip: TRect; const S: string; const CalcHeight: Boolean): Integer; +{ RATextCalcHeight calculate needed height for + correct output, using RATextOut or RATextOutEx functions } +function RATextCalcHeight(Canvas: TCanvas; const R: TRect; const S: string): Integer; +{ Cinema draws some visual effect } +procedure Cinema(Canvas: TCanvas; rS {Source}, rD {Dest}: TRect); +{ Roughed fills rect with special 3D pattern } +procedure Roughed(ACanvas: TCanvas; const ARect: TRect; const AVert: Boolean); +{ BitmapFromBitmap creates new small bitmap from part + of source bitmap, SrcBitmap, with specified width and height, + AWidth, AHeight and placed on a specified Index, Index in the + source bitmap } +function BitmapFromBitmap(SrcBitmap: TBitmap; const AWidth, AHeight, Index: Integer): TBitmap; +{ TextWidth calculate text with for writing using standard desktop font } +function TextWidth(const AStr: string): Integer; +{ TextHeight calculate text height for writing using standard desktop font } +function TextHeight(const AStr: string): Integer; + +procedure SetChildPropOrd(Owner: TComponent; const PropName: string; Value: Longint); +procedure Error(const Msg: string); +procedure ItemHtDrawEx(Canvas: TCanvas; Rect: TRect; + const State: TOwnerDrawState; const Text: string; + const HideSelColor: Boolean; var PlainItem: string; + var Width: Integer; CalcWidth: Boolean); +{ example for Text parameter : + 'Item 1 bold italic ITALIC red green blue ' } +function ItemHtDraw(Canvas: TCanvas; Rect: TRect; + const State: TOwnerDrawState; const Text: string; + const HideSelColor: Boolean): string; +function ItemHtWidth(Canvas: TCanvas; Rect: TRect; + const State: TOwnerDrawState; const Text: string; + const HideSelColor: Boolean): Integer; +function ItemHtPlain(const Text: string): string; +{ ClearList - clears list of TObject } +procedure ClearList(List: TList); + +{$IFNDEF CLR} +procedure MemStreamToClipBoard(MemStream: TMemoryStream; const Format: Word); +procedure ClipBoardToMemStream(MemStream: TMemoryStream; const Format: Word); +{$ENDIF !CLR} + +{ RTTI support } +function GetPropType(Obj: TObject; const PropName: string): TTypeKind; +function GetPropStr(Obj: TObject; const PropName: string): string; +function GetPropOrd(Obj: TObject; const PropName: string): Integer; +function GetPropMethod(Obj: TObject; const PropName: string): TMethod; + +procedure PrepareIniSection(Ss: TStrings); +{ following functions are not documented because + they are don't work properly, so don't use them } + +// (rom) from JvBandWindows to make it obsolete +function PointL(const X, Y: Longint): TPointL; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +// (rom) from JvBandUtils to make it obsolete +function iif(const Test: Boolean; const ATrue, AFalse: Variant): Variant; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} + +{$IFNDEF CLR} +procedure CopyIconToClipboard(Icon: TIcon; BackColor: TColor); +function CreateIconFromClipboard: TIcon; +{$ENDIF !CLR} +{ begin JvIconClipboardUtils } +{ Icon clipboard routines } +function CF_ICON: Word; +{$IFNDEF CLR} +procedure AssignClipboardIcon(Icon: TIcon); + +{ Real-size icons support routines (32-bit only) } +procedure GetIconSize(Icon: HICON; var W, H: Integer); +function CreateRealSizeIcon(Icon: TIcon): HICON; +procedure DrawRealSizeIcon(Canvas: TCanvas; Icon: TIcon; X, Y: Integer); +{end JvIconClipboardUtils } + +function CreateScreenCompatibleDC: HDC; +{$ENDIF !CLR} + +{ begin JvRLE } + +// (rom) changed API for inclusion in JCL + +procedure RleCompressTo(InStream, OutStream: TStream); +procedure RleDecompressTo(InStream, OutStream: TStream); +procedure RleCompress(Stream: TStream); +procedure RleDecompress(Stream: TStream); +{ end JvRLE } + +{ begin JvDateUtil } +function CurrentYear: Word; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +function IsLeapYear(AYear: Integer): Boolean; +function DaysInAMonth(const AYear, AMonth: Word): Word; +function DaysPerMonth(AYear, AMonth: Integer): Integer; +function FirstDayOfPrevMonth: TDateTime; +function LastDayOfPrevMonth: TDateTime; +function FirstDayOfNextMonth: TDateTime; +function ExtractDay(ADate: TDateTime): Word; +function ExtractMonth(ADate: TDateTime): Word; +function ExtractYear(ADate: TDateTime): Word; +function IncDate(ADate: TDateTime; Days, Months, Years: Integer): TDateTime; +function IncDay(ADate: TDateTime; Delta: Integer): TDateTime; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +function IncMonth(ADate: TDateTime; Delta: Integer): TDateTime; +function IncYear(ADate: TDateTime; Delta: Integer): TDateTime; +function ValidDate(ADate: TDateTime): Boolean; +procedure DateDiff(Date1, Date2: TDateTime; var Days, Months, Years: Word); +function MonthsBetween(Date1, Date2: TDateTime): Double; +function DaysInPeriod(Date1, Date2: TDateTime): Longint; +{ Count days between Date1 and Date2 + 1, so if Date1 = Date2 result = 1 } +function DaysBetween(Date1, Date2: TDateTime): Longint; +{ The same as previous but if Date2 < Date1 result = 0 } +function IncTime(ATime: TDateTime; Hours, Minutes, Seconds, MSecs: Integer): TDateTime; +function IncHour(ATime: TDateTime; Delta: Integer): TDateTime; +function IncMinute(ATime: TDateTime; Delta: Integer): TDateTime; +function IncSecond(ATime: TDateTime; Delta: Integer): TDateTime; +function IncMSec(ATime: TDateTime; Delta: Integer): TDateTime; +function CutTime(ADate: TDateTime): TDateTime; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} { Set time to 00:00:00:00 } + +{ String to date conversions } +function GetDateOrder(const DateFormat: string): TDateOrder; +function MonthFromName(const S: string; MaxLen: Byte): Byte; +function StrToDateDef(const S: string; Default: TDateTime): TDateTime; +function StrToDateFmt(const DateFormat, S: string): TDateTime; +function StrToDateFmtDef(const DateFormat, S: string; Default: TDateTime): TDateTime; +function DefDateFormat(AFourDigitYear: Boolean): string; +function DefDateMask(BlanksChar: Char; AFourDigitYear: Boolean): string; + +function FormatLongDate(Value: TDateTime): string; +function FormatLongDateTime(Value: TDateTime): string; +{ end JvDateUtil } +{$IFDEF CLR} +function BufToBinStr(const Buf: TBytes; BufSize: Integer): string; +function BinStrToBuf(Value: string; Buf: TBytes; BufSize: Integer): Integer; +{$ELSE} +function BufToBinStr(Buf: Pointer; BufSize: Integer): string; +function BinStrToBuf(Value: string; Buf: Pointer; BufSize: Integer): Integer; +{$ENDIF CLR} + + +{ begin JvStrUtils } + + { ** Common string handling routines ** } + +{$IFDEF UNIX} +function iconversion(InP: PChar; OutP: Pointer; InBytes, OutBytes: Cardinal; + const ToCode, FromCode: string): Boolean; +function iconvString(const S, ToCode, FromCode: string): string; +function iconvWideString(const S: WideString; const ToCode, FromCode: string): WideString; +function OemStrToAnsi(const S: string): string; +function AnsiStrToOem(const S: string): string; +{$ENDIF UNIX} + +function StrToOem(const AnsiStr: string): string; +{ StrToOem translates a string from the Windows character set into the + OEM character set. } +function OemToAnsiStr(const OemStr: string): string; +{ OemToAnsiStr translates a string from the OEM character set into the + Windows character set. } +function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean; +{ EmptyStr returns True if the given string contains only character + from the EmptyChars. } +function ReplaceStr(const S, Srch, Replace: string): string; +{ Returns string with every occurrence of Srch string replaced with + Replace string. } +function DelSpace(const S: string): string; +{ DelSpace return a string with all white spaces removed. } +function DelChars(const S: string; Chr: Char): string; +{ DelChars return a string with all Chr characters removed. } +function DelBSpace(const S: string): string; +{ DelBSpace trims leading spaces from the given string. } +function DelESpace(const S: string): string; +{ DelESpace trims trailing spaces from the given string. } +function DelRSpace(const S: string): string; +{ DelRSpace trims leading and trailing spaces from the given string. } +function DelSpace1(const S: string): string; +{ DelSpace1 return a string with all non-single white spaces removed. } +function Tab2Space(const S: string; Numb: Byte): string; +{ Tab2Space converts any tabulation character in the given string to the + Numb spaces characters. } +function NPos(const C: string; S: string; N: Integer): Integer; +{ NPos searches for a N-th position of substring C in a given string. } +function MakeStr(C: Char; N: Integer): string; overload; +{$IFNDEF CLR} +function MakeStr(C: WideChar; N: Integer): WideString; overload; +{$ENDIF !CLR} +function MS(C: Char; N: Integer): string; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +{ MakeStr return a string of length N filled with character C. } +function AddChar(C: Char; const S: string; N: Integer): string; +{ AddChar return a string left-padded to length N with characters C. } +function AddCharR(C: Char; const S: string; N: Integer): string; +{ AddCharR return a string right-padded to length N with characters C. } +function LeftStr(const S: string; N: Integer): string; +{ LeftStr return a string right-padded to length N with blanks. } +function RightStr(const S: string; N: Integer): string; +{ RightStr return a string left-padded to length N with blanks. } +function CenterStr(const S: string; Len: Integer): string; +{ CenterStr centers the characters in the string based upon the + Len specified. } +function CompStr(const S1, S2: string): Integer; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +{ CompStr compares S1 to S2, with case-sensitivity. The return value is + -1 if S1 < S2, 0 if S1 = S2, or 1 if S1 > S2. } +function CompText(const S1, S2: string): Integer; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +{ CompText compares S1 to S2, without case-sensitivity. The return value + is the same as for CompStr. } +function Copy2Symb(const S: string; Symb: Char): string; +{ Copy2Symb returns a substring of a string S from begining to first + character Symb. } +function Copy2SymbDel(var S: string; Symb: Char): string; +{ Copy2SymbDel returns a substring of a string S from begining to first + character Symb and removes this substring from S. } +function Copy2Space(const S: string): string; +{ Copy2Symb returns a substring of a string S from begining to first + white space. } +function Copy2SpaceDel(var S: string): string; +{ Copy2SpaceDel returns a substring of a string S from begining to first + white space and removes this substring from S. } +function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string; +{ Returns string, with the first letter of each word in uppercase, + all other letters in lowercase. Words are delimited by WordDelims. } +function WordCount(const S: string; const WordDelims: TSysCharSet): Integer; +{ WordCount given a set of word delimiters, returns number of words in S. } +function WordPosition(const N: Integer; const S: string; + const WordDelims: TSysCharSet): Integer; +{ Given a set of word delimiters, returns start position of N'th word in S. } +function ExtractWord(N: Integer; const S: string; + const WordDelims: TSysCharSet): string; +function ExtractWordPos(N: Integer; const S: string; + const WordDelims: TSysCharSet; var Pos: Integer): string; +function ExtractDelimited(N: Integer; const S: string; + const Delims: TSysCharSet): string; +{ ExtractWord, ExtractWordPos and ExtractDelimited given a set of word + delimiters, return the N'th word in S. } +function ExtractSubstr(const S: string; var Pos: Integer; + const Delims: TSysCharSet): string; +{ ExtractSubstr given a set of word delimiters, returns the substring from S, + that started from position Pos. } +function IsWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean; +{ IsWordPresent given a set of word delimiters, returns True if word W is + present in string S. } +function QuotedString(const S: string; Quote: Char): string; +{ QuotedString returns the given string as a quoted string, using the + provided Quote character. } +function ExtractQuotedString(const S: string; Quote: Char): string; +{ ExtractQuotedString removes the Quote characters from the beginning and + end of a quoted string, and reduces pairs of Quote characters within + the quoted string to a single character. } +function FindPart(const HelpWilds, InputStr: string): Integer; +{ FindPart compares a string with '?' and another, returns the position of + HelpWilds in InputStr. } +function IsWild(InputStr, Wilds: string; IgnoreCase: Boolean): Boolean; +{ IsWild compares InputString with WildCard string and returns True + if corresponds. } +function XorString(const Key, Src: ShortString): ShortString; +function XorEncode(const Key, Source: string): string; +function XorDecode(const Key, Source: string): string; + +{ ** Command line routines ** } + +function GetCmdLineArg(const Switch: string; ASwitchChars: TSysCharSet): string; + +{ ** Numeric string handling routines ** } + +function Numb2USA(const S: string): string; +{ Numb2USA converts numeric string S to USA-format. } +function Dec2Hex(N: Longint; A: Byte): string; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF SUPPORTS_INLINE} +{ Dec2Hex converts the given value to a hexadecimal string representation + with the minimum number of digits (A) specified. } +function Hex2Dec(const S: string): Longint; +{ Hex2Dec converts the given hexadecimal string to the corresponding integer + value. } +function Dec2Numb(N: Int64; A, B: Byte): string; +{ Dec2Numb converts the given value to a string representation with the + base equal to B and with the minimum number of digits (A) specified. } +function Numb2Dec(S: string; B: Byte): Int64; +{ Numb2Dec converts the given B-based numeric string to the corresponding + integer value. } +function IntToBin(Value: Longint; Digits, Spaces: Integer): string; +{ IntToBin converts the given value to a binary string representation + with the minimum number of digits specified. } +function IntToRoman(Value: Longint): string; +{ IntToRoman converts the given value to a roman numeric string + representation. } +function RomanToInt(const S: string): Longint; +{ RomanToInt converts the given string to an integer value. If the string + doesn't contain a valid roman numeric value, the 0 value is returned. } + +function FindNotBlankCharPos(const S: string): Integer; +function FindNotBlankCharPosW(const S: WideString): Integer; +function AnsiChangeCase(const S: string): string; +function WideChangeCase(const S: string): string; + +{$IFNDEF CLR} +function StartsText(const SubStr, S: string): Boolean; +function EndsText(const SubStr, S: string): Boolean; + +function DequotedStr(const S: string; QuoteChar: Char = ''''): string; +function AnsiDequotedStr(const S: AnsiString; AQuote: AnsiChar): AnsiString; +{$ENDIF !CLR} + +{end JvStrUtils} + +{$IFDEF UNIX} +function GetTempFileName(const Prefix: string): string; +{$ENDIF UNIX} + +{ begin JvFileUtil } +function FileDateTime(const FileName: string): TDateTime; +function HasAttr(const FileName: string; Attr: Integer): Boolean; +function DeleteFilesEx(const FileMasks: array of string): Boolean; +function NormalDir(const DirName: string): string; +function RemoveBackSlash(const DirName: string): string; // only for Windows/DOS Paths +function ValidFileName(const FileName: string): Boolean; + +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} +function FileLock(Handle: Integer; Offset, LockSize: Longint): Integer; overload; +function FileLock(Handle: Integer; Offset, LockSize: Int64): Integer; overload; +function FileUnlock(Handle: Integer; Offset, LockSize: Longint): Integer; overload; +function FileUnlock(Handle: Integer; Offset, LockSize: Int64): Integer; overload; +{$ENDIF MSWINDOWS} +function GetWindowsDir: string; +{$ENDIF !CLR} +function GetSystemDir: string; + +function ShortToLongFileName(const ShortName: string): string; +function LongToShortFileName(const LongName: string): string; +function ShortToLongPath(const ShortName: string): string; +function LongToShortPath(const LongName: string): string; +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} +procedure CreateFileLink(const FileName, DisplayName: string; Folder: Integer); +procedure DeleteFileLink(const DisplayName: string; Folder: Integer); +{$ENDIF MSWINDOWS} +{$ENDIF !CLR} + +{ end JvFileUtil } + +// Works like PtInRect but includes all edges in comparision +function PtInRectInclusive(R: TRect; Pt: TPoint): Boolean; +// Works like PtInRect but excludes all edges from comparision +function PtInRectExclusive(R: TRect; Pt: TPoint): Boolean; + +function FourDigitYear: Boolean; {$IFDEF SUPPORTS_DEPRECATED} deprecated; {$ENDIF} +function IsFourDigitYear: Boolean; + +{ moved from JvJVCLUTils } + +//Open an object with the shell (url or something like that) +function OpenObject(const Value: string): Boolean; overload; +{$IFNDEF CLR} +function OpenObject(Value: PChar): Boolean; overload; +{$ENDIF !CLR} + +{$IFDEF MSWINDOWS} +//Raise the last Exception +procedure RaiseLastWin32; overload; +procedure RaiseLastWin32(const Text: string); overload; +//Raise the last Exception with a small comment from your part + +{ GetFileVersion returns the most significant 32 bits of a file's binary + version number. Typically, this includes the major and minor version placed + together in one 32-bit Integer. It generally does not include the release + or build numbers. It returns 0 if it failed. } +function GetFileVersion(const AFileName: string): Cardinal; +{$EXTERNALSYM GetFileVersion} + +//Get version of Shell.dll +function GetShellVersion: Cardinal; +{$EXTERNALSYM GetShellVersion} + +{$IFNDEF CLR} +// CD functions +procedure OpenCdDrive; +procedure CloseCdDrive; + +// returns True if Drive is accessible +function DiskInDrive(Drive: Char): Boolean; +{$ENDIF !CLR} +{$ENDIF MSWINDOWS} + +//Same as linux function ;) +procedure PError(const Text: string); + +// execute a program without waiting +procedure Exec(const FileName, Parameters, Directory: string); +// execute a program and wait for it to finish +function ExecuteAndWait(const CommandLine, WorkingDirectory: string; Visibility: Integer = SW_SHOW): Integer; + + +// returns True if this is the first instance of the program that is running +function FirstInstance(const ATitle: string): Boolean; +// restores a window based on it's classname and Caption. Either can be left empty +// to widen the search +procedure RestoreOtherInstance(const MainFormClassName, MainFormCaption: string); + +// manipulate the traybar and start button +procedure HideTraybar; +procedure ShowTraybar; +{$IFNDEF CLR} +procedure ShowStartButton(Visible: Boolean = True); +{$ENDIF !CLR} + +// (rom) SC_MONITORPOWER is documented as Windows 95 only +// (rom) better do some testing +// set monitor functions +procedure MonitorOn; +procedure MonitorOff; +procedure LowPower; + +// send a key to the window named AppName +function SendKey(const AppName: string; Key: Char): Boolean; + +{$IFDEF MSWINDOWS} + +{$IFNDEF CLR} +// returns a list of all windows currently visible, the Objects property is filled with their window handle +procedure GetVisibleWindows(List: TStrings); +// associates an extension to a specific program +procedure AssociateExtension(const IconPath, ProgramName, Path, Extension: string); + +procedure AddToRecentDocs(const FileName: string); +{$ENDIF !CLR} +function GetRecentDocs: TStringList; +{$ENDIF MSWINDOWS} + +// JvComponentFunctions +{----------------------------------------------------------------------------- +Comments: + Functions pulled out of MemoEx, used in MemoEx.pas and TypedEdit.pas + + This unit has low internal cohesion (ie it contains routines that do all kinds of stuff) + Some are very good candidates for wider reuse + some are quite specific to the controls + and in a larger library this unit would be broken up + + I have tried to group related functions together +} + +function CharIsMoney(const Ch: AnsiChar): Boolean; + +{ there is a STrToIntDef provided by Delphi, but no "safe" versions of + StrToFloat or StrToCurr } +// Note: before using StrToFloatDef, please be aware that it will ignore +// any character that is not a valid character for a float, which is different +// from what the one in Delphi 6 up is doing. This has been documented in Mantis +// issue# 2935: http://homepages.borland.com/jedi/issuetracker/view.php?id=2935 +function StrToFloatDef(const Str: string; Def: Extended): Extended; +function StrToCurrDef(const Str: string; Def: Currency): Currency; +function IntToExtended(I: Integer): Extended; + +{ GetChangedText works out the new text given the current cursor pos & the key pressed + It is not very useful in other contexts, + but it is in this unit as it is needed in both MemoEx and TypedEdit } +function GetChangedText(const Text: string; SelStart, SelLength: Integer; Key: Char): string; + +function MakeYear4Digit(Year, Pivot: Integer): Integer; + +function StrIsInteger(const S: string): Boolean; +function StrIsFloatMoney(const Ps: string): Boolean; +function StrIsDateTime(const Ps: string): Boolean; + +function PreformatDateString(Ps: string): string; + +function BooleanToInteger(const B: Boolean): Integer; +function StringToBoolean(const Ps: string): Boolean; + +function SafeStrToDateTime(const Ps: string): TDateTime; +function SafeStrToDate(const Ps: string): TDateTime; +function SafeStrToTime(const Ps: string): TDateTime; + +function StrDelete(const psSub, psMain: string): string; + + { returns the fractional value of pcValue} +function TimeOnly(pcValue: TDateTime): TTime; +{ returns the integral value of pcValue } +function DateOnly(pcValue: TDateTime): TDate; + +type + TdtKind = (dtkDateOnly, dtkTimeOnly, dtkDateTime); + +const + { TDateTime value used to signify Null value} + NullEquivalentDate: TDateTime = 0.0; + +function DateIsNull(const pdtValue: TDateTime; const pdtKind: TdtKind): Boolean; +// Replacement for Win32Check to avoid platform specific warnings in D6 +function OSCheck(RetVal: Boolean): Boolean; + +{ Shortens a fully qualified Path name so that it can be drawn with a specified length limit. + Same as FileCtrl.MinimizeName in functionality (but not implementation). Included here to + not be forced to use FileCtrl unnecessarily } +function MinimizeFileName(const FileName: string; Canvas: TCanvas; MaxLen: Integer): string; +function MinimizeText(const Text: string; Canvas: TCanvas; MaxWidth: Integer): string; +{ MinimizeString trunactes long string, S, and appends + '...' symbols, if Length of S is more than MaxLen } +function MinimizeString(const S: string; const MaxLen: Integer): string; + +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} +{ RunDLL32 runs a function in a DLL using the utility rundll32.exe (on NT) or rundll.exe (on Win95/98) + ModuleName is the name of the DLL to load, FuncName is the function to call and CmdLine is + the command-line parameters (if any) to send to the function. Set WaitForCompletion to False to + return immediately after the call. + CmdShow should be one of the SW_SHOWXXXX constants and defaults SW_SHOWDEFAULT + Return value: + if WaitForCompletion is True, returns True if the wait didn't return WAIT_FAILED + if WaitForCompletion is False, returns True if the process could be created + To get information on why RunDLL32 might have failed, call GetLastError + To get more info on what can actually be called using rundll32.exe, take a look at + http://www.dx21.com/SCRIPTING/RUNDLL32/REFGUIDE.ASP?NTI=4&SI=6 +} +type + // the signature of procedures in DLL's that can be called using rundll32.exe + TRunDLL32Proc = procedure(Handle: THandle; HInstance: HMODULE; CmdLine: PChar; CmdShow: Integer); stdcall; + +function RunDLL32(const ModuleName, FuncName, CmdLine: string; WaitForCompletion: Boolean; CmdShow: Integer = + SW_SHOWDEFAULT): Boolean; +{ RunDll32Internal does the same as RunDLL32 but does not use the RunDLL32.exe application to do it. + Rather it loads the DLL, gets a pointer to the function in FuncName and calls it with the given parameters. + Because of this behaviour, RunDll32Internal works slightly different from RunDLL32: + * It doesn't return any value indicating success/failure + * There is no WaitForCompletion parameter (but see comment below on how to circumvent this) + * You must pass in a valid windows handle in Wnd. Note that if you pass 0, the call might fail, with no indication of why. + * To simulate WaitForCompletion = False, pass the return value of GetDesktopWindow as the Wnd parameter, + * To simulate WaitForCompletion = True, pass the handle of the calling window (f ex the form you are calling the procedure from) + * If you try to call a function in a DLL that doesn't use the TRunDLL32Proc signature, your program + might crash. Using the RunDLL32 function protects you from any problems with calling the wrong functions + (a dialog is displayed if do something wrong) + * RunDll32Internal is slightly faster but RunDLL32 is safer +} +procedure RunDll32Internal(Wnd: THandle; const DLLName, FuncName, CmdLine: string; CmdShow: Integer = SW_SHOWDEFAULT); +{ GetDLLVersion loads DLLName, gets a pointer to the DLLVersion function and calls it, returning the major and minor version values +from the function. Returns False if the DLL couldn't be loaded or if GetDLLVersion couldn't be found. } +function GetDLLVersion(const DLLName: string; var pdwMajor, pdwMinor: Integer): Boolean; +{$ENDIF MSWINDOWS} +{$ENDIF !CLR} + +{$IFNDEF CLR} +procedure ResourceNotFound(ResID: PChar); +{$ENDIF !CLR} + +******************** NOT CONVERTED *) + +function RectWidth(R: TRect): Integer; +function RectHeight(R: TRect): Integer; +function CompareRect(const R1, R2: TRect): Boolean; + +(******************** NOT CONVERTED +{$IFDEF MSWINDOWS} +{$IFNDEF CLR} +procedure FreeUnusedOle; +function GetWindowsVersion: string; +function LoadDLL(const LibName: string): THandle; +function RegisterServer(const ModuleName: string): Boolean; +function UnregisterServer(const ModuleName: string): Boolean; +{$ENDIF !CLR} +{$ENDIF MSWINDOWS} + +{ String routines } +function GetEnvVar(const VarName: string): string; +function AnsiUpperFirstChar(const S: AnsiString): AnsiString; +{$IFNDEF CLR} +function StringToPChar(var S: string): PChar; +function StrPAlloc(const S: string): PChar; +{$ENDIF !CLR} +procedure SplitCommandLine(const CmdLine: string; var ExeName, Params: string); +function DropT(const S: string): string; + +{ Memory routines } + +{$IFNDEF CLR} +function AllocMemo(Size: Longint): Pointer; +function ReallocMemo(fpBlock: Pointer; Size: Longint): Pointer; +procedure FreeMemo(var fpBlock: Pointer); +function GetMemoSize(fpBlock: Pointer): Longint; +function CompareMem(fpBlock1, fpBlock2: Pointer; Size: Cardinal): Boolean; +{$ENDIF !CLR} + +{ Manipulate huge pointers routines } + +{$IFNDEF CLR} +procedure HugeInc(var HugePtr: Pointer; Amount: Longint); +procedure HugeDec(var HugePtr: Pointer; Amount: Longint); +function HugeOffset(HugePtr: Pointer; Amount: Longint): Pointer; +procedure HugeMove(Base: Pointer; Dst, Src, Size: Longint); +procedure HMemCpy(DstPtr, SrcPtr: Pointer; Amount: Longint); +{$ENDIF !CLR} + +{$IFNDEF CLR} +function WindowClassName(Wnd: THandle): string; +{$ENDIF !CLR} + +procedure SwitchToWindow(Wnd: THandle; Restore: Boolean); +procedure ActivateWindow(Wnd: THandle); +procedure ShowWinNoAnimate(Handle: THandle; CmdShow: Integer); +procedure KillMessage(Wnd: THandle; Msg: Cardinal); + +{ SetWindowTop put window to top without recreating window } +procedure SetWindowTop(const Handle: THandle; const Top: Boolean); +procedure CenterWindow(Wnd: THandle); +function MakeVariant(const Values: array of Variant): Variant; + +{ Convert dialog units to pixels and backwards } + +{$IFDEF MSWINDOWS} +function DialogUnitsToPixelsX(DlgUnits: Word): Word; +function DialogUnitsToPixelsY(DlgUnits: Word): Word; +function PixelsToDialogUnitsX(PixUnits: Word): Word; +function PixelsToDialogUnitsY(PixUnits: Word): Word; +{$ENDIF MSWINDOWS} + +function GetUniqueFileNameInDir(const Path, FileNameMask: string): string; + +{$IFNDEF CLR} + +{$IFDEF BCB} +function FindPrevInstance(const MainFormClass: ShortString; + const ATitle: string): THandle; +function ActivatePrevInstance(const MainFormClass: ShortString; + const ATitle: string): Boolean; +{$ELSE} +function FindPrevInstance(const MainFormClass, ATitle: string): THandle; +function ActivatePrevInstance(const MainFormClass, ATitle: string): Boolean; +{$ENDIF BCB} + + +{$IFDEF MSWINDOWS} +{ BrowseForFolderNative displays Browse For Folder dialog } +function BrowseForFolderNative(const Handle: THandle; const Title: string; var Folder: string): Boolean; +{$ENDIF MSWINDOWS} + + +procedure AntiAlias(Clip: TBitmap); +procedure AntiAliasRect(Clip: TBitmap; XOrigin, YOrigin, + XFinal, YFinal: Integer); + +{$ENDIF !CLR} + + +{$IFNDEF CLR} +procedure CopyRectDIBits(ACanvas: TCanvas; const DestRect: TRect; + ABitmap: TBitmap; const SourceRect: TRect); +{$ENDIF !CLR} +function IsTrueType(const FontName: string): Boolean; + + +// Removes all non-numeric characters from AValue and returns +// the resulting string +function TextToValText(const AValue: string): string; + +// VisualCLX compatibility functions +function DrawText(DC: HDC; const Text: TCaption; Len: Integer; var R: TRect; WinFlags: Integer): Integer; overload; +******************** NOT CONVERTED *) + +function DrawText(Canvas: TCanvas; const Text: string; Len: Integer; var R: TRect; WinFlags: Integer): Integer; overload; +function DrawText(Canvas: TCanvas; Text: PAnsiChar; Len: Integer; var R: TRect; WinFlags: Integer): Integer; overload; + +(******************** NOT CONVERTED +function DrawTextEx(Canvas: TCanvas; lpchText: PChar; cchText: Integer; var p4: TRect; dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; overload; +function DrawTextEx(Canvas: TCanvas; const Text: string; cchText: Integer; var p4: TRect; dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; overload; +{$IFDEF COMPILER6_UP} +function DrawText(Canvas: TCanvas; const Text: WideString; Len: Integer; var R: TRect; WinFlags: Integer): Integer; overload; +function DrawTextEx(Canvas: TCanvas; const Text: WideString; cchText: Integer; var p4: TRect; dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; overload; +{$ENDIF COMPILER6_UP} +{$ENDIF !CLR} + +{$IFNDEF CLR} +function DrawTextW(Canvas: TCanvas; const Text: WideString; Len: Integer; var R: TRect; WinFlags: Integer): Integer; overload; +function DrawTextW(Canvas: TCanvas; Text: PWideChar; Len: Integer; var R: TRect; WinFlags: Integer): Integer; overload; +function DrawTextExW(Canvas: TCanvas; lpchText: PWideChar; cchText: Integer; var p4: TRect; dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; overload; +function DrawTextExW(Canvas: TCanvas; const Text: WideString; cchText: Integer; var p4: TRect; dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; overload; +{$ENDIF !CLR} + +type + {$IFDEF COMPILER6_UP} + RasterOp = ( + RasterOp_CopyROP, + RasterOp_OrROP, + RasterOp_XorROP, + RasterOp_NotAndROP, + RasterOp_EraseROP = 3, + RasterOp_NotCopyROP, + RasterOp_NotOrROP, + RasterOp_NotXorROP, + RasterOp_AndROP, + RasterOp_NotEraseROP = 7, + RasterOp_NotROP, + RasterOp_ClearROP, + RasterOp_SetROP, + RasterOp_NopROP, + RasterOp_AndNotROP, + RasterOp_OrNotROP, + RasterOp_NandROP, + RasterOp_NorROP, + RasterOp_LastROP = 15); + {$ELSE} + // Delphi 5 and below doesn't support values in enums + RasterOp = Integer; +const + RasterOp_CopyROP = 0; + RasterOp_OrROP = 1; + RasterOp_XorROP = 2; + RasterOp_NotAndROP = 3; + RasterOp_EraseROP = 3; + RasterOp_NotCopyROP = 4; + RasterOp_NotOrROP = 5; + RasterOp_NotXorROP = 6; + RasterOp_AndROP = 7; + RasterOp_NotEraseROP = 7; + RasterOp_NotROP = 8; + RasterOp_ClearROP = 9; + RasterOp_SetROP = 10; + RasterOp_NopROP = 11; + RasterOp_AndNotROP = 12; + RasterOp_OrNotROP = 13; + RasterOp_NandROP = 14; + RasterOp_NorROP = 15; + RasterOp_LastROP = 15; + {$ENDIF COMPILER6_UP} + +function BitBlt(DestCanvas: TCanvas; X, Y, Width, Height: Integer; SrcCanvas: TCanvas; + XSrc, YSrc: Integer; WinRop: Cardinal; IgnoreMask: Boolean = True): LongBool;overload; +function BitBlt(DestDC: HDC; X, Y, Width, Height: Integer; SrcDC: HDC; + XSrc, YSrc: Integer; Rop: RasterOp; IgnoreMask: Boolean): LongBool; overload; +function BitBlt(DestDC: HDC; X, Y, Width, Height: Integer; SrcDC: HDC; + XSrc, YSrc: Integer; WinRop: Cardinal; IgnoreMask: Boolean): LongBool; overload; +function BitBlt(DestDC: HDC; X, Y, Width, Height: Integer; SrcDC: HDC; + XSrc, YSrc: Integer; WinRop: Cardinal): LongBool; overload; + + + +function IsEqualGUID(const IID1, IID2: TGUID): Boolean; +{$EXTERNALSYM IsEqualGUID} + + +{$IFNDEF BCB} +{$IFDEF COMPILER5} +{ These functions simply call their JvVCL5Utils equivalents } + +function TryStrToInt(const S: string; out Value: Integer): Boolean; +function TryStrToDateTime(const S: string; out Date: TDateTime): Boolean; +function StrToDateTimeDef(const S: string; Default: TDateTime): TDateTime; +// function StrToFloatDef(const Str: string; Default: Extended): Extended; +procedure RaiseLastOSError; +function IncludeTrailingPathDelimiter(const APath: string): string; +function ExcludeTrailingPathDelimiter(const APath: string): string; +function DirectoryExists(const Name: string): Boolean; +function ForceDirectories(Dir: string): Boolean; +function SameFileName(const FN1, FN2: string): Boolean; + +function WideCompareText(const S1, S2: WideString): Integer; +function WideUpperCase(const S: WideString): WideString; +function WideLowerCase(const S: WideString): WideString; +function CompareDateTime(const A, B: TDateTime): Integer; + +// StrUtils +function AnsiStartsText(const SubText, Text: string): Boolean; +function AnsiEndsText(const SubText, Text: string): Boolean; +function AnsiStartsStr(const SubStr, Str: string): Boolean; +function AnsiEndsStr(const SubStr, Str: string): Boolean; + +// Math +type + TValueSign = JvVCL5Utils.TValueSign; + +const + NegativeValue = Low(TValueSign); + ZeroValue = 0; + PositiveValue = High(TValueSign); + +// Variants +function VarIsStr(const V: Variant): Boolean; +{$ENDIF COMPILER5} +{$ENDIF !BCB} + +// Containers +type + TIntegerListChange = procedure(Sender: TObject; Item: Integer; Action: TListNotification) of object; + + TIntegerList = class(TList) + private + FOnChange: TIntegerListChange; + FLoading: Boolean; + + function GetItem(Index: Integer): Integer; + procedure SetItem(Index: Integer; const Value: Integer); + protected + procedure Notify(Ptr: Pointer; Action: TListNotification); override; + procedure DoChange(Item: Integer; Action: TListNotification); + public + {$IFDEF COMPILER5} + procedure Assign(Source: TList); + {$ENDIF COMPILER5} + + // To be used with DefineProperties in client classes. + procedure ReadData(Reader: TReader); + procedure WriteData(Writer: TWriter); + property Loading: Boolean read FLoading; + + // Overloaded to accept/return Integer instead of Pointer. + function Add(Value: Integer): Integer; + function Extract(Item: Integer): Integer; + function First: Integer; + function IndexOf(Item: Integer): Integer; + procedure Insert(Index: Integer; Item: Integer); + function Last: Integer; + function Remove(Item: Integer): Integer; + property Items[Index: Integer]: Integer read GetItem write SetItem; default; + + property OnChange: TIntegerListChange read FOnChange write FOnChange; + end; + +type + TCollectionSortProc = function(Item1, Item2: TCollectionItem): Integer; + +procedure CollectionSort(Collection: Classes.TCollection; SortProc: TCollectionSortProc); + +{$IFDEF COMPILER5} +function SecondsBetween(const Now: TDateTime; const FTime: TDateTime): Integer; +{$ENDIF COMPILER5} + +******************** NOT CONVERTED *) + +implementation + +(******************** NOT CONVERTED +uses + {$IFDEF HAS_UNIT_RTLCONSTS} + RTLConsts, + {$ENDIF HAS_UNIT_RTLCONSTS} + SysConst, + {$IFDEF MSWINDOWS} + ComObj, ShellAPI, MMSystem, Registry, + {$ENDIF MSWINDOWS} + Consts, + {$IFNDEF NO_JCL} + JclStrings, JclSysInfo, + {$ENDIF !NO_JCL} + Math; + +{$IFDEF CLR} +type + PPropInfo = TPropInfo; +{$ENDIF CLR} + +const + Separators: TSysCharSet = [#00, ' ', '-', #13, #10, '.', ',', '/', '\', '#', '"', '''', + ':', '+', '%', '*', '(', ')', ';', '=', '{', '}', '[', ']', '{', '}', '<', '>']; + {$IFDEF MSWINDOWS} + RC_OpenCDDrive = 'set cdaudio door open wait'; + RC_CloseCDDrive = 'set cdaudio door closed wait'; + RC_ShellName = 'Shell_TrayWnd'; + RC_DefaultIcon = 'DefaultIcon'; + {$ENDIF MSWINDOWS} + +resourcestring + // (p3) duplicated from JvConsts since this unit should not rely on JVCL at all + RsEPropertyNotExists = 'Property "%s" does not exist'; + RsEInvalidPropertyType = 'Property "%s" has invalid type'; + RsEPivotLessThanZero = 'JvJCLUtils.MakeYear4Digit: Pivot < 0'; + +{$IFDEF NO_JCL} + + // These are the replacement functions for the JCL. + +const + AnsiSpace = AnsiChar(#32); + AnsiForwardSlash = AnsiChar('/'); + +function StrIPos(const SubStr, S: string): Integer; +begin + {$IFDEF CLR} + Result := S.ToLower().IndexOf(SubStr.ToLower()); + {$ELSE} + Result := Pos(AnsiLowerCase(SubStr), AnsiLowerCase(S)); + {$ENDIF CLR} +end; + +function CharIsDigit(Ch: AnsiChar): Boolean; +begin + Result := Ch in ['0'..'9']; +end; + +function CharIsNumber(Ch: AnsiChar): Boolean; +begin + Result := Ch in ['0'..'9']; +end; + +function CharIsAlpha(Ch: AnsiChar): Boolean; +begin + Result := Windows.IsCharAlpha(Char(Ch)); +end; + +{$IFDEF MSWINDOWS} +function GetRecentFolder: string; +{$IFDEF CLR} +begin + Result := System.Environment.GetFolderPath(Environment.SpecialFolder.Recent); +end; +{$ELSE} +var + ItemIDList: PItemIDList; +begin + OleCheck(SHGetSpecialFolderLocation(0, CSIDL_RECENT, ItemIDList)); + SetLength(Result, MAX_PATH); + SHGetPathFromIDList(ItemIDList, PChar(Result)); + SetLength(Result, Length(PChar(Result))); +end; +{$ENDIF CLR} +{$ENDIF MSWINDOWS} + +{$ENDIF NO_JCL} + +function SendRectMessage(Handle: THandle; Msg: Integer; wParam: WPARAM; var R: TRect): Integer; +{$IFDEF CLR} +var + Mem: IntPtr; +begin + { R is a System.ValueType } + Mem := Marshal.AllocHGlobal(Marshal.SizeOf(R)); + try + Marshal.StructureToPtr(R, Mem, False); + Result := SendMessage(Handle, Msg, wParam, Longint(Mem)); + R := TRect(Marshal.PtrToStructure(Mem, R.GetType)); + finally + Marshal.DestroyStructure(Mem, R.GetType); + end; +end; +{$ELSE} +begin + Result := SendMessage(Handle, Msg, wParam, Longint(@R)); +end; +{$ENDIF CLR} + +function SendStructMessage(Handle: THandle; Msg: Integer; wParam: WPARAM; var Data): Integer; +{$IFDEF CLR} +var + Mem: IntPtr; +begin + { Data is System.Object } + Mem := Marshal.AllocHGlobal(Marshal.SizeOf(TObject(Data))); + try + Marshal.StructureToPtr(TObject(Data), Mem, False); + Result := SendMessage(Handle, Msg, wParam, Longint(Mem)); + Data := Marshal.PtrToStructure(Mem, TObject(Data).GetType); + finally + Marshal.DestroyStructure(Mem, TObject(Data).GetType); + end; +end; +{$ELSE} +begin + Result := SendMessage(Handle, Msg, wParam, Longint(@Data)); +end; +{$ENDIF CLR} + + +{$IFDEF CLR} +function VarFromDateTime(const Value: TDateTime): Variant; +begin + Result := Value; +end; + +function VarToDateTime(const Value: Variant): TDateTime; +begin + Result := Value; +end; + +function SucceededCom(out Intf; Value: TObject): Boolean; +begin + Intf := Value; + Result := Value <> nil; +end; + +function GetPrivateField(Instance: TObject; const FieldName: string): TObject; +var + Info: FieldInfo; +begin + Result := nil; + if Instance <> nil then + begin + Info := Instance.GetType.GetField(FieldName, BindingFlags.NonPublic or BindingFlags.Instance); + if Info <> nil then + Result := Info.GetValue(Instance); + end; +end; + +procedure SetPrivateField(Instance: TObject; const FieldName: string; Value: TObject); +var + Info: FieldInfo; +begin + if Instance <> nil then + begin + Info := Instance.GetType.GetField(FieldName, BindingFlags.NonPublic or BindingFlags.Instance); + if Info <> nil then + Info.SetValue(Instance, Value); + end; +end; + +procedure SetProtectedObjectEvent(Instance: TObject; const EventName: string; Ev: Delegate); +var + Info: EventInfo; +begin + if Instance <> nil then + begin + Info := Instance.GetType.GetEvent(EventName, BindingFlags.NonPublic or BindingFlags.Instance); + if Info <> nil then + { TODO : Implement } + //Info.RemoveEventHandler(); + end; +end; + +function GetProtectedObjectEvent(Instance: TObject; const EventName: string): Delegate; +var + Info: EventInfo; +begin + Result := nil; + if Instance <> nil then + begin + Info := Instance.GetType.GetEvent(EventName, BindingFlags.NonPublic or BindingFlags.Instance); + if Info <> nil then + { TODO : Implement } + //Info.RemoveEventHandler(); + end; +end; + +function AnsiLastChar(const S: string): Char; +begin + if (S <> nil) and (S <> '') then + Result := S[Length(S)] + else + Result := #0; +end; +{$ENDIF CLR} + +function ReadCharsFromStream(Stream: TStream; var Buf: array of Char; BufSize: Integer): Integer; +{$IFDEF CLR} +var + Bytes: TBytes; +{$ENDIF CLR} +begin + {$IFDEF CLR} + SetLength(Bytes, BufSize); + Result := Stream.Read(Bytes, 0, BufSize); + System.Array.Copy(AnsiEncoding.GetChars(Bytes), 0, Buf, 0, BufSize); + {$ELSE} + Result := Stream.Read(Buf, BufSize); + {$ENDIF CLR} +end; + +function WriteStringToStream(Stream: TStream; const Buf: string; BufSize: Integer): Integer; +begin + {$IFDEF CLR} + Result := Stream.Write(BytesOf(Buf), BufSize); + {$ELSE} + Result := Stream.Write(Buf[1], BufSize); + {$ENDIF CLR} +end; + + +// StrToFloatUS uses US '.' as decimal separator and ',' as thousand separator + +function USToLocalFloatStr(const Text: string): string; +var + I: Integer; +begin + Result := Text; + if (DecimalSeparator <> '.') or (ThousandSeparator <> ',') then + begin + for I := 0 to Length(Result) do + {$IFNDEF CLR} + case Result[I] of + '.': + Result[I] := DecimalSeparator; + ',': + Result[I] := ThousandSeparator; + end; + {$ELSE} + case Result[I] of + '.': + Result[I] := DecimalSeparator[1]; + ',': + Result[I] := ThousandSeparator[1]; + end; + {$ENDIF !CLR} + end; +end; + +function StrToFloatUS(const Text: string): Extended; +begin + try + Result := StrToFloat(USToLocalFloatStr(Text)); + except + Result := StrToFloat(Text); // try it with local settings + end; +end; + +function StrToFloatUSDef(const Text: string; Default: Extended): Extended; +begin + Result := StrToFloatDef(USToLocalFloatStr(Text), Default); +end; + +function VarIsInt(Value: Variant): Boolean; +begin + Result := VarType(Value) in [varByte, + {$IFDEF COMPILER6_UP} + varShortInt, varWord, varLongWord, {varInt64,} + {$ENDIF COMPILER6_UP} + varSmallint, varInteger]; +end; + +function PosIdx(const SubStr, S: string; Index: Integer = 0): Integer; +{$IFDEF CLR} +begin + Result := S.IndexOf(SubStr, Index - 1) + 1; +end; +{$ELSE} + // use best register allocation + function Find(Index, EndPos: Integer; StartChar: Char; const S: string): Integer; + begin + for Result := Index to EndPos do + if S[Result] = StartChar then + Exit; + Result := 0; + end; + + // use best register allocation + function FindNext(Index, EndPos: Integer; const S, SubStr: string): Integer; + begin + for Result := Index + 1 to EndPos do + if S[Result] <> SubStr[Result - Index + 1] then + Exit; + Result := 0; + end; + +var + StartChar: Char; + LenSubStr, LenStr: Integer; + EndPos: Cardinal; +begin + if Index <= 0 then + Index := 1; + Result := 0; + LenSubStr := Length(SubStr); + LenStr := Length(S); + if (LenSubStr = 0) or (S = '') or (LenSubStr > LenStr - (Index - 1)) then + Exit; + + StartChar := SubStr[1]; + EndPos := LenStr - LenSubStr + 1; + if LenSubStr = 1 then + Result := Find(Index, EndPos, StartChar, S) + else + begin + repeat + Result := Find(Index, EndPos, StartChar, S); + if Result = 0 then + Break; + Index := Result; + Result := FindNext(Result, Index + LenSubStr - 1, S, SubStr); + if Result = 0 then + begin + Result := Index; + Exit; + end + else + Inc(Index); + until False; + end; +end; + +function PosIdxW(const SubStr, S: WideString; Index: Integer = 0): Integer; + + // use best register allocation + function Find(Index, EndPos: Integer; StartChar: WideChar; const S: WideString): Integer; + begin + for Result := Index to EndPos do + if S[Result] = StartChar then + Exit; + Result := 0; + end; + + // use best register allocation + function FindNext(Index, EndPos: Integer; const S, SubStr: WideString): Integer; + begin + for Result := Index + 1 to EndPos do + if S[Result] <> SubStr[Result - Index + 1] then + Exit; + Result := 0; + end; + +var + StartChar: WideChar; + LenSubStr, LenStr: Integer; + EndPos: Cardinal; +begin + if Index <= 0 then + Index := 1; + Result := 0; + LenSubStr := Length(SubStr); + LenStr := Length(S); + if (LenSubStr = 0) or (S = '') or (LenSubStr > LenStr - (Index - 1)) then + Exit; + + StartChar := SubStr[1]; + EndPos := LenStr - LenSubStr + 1; + if LenSubStr = 1 then + Result := Find(Index, EndPos, StartChar, S) + else + begin + repeat + Result := Find(Index, EndPos, StartChar, S); + if Result = 0 then + Break; + Index := Result; + Result := FindNext(Result, Index + LenSubStr - 1, S, SubStr); + if Result = 0 then + begin + Result := Index; + Exit; + end + else + Inc(Index); + until False; + end; +end; +{$ENDIF CLR} + +function PosLastCharIdx(Ch: Char; const S: string; Index: Integer = 0): Integer; +begin + if (Index = 0) or (Index > Length(S)) then + Index := Length(S); + for Result := Index downto 1 do + if S[Result] = Ch then + Exit; + Result := 0; +end; + + +function GetLineByPos(const S: string; const Pos: Integer): Integer; +var + I: Integer; +begin + if Length(S) < Pos then + Result := -1 + else + begin + I := 1; + Result := 0; + while I <= Pos do + begin + if S[I] = #13 then + Inc(Result); + Inc(I); + end; + end; +end; + +procedure GetXYByPos(const S: string; const Pos: Integer; var X, Y: Integer); +var + I, iB: Integer; +begin + X := -1; + Y := -1; + iB := 0; + if (Length(S) >= Pos) and (Pos >= 0) then + begin + I := 1; + Y := 0; + while I <= Pos do + begin + if S[I] = #10 then + begin + Inc(Y); + iB := I + 1; + end; + Inc(I); + end; + X := Pos - iB; + end; +end; + +procedure GetXYByPosW(const S: WideString; const Pos: Integer; var X, Y: Integer); +var + I, iB: Integer; +begin + X := -1; + Y := -1; + iB := 0; + if (Length(S) >= Pos) and (Pos >= 0) then + begin + I := 1; + Y := 0; + while I <= Pos do + begin + if S[I] = #10 then + begin + Inc(Y); + iB := I + 1; + end; + Inc(I); + end; + X := Pos - iB; + end; +end; + +function GetWordOnPos(const S: string; const P: Integer): string; +var + I, Beg: Integer; +begin + Result := ''; + if (P > Length(S)) or (P < 1) then + Exit; + for I := P downto 1 do + if S[I] in Separators then + Break; + Beg := I + 1; + for I := P to Length(S) do + if S[I] in Separators then + Break; + if I > Beg then + Result := Copy(S, Beg, I - Beg) + else + Result := S[P]; +end; + +function GetWordOnPosW(const S: WideString; const P: Integer): WideString; +var + I, Beg: Integer; +begin + Result := ''; + if (P > Length(S)) or (P < 1) then + Exit; + for I := P downto 1 do + if CharInSetW(S[I], Separators) then + Break; + Beg := I + 1; + for I := P to Length(S) do + if CharInSetW(S[I], Separators) then + Break; + if I > Beg then + Result := Copy(S, Beg, I - Beg) + else + Result := S[P]; +end; + +function GetWordOnPos2(const S: string; P: Integer; var iBeg, iEnd: Integer): string; +begin + Result := ''; + if P < 1 then + Exit; + if (S[P] in Separators) and ((P < 1) or (S[P - 1] in Separators)) then + Inc(P); + iBeg := P; + while iBeg >= 1 do + if S[iBeg] in Separators then + Break + else + Dec(iBeg); + Inc(iBeg); + iEnd := P; + while iEnd <= Length(S) do + if S[iEnd] in Separators then + Break + else + Inc(iEnd); + if iEnd > iBeg then + Result := Copy(S, iBeg, iEnd - iBeg) + else + Result := S[P]; +end; + +function GetWordOnPos2W(const S: WideString; P: Integer; var iBeg, iEnd: Integer): WideString; +begin + Result := ''; + if P < 1 then + Exit; + if (CharInSetW(S[P], Separators)) and + ((P < 1) or (CharInSetW(S[P - 1], Separators))) then + Inc(P); + iBeg := P; + while iBeg >= 1 do + if CharInSetW(S[iBeg], Separators) then + Break + else + Dec(iBeg); + Inc(iBeg); + iEnd := P; + while iEnd <= Length(S) do + if CharInSetW(S[iEnd], Separators) then + Break + else + Inc(iEnd); + if iEnd > iBeg then + Result := Copy(S, iBeg, iEnd - iBeg) + else + Result := S[P]; +end; + +function GetWordOnPosEx(const S: string; const P: Integer; var iBeg, iEnd: Integer): string; +begin + Result := ''; + if (P > Length(S)) or (P < 1) then + Exit; + iBeg := P; + if P > 1 then + if S[P] in Separators then + if (P < 1) or ((P - 1 > 0) and (S[P - 1] in Separators)) then + Inc(iBeg) + else + if not ((P - 1 > 0) and (S[P - 1] in Separators)) then + Dec(iBeg); + while iBeg >= 1 do + if S[iBeg] in Separators then + Break + else + Dec(iBeg); + Inc(iBeg); + iEnd := P; + while iEnd <= Length(S) do + if S[iEnd] in Separators then + Break + else + Inc(iEnd); + if iEnd > iBeg then + Result := Copy(S, iBeg, iEnd - iBeg) + else + Result := S[P]; +end; + +function GetWordOnPosExW(const S: WideString; const P: Integer; var iBeg, iEnd: Integer): WideString; +begin + Result := ''; + if (P > Length(S)) or (P < 1) then + Exit; + iBeg := P; + if P > 1 then + if CharInSetW(S[P], Separators) then + if (P < 1) or ((P - 1 > 0) and CharInSetW(S[P - 1], Separators)) then + Inc(iBeg) + else + if not ((P - 1 > 0) and CharInSetW(S[P - 1], Separators)) then + Dec(iBeg); + while iBeg >= 1 do + if CharInSetW(S[iBeg], Separators) then + Break + else + Dec(iBeg); + Inc(iBeg); + iEnd := P; + while iEnd <= Length(S) do + if CharInSetW(S[iEnd], Separators) then + Break + else + Inc(iEnd); + if iEnd > iBeg then + Result := Copy(S, iBeg, iEnd - iBeg) + else + Result := S[P]; +end; + +function GetNextWordPosEx(const Text: string; StartIndex: Integer; + var iBeg, iEnd: Integer): string; +var + Len: Integer; +begin + Len := Length(Text); + Result := ''; + if (StartIndex < 1) or (StartIndex > Len) then + Exit; + if (Text[StartIndex] in Separators) and + ((StartIndex < 1) or (Text[StartIndex - 1] in Separators)) then + Inc(StartIndex); + iBeg := StartIndex; + while iBeg >= 1 do + if Text[iBeg] in Separators then + Break + else + Dec(iBeg); + Inc(iBeg); + iEnd := StartIndex; + while iEnd <= Len do + if Text[iEnd] in Separators then + Break + else + Inc(iEnd); + Dec(iEnd); + if iEnd >= iBeg then + Result := Copy(Text, iBeg, iEnd - iBeg) + else + Result := Text[StartIndex]; + + // go right + iEnd := iBeg; + while (iEnd <= Len) and (not (Text[iEnd] in Separators)) do + Inc(iEnd); + if iEnd > Len then + iEnd := Len + else + Dec(iEnd); + Result := Copy(Text, iBeg, iEnd - iBeg + 1); +end; + +function GetNextWordPosExW(const Text: WideString; StartIndex: Integer; + var iBeg, iEnd: Integer): WideString; +var + Len: Integer; +begin + Len := Length(Text); + Result := ''; + if (StartIndex < 1) or (StartIndex > Len) then + Exit; + if CharInSetW(Text[StartIndex], Separators) and + ((StartIndex < 1) or CharInSetW(Text[StartIndex - 1], Separators)) then + Inc(StartIndex); + iBeg := StartIndex; + while iBeg >= 1 do + if CharInSetW(Text[iBeg], Separators) then + Break + else + Dec(iBeg); + Inc(iBeg); + iEnd := StartIndex; + while iEnd <= Len do + if CharInSetW(Text[iEnd], Separators) then + Break + else + Inc(iEnd); + Dec(iEnd); + if iEnd >= iBeg then + Result := Copy(Text, iBeg, iEnd - iBeg) + else + Result := Text[StartIndex]; + + // go right + iEnd := iBeg; + while (iEnd <= Len) and (not CharInSetW(Text[iEnd], Separators)) do + Inc(iEnd); + if iEnd > Len then + iEnd := Len + else + Dec(iEnd); + Result := Copy(Text, iBeg, iEnd - iBeg + 1); +end; + +procedure GetEndPosCaret(const Text: string; CaretX, CaretY: Integer; + var X, Y: Integer); +begin + GetXYByPos(Text, Length(Text), X, Y); + if Y = 0 then + Inc(X, CaretX) + else + Inc(X); + Dec(X); + Inc(Y, CaretY); +end; + +procedure GetEndPosCaretW(const Text: WideString; CaretX, CaretY: Integer; + var X, Y: Integer); +begin + GetXYByPosW(Text, Length(Text), X, Y); + if Y = 0 then + Inc(X, CaretX) + else + Inc(X); + Dec(X); + Inc(Y, CaretY); +end; + +function SubStrBySeparator(const S: string; const Index: Integer; const Separator: string; StartIndex: Integer): string; +{ Returns a substring. Substrings are divided by a separator character } +var + I, LenS, LenSeparator: Integer; +begin + Result := ''; + LenSeparator := Length(Separator); + LenS := Length(S); + + if StartIndex <= 0 then + StartIndex := 1; + if (LenS = 0) or (LenSeparator = 0) or (StartIndex > LenS) or + ((Index < 0) or ((Index = 0) and (LenS > 0) and (S[StartIndex] = Separator[1]))) then + Exit; + + for I := 1 to Index do + begin + StartIndex := PosIdx(Separator, S, StartIndex); + if StartIndex = 0 then + Exit; + Inc(StartIndex, LenSeparator); + if StartIndex > LenS then + Exit; + end; + I := PosIdx(Separator, S, StartIndex + 1); + if I = 0 then + I := LenS + 1; + Result := Copy(S, StartIndex, I - StartIndex); + if CompareText(Result, Separator) = 0 then + Result := ''; +end; + +{$IFNDEF CLR} +function SubStrBySeparatorW(const S: WideString; const Index: Integer; const Separator: WideString; StartIndex: Integer): WideString; +{ Returns a substring. Substrings are divided by a separator character } +var + I, LenS, LenSeparator: Integer; +begin + Result := ''; + LenSeparator := Length(Separator); + LenS := Length(S); + + if StartIndex <= 0 then + StartIndex := 1; + if (LenS = 0) or (LenSeparator = 0) or (StartIndex > LenS) or + ((Index < 0) or ((Index = 0) and (LenS > 0) and (S[StartIndex] = Separator[1]))) then + Exit; + + for I := 1 to Index do + begin + StartIndex := PosIdx(Separator, S, StartIndex); + if StartIndex = 0 then + Exit; + Inc(StartIndex, LenSeparator); + if StartIndex > LenS then + Exit; + end; + I := PosIdx(Separator, S, StartIndex + 1); + if I = 0 then + I := LenS + 1; + Result := Copy(S, StartIndex, I - StartIndex); + if WideCompareText(Result, Separator) = 0 then + Result := ''; +end; +{$ENDIF !CLR} + +{$IFDEF CLR} +function SubWord(P: string; var P2: string): string; +var + I: Integer; +begin + for I := 1 to Length(P) do + if P[I] in Separators then + Break; + Result := Copy(P, 1, I); + P2 := Copy(Result, I + 1, MaxInt); +end; +{$ELSE} +function SubWord(P: PChar; var P2: PChar): string; +var + I: Integer; +begin + I := 0; + while not (P[I] in Separators) do + Inc(I); + SetString(Result, P, I); + P2 := P + I; +end; +{$ENDIF CLR} + +function ReplaceString(S: string; const OldPattern, NewPattern: string; StartIndex: Integer): string; +var + I, LenOldPattern: Integer; +begin + if OldPattern <> '' then + begin + if StartIndex <= 0 then + StartIndex := 1; + LenOldPattern := Length(OldPattern); + I := PosIdx(OldPattern, S, StartIndex); + while I > 0 do + begin + StartIndex := I + LenOldPattern; + S := Copy(S, 1, I - 1) + NewPattern + Copy(S, StartIndex, MaxInt); + I := PosIdx(OldPattern, S, StartIndex); + end; + end; + Result := S; +end; + +{$IFNDEF CLR} +function ReplaceStringW(S: WideString; const OldPattern, NewPattern: WideString; StartIndex: Integer): WideString; +var + I, LenOldPattern: Integer; +begin + if OldPattern <> '' then + begin + if StartIndex <= 0 then + StartIndex := 1; + LenOldPattern := Length(OldPattern); + I := PosIdxW(OldPattern, S, StartIndex); + while I > 0 do + begin + StartIndex := I + LenOldPattern; + S := Copy(S, 1, I - 1) + NewPattern + Copy(S, StartIndex, MaxInt); + I := PosIdxW(OldPattern, S, StartIndex); + end; + end; + Result := S; +end; +{$ENDIF !CLR} + +function ConcatSep(const S1, S2, Separator: string): string; +begin + Result := S1; + if Result <> '' then + Result := Result + Separator; + Result := Result + S2; +end; + +function ConcatLeftSep(const S1, S2, Separator: string): string; +begin + Result := S1; + if Result <> '' then + Result := Separator + Result; + Result := S2 + Result; +end; + +function MinimizeString(const S: string; const MaxLen: Integer): string; +begin + if Length(S) > MaxLen then + if MaxLen < 3 then + Result := Copy(S, 1, MaxLen) + else + Result := Copy(S, 1, MaxLen - 3) + '...' + else + Result := S; +end; + +function TrueInflateRect(const R: TRect; const I: Integer): TRect; +begin + with R do + SetRect(Result, Left - I, Top - I, Right + I, Bottom + I); +end; + +function FileGetInfo(FileName: TFileName; var SearchRec: TSearchRec): Boolean; +var + DosError: Integer; + Path: TFileName; +begin + Result := False; + Path := ExtractFilePath(ExpandFileName(FileName)) + AllFilesMask; + {$IFDEF MSWINDOWS} + {$IFDEF CLR} + FileName := ExtractFileName(FileName).ToUpper(); + {$ELSE} + FileName := AnsiUpperCase(ExtractFileName(FileName)); + {$ENDIF CLR} + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + FileName := ExtractFileName(FileName); + {$ENDIF UNIX} + DosError := FindFirst(Path, faAnyFile, SearchRec); + while DosError = 0 do + begin + {$IFDEF MSWINDOWS} + if SameFileName(SearchRec.FindData.cFileName, FileName) or + SameFileName(SearchRec.FindData.cAlternateFileName, FileName) then + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + if AnsiSameStr(SearchRec.Name, FileName) then + {$ENDIF UNIX} + begin + Result := True; + Break; + end; + DosError := FindNext(SearchRec); + end; + FindClose(SearchRec); +end; + +function HasSubFolder(APath: TFileName): Boolean; +var + SearchRec: TSearchRec; + DosError: Integer; +begin + Result := False; + APath := Concat(AddSlash(APath), AllFilesMask); + DosError := FindFirst(APath, faDirectory, SearchRec); + while DosError = 0 do + begin + if (SearchRec.Attr and faDirectory = faDirectory) and + (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then + begin + Result := True; + Break; + end; + DosError := FindNext(SearchRec); + end; + FindClose(SearchRec); +end; + +function IsEmptyFolder(APath: TFileName): Boolean; +var + SearchRec: TSearchRec; + DosError: Integer; +begin + Result := True; + APath := Concat(AddSlash(APath), AllFilesMask); + DosError := FindFirst(APath, faDirectory, SearchRec); + while DosError = 0 do + begin + if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then + begin + Result := False; + Break; + end; + DosError := FindNext(SearchRec); + end; + FindClose(SearchRec); +end; + +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} +function LZFileExpand(const FileSource, FileDest: string): Boolean; +type + TLZCopy = function(Source, Dest: Integer): Longint; stdcall; + TLZOpenFile = function(FileName: PChar; var ReOpenBuff: TOFStruct; Style: Word): Integer; stdcall; + TLZClose = procedure(hFile: Integer); stdcall; +var + Source, Dest: Integer; + OSSource, OSDest: TOFStruct; + Res: Integer; + Inst: THandle; + LZCopy: TLZCopy; + LZOpenFile: TLZOpenFile; + LZClose: TLZClose; +begin + Result := False; + Inst := SafeLoadLibrary('LZ32.dll'); + try + if Inst = 0 then + RaiseLastOSError; + LZCopy := GetProcAddress(Inst, 'LZCopy'); + LZOpenFile := GetProcAddress(Inst, 'LZOpenFileA'); + LZClose := GetProcAddress(Inst, 'LZClose'); + if not Assigned(LZCopy) or not Assigned(LZOpenFile) or not Assigned(LZClose) then + begin + SetLastError(ERROR_NOT_SUPPORTED); + RaiseLastOSError; + end; + OSSource.cBytes := SizeOf(TOFStruct); + OSDest.cBytes := SizeOf(TOFStruct); + Source := LZOpenFile( + PChar(FileSource), // address of name of file to be opened + OSSource, // address of open file structure + OF_READ or OF_SHARE_DENY_NONE); // action to take + if Source < 0 then + begin + DeleteFile(FileDest); + Dest := LZOpenFile( + PChar(FileDest), // address of name of file to be opened + OSDest, // address of open file structure + OF_CREATE or OF_WRITE or OF_SHARE_EXCLUSIVE); // action to take + if Dest >= 0 then + begin + Res := LZCopy(Source, Dest); + if Res >= 0 then + Result := True; + end; + LZClose(Source); + LZClose(Dest); + end; + finally + FreeLibrary(Inst); + end; +end; +{$ENDIF MSWINDOWS} +{$ENDIF !CLR} + +procedure Dos2Win(var S: string); +var + I: Integer; +begin + for I := 1 to Length(S) do + case S[I] of + #$80..#$AF: + S[I] := Char(Byte(S[I]) + (192 - $80)); + #$E0..#$EF: + S[I] := Char(Byte(S[I]) + (240 - $E0)); + end; +end; + +procedure Win2Dos(var S: string); +var + I: Integer; +begin + for I := 1 to Length(S) do + case S[I] of + #$C0..#$EF: + S[I] := Char(Byte(S[I]) - (192 - $80)); + #$F0..#$FF: + S[I] := Char(Byte(S[I]) - (240 - $E0)); + end; +end; + +function Dos2WinRes(const S: string): string; +begin + Result := S; + Dos2Win(Result); +end; + +function Win2DosRes(const S: string): string; +begin + Result := S; + Win2Dos(Result); +end; + +function Win2Koi(const S: string): string; +const + W = 'àáâãä叿çèéêëìíîïðñ=óôõ÷öøùüûúýÝÿ+--+-+¨ÆÇ++--Ý-+ÏÐÑÒÓÔi×ÖØ+_Ý+ÝÞî'; + K = '--×Ç-+£Ö++--Ý-+ÏÐÒÓÔiÆ+Þ+ÝÝØ+î_+Ñáâ÷çäåÝöúéêëìíîïð=óôõæèÝãûýøùÿüàñ'; +var + I, J: Integer; +begin + Result := S; + for I := 1 to Length(Result) do + begin + J := Pos(Result[I], W); + if J > 0 then + Result[I] := K[J]; + end; +end; + +{$IFNDEF CLR} +procedure FillString(var Buffer: string; Count: Integer; const Value: Char); +begin + FillChar(Buffer[1], Count, Value); +end; + +procedure FillString(var Buffer: string; StartIndex, Count: Integer; const Value: Char); +begin + if StartIndex <= 0 then + StartIndex := 1; + FillChar(Buffer[StartIndex], Count, Value); +end; + +procedure MoveString(const Source: string; var Dest: string; Count: Integer); +begin + Move(Source[1], Dest[1], Count); +end; + +procedure MoveString(const Source: string; SrcStartIdx: Integer; var Dest: string; + DstStartIdx: Integer; Count: Integer); +begin + if DstStartIdx <= 0 then + DstStartIdx := 1; + if SrcStartIdx <= 0 then + SrcStartIdx := 1; + + Move(Source[SrcStartIdx], Dest[DstStartIdx], Count); +end; + +procedure FillWideChar(var Buffer; Count: Integer; const Value: WideChar); +var + P: PLongint; + Value2: Cardinal; + CopyWord: Boolean; +begin + Value2 := (Cardinal(Value) shl 16) or Cardinal(Value); + CopyWord := Count and $1 <> 0; + Count := Count div 2; + P := @Buffer; + while Count > 0 do + begin + P^ := Value2; + Inc(P); + Dec(Count); + end; + if CopyWord then + PWideChar(P)^ := Value; +end; + +procedure MoveWideChar(const Source; var Dest; Count: Integer); +begin + Move(Source, Dest, Count * SizeOf(WideChar)); +end; +{$ELSE} +procedure FillString(var Buffer: string; Count: Integer; const Value: Char); +var + sb: StringBuilder; + I: Integer; +begin + sb := StringBuilder.Create(Count); + for I := 1 to Count do + sb.Append(Value); + Buffer := sb.ToString() + Buffer.Substring(Count); +end; + +procedure FillString(var Buffer: string; StartIndex, Count: Integer; const Value: Char); overload; +var + sb: StringBuilder; + I: Integer; +begin + if StartIndex <= 0 then + StartIndex := 1; + sb := StringBuilder.Create(Count); + for I := 1 to Count do + sb.Append(Value); + Buffer := Buffer.Substring(0, StartIndex - 1) + sb.ToString() + Buffer.Substring(StartIndex - 1 + Count); +end; + +procedure MoveString(const Source: string; var Dest: string; Count: Integer); +begin + Dest.Remove(0, Count); + Dest.Insert(0, Source.Substring(0, Count)); +end; + +procedure MoveString(const Source: string; SrcStartIdx: Integer; var Dest: string; + DstStartIdx: Integer; Count: Integer); +begin + if DstStartIdx <= 0 then + DstStartIdx := 1; + if SrcStartIdx <= 0 then + SrcStartIdx := 1; + + Dest.Remove(DstStartIdx - 1, Count); + Dest.Insert(DstStartIdx - 1, Source.Substring(SrcStartIdx - 1, Count)); +end; +{$ENDIF !CLR} + +function IsSubString(const S: string; StartIndex: Integer; const SubStr: string): Boolean; +begin + {$IFDEF CLR} + Result := Copy(S, StartIndex, Length(SubStr)) = SubStr; + {$ELSE} + if StartIndex < 1 then + StartIndex := 1; + if StartIndex > Length(S) then + StartIndex := Length(S); + Result := StrLComp(PChar(S) + StartIndex - 1, PChar(SubStr), Length(SubStr)) = 0; + {$ENDIF CLR} +end; + +function Spaces(const N: Integer): string; +begin + if N > 0 then + begin + SetLength(Result, N); + FillString(Result, N, ' '); + end + else + Result := ''; +end; + +function AddSpaces(const S: string; const N: Integer): string; +var + Len: Integer; +begin + Len := Length(S); + if (Len < N) and (N > 0) then + begin + SetLength(Result, N); + MoveString(S, Result, Len); + FillString(Result, Len + 1, N - Len, ' '); + end + else + Result := S; +end; + +{$IFNDEF CLR} +function SpacesW(const N: Integer): WideString; +begin + if N > 0 then + begin + SetLength(Result, N); + FillWideChar(Result[1], N, ' '); + end + else + Result := ''; +end; + +function AddSpacesW(const S: WideString; const N: Integer): WideString; +var + Len: Integer; +begin + Len := Length(S); + if (Len < N) and (N > 0) then + begin + SetLength(Result, N); + MoveWideChar(S[1], Result[1], Len); + FillWideChar(Result[Len + 1], N - Len, ' '); + end + else + Result := S; +end; +{$ENDIF !CLR} + +{ (rb) maybe construct an english variant? } + +function LastDateRUS(const Dat: TDateTime): string; +const + D2D: array [0..9] of Byte = + (3, 1, 2, 2, 2, 3, 3, 3, 3, 3); + Day: array [1..3] of string = + ('äåíü', 'äíÿ', 'äíåé'); // Day, Days, Days + Month: array [1..3] of string = + ('ìåñÿö', 'ìåñÿöà', 'ìåñÿöåâ'); // Month, Months, Months + Year: array [1..3] of string = + ('ãîä', 'ãîäà', 'ëå='); // Year, Years, Years + Week: array [1..4] of string = + ('íåäåëÝ', '2 íåäåëè', '3 íåäåëè', 'ìåñÿö'); // Week, 2 Weeks, 3 Weeks, Month +var + Y, M, D: Integer; +begin + if Date = Dat then + Result := 'ñåãîäíÿ' // Today + else + if Dat = Date - 1 then + Result := 'â÷åðà' // Yesterday + else + if Dat = Date - 2 then + Result := 'ïîçàâ÷åðà' // Day before yesterday + else + if Dat > Date then + Result := 'â áóäóùåì' // In the future + else + begin + D := Trunc(Date - Dat); + Y := Round(D / 365); + M := Round(D / 30); + if Y > 0 then + Result := IntToStr(Y) + ' ' + Year[D2D[StrToInt(IntToStr(Y)[Length(IntToStr(Y))])]] + ' íàçàä' // ago + else + if M > 0 then + Result := IntToStr(M) + ' ' + Month[D2D[StrToInt(IntToStr(M)[Length(IntToStr(M))])]] + ' íàçàä' // ago + else + if D > 6 then + Result := Week[D div 7] + ' íàçàä' // ago + else + if D > 0 then + Result := IntToStr(D) + ' ' + Day[D2D[StrToInt(IntToStr(D)[Length(IntToStr(D))])]] + ' íàçàä' // ago + end; +end; + +function AddSlash(const Dir: TFileName): string; +begin + Result := Dir; + if (Length(Dir) > 0) and (Dir[Length(Dir)] <> PathDelim) then + Result := Dir + PathDelim; +end; + +function AddPath(const FileName, Path: TFileName): TFileName; +begin + if ExtractFileDrive(FileName) = '' then + Result := AddSlash(Path) + FileName + else + Result := FileName; +end; + +function AddPaths(const PathList, Path: string): string; +var + I: Integer; + S: string; +begin + Result := ''; + I := 0; + S := SubStrBySeparator(PathList, I, PathSep); + while S <> '' do + begin + Result := ConcatSep(Result, AddPath(S, Path), PathSep); + Inc(I); + S := SubStrBySeparator(PathList, I, PathSep); + end; +end; + +function ParentPath(const Path: TFileName): TFileName; +begin + Result := Path; + if (Length(Result) > 0) and (Result[Length(Result)] = PathDelim) then + Delete(Result, Length(Result), 1); + Result := ExtractFilePath(Result); +end; + +function FindInPath(const FileName, PathList: string): TFileName; +var + I: Integer; + S: string; +begin + I := 0; + S := SubStrBySeparator(PathList, I, PathSep); + while S <> '' do + begin + Result := AddSlash(S) + FileName; + if FileExists(Result) then + Exit; + Inc(I); + S := SubStrBySeparator(PathList, I, PathSep); + end; + Result := ''; +end; + +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} +function GetComputerID: string; +var + SN: DWORD; + Nul: DWORD; + WinDir: array [0..MAX_PATH] of Char; +begin + GetWindowsDirectory(WinDir, MAX_PATH); + WinDir[3] := #0; + if GetVolumeInformation( + WinDir, // address of root directory of the file system + nil, // address of name of the volume + 0, // Length of lpVolumeNameBuffer + @SN, // address of volume serial number + Nul, // address of system's maximum filename Length + Nul, // address of file system flags + nil, // address of name of file system + 0) {// Length of lpFileSystemNameBuffer} then + Result := IntToHex(SN, 8) + else + Result := 'None'; +end; +{$ENDIF MSWINDOWS} +{$IFDEF UNIX} +function GetComputerID: string; +begin + Result := 'None'; +end; +{$ENDIF UNIX} + +{$ENDIF !CLR} + +function GetComputerName: string; +{$IFDEF CLR} +begin + Result := System.Environment.MachineName; +end; +{$ELSE} +var + nSize: Cardinal; +begin + nSize := MAX_COMPUTERNAME_LENGTH + 1; + SetLength(Result, nSize); + if Windows.GetComputerName(PChar(Result), nSize) then + SetLength(Result, nSize) + else + Result := ''; +end; +{$ENDIF CLR} + +function CurrencyToStr(const Cur: Currency): string; +begin + Result := CurrToStrF(Cur, ffCurrency, CurrencyDecimals) +end; + +function HasChar(const Ch: Char; const S: string): Boolean; +var + I: Integer; +begin + Result := True; + for I := 1 to Length(S) do + if S[I] = Ch then + Exit; + Result := False; +end; + +function HasCharW(const Ch: WideChar; const S: WideString): Boolean; +begin + Result := Pos(Ch, S) > 0; +end; + +function HasAnyChar(const Chars: string; const S: string): Boolean; +var + I: Integer; +begin + for I := 1 to Length(Chars) do + if HasChar(Chars[I], S) then + begin + Result := True; + Exit; + end; + Result := False; +end; + +function CountOfChar(const Ch: Char; const S: string): Integer; +var + I: Integer; +begin + Result := 0; + for I := 1 to Length(S) do + if S[I] = Ch then + Inc(Result); +end; + +procedure SwapInt(var Int1, Int2: Integer); +var + Tmp: Integer; +begin + Tmp := Int1; + Int1 := Int2; + Int2 := Tmp; +end; + +function DeleteReadOnlyFile(const FileName: TFileName): Boolean; +begin + {$IFDEF MSWINDOWS} + FileSetAttr(FileName, 0); {clear Read Only Flag} + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + FileSetReadOnly(FileName, False); + {$ENDIF UNIX} + Result := DeleteFile(FileName); +end; + +function HasParam(const Param: string): Boolean; +var + I: Integer; +begin + Result := False; + for I := 1 to ParamCount do + begin + Result := SameText(ParamStr(I), Param); + if Result then + Exit; + end; +end; + +function HasSwitch(const Param: string): Boolean; +var + I: Integer; +begin + Result := False; + for I := 1 to ParamCount do + if HasChar(ParamStr(I)[1], '-/') then + begin + Result := SameText(Copy(ParamStr(I), 2, Length(Param)), Param); + if Result then + Exit; + end; +end; + +function Switch(const Param: string): string; +var + I: Integer; +begin + Result := ''; + for I := 1 to ParamCount do + if HasChar(ParamStr(I)[1], '-/\') and + SameText(Copy(ParamStr(I), 2, Length(Param)), Param) then + begin + Result := Copy(ParamStr(I), 2 + Length(Param), 260); + Exit; + end; +end; + +function ExePath: TFileName; +begin + Result := ExtractFilePath(ParamStr(0)); +end; + +function FileNewExt(const FileName, NewExt: TFileName): TFileName; +begin + Result := Copy(FileName, 1, Length(FileName) - Length(ExtractFileExt(FileName))) + NewExt; +end; + +function CharInSet(const Ch: Char; const SetOfChar: TSysCharSet): Boolean; +begin + Result := Ch in SetOfChar; +end; + +function CharInSetW(const Ch: WideChar; const SetOfChar: TSysCharSet): Boolean; +begin + if Word(Ch) > 255 then + Result := False + else + Result := Char(Ch) in SetOfChar; +end; + +function IntPower(Base, Exponent: Integer): Integer; +begin + if Exponent > 0 then + begin + Result := Base; + Dec(Exponent); + while Exponent > 0 do + begin + Result := Result * Base; + Dec(Exponent); + end; + end + else + if Exponent < 0 then + Result := 0 + else + Result := 1; +end; + +{$IFNDEF CLR} +function ChangeTopException(E: TObject): TObject; +type + PRaiseFrame = ^TRaiseFrame; + TRaiseFrame = record + NextRaise: PRaiseFrame; + ExceptAddr: Pointer; + ExceptObject: TObject; + //ExceptionRecord: PExceptionRecord; + end; +begin + { C++ Builder 3 Warning !} + { if linker error occured with message "unresolved external 'System::RaiseList'" try + comment this function implementation, compile, + then uncomment and compile again. } + {$IFDEF MSWINDOWS} + {$IFDEF SUPPORTS_DEPRECATED} + {$WARN SYMBOL_DEPRECATED OFF} + {$ENDIF SUPPORTS_DEPRECATED} + if RaiseList <> nil then + begin + Result := PRaiseFrame(RaiseList)^.ExceptObject; + PRaiseFrame(RaiseList)^.ExceptObject := E + end + else + Result := nil; + {$IFDEF SUPPORTS_DEPRECATED} + {$WARN SYMBOL_DEPRECATED ON} + {$ENDIF SUPPORTS_DEPRECATED} + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + // XXX: changing exception in stack frame is not supported on Kylix + Writeln(ErrOutput, 'ChangeTopException'); + Result := E; + {$ENDIF UNIX} +end; +{$ENDIF !CLR} + + +function KeyPressed(VK: Integer): Boolean; +begin + Result := Windows.GetKeyState(VK) and $8000 = $8000; +end; + + +function Var2Type(V: Variant; const DestVarType: Integer): Variant; +var + VType: TVarType; +begin + {$IFDEF CLR} + VType := VarType(V); + {$ELSE} + VType := TVarData(V).VType; + {$ENDIF CLR} + if VType in [varEmpty, varNull] then + begin + case DestVarType of + {$IFNDEF CLR} + varOleStr, + {$ENDIF !CLR} + varString: + Result := ''; + varInteger, varSmallint, varByte: + Result := 0; + varBoolean: + Result := False; + varSingle, varDouble, varCurrency, varDate: + Result := 0.0; + {$IFDEF CLR} + varObject: + {$ELSE} + varVariant: + {$ENDIF CLR} + Result := Null; + else + Result := VarAsType(V, DestVarType); + end; + end + else + Result := VarAsType(V, DestVarType); + if (DestVarType = varInteger) and (VType = varBoolean) then + Result := Integer(V = True); +end; + +function VarToInt(V: Variant): Integer; +begin + Result := Var2Type(V, varInteger); +end; + +function VarToFloat(V: Variant): Double; +begin + Result := Var2Type(V, varDouble); +end; + +function CopyDir(const SourceDir, DestDir: TFileName): Boolean; +var + SearchRec: TSearchRec; + DosError: Integer; + Path, DestPath: TFileName; +begin + Result := False; + if not CreateDir(DestDir) then + Exit; + Path := SourceDir; + DestPath := AddSlash(DestDir); + Path := AddSlash(Path); + DosError := FindFirst(Path + AllFilesMask, faAnyFile, SearchRec); + while DosError = 0 do + begin + if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then + begin + if (SearchRec.Attr and faDirectory) = faDirectory then + Result := CopyDir(Path + SearchRec.Name, AddSlash(DestDir) + SearchRec.Name) + else + {$IFDEF CLR} + Result := CopyFile(Path + SearchRec.Name, DestPath + SearchRec.Name, True); + {$ELSE} + Result := CopyFile(PChar(Path + SearchRec.Name), PChar(DestPath + SearchRec.Name), True); + {$ENDIF CLR} + if not Result then + Exit; + end; + DosError := FindNext(SearchRec); + end; + FindClose(SearchRec); + Result := True; +end; + +////////////////////////////////////////////////////////////////////////////// +{ Note: FileTimeToDateTime has been commented out, it is not used anywhere + in the JVCL code. Further, the old version is not to be returned + as it does not behave like the JCL version it is supposed to mimick. + See Mantis 2452 for details. +} +{const + FileTimeBase = -109205.0; + FileTimeStep: Extended = 24.0 * 60.0 * 60.0 * 1000.0 * 1000.0 * 10.0; // 100 nSek per Day +function FileTimeToDateTime(const FT: TFileTime): TDateTime; +begin + Result := Int64(FileTime) / FileTimeStep; + Result := Result + FileTimeBase; +end;} +// ---------------------------- old version --------------------------- +//{$IFDEF MSWINDOWS} +{var + LocalFileTime: TFileTime; + FileDate: Integer; +begin + FileTimeToLocalFileTime(FT, LocalFileTime); + FileTimeToDosDateTime(LocalFileTime, LongRec(FileDate).Hi, LongRec(FileDate).Lo); + Result := FileDateToDateTime(FileDate); +end;} +//{$ENDIF MSWINDOWS} +//{$IFDEF UNIX} +{begin + Result := FileDateToDateTime(FT); +end;} +//{$ENDIF UNIX} +// ------------------------- old version -------------------------------- + +procedure FileTimeToDosDateTimeDWord(const FT: TFileTime; out Dft: DWORD); +{$IFDEF CLR} +var + wHi, wLo: Word; +{$ENDIF CLR} +begin + {$IFDEF CLR} + FileTimeToDosDateTime(FT, wHi, wLo); + Dft := (wHi shl 16) or wLo; + {$ELSE} + FileTimeToDosDateTime(FT, LongRec(Dft).Hi, LongRec(Dft).Lo); + {$ENDIF CLR} +end; + +function MakeValidFileName(const FileName: TFileName; + ReplaceBadChar: Char): TFileName; +var + I: Integer; +begin + Result := FileName; + for I := 1 to Length(Result) do + if HasChar(Result[I], '''":?*\/') then + Result[I] := ReplaceBadChar; +end; + +function DefStr(const S: string; Default: string): string; +begin + if S <> '' then + Result := S + else + Result := Default; +end; + +{$IFNDEF CLR} +function StrLICompW2(S1, S2: PWideChar; MaxLen: Integer): Integer; +// faster than the JclUnicode.StrLICompW function +var + P1, P2: WideString; +begin + SetString(P1, S1, Min(MaxLen, StrLenW(S1))); + SetString(P2, S2, Min(MaxLen, StrLenW(S2))); + {$IFDEF COMPILER6_UP} + Result := SysUtils.WideCompareText(P1, P2); + {$ELSE} + Result := WideCompareText(P1, P2); + {$ENDIF COMPILER6_UP} +end; + +function StrPosW(S, SubStr: PWideChar): PWideChar; +var + P: PWideChar; + I: Integer; +begin + Result := nil; + if (S = nil) or (SubStr = nil) or + (S[0] = #0) or (SubStr[0] = #0) then + Exit; + Result := S; + while Result[0] <> #0 do + begin + if Result[0] <> SubStr[0] then + Inc(Result) + else + begin + P := Result + 1; + I := 0; + while (P[0] <> #0) and (P[0] = SubStr[I]) do + begin + Inc(I); + Inc(P); + end; + if SubStr[I] = #0 then + Exit + else + Inc(Result); + end; + end; + Result := nil; +end; + +function StrLenW(S: PWideChar): Integer; +begin + Result := 0; + if S <> nil then + while S[Result] <> #0 do + Inc(Result); +end; +{$ENDIF !CLR} + +function TrimW(const S: WideString): WideString; +{$IFDEF COMPILER6_UP} +begin + Result := Trim(S); +end; +{$ELSE} +var + I, L: Integer; +begin + L := Length(S); + I := 1; + while (I <= L) and (S[I] <= ' ') do + Inc(I); + if I > L then + Result := '' + else + begin + while S[L] <= ' ' do + Dec(L); + Result := Copy(S, I, L - I + 1); + end; +end; +{$ENDIF COMPILER6_UP} + +function TrimLeftW(const S: WideString): WideString; +{$IFDEF COMPILER6_UP} +begin + Result := TrimLeft(S); +end; +{$ELSE} +var + I, L: Integer; +begin + L := Length(S); + I := 1; + while (I <= L) and (S[I] <= ' ') do + Inc(I); + Result := Copy(S, I, MaxInt); +end; +{$ENDIF COMPILER6_UP} + +function TrimRightW(const S: WideString): WideString; +{$IFDEF COMPILER6_UP} +begin + Result := TrimRight(S); +end; +{$ELSE} +var + I: Integer; +begin + I := Length(S); + while (I > 0) and (S[I] <= ' ') do + Dec(I); + Result := Copy(S, 1, I); +end; +{$ENDIF COMPILER6_UP} + +procedure SetDelimitedText(List: TStrings; const Text: string; Delimiter: Char); +var + {$IFDEF COMPILER6_UP} + Ch: Char; + {$ELSE} + S: string; + F, P: PChar; + {$ENDIF COMPILER6_UP} +begin + {$IFDEF COMPILER6_UP} + Ch := List.Delimiter; + try + List.Delimiter := Delimiter; + List.DelimitedText := Text; + finally + List.Delimiter := Ch; + end; + {$ELSE} + List.BeginUpdate; + try + List.Clear; + P := PChar(Text); + while P^ in [#1..#32] do + Inc(P); + while P^ <> #0 do + begin + if P^ = '"' then + begin + F := P; + while (P[0] <> #0) and (P[0] <> '"') do + Inc(P); + SetString(S, F, P - F); + end + else + begin + F := P; + while not (P[0] < #32) and (P[0] <> Delimiter) do + Inc(P); + SetString(S, F, P - F); + end; + List.Add(S); + while P[0] in [#1..#32] do + Inc(P); + if P[0] = Delimiter then + begin + F := P; + Inc(F); + if F[0] = #0 then + List.Add(''); + repeat + Inc(P); + until not (P[0] in [#1..#32]); + end; + end; + finally + List.EndUpdate; + end; + {$ENDIF COMPILER6_UP} +end; + +function StrToBool(const S: string): Boolean; +begin + Result := (S = '1') or SameText(S, 'True') or SameText(S, 'yes'); +end; + +function RATextOutEx(Canvas: TCanvas; const R, RClip: TRect; const S: string; + const CalcHeight: Boolean): Integer; +var + Ss: TStrings; + I: Integer; + H: Integer; +begin + Ss := TStringList.Create; + try + Ss.Text := S; + H := Canvas.TextHeight('A'); + Result := H * Ss.Count; + if not CalcHeight then + for I := 0 to Ss.Count - 1 do + ExtTextOut( + Canvas.Handle, // handle of device context + R.Left, // X-coordinate of reference point + R.Top + H * I, // Y-coordinate of reference point + ETO_CLIPPED, // text-output options + {$IFDEF CLR} + RClip, + Ss[I], + Length(Ss[I]), + {$ELSE} + @RClip, // optional clipping and/or opaquing rectangle + PChar(Ss[I]), + Length(Ss[I]), // number of characters in string + {$ENDIF CLR} + nil); // address of array of intercharacter spacing values + finally + Ss.Free; + end; +end; + +procedure RATextOut(Canvas: TCanvas; const R, RClip: TRect; const S: string); +begin + RATextOutEx(Canvas, R, RClip, S, False); +end; + +function RATextCalcHeight(Canvas: TCanvas; const R: TRect; const S: string): Integer; +begin + Result := RATextOutEx(Canvas, R, R, S, True); +end; + +procedure Cinema(Canvas: TCanvas; rS, rD: TRect); +const + Pause = 30; {milliseconds} + Steps = 7; + Width = 1; +var + R: TRect; + I: Integer; + PenOld: TPen; + + procedure FrameR(R: TRect); + begin + with Canvas do + begin + MoveTo(R.Left, R.Top); + LineTo(R.Left, R.Bottom); + LineTo(R.Right, R.Bottom); + LineTo(R.Right, R.Top); + LineTo(R.Left, R.Top); + end; + end; + + procedure Frame; + begin + FrameR(R); + with Canvas do + begin + MoveTo(rS.Left, rS.Top); + LineTo(R.Left, R.Top); + if R.Top <> rS.Top then + begin + MoveTo(rS.Right, rS.Top); + LineTo(R.Right, R.Top); + end; + if R.Left <> rS.Left then + begin + MoveTo(rS.Left, rS.Bottom); + LineTo(R.Left, R.Bottom); + end; + if (R.Bottom <> rS.Bottom) and (R.Right <> rS.Right) then + begin + MoveTo(rS.Right, rS.Bottom); + LineTo(R.Right, R.Bottom); + end; + end; + end; + +begin + PenOld := TPen.Create; + PenOld.Assign(Canvas.Pen); + Canvas.Pen.Mode := pmNot; + Canvas.Pen.Width := Width; + Canvas.Pen.Style := psDot; + FrameR(rS); + R := rS; + for I := 1 to Steps do + begin + R.Left := rS.Left + (rD.Left - rS.Left) div Steps * I; + R.Top := rS.Top + (rD.Top - rS.Top) div Steps * I; + R.Bottom := rS.Bottom + (rD.Bottom - rS.Bottom) div Steps * I; + R.Right := rS.Right + (rD.Right - rS.Right) div Steps * I; + Frame; + Sleep(Pause); + Frame; + end; + FrameR(rS); + Canvas.Pen.Assign(PenOld); +end; + +function IniReadSection(const IniFileName: TFileName; const Section: string; Ss: TStrings): Boolean; +var + F: Integer; + S: string; +begin + with TStringList.Create do + try + LoadFromFile(IniFileName); + F := IndexOf('[' + Section + ']'); + Result := F > -1; + if Result then + begin + Ss.BeginUpdate; + try + Ss.Clear; + Inc(F); + while F < Count do + begin + S := Strings[F]; + if (Length(S) > 0) and (Trim(S[1]) = '[') then + Break; + Ss.Add(S); + Inc(F); + end; + finally + Ss.EndUpdate; + end; + end; + finally + Free; + end; +end; + +procedure SaveTextFile(const FileName: TFileName; const Source: string); +begin + with TStringList.Create do + try + Text := Source; + SaveToFile(FileName); + finally + Free; + end; +end; + +function LoadTextFile(const FileName: TFileName): string; +begin + with TStringList.Create do + try + LoadFromFile(FileName); + Result := Text; + finally + Free; + end; +end; + +function ReadFolder(const Folder, Mask: TFileName; FileList: TStrings): Integer; +var + SearchRec: TSearchRec; + DosError: Integer; +begin + FileList.BeginUpdate; + try + FileList.Clear; + Result := FindFirst(AddSlash(Folder) + Mask, faAnyFile, SearchRec); + DosError := Result; + while DosError = 0 do + begin + if not ((SearchRec.Attr and faDirectory) = faDirectory) then + FileList.Add(SearchRec.Name); + DosError := FindNext(SearchRec); + end; + FindClose(SearchRec); + finally + FileList.EndUpdate; + end; +end; + +function ReadFolders(const Folder: TFileName; FolderList: TStrings): Integer; +var + SearchRec: TSearchRec; + DosError: Integer; +begin + FolderList.BeginUpdate; + try + FolderList.Clear; + Result := FindFirst(AddSlash(Folder) + AllFilesMask, faAnyFile, SearchRec); + DosError := Result; + while DosError = 0 do + begin + if ((SearchRec.Attr and faDirectory) = faDirectory) and + (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then + FolderList.Add(SearchRec.Name); + DosError := FindNext(SearchRec); + end; + FindClose(SearchRec); + finally + FolderList.EndUpdate; + end; +end; + +{ example for ReplaceStrings: + with memEdit do + begin + Text := ReplaceStrings(Text, SelStart+1, SelLength, memWords.Lines, memFrases.Lines, NewSelStart); + SelStart := NewSelStart-1; + end; } + +function ReplaceStrings(const S: string; PosBeg, Len: Integer; Words, Frases: TStrings; + var NewSelStart: Integer): string; +var + I, Beg, Ent, LS, F: Integer; + Word: string; +begin + NewSelStart := PosBeg; + Result := S; + LS := Length(S); + if Len = 0 then + begin + if PosBeg < 1 then + Exit; + if PosBeg = 1 then + PosBeg := 2; + for I := PosBeg - 1 downto 1 do + if S[I] in Separators then + Break; + Beg := I + 1; + for Ent := PosBeg to LS do + if S[Ent] in Separators then + Break; + if Ent > Beg then + Word := Copy(S, Beg, Ent - Beg) + else + Word := S[PosBeg]; + end + else + begin + Word := Copy(S, PosBeg, Len); + Beg := PosBeg; + Ent := PosBeg + Len; + end; + if Word = '' then + Exit; + F := Words.IndexOf(Word); + if (F > -1) and (F < Frases.Count) then + begin + Result := Copy(S, 1, Beg - 1) + Frases[F] + Copy(S, Ent, LS); + NewSelStart := Beg + Length(Frases[F]); + end; +end; + +{ example for ReplaceAllStrings: + + with memEdit do + Text := ReplaceAllStrings(Text, memWords.Lines, memFrases.Lines); +} + +function ReplaceAllStrings(const S: string; Words, Frases: TStrings): string; +var + I: Integer; +begin + Result := S; + for I := 0 to Words.Count - 1 do + Result := ReplaceString(Result, Words[I], Frases[I]); +end; + +function CountOfLines(const S: string): Integer; +begin + with TStringList.Create do + try + Text := S; + Result := Count; + finally + Free; + end; +end; + +procedure DeleteOfLines(Ss: TStrings; const Words: array of string); +var + I, J: Integer; +begin + Ss.BeginUpdate; + try + for J:= Low(Words) to High(Words) do + for I := Ss.Count - 1 downto 0 do + if Trim(Ss[I]) = Trim(Words[J]) then + Ss.Delete(I); + finally + Ss.EndUpdate; + end; +end; + +procedure DeleteEmptyLines(Ss: TStrings); +begin + DeleteOfLines(Ss,['']); +end; + +procedure SQLAddWhere(SQL: TStrings; const Where: string); +var + I, J: Integer; +begin + J := SQL.Count - 1; + for I := 0 to SQL.Count - 1 do + // (rom) does this always work? Think of a fieldname "grouporder" + {$IFDEF CLR} + if StartsText('where ', SQL[I]) then + begin + J := I + 1; + while J < SQL.Count do + begin + if StartsText('order ', SQL[J]) or StartsText('group ', SQL[J]) then + Break; + Inc(J); + end; + end; + {$ELSE} + if StrLIComp(PChar(SQL[I]), 'where ', 6) = 0 then + begin + J := I + 1; + while J < SQL.Count do + begin + if (StrLIComp(PChar(SQL[J]), 'order ', 6) = 0) or + (StrLIComp(PChar(SQL[J]), 'group ', 6) = 0) then + Break; + Inc(J); + end; + end; + {$ENDIF CLR} + SQL.Insert(J, 'and ' + Where); +end; + +procedure InternalFrame3D(Canvas: TCanvas; var Rect: TRect; TopColor, BottomColor: TColor; + Width: Integer); + + procedure DoRect; + var + TopRight, BottomLeft: TPoint; + begin + with Canvas, Rect do + begin + TopRight.X := Right; + TopRight.Y := Top; + BottomLeft.X := Left; + BottomLeft.Y := Bottom; + Pen.Color := TopColor; + PolyLine([BottomLeft, TopLeft, TopRight]); + Pen.Color := BottomColor; + Dec(BottomLeft.X); + PolyLine([TopRight, BottomRight, BottomLeft]); + end; + end; + +begin + Canvas.Pen.Width := 1; + Dec(Rect.Bottom); + Dec(Rect.Right); + while Width > 0 do + begin + Dec(Width); + DoRect; + InflateRect(Rect, -1, -1); + end; + Inc(Rect.Bottom); + Inc(Rect.Right); +end; + +procedure Roughed(ACanvas: TCanvas; const ARect: TRect; const AVert: Boolean); +var + I: Integer; + J: Integer; + R: TRect; + V: Boolean; + H: Boolean; +begin + H := True; + V := True; + for I := 0 to (ARect.Right - ARect.Left) div 4 do + begin + for J := 0 to (ARect.Bottom - ARect.Top) div 4 do + begin + if AVert then + begin + if V then + R := Bounds(ARect.Left + I * 4 + 2, ARect.Top + J * 4, 2, 2) + else + R := Bounds(ARect.Left + I * 4, ARect.Top + J * 4, 2, 2); + end + else + begin + if H then + R := Bounds(ARect.Left + I * 4, ARect.Top + J * 4 + 2, 2, 2) + else + R := Bounds(ARect.Left + I * 4, ARect.Top + J * 4, 2, 2); + end; + + InternalFrame3D(ACanvas, R, clBtnHighlight, clBtnShadow, 1); + V := not V; + end; + H := not H; + end; +end; + +function BitmapFromBitmap(SrcBitmap: TBitmap; const AWidth, AHeight, Index: Integer): TBitmap; +begin + Result := TBitmap.Create; + Result.Width := AWidth; + Result.Height := AHeight; + Result.Canvas.CopyRect(Rect(0, 0, AWidth, AHeight), SrcBitmap.Canvas, Bounds(AWidth * Index, 0, AWidth, AHeight)); +end; + +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} + +function ResSaveToFileEx(Instance: HINST; Typ, Name: PChar; + const Compressed: Boolean; const FileName: string): Boolean; +var + RhRsrc: HRSRC; + RhGlobal: HGLOBAL; + RAddr: Pointer; + RLen: DWORD; + Stream: TFileStream; + FileDest: string; +begin + Result := False; + RhRsrc := FindResource( + Instance, // resource-module handle + Name, // address of resource name + Typ); // address of resource type + if RhRsrc = 0 then + Exit; + RhGlobal := LoadResource( + Instance, // resource-module handle + RhRsrc); // resource handle + if RhGlobal = 0 then + Exit; + RAddr := LockResource( + RhGlobal); // handle to resource to lock + FreeResource(RhGlobal); + if RAddr = nil then + Exit; + RLen := SizeofResource( + Instance, // resource-module handle + RhRsrc); // resource handle + if RLen = 0 then + Exit; + { And now it is possible to duplicate [translated] } + Stream := nil; { for Free [translated] } + if Compressed then + FileDest := GenTempFileName(FileName) + else + FileDest := FileName; + try + try + Stream := TFileStream.Create(FileDest, fmCreate or fmOpenWrite or fmShareExclusive); + Stream.WriteBuffer(RAddr^, RLen); + finally + Stream.Free; + end; + if Compressed then + begin + Result := LZFileExpand(FileDest, FileName); + DeleteFile(FileDest); + end + else + Result := True; + except + end; +end; + +function ResSaveToFile(const Typ, Name: string; const Compressed: Boolean; + const FileName: string): Boolean; +begin + Result := ResSaveToFileEx(HInstance, PChar(Typ), PChar(Name), Compressed, FileName); +end; + +function ResSaveToString(Instance: HINST; const Typ, Name: string; + var S: string): Boolean; +var + RhRsrc: HRSRC; + RhGlobal: HGLOBAL; + RAddr: Pointer; + RLen: DWORD; +begin + Result := False; + RhRsrc := FindResource( + Instance, // resource-module handle + PChar(Name), // address of resource name + PChar(Typ)); // address of resource type + if RhRsrc = 0 then + Exit; + RhGlobal := LoadResource( + Instance, // resource-module handle + RhRsrc); // resource handle + if RhGlobal = 0 then + Exit; + RAddr := LockResource(RhGlobal); // handle to resource to lock + FreeResource(RhGlobal); + if RAddr = nil then + Exit; + RLen := SizeofResource( + Instance, // resource-module handle + RhRsrc); // resource handle + if RLen = 0 then + Exit; + { And now it is possible to duplicate [translated] } + SetString(S, PChar(RAddr), RLen); +end; + +{$ENDIF MSWINDOWS} +{$ENDIF !CLR} + +function TextHeight(const AStr: string): Integer; +var + Canvas: TCanvas; + DC: HDC; +begin + DC := GetDC(HWND_DESKTOP); + Canvas := TCanvas.Create; + try + Canvas.Handle := DC; + Result := Canvas.TextHeight(AStr); + Canvas.Handle := NullHandle; + finally + ReleaseDC(HWND_DESKTOP, DC); + Canvas.Free; + end; +end; + +function TextWidth(const AStr: string): Integer; +var + Canvas: TCanvas; + DC: HDC; +begin + DC := GetDC(HWND_DESKTOP); + Canvas := TCanvas.Create; + try + Canvas.Handle := DC; + Result := Canvas.TextWidth(AStr); + Canvas.Handle := NullHandle; + finally + ReleaseDC(HWND_DESKTOP, DC); + Canvas.Free; + end; +end; + +procedure SetChildPropOrd(Owner: TComponent; const PropName: string; Value: Longint); +var + I: Integer; + PropInfo: PPropInfo; +begin + for I := 0 to Owner.ComponentCount - 1 do + begin + PropInfo := GetPropInfo(Owner.Components[I].ClassInfo, PropName); + if PropInfo <> nil then + SetOrdProp(Owner.Components[I], PropInfo, Value); + end; +end; + +procedure Error(const Msg: string); +begin + raise Exception.Create(Msg); +end; + +procedure ItemHtDrawEx(Canvas: TCanvas; Rect: TRect; + const State: TOwnerDrawState; const Text: string; + const HideSelColor: Boolean; var PlainItem: string; + var Width: Integer; CalcWidth: Boolean); +var + CL: string; + I: Integer; + M1: string; + OriRect: TRect; // it's added + LastFontStyle: TFontStyles; + LastFontColor: TColor; + + function Cmp(const M1: string): Boolean; + begin + {$IFDEF CLR} + Result := System.String.Compare(Text, I, M1, 0, M1.Length, True) = 0; + {$ELSE} + Result := AnsiStrLIComp(PChar(Text) + I, PChar(M1), Length(M1)) = 0; + {$ENDIF CLR} + end; + + function Cmp1(const M1: string): Boolean; + begin + Result := Cmp(M1); + if Result then + Inc(I, Length(M1)); + end; + + function CmpL(const M1: string): Boolean; + begin + Result := Cmp(M1 + '>'); + end; + + function CmpL1(const M1: string): Boolean; + begin + Result := Cmp1(M1 + '>'); + end; + + procedure Draw(const M: string); + begin + if not Assigned(Canvas) then + Exit; + if not CalcWidth then + Canvas.TextOut(Rect.Left, Rect.Top, M); + Rect.Left := Rect.Left + Canvas.TextWidth(M); + end; + + procedure Style(const Style: TFontStyle; const Include: Boolean); + begin + if not Assigned(Canvas) then + Exit; + if Include then + Canvas.Font.Style := Canvas.Font.Style + [Style] + else + Canvas.Font.Style := Canvas.Font.Style - [Style]; + end; + +begin + PlainItem := ''; + LastFontColor := 0; { satisfy compiler } + if Canvas <> nil then + begin + LastFontStyle := Canvas.Font.Style; + LastFontColor := Canvas.Font.Color; + end; + try + if HideSelColor and Assigned(Canvas) then + begin + Canvas.Brush.Color := clWindow; + Canvas.Font.Color := clWindowText; + end; + if Assigned(Canvas) then + Canvas.FillRect(Rect); + + Width := Rect.Left; + Rect.Left := Rect.Left + 2; + + OriRect := Rect; //save origin rectangle + + M1 := ''; + I := 1; + while I <= Length(Text) do + begin + if (Text[I] = '<') and + (CmpL('b') or CmpL('/b') or + CmpL('i') or CmpL('/i') or + CmpL('u') or CmpL('/u') or + Cmp('c:')) then + begin + Draw(M1); + PlainItem := PlainItem + M1; + + if CmpL1('b') then + Style(fsBold, True) + else + if CmpL1('/b') then + Style(fsBold, False) + else + if CmpL1('i') then + Style(fsItalic, True) + else + if CmpL1('/i') then + Style(fsItalic, False) + else + if CmpL1('u') then + Style(fsUnderline, True) + else + if CmpL1('/u') then + Style(fsUnderline, False) + else + if Cmp1('c:') then + begin + CL := SubStrBySeparator(Text, 0, '>', I); + if (HideSelColor or not (odSelected in State)) and Assigned(Canvas) then + try + if (Length(CL) > 0) and (CL[1] <> '$') then + Canvas.Font.Color := StringToColor('cl' + CL) + else + Canvas.Font.Color := StringToColor(CL); + except + end; + Inc(I, Length(CL) + 1 {'>'}); + end; + Inc(I); + if (Text[I] = Chr(13)) and Cmp1(string(Chr(10))) then + begin + Rect.Left := OriRect.Left; + Rect.Top := Rect.Top + Canvas.TextHeight(M1 + 'W'); + Inc(I); + end; + Dec(I); + M1 := ''; + end + else + if (Text[I] = Chr(13)) and Cmp1(string(Chr(10))) then + begin + // new line + Draw(M1); + PlainItem := PlainItem + M1; + Rect.Left := OriRect.Left; + Rect.Top := Rect.Top + Canvas.TextHeight(M1 + 'W'); + M1 := ''; + end + else + M1 := M1 + Text[I]; // add text + Inc(I); + end; { for } + Draw(M1); + PlainItem := PlainItem + M1; + finally + if Canvas <> nil then + begin + Canvas.Font.Style := LastFontStyle; + Canvas.Font.Color := LastFontColor; + end; + end; + Width := Rect.Left - Width + 2; +end; + +function ItemHtDraw(Canvas: TCanvas; Rect: TRect; + const State: TOwnerDrawState; const Text: string; + const HideSelColor: Boolean): string; +var + S: string; + W: Integer; +begin + ItemHtDrawEx(Canvas, Rect, State, Text, HideSelColor, S, W, False); +end; + +function ItemHtPlain(const Text: string): string; +var + S: string; + W: Integer; +begin + ItemHtDrawEx(nil, Rect(0, 0, -1, -1), [], Text, False, S, W, False); + Result := S; +end; + +function ItemHtWidth(Canvas: TCanvas; Rect: TRect; + const State: TOwnerDrawState; const Text: string; + const HideSelColor: Boolean): Integer; +var + S: string; + W: Integer; +begin + ItemHtDrawEx(Canvas, Rect, State, Text, HideSelColor, S, W, True); + Result := W; +end; + +procedure ClearList(List: TList); +var + I: Integer; +begin + if Assigned(List) then + begin + if not (List is TObjectList) then + for I := 0 to List.Count - 1 do + TObject(List[I]).Free; + List.Clear; + end; +end; + +{$IFNDEF CLR} +procedure MemStreamToClipBoard(MemStream: TMemoryStream; const Format: Word); + +var + Data: THandle; + DataPtr: Pointer; + + +begin + Clipboard.Open; + try + Data := GlobalAlloc(GMEM_MOVEABLE, MemStream.Size); + try + DataPtr := GlobalLock(Data); + try + Move(MemStream.Memory^, DataPtr^, MemStream.Size); + Clipboard.Clear; + SetClipboardData(Format, Data); + finally + GlobalUnlock(Data); + end; + except + GlobalFree(Data); + raise; + end; + finally + Clipboard.Close; + end; +end; + +procedure ClipBoardToMemStream(MemStream: TMemoryStream; const Format: Word); + +var + Data: THandle; + DataPtr: Pointer; + +begin + Clipboard.Open; + try + Data := GetClipboardData(Format); + if Data = 0 then + Exit; + DataPtr := GlobalLock(Data); + if DataPtr = nil then + Exit; + try + MemStream.WriteBuffer(DataPtr^, GlobalSize(Data)); + MemStream.Position := 0; + finally + GlobalUnlock(Data); + end; + finally + Clipboard.Close; + end; +end; +{$ENDIF !CLR} + +function GetPropTypeKind(PropInf: PPropInfo): TTypeKind; +begin + {$IFDEF CLR} + Result := PropInf.TypeKind; + {$ELSE} + Result := PropInf.PropType^.Kind; + {$ENDIF CLR} +end; + +function GetPropType(Obj: TObject; const PropName: string): TTypeKind; +var + PropInf: PPropInfo; +begin + PropInf := GetPropInfo(Obj.ClassInfo, PropName); + if PropInf = nil then + Result := tkUnknown + else + Result := GetPropTypeKind(PropInf); +end; + +function GetPropStr(Obj: TObject; const PropName: string): string; +var + PropInf: PPropInfo; +begin + PropInf := GetPropInfo(Obj.ClassInfo, PropName); + if PropInf = nil then + {$IFDEF CLR} + raise Exception.CreateFmt(RsEPropertyNotExists, [PropName]); + {$ELSE} + raise Exception.CreateResFmt(@RsEPropertyNotExists, [PropName]); + {$ENDIF CLR} + if not (GetPropTypeKind(PropInf) in [tkString, tkLString, tkWString]) then + {$IFDEF CLR} + raise Exception.CreateFmt(RsEInvalidPropertyType, [PropName]); + {$ELSE} + raise Exception.CreateResFmt(@RsEInvalidPropertyType, [PropName]); + {$ENDIF CLR} + Result := GetStrProp(Obj, PropInf); +end; + +function GetPropOrd(Obj: TObject; const PropName: string): Integer; +var + PropInf: PPropInfo; +begin + PropInf := GetPropInfo(Obj.ClassInfo, PropName); + if PropInf = nil then + {$IFDEF CLR} + raise Exception.CreateFmt(RsEPropertyNotExists, [PropName]); + {$ELSE} + raise Exception.CreateResFmt(@RsEPropertyNotExists, [PropName]); + {$ENDIF CLR} + if not (GetPropTypeKind(PropInf) in [tkInteger, tkChar, tkWChar, tkEnumeration, tkClass]) then + {$IFDEF CLR} + raise Exception.CreateFmt(RsEInvalidPropertyType, [PropName]); + {$ELSE} + raise Exception.CreateResFmt(@RsEInvalidPropertyType, [PropName]); + {$ENDIF CLR} + Result := GetOrdProp(Obj, PropInf); +end; + +function GetPropMethod(Obj: TObject; const PropName: string): TMethod; +var + PropInf: PPropInfo; +begin + PropInf := GetPropInfo(Obj.ClassInfo, PropName); + if PropInf = nil then + {$IFDEF CLR} + raise Exception.CreateFmt(RsEPropertyNotExists, [PropName]); + {$ELSE} + raise Exception.CreateResFmt(@RsEPropertyNotExists, [PropName]); + {$ENDIF CLR} + if not (GetPropTypeKind(PropInf) = tkMethod) then + {$IFDEF CLR} + raise Exception.CreateFmt(RsEInvalidPropertyType, [PropName]); + {$ELSE} + raise Exception.CreateResFmt(@RsEInvalidPropertyType, [PropName]); + {$ENDIF CLR} + Result := GetMethodProp(Obj, PropInf); +end; + +procedure PrepareIniSection(Ss: TStrings); +var + I: Integer; + S: string; +begin + Ss.BeginUpdate; + try + for I := Ss.Count - 1 downto 0 do + begin + S := Trim(Ss[I]); + if (S = '') or (S[1] in [';', '#']) then + Ss.Delete(I); + end; + finally + Ss.EndUpdate; + end; +end; + +{:Creates a TPointL structure from a pair of coordinates. +Call PointL to create a TPointL structure that represents the specified +coordinates. Use PointL to construct parameters for functions +that require a TPointL, rather than setting up local variables +for each parameter. +@param X The X coordinate. +@param Y The Y coordinate. +@return A TPointL structure for coordinates X and Y. +@example +var + p: TPointL; +begin + p := PointL(100, 100); +end; + +} + +function PointL(const X, Y: Longint): TPointL; +begin + Result.X := X; + Result.Y := Y; +end; + +{:Conditional assignment. +Returns the value in True or False depending on the condition Test. +@param Test The test condition. +@param True Returns this value if Test is True. +@param False Returns this value if Test is False. +@return Value in True or False depending on Test. +@example +bar := iif(foo, 1, 0); + +
has the same effects as:
+ +if foo then + bar := 1 +else + bar := 0; + +} + +function iif(const Test: Boolean; const ATrue, AFalse: Variant): Variant; +begin + if Test then + Result := ATrue + else + Result := AFalse; +end; + + +{ begin JvIconClipboardUtils} +{ Icon clipboard routines } + +var + Private_CF_ICON: Word; + +function CF_ICON: Word; +begin + if Private_CF_ICON = 0 then + begin + { The following string should not be localized } + Private_CF_ICON := RegisterClipboardFormat('Delphi Icon'); + TPicture.RegisterClipboardFormat(Private_CF_ICON, TIcon); + end; + Result := Private_CF_ICON; +end; + +{$IFNDEF CLR} +function CreateBitmapFromIcon(Icon: TIcon; BackColor: TColor): TBitmap; +var + Ico: HICON; + W, H: Integer; +begin + Ico := CreateRealSizeIcon(Icon); + try + GetIconSize(Ico, W, H); + Result := TBitmap.Create; + try + Result.Width := W; + Result.Height := H; + with Result.Canvas do + begin + Brush.Color := BackColor; + FillRect(Rect(0, 0, W, H)); + DrawIconEx(Handle, 0, 0, Ico, W, H, 0, 0, DI_NORMAL); + end; + except + Result.Free; + raise; + end; + finally + DestroyIcon(Ico); + end; +end; + +procedure CopyIconToClipboard(Icon: TIcon; BackColor: TColor); +var + Bmp: TBitmap; + Stream: TStream; + Data: THandle; + Format: Word; + Palette: HPalette; + Buffer: Pointer; +begin + Bmp := CreateBitmapFromIcon(Icon, BackColor); + try + Stream := TMemoryStream.Create; + try + Icon.SaveToStream(Stream); + Palette := 0; + with Clipboard do + begin + Open; + try + Clear; + Bmp.SaveToClipboardFormat(Format, Data, Palette); + SetClipboardData(Format, Data); + if Palette <> 0 then + SetClipboardData(CF_PALETTE, Palette); + Data := GlobalAlloc(HeapAllocFlags, Stream.Size); + try + if Data <> 0 then + begin + Buffer := GlobalLock(Data); + try + Stream.Seek(0, 0); + Stream.Read(Buffer^, Stream.Size); + SetClipboardData(CF_ICON, Data); + finally + GlobalUnlock(Data); + end; + end; + except + GlobalFree(Data); + raise; + end; + finally + Close; + end; + end; + finally + Stream.Free; + end; + finally + Bmp.Free; + end; +end; + +procedure AssignClipboardIcon(Icon: TIcon); +var + Stream: TStream; + Data: THandle; + Buffer: Pointer; +begin + if not Clipboard.HasFormat(CF_ICON) then + Exit; + with Clipboard do + begin + Open; + try + Data := GetClipboardData(CF_ICON); + Buffer := GlobalLock(Data); + try + Stream := TMemoryStream.Create; + try + Stream.Write(Buffer^, GlobalSize(Data)); + Stream.Seek(0, 0); + Icon.LoadFromStream(Stream); + finally + Stream.Free; + end; + finally + GlobalUnlock(Data); + end; + finally + Close; + end; + end; +end; + +function CreateIconFromClipboard: TIcon; +begin + Result := nil; + if not Clipboard.HasFormat(CF_ICON) then + Exit; + Result := TIcon.Create; + try + AssignClipboardIcon(Result); + except + Result.Free; + raise; + end; +end; +{$ENDIF !CLR} + + + + + +{ Real-size icons support routines } +const + RC3_STOCKICON = 0; + RC3_ICON = 1; + RC3_CURSOR = 2; + +type + PCursorOrIcon = ^TCursorOrIcon; + TCursorOrIcon = packed record + Reserved: Word; + wType: Word; + Count: Word; + end; + + PIconRec = ^TIconRec; + TIconRec = packed record + Width: Byte; + Height: Byte; + Colors: Word; + Reserved1: Word; + Reserved2: Word; + DIBSize: Longint; + DIBOffset: Longint; + end; + +function WidthBytes(I: Longint): Longint; +begin + Result := ((I + 31) div 32) * 4; +end; + +function GetDInColors(BitCount: Word): Integer; +begin + case BitCount of + 1, 4, 8: + Result := 1 shl BitCount; + else + Result := 0; + end; +end; + +{$IFNDEF CLR} +procedure OutOfResources; +begin + raise EOutOfResources.Create(SOutOfResources); +end; + +function DupBits(Src: HBITMAP; Size: TPoint; Mono: Boolean): HBITMAP; +var + DC, Mem1, Mem2: HDC; + Old1, Old2: HBITMAP; + Bitmap: tagBITMAP; +begin + Mem1 := CreateCompatibleDC(NullHandle); + Mem2 := CreateCompatibleDC(NullHandle); + GetObject(Src, SizeOf(Bitmap), @Bitmap); + if Mono then + Result := CreateBitmap(Size.X, Size.Y, 1, 1, nil) + else + begin + DC := GetDC(HWND_DESKTOP); + if DC = NullHandle then + OutOfResources; + try + Result := CreateCompatibleBitmap(DC, Size.X, Size.Y); + if Result = NullHandle then + OutOfResources; + finally + ReleaseDC(HWND_DESKTOP, DC); + end; + end; + if Result <> NullHandle then + begin + Old1 := SelectObject(Mem1, Src); + Old2 := SelectObject(Mem2, Result); + StretchBlt(Mem2, 0, 0, Size.X, Size.Y, Mem1, 0, 0, Bitmap.bmWidth, + Bitmap.bmHeight, SRCCOPY); + if Old1 <> NullHandle then + SelectObject(Mem1, Old1); + if Old2 <> NullHandle then + SelectObject(Mem2, Old2); + end; + DeleteDC(Mem1); + DeleteDC(Mem2); +end; + +{$IFDEF MSWINDOWS} +procedure TwoBitsFromDIB(var BI: TBitmapInfoHeader; var XorBits, AndBits: HBITMAP); +type + PLongArray = ^TLongArray; + TLongArray = array [0..1] of Longint; +var + Temp: HBITMAP; + NumColors: Integer; + DC: HDC; + Bits: Pointer; + Colors: PLongArray; + IconSize: TPoint; + BM: tagBITMAP; +begin + IconSize.X := GetSystemMetrics(SM_CXICON); + IconSize.Y := GetSystemMetrics(SM_CYICON); + with BI do + begin + biHeight := biHeight shr 1; { Size in record is doubled } + biSizeImage := WidthBytes(Longint(biWidth) * biBitCount) * biHeight; + NumColors := GetDInColors(biBitCount); + end; + DC := GetDC(HWND_DESKTOP); + if DC = NullHandle then + OutOfResources; + try + Bits := Pointer(Longint(@BI) + SizeOf(BI) + NumColors * SizeOf(TRGBQuad)); + Temp := CreateDIBitmap(DC, BI, CBM_INIT, Bits, PBitmapInfo(@BI)^, DIB_RGB_COLORS); + if Temp = NullHandle then + OutOfResources; + try + GetObject(Temp, SizeOf(BM), @BM); + IconSize.X := BM.bmWidth; + IconSize.Y := BM.bmHeight; + XorBits := DupBits(Temp, IconSize, False); + finally + DeleteObject(Temp); + end; + with BI do + begin + Inc(Longint(Bits), biSizeImage); + biBitCount := 1; + biSizeImage := WidthBytes(Longint(biWidth) * biBitCount) * biHeight; + biClrUsed := 2; + biClrImportant := 2; + end; + Colors := Pointer(Longint(@BI) + SizeOf(BI)); + Colors^[0] := 0; + Colors^[1] := $FFFFFF; + Temp := CreateDIBitmap(DC, BI, CBM_INIT, Bits, PBitmapInfo(@BI)^, DIB_RGB_COLORS); + if Temp = NullHandle then + OutOfResources; + try + AndBits := DupBits(Temp, IconSize, True); + finally + DeleteObject(Temp); + end; + finally + ReleaseDC(HWND_DESKTOP, DC); + end; +end; + +procedure ReadIcon(Stream: TStream; var Icon: HICON; ImageCount: Integer; + StartOffset: Integer); +type + PIconRecArray = ^TIconRecArray; + TIconRecArray = array [0..300] of TIconRec; +var + List: PIconRecArray; + HeaderLen, Length: Integer; + Colors, BitsPerPixel: Word; + C1, C2, N, Index: Integer; + IconSize: TPoint; + DC: HDC; + BI: PBitmapInfoHeader; + ResData: Pointer; + XorBits, AndBits: HBITMAP; + XorInfo, AndInfo: Windows.TBitmap; + XorMem, AndMem: Pointer; + XorLen, AndLen: Integer; +begin + HeaderLen := SizeOf(TIconRec) * ImageCount; + List := AllocMem(HeaderLen); + try + Stream.Read(List^, HeaderLen); + IconSize.X := GetSystemMetrics(SM_CXICON); + IconSize.Y := GetSystemMetrics(SM_CYICON); + DC := GetDC(HWND_DESKTOP); + if DC = NullHandle then + OutOfResources; + try + BitsPerPixel := GetDeviceCaps(DC, PLANES) * GetDeviceCaps(DC, BITSPIXEL); + if BitsPerPixel = 24 then + Colors := 0 + else + Colors := 1 shl BitsPerPixel; + finally + ReleaseDC(HWND_DESKTOP, DC); + end; + Index := -1; + { the following code determines which image most closely matches the + current device. It is not meant to absolutely match Windows + (known broken) algorithm } + C2 := 0; + for N := 0 to ImageCount - 1 do + begin + C1 := List^[N].Colors; + if C1 = Colors then + begin + Index := N; + Break; + end + else + if Index = -1 then + begin + if C1 <= Colors then + begin + Index := N; + C2 := List^[N].Colors; + end; + end + else + if C1 > C2 then + Index := N; + end; + if Index = -1 then + Index := 0; + with List^[Index] do + begin + BI := AllocMem(DIBSize); + try + Stream.Seek(DIBOffset - (HeaderLen + StartOffset), 1); + Stream.Read(BI^, DIBSize); + TwoBitsFromDIB(BI^, XorBits, AndBits); + GetObject(AndBits, SizeOf(Windows.TBitmap), @AndInfo); + GetObject(XorBits, SizeOf(Windows.TBitmap), @XorInfo); + IconSize.X := AndInfo.bmWidth; + IconSize.Y := AndInfo.bmHeight; + with AndInfo do + AndLen := bmWidthBytes * bmHeight * bmPlanes; + with XorInfo do + XorLen := bmWidthBytes * bmHeight * bmPlanes; + Length := AndLen + XorLen; + ResData := AllocMem(Length); + try + AndMem := ResData; + with AndInfo do + XorMem := Pointer(Longint(ResData) + AndLen); + GetBitmapBits(AndBits, AndLen, AndMem); + GetBitmapBits(XorBits, XorLen, XorMem); + DeleteObject(XorBits); + DeleteObject(AndBits); + Icon := CreateIcon(HInstance, IconSize.X, IconSize.Y, + XorInfo.bmPlanes, XorInfo.bmBitsPixel, AndMem, XorMem); + if Icon = 0 then + OutOfResources; + finally + FreeMem(ResData, Length); + end; + finally + FreeMem(BI, DIBSize); + end; + end; + finally + FreeMem(List, HeaderLen); + end; +end; +{$ENDIF MSWINDOWS} + + + +procedure GetIconSize(Icon: HICON; var W, H: Integer); +var + IconInfo: TIconInfo; + BM: Windows.TBitmap; +begin + if GetIconInfo(Icon, IconInfo) then + begin + try + if IconInfo.hbmColor <> 0 then + begin + GetObject(IconInfo.hbmColor, SizeOf(BM), @BM); + W := BM.bmWidth; + H := BM.bmHeight; + end + else + if IconInfo.hbmMask <> 0 then + begin { Monochrome icon } + GetObject(IconInfo.hbmMask, SizeOf(BM), @BM); + W := BM.bmWidth; + H := BM.bmHeight shr 1; { Size in record is doubled } + end + else + begin + W := GetSystemMetrics(SM_CXICON); + H := GetSystemMetrics(SM_CYICON); + end; + finally + if IconInfo.hbmColor <> 0 then + DeleteObject(IconInfo.hbmColor); + if IconInfo.hbmMask <> 0 then + DeleteObject(IconInfo.hbmMask); + end; + end + else + begin + W := GetSystemMetrics(SM_CXICON); + H := GetSystemMetrics(SM_CYICON); + end; +end; + +function CreateRealSizeIcon(Icon: TIcon): HICON; +var + Mem: TMemoryStream; + CI: TCursorOrIcon; +begin + Result := 0; + Mem := TMemoryStream.Create; + try + Icon.SaveToStream(Mem); + Mem.Position := 0; + Mem.ReadBuffer(CI, SizeOf(CI)); + case CI.wType of + RC3_STOCKICON: + Result := LoadIcon(0, IDI_APPLICATION); + RC3_ICON: + ReadIcon(Mem, Result, CI.Count, SizeOf(CI)); + else + Result := CopyIcon(Icon.Handle); + end; + finally + Mem.Free; + end; +end; + +procedure DrawRealSizeIcon(Canvas: TCanvas; Icon: TIcon; X, Y: Integer); +var + Ico: HICON; + W, H: Integer; +begin + Ico := CreateRealSizeIcon(Icon); + try + GetIconSize(Ico, W, H); + DrawIconEx(Canvas.Handle, X, Y, Ico, W, H, 0, 0, DI_NORMAL); + finally + DestroyIcon(Ico); + end; +end; + +function CreateScreenCompatibleDC: HDC; +const + HDC_DESKTOP = HDC(0); +begin + Result := CreateCompatibleDC(HDC_DESKTOP); +end; + + +{$ENDIF !CLR} + +{ end JvIconClipboardUtils } + +{ begin JvRLE } + +procedure RleCompressTo(InStream, OutStream: TStream); +var + Count, Count2, Count3, I: Integer; + Buf1: array [0..1024] of Byte; + Buf2: array [0..60000] of Byte; + B: Byte; +begin + InStream.Position := 0; + Count := 1024; + while Count = 1024 do + begin + Count := InStream.Read(Buf1, 1024); + Count2 := 0; + I := 0; + while I < Count do + begin + B := Buf1[I]; + Count3 := 0; + while (Buf1[I] = B) and (I < Count) and (Count3 < $30) do + begin + Inc(I); + Inc(Count3); + end; + if (I = Count) and (Count3 in [2..$2F]) and (Count = 1024) then + InStream.Position := InStream.Position - Count3 + else + begin + if Count3 = 1 then + begin + if (B and $C0) = $C0 then + begin + Buf2[Count2] := $C1; + Buf2[Count2 + 1] := B; + Inc(Count2, 2); + end + else + begin + Buf2[Count2] := B; + Inc(Count2); + end; + end + else + begin + Buf2[Count2] := Count3 or $C0; + Buf2[Count2 + 1] := B; + Inc(Count2, 2); + end; + end; + end; + OutStream.Write(Buf2, Count2); + end; +end; + +procedure RleDecompressTo(InStream, OutStream: TStream); +var + Count, Count2, Count3, I: Integer; + Buf1: array [0..1024] of Byte; + Buf2: array [0..60000] of Byte; + B: Byte; +begin + InStream.Position := 0; + Count := 1024; + while Count = 1024 do + begin + Count := InStream.Read(Buf1, 1024); + Count2 := 0; + I := 0; + while I < Count do + begin + if (Buf1[I] and $C0) = $C0 then + begin + if I = Count - 1 then + InStream.Position := InStream.Position - 1 + else + begin + B := Buf1[I] and $3F; + Inc(I); + for Count3 := Count2 to Count2 + B - 1 do + Buf2[Count3] := Buf1[I]; + Count2 := Count2 + B; + end; + end + else + begin + Buf2[Count2] := Buf1[I]; + Inc(Count2); + end; + Inc(I); + end; + OutStream.Write(Buf2, Count2); + end; +end; + +procedure RleCompress(Stream: TStream); +var + Tmp: TMemoryStream; +begin + Tmp := TMemoryStream.Create; + try + RleCompressTo(Stream, Tmp); + Tmp.Position := 0; + Stream.Size := 0; + Stream.CopyFrom(Tmp, 0); + finally + Tmp.Free; + end; +end; + +procedure RleDecompress(Stream: TStream); +var + Tmp: TMemoryStream; +begin + Tmp := TMemoryStream.Create; + try + RleDecompressTo(Stream, Tmp); + Tmp.Position := 0; + Stream.Size := 0; + Stream.CopyFrom(Tmp, 0); + finally + Tmp.Free; + end; +end; +{ end JvRLE } + +{ begin JvDateUtil } + +function IsLeapYear(AYear: Integer): Boolean; +begin + Result := (AYear mod 4 = 0) and ((AYear mod 100 <> 0) or (AYear mod 400 = 0)); +end; + +function DaysInAMonth(const AYear, AMonth: Word): Word; +begin + Result := MonthDays[(AMonth = 2) and IsLeapYear(AYear), AMonth]; +end; + +function DaysPerMonth(AYear, AMonth: Integer): Integer; +begin + Result := DaysInAMonth(AYear, AMonth); +end; + +function FirstDayOfNextMonth: TDateTime; +var + Year, Month, Day: Word; +begin + DecodeDate(Date, Year, Month, Day); + Day := 1; + if Month < 12 then + Inc(Month) + else + begin + Inc(Year); + Month := 1; + end; + Result := EncodeDate(Year, Month, Day); +end; + +function FirstDayOfPrevMonth: TDateTime; +var + Year, Month, Day: Word; +begin + DecodeDate(Date, Year, Month, Day); + Day := 1; + if Month > 1 then + Dec(Month) + else + begin + Dec(Year); + Month := 12; + end; + Result := EncodeDate(Year, Month, Day); +end; + +function LastDayOfPrevMonth: TDateTime; +var + D: TDateTime; + Year, Month, Day: Word; +begin + D := FirstDayOfPrevMonth; + DecodeDate(D, Year, Month, Day); + Day := DaysPerMonth(Year, Month); + Result := EncodeDate(Year, Month, Day); +end; + +function ExtractDay(ADate: TDateTime): Word; +var + M, Y: Word; +begin + DecodeDate(ADate, Y, M, Result); +end; + +function ExtractMonth(ADate: TDateTime): Word; +var + D, Y: Word; +begin + DecodeDate(ADate, Y, Result, D); +end; + +function ExtractYear(ADate: TDateTime): Word; +var + D, M: Word; +begin + DecodeDate(ADate, Result, M, D); +end; + +function IncDate(ADate: TDateTime; Days, Months, Years: Integer): TDateTime; +var + D, M, Y: Word; + Day, Month, Year: Longint; +begin + DecodeDate(ADate, Y, M, D); + Year := Y; + Month := M; + Day := D; + Inc(Year, Years); + Inc(Year, Months div 12); + Inc(Month, Months mod 12); + if Month < 1 then + begin + Inc(Month, 12); + Dec(Year); + end + else + if Month > 12 then + begin + Dec(Month, 12); + Inc(Year); + end; + if Day > DaysPerMonth(Year, Month) then + Day := DaysPerMonth(Year, Month); + Result := EncodeDate(Year, Month, Day) + Days + Frac(ADate); +end; + +procedure DateDiff(Date1, Date2: TDateTime; var Days, Months, Years: Word); +{ Corrected by Anatoly A. Sanko (2:450/73) } +var + DtSwap: TDateTime; + Day1, Day2, Month1, Month2, Year1, Year2: Word; +begin + if Date1 > Date2 then + begin + DtSwap := Date1; + Date1 := Date2; + Date2 := DtSwap; + end; + DecodeDate(Date1, Year1, Month1, Day1); + DecodeDate(Date2, Year2, Month2, Day2); + Years := Year2 - Year1; + Months := 0; + Days := 0; + if Month2 < Month1 then + begin + Inc(Months, 12); + Dec(Years); + end; + Inc(Months, Month2 - Month1); + if Day2 < Day1 then + begin + Inc(Days, DaysPerMonth(Year1, Month1)); + if Months = 0 then + begin + Dec(Years); + Months := 11; + end + else + Dec(Months); + end; + Inc(Days, Day2 - Day1); +end; + +function IncDay(ADate: TDateTime; Delta: Integer): TDateTime; +begin + Result := ADate + Delta; +end; + +function IncMonth(ADate: TDateTime; Delta: Integer): TDateTime; +begin + Result := IncDate(ADate, 0, Delta, 0); +end; + +function IncYear(ADate: TDateTime; Delta: Integer): TDateTime; +begin + Result := IncDate(ADate, 0, 0, Delta); +end; + +function MonthsBetween(Date1, Date2: TDateTime): Double; +var + D, M, Y: Word; +begin + DateDiff(Date1, Date2, D, M, Y); + Result := 12 * Y + M; + if (D > 1) and (D < 7) then + Result := Result + 0.25 + else + if (D >= 7) and (D < 15) then + Result := Result + 0.5 + else + if (D >= 15) and (D < 21) then + Result := Result + 0.75 + else + if D >= 21 then + Result := Result + 1; +end; + +function IsValidDate(Y, M, D: Word): Boolean; +begin + Result := (Y >= 1) and (Y <= 9999) and (M >= 1) and (M <= 12) and + (D >= 1) and (D <= DaysPerMonth(Y, M)); +end; + +function ValidDate(ADate: TDateTime): Boolean; +var + Year, Month, Day: Word; +begin + try + DecodeDate(ADate, Year, Month, Day); + Result := IsValidDate(Year, Month, Day); + except + Result := False; + end; +end; + +function DaysInPeriod(Date1, Date2: TDateTime): Longint; +begin + if ValidDate(Date1) and ValidDate(Date2) then + Result := Abs(Trunc(Date2) - Trunc(Date1)) + 1 + else + Result := 0; +end; + +{ // (ahuser) wrong implementation +function DaysBetween(Date1, Date2: TDateTime): Longint; +begin + Result := Trunc(Date2) - Trunc(Date1) + 1; + if Result < 0 then + Result := 0; +end;} + +function DaysBetween(Date1, Date2: TDateTime): Longint; +begin + if Date1 < Date2 then + Result := Trunc(Date2 - Date1) + else + Result := Trunc(Date1 - Date2); +end; + +function IncTime(ATime: TDateTime; Hours, Minutes, Seconds, + MSecs: Integer): TDateTime; +begin + Result := ATime + (Hours div 24) + (((Hours mod 24) * 3600000 + + Minutes * 60000 + Seconds * 1000 + MSecs) / MSecsPerDay); + if Result < 0 then + Result := Result + 1; +end; + +function IncHour(ATime: TDateTime; Delta: Integer): TDateTime; +begin + Result := IncTime(ATime, Delta, 0, 0, 0); +end; + +function IncMinute(ATime: TDateTime; Delta: Integer): TDateTime; +begin + Result := IncTime(ATime, 0, Delta, 0, 0); +end; + +function IncSecond(ATime: TDateTime; Delta: Integer): TDateTime; +begin + Result := IncTime(ATime, 0, 0, Delta, 0); +end; + +function IncMSec(ATime: TDateTime; Delta: Integer): TDateTime; +begin + Result := IncTime(ATime, 0, 0, 0, Delta); +end; + +function CutTime(ADate: TDateTime): TDateTime; +begin + Result := Trunc(ADate); +end; + +function CurrentYear: Word; +begin + Result := ExtractYear(Date); +end; + +{ String to date conversions. Copied from SYSUTILS.PAS unit. } + +procedure ScanBlanks(const S: string; var Pos: Integer); +var + I: Integer; +begin + I := Pos; + while (I <= Length(S)) and (S[I] = ' ') do + Inc(I); + Pos := I; +end; + +function ScanNumber(const S: string; MaxLength: Integer; var Pos: Integer; + var Number: Longint): Boolean; +var + I: Integer; + N: Word; +begin + Result := False; + ScanBlanks(S, Pos); + I := Pos; + N := 0; + while (I <= Length(S)) and (Longint(I - Pos) < MaxLength) and + (S[I] in ['0'..'9']) and (N < 1000) do + begin + N := N * 10 + (Ord(S[I]) - Ord('0')); + Inc(I); + end; + if I > Pos then + begin + Pos := I; + Number := N; + Result := True; + end; +end; + +function ScanChar(const S: string; var Pos: Integer; Ch: Char): Boolean; +begin + Result := False; + ScanBlanks(S, Pos); + if (Pos <= Length(S)) and (S[Pos] = Ch) then + begin + Inc(Pos); + Result := True; + end; +end; + +procedure ScanToNumber(const S: string; var Pos: Integer); +begin + while (Pos <= Length(S)) and not (S[Pos] in ['0'..'9']) do + begin + if S[Pos] in LeadBytes then + Inc(Pos); + Inc(Pos); + end; +end; + +function GetDateOrder(const DateFormat: string): TDateOrder; +var + I: Integer; +begin + Result := DefaultDateOrder; + I := 1; + while I <= Length(DateFormat) do + begin + case Chr(Ord(DateFormat[I]) and $DF) of + 'E': + Result := doYMD; + 'Y': + Result := doYMD; + 'M': + Result := doMDY; + 'D': + Result := doDMY; + else + Inc(I); + Continue; + end; + Exit; + end; + Result := DefaultDateOrder; { default } +end; + +function CurrentMonth: Word; +begin + Result := ExtractMonth(Date); +end; + +{Modified} + +function ExpandYear(Year: Integer): Integer; +var + N: Longint; +begin + if Year = -1 then + Result := CurrentYear + else + begin + Result := Year; + if Result < 100 then + begin + N := CurrentYear - CenturyOffset; + Inc(Result, N div 100 * 100); + if (CenturyOffset > 0) and (Result < N) then + Inc(Result, 100); + end; + end; +end; + +function ScanDate(const S, DateFormat: string; var Position: Integer; + var Y, M, D: Integer): Boolean; +var + DateOrder: TDateOrder; + N1, N2, N3: Longint; +begin + Result := False; + Y := 0; + M := 0; + D := 0; + DateOrder := GetDateOrder(DateFormat); + if ShortDateFormat[1] = 'g' then { skip over prefix text } + ScanToNumber(S, Position); + if not (ScanNumber(S, MaxInt, Position, N1) and ScanChar(S, Position, DateSeparator{$IFDEF CLR}[1]{$ENDIF}) and + ScanNumber(S, MaxInt, Position, N2)) then + Exit; + if ScanChar(S, Position, DateSeparator{$IFDEF CLR}[1]{$ENDIF}) then + begin + if not ScanNumber(S, MaxInt, Position, N3) then + Exit; + case DateOrder of + doMDY: + begin + Y := N3; + M := N1; + D := N2; + end; + doDMY: + begin + Y := N3; + M := N2; + D := N1; + end; + doYMD: + begin + Y := N1; + M := N2; + D := N3; + end; + end; + Y := ExpandYear(Y); + end + else + begin + Y := CurrentYear; + if DateOrder = doDMY then + begin + D := N1; + M := N2; + end + else + begin + M := N1; + D := N2; + end; + end; + ScanChar(S, Position, DateSeparator{$IFDEF CLR}[1]{$ENDIF}); + ScanBlanks(S, Position); + if SysLocale.FarEast and (Pos('ddd', ShortDateFormat) <> 0) then + begin { ignore trailing text } + if ShortTimeFormat[1] in ['0'..'9'] then { stop at time digit } + ScanToNumber(S, Position) + else { stop at time prefix } + repeat + while (Position <= Length(S)) and (S[Position] <> ' ') do + Inc(Position); + ScanBlanks(S, Position); + until (Position > Length(S)) or + {$IFDEF CLR} + SameText(TimeAMString, Copy(S, Position, Length(TimeAMString))) or + SameText(TimePMString, Copy(S, Position, Length(TimePMString))); + {$ELSE} + AnsiSameText(TimeAMString, Copy(S, Position, Length(TimeAMString))) or + AnsiSameText(TimePMString, Copy(S, Position, Length(TimePMString))); + {$ENDIF CLR} + end; + Result := IsValidDate(Y, M, D) and (Position > Length(S)); +end; + +function MonthFromName(const S: string; MaxLen: Byte): Byte; +begin + if Length(S) > 0 then + for Result := 1 to 12 do + begin + if (Length(LongMonthNames[Result]) > 0) and + {$IFDEF CLR} + SameText(Copy(S, 1, MaxLen), Copy(LongMonthNames[Result], 1, MaxLen)) then + {$ELSE} + AnsiSameText(Copy(S, 1, MaxLen), Copy(LongMonthNames[Result], 1, MaxLen)) then + {$ENDIF CLR} + Exit; + end; + Result := 0; +end; + +procedure ExtractMask(const Format, S: string; Ch: Char; Cnt: Integer; + var I: Integer; Blank, Default: Integer); +var + Tmp: string[20]; + J, L: Integer; +begin + I := Default; + Ch := UpCase(Ch); + L := Length(Format); + if Length(S) < L then + L := Length(S) + else + if Length(S) > L then + Exit; + {$IFDEF CLR} + J := Pos(MakeStr(Ch, Cnt), Format.ToUpper()); + {$ELSE} + J := Pos(MakeStr(Ch, Cnt), AnsiUpperCase(Format)); + {$ENDIF CLR} + if J <= 0 then + Exit; + Tmp := ''; + while (UpCase(Format[J]) = Ch) and (J <= L) do + begin + if S[J] <> ' ' then + Tmp := Tmp + S[J]; + Inc(J); + end; + if Tmp = '' then + I := Blank + else + if Cnt > 1 then + begin + I := MonthFromName(Tmp, Length(Tmp)); + if I = 0 then + I := -1; + end + else + I := StrToIntDef(Tmp, -1); +end; + +function ScanDateStr(const Format, S: string; var D, M, Y: Integer): Boolean; +var + Pos: Integer; +begin + ExtractMask(Format, S, 'm', 3, M, -1, 0); { short month name? } + if M = 0 then + ExtractMask(Format, S, 'm', 1, M, -1, 0); + ExtractMask(Format, S, 'd', 1, D, -1, 1); + ExtractMask(Format, S, 'y', 1, Y, -1, CurrentYear); + if M = -1 then + M := CurrentMonth; + Y := ExpandYear(Y); + Result := IsValidDate(Y, M, D); + if not Result then + begin + Pos := 1; + Result := ScanDate(S, Format, Pos, Y, M, D); + end; +end; + +function InternalStrToDate(const DateFormat, S: string; + var Date: TDateTime): Boolean; +var + D, M, Y: Integer; +begin + if S = '' then + begin + Date := NullDate; + Result := True; + end + else + begin + Result := ScanDateStr(DateFormat, S, D, M, Y); + if Result then + try + Date := EncodeDate(Y, M, D); + except + Result := False; + end; + end; +end; + +function StrToDateFmt(const DateFormat, S: string): TDateTime; +begin + if not InternalStrToDate(DateFormat, S, Result) then + {$IFDEF CLR} + raise EConvertError.CreateFmt(SInvalidDate, [S]); + {$ELSE} + raise EConvertError.CreateResFmt(@SInvalidDate, [S]); + {$ENDIF CLR} +end; + +function StrToDateDef(const S: string; Default: TDateTime): TDateTime; +begin + if not InternalStrToDate(ShortDateFormat, S, Result) then + Result := Trunc(Default); +end; + +function StrToDateFmtDef(const DateFormat, S: string; Default: TDateTime): TDateTime; +begin + if not InternalStrToDate(DateFormat, S, Result) then + Result := Trunc(Default); +end; + +function DefDateFormat(AFourDigitYear: Boolean): string; +begin + if AFourDigitYear then + begin + case GetDateOrder(ShortDateFormat) of + doMDY: + Result := 'MM/DD/YYYY'; + doDMY: + Result := 'DD/MM/YYYY'; + doYMD: + Result := 'YYYY/MM/DD'; + end; + end + else + begin + case GetDateOrder(ShortDateFormat) of + doMDY: + Result := 'MM/DD/YY'; + doDMY: + Result := 'DD/MM/YY'; + doYMD: + Result := 'YY/MM/DD'; + end; + end; +end; + +function DefDateMask(BlanksChar: Char; AFourDigitYear: Boolean): string; +begin + if AFourDigitYear then + begin + case GetDateOrder(ShortDateFormat) of + doMDY, doDMY: + Result := '!99/99/9999;1;'; + doYMD: + Result := '!9999/99/99;1;'; + end; + end + else + begin + case GetDateOrder(ShortDateFormat) of + doMDY, doDMY: + Result := '!99/99/99;1;'; + doYMD: + Result := '!99/99/99;1;'; + end; + end; + if Result <> '' then + Result := Result + BlanksChar; +end; + +function FormatLongDate(Value: TDateTime): string; +{$IFDEF CLR} +begin + Result := TrimRight(FormatDateTime(LongDateFormat, Value)); +end; +{$ELSE} +{$IFDEF MSWINDOWS} +var + Buffer: array [0..1023] of Char; + SystemTime: TSystemTime; +begin + DateTimeToSystemTime(Value, SystemTime); + SetString(Result, Buffer, GetDateFormat(GetThreadLocale, DATE_LONGDATE, + @SystemTime, nil, Buffer, SizeOf(Buffer) - 1)); + Result := TrimRight(Result); +end; +{$ENDIF MSWINDOWS} +{$IFDEF UNIX} +begin + Result := TrimRight(FormatDateTime(LongDateFormat, Value)); +end; +{$ENDIF UNIX} +{$ENDIF CLR} + +function FormatLongDateTime(Value: TDateTime): string; +begin + if Value <> NullDate then + Result := FormatLongDate(Value) + FormatDateTime(' tt', Value) + else + Result := ''; +end; + +function FourDigitYear: Boolean; // deprecated +begin + Result := IsFourDigitYear; +end; + +function IsFourDigitYear: Boolean; +begin + {$IFDEF CLR} + Result := Pos('YYYY', ShortDateFormat.ToUpper()) > 0; + {$ELSE} + Result := Pos('YYYY', AnsiUpperCase(ShortDateFormat)) > 0; + {$ENDIF CLR} +end; +{ end JvDateUtil } + +{$IFDEF CLR} + +function BufToBinStr(const Buf: TBytes; BufSize: Integer): string; +var + I: Integer; + P: TBytes; +begin + P := Buf; + for I := 0 to Pred(BufSize) do + Result := Result + IntToHex(P[I] , 2); +end; + +function BinStrToBuf(Value: string; Buf: TBytes; BufSize: Integer): Integer; +var + I: Integer; + P: TBytes; +begin + if Odd(Length(Value)) then + Value := '0' + Value; // should not occur, might indicate corrupted Value + if (Length(Value) div 2) < BufSize then + BufSize := Length(Value) div 2; + P := Buf; + for I := 0 to Pred(BufSize) do + P[I] := StrToInt('$' + Value[2 * I + 1] + Value[2 * I + 2]); + Result := BufSize; +end; + +{$ELSE} + +function BufToBinStr(Buf: Pointer; BufSize: Integer): string; +var + I: Integer; + P: PByteArray; +begin + P := Buf; + for I := 0 to Pred(BufSize) do + Result := Result + IntToHex(P[I] , 2); +end; + +function BinStrToBuf(Value: string; Buf: Pointer; BufSize: Integer): Integer; +var + I: Integer; + P: PByteArray; +begin + if Odd(Length(Value)) then + Value := '0' + Value; // should not occur, might indicate corrupted Value + if (Length(Value) div 2) < BufSize then + BufSize := Length(Value) div 2; + P := Buf; + for I := 0 to Pred(BufSize) do + P[I] := StrToInt('$' + Value[2 * I + 1] + Value[2 * I + 2]); + Result := BufSize; +end; + +{$ENDIF CLR} + +{ begin JvStrUtils } +{$IFDEF UNIX} + +function iconversion(InP: PChar; OutP: Pointer; InBytes, OutBytes: Cardinal; + const ToCode, FromCode: string): Boolean; +var + conv: iconv_t; +begin + Result := False; + if (InBytes > 0) and (OutBytes > 0) and (InP <> nil) and (OutP <> nil) then + begin + conv := iconv_open(PChar(ToCode), PChar(FromCode)); + if Integer(conv) <> -1 then + begin + if Integer(iconv(conv, InP, InBytes, OutP, OutBytes)) <> -1 then + Result := True; + iconv_close(conv); + end; + end; +end; + +function iconvString(const S, ToCode, FromCode: string): string; +begin + SetLength(Result, Length(S)); + if not iconversion(PChar(S), Pointer(Result), + Length(S), Length(Result), + ToCode, FromCode) then + Result := S; +end; + +function iconvWideString(const S: WideString; const ToCode, FromCode: string): WideString; +begin + SetLength(Result, Length(S)); + if not iconversion(Pointer(S), Pointer(Result), + Length(S) * SizeOf(WideChar), Length(Result) * SizeOf(WideChar), + ToCode, FromCode) then + Result := S; +end; + +function OemStrToAnsi(const S: string): string; +begin + Result := iconvString(S, 'WINDOWS-1252', 'CP850'); +end; + +function AnsiStrToOem(const S: string): string; +begin + Result := iconvString(S, 'CP850', 'WINDOWS-1250'); +end; + +{$ENDIF UNIX} + +function StrToOem(const AnsiStr: string): string; +{$IFDEF CLR} +var + sb: StringBuilder; +begin + if AnsiStr <> '' then + begin + sb := StringBuilder.Create(AnsiStr.Length); + CharToOemBuff(AnsiStr, sb, sb.Capacity); + Result := sb.ToString(); + end + else + Result := ''; +end; +{$ELSE} +begin + {$IFDEF MSWINDOWS} + SetLength(Result, Length(AnsiStr)); + if Result <> '' then + CharToOemBuff(PChar(AnsiStr), PChar(Result), Length(Result)); + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + Result := AnsiStrToOem(AnsiStr); + {$ENDIF UNIX} +end; +{$ENDIF CLR} + +function OemToAnsiStr(const OemStr: string): string; +{$IFDEF CLR} +var + sb: StringBuilder; +begin + if OemStr <> '' then + begin + sb := StringBuilder.Create(OemStr.Length); + OemToCharBuff(OemStr, sb, sb.Capacity); + Result := sb.ToString(); + end + else + Result := ''; +end; +{$ELSE} +begin + {$IFDEF MSWINDOWS} + SetLength(Result, Length(OemStr)); + if Length(Result) > 0 then + OemToCharBuff(PChar(OemStr), PChar(Result), Length(Result)); + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + Result := OemStrToAnsi(OemStr); + {$ENDIF UNIX} +end; +{$ENDIF CLR} + +function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean; +var + I, SLen: Integer; +begin + SLen := Length(S); + I := 1; + while I <= SLen do + begin + if not (S[I] in EmptyChars) then + begin + Result := False; + Exit; + end + else + Inc(I); + end; + Result := True; +end; + +function ReplaceStr(const S, Srch, Replace: string): string; +var + I: Integer; + Source: string; +begin + Source := S; + Result := ''; + repeat + I := Pos(Srch, Source); + if I > 0 then + begin + Result := Result + Copy(Source, 1, I - 1) + Replace; + Source := Copy(Source, I + Length(Srch), MaxInt); + end + else + Result := Result + Source; + until I <= 0; +end; + +function DelSpace(const S: string): string; +begin + Result := DelChars(S, ' '); +end; + +function DelChars(const S: string; Chr: Char): string; +var + I: Integer; +begin + Result := S; + for I := Length(Result) downto 1 do + begin + if Result[I] = Chr then + Delete(Result, I, 1); + end; +end; + +function DelBSpace(const S: string): string; +var + I, L: Integer; +begin + L := Length(S); + I := 1; + while (I <= L) and (S[I] = ' ') do + Inc(I); + Result := Copy(S, I, MaxInt); +end; + +function DelESpace(const S: string): string; +var + I: Integer; +begin + I := Length(S); + while (I > 0) and (S[I] = ' ') do + Dec(I); + Result := Copy(S, 1, I); +end; + +function DelRSpace(const S: string): string; +begin + Result := DelBSpace(DelESpace(S)); +end; + +function DelSpace1(const S: string): string; +var + I: Integer; +begin + Result := S; + for I := Length(Result) downto 2 do + begin + if (Result[I] = ' ') and (Result[I - 1] = ' ') then + Delete(Result, I, 1); + end; +end; + +function Tab2Space(const S: string; Numb: Byte): string; +var + I: Integer; +begin + I := 1; + Result := S; + while I <= Length(Result) do + begin + if Result[I] = Chr(9) then + begin + Delete(Result, I, 1); + Insert(MakeStr(' ', Numb), Result, I); + Inc(I, Numb); + end + else + Inc(I); + end; +end; + +function MakeStr(C: Char; N: Integer): string; overload; +begin + if N < 1 then + Result := '' + else + begin + SetLength(Result, N); + FillString(Result, Length(Result), C); + end; +end; + +{$IFNDEF CLR} +function MakeStr(C: WideChar; N: Integer): WideString; overload; +begin + if N < 1 then + Result := '' + else + begin + SetLength(Result, N); + FillWideChar(Result[1], Length(Result), C); + end; +end; +{$ENDIF !CLR} + +function MS(C: Char; N: Integer): string; +begin + Result := MakeStr(C, N); +end; + +function NPos(const C: string; S: string; N: Integer): Integer; +var + I, P, K: Integer; +begin + Result := 0; + K := 0; + for I := 1 to N do + begin + P := Pos(C, S); + Inc(K, P); + if (I = N) and (P > 0) then + begin + Result := K; + Exit; + end; + if P > 0 then + Delete(S, 1, P) + else + Exit; + end; +end; + +function AddChar(C: Char; const S: string; N: Integer): string; +begin + if Length(S) < N then + Result := MakeStr(C, N - Length(S)) + S + else + Result := S; +end; + +function AddCharR(C: Char; const S: string; N: Integer): string; +begin + if Length(S) < N then + Result := S + MakeStr(C, N - Length(S)) + else + Result := S; +end; + +function LeftStr(const S: string; N: Integer): string; +begin + Result := AddCharR(' ', S, N); +end; + +function RightStr(const S: string; N: Integer): string; +begin + Result := AddChar(' ', S, N); +end; + +{$IFDEF MSWINDOWS} + +function CompStr(const S1, S2: string): Integer; +begin + {$IFDEF CLR} + Result := System.String.Compare(S1, S2, False); + {$ELSE} + Result := CompareString(GetThreadLocale, SORT_STRINGSORT, PChar(S1), + Length(S1), PChar(S2), Length(S2)) - 2; + {$ENDIF CLR} +end; + +function CompText(const S1, S2: string): Integer; +begin + {$IFDEF CLR} + Result := System.String.Compare(S1, S2, True); + {$ELSE} + Result := CompareString(GetThreadLocale, SORT_STRINGSORT or NORM_IGNORECASE, + PChar(S1), Length(S1), PChar(S2), Length(S2)) - 2; + {$ENDIF CLR} +end; + +{$ENDIF MSWINDOWS} + +{$IFDEF UNIX} + +function CompStr(const S1, S2: string): Integer; +begin + Result := AnsiCompareStr(S1, S2); +end; + +function CompText(const S1, S2: string): Integer; +begin + Result := AnsiCompareText(S1, S2); +end; + +{$ENDIF UNIX} + +function Copy2Symb(const S: string; Symb: Char): string; +var + P: Integer; +begin + P := Pos(Symb, S); + if P = 0 then + P := Length(S) + 1; + Result := Copy(S, 1, P - 1); +end; + +function Copy2SymbDel(var S: string; Symb: Char): string; +begin + Result := Copy2Symb(S, Symb); + S := DelBSpace(Copy(S, Length(Result) + 1, Length(S))); +end; + +function Copy2Space(const S: string): string; +begin + Result := Copy2Symb(S, ' '); +end; + +function Copy2SpaceDel(var S: string): string; +begin + Result := Copy2SymbDel(S, ' '); +end; + +function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string; +var + SLen, I: Cardinal; +begin + {$IFDEF CLR} + Result := LowerCase(S); + {$ELSE} + Result := AnsiLowerCase(S); + {$ENDIF CLR} + I := 1; + SLen := Length(Result); + while I <= SLen do + begin + while (I <= SLen) and (Result[I] in WordDelims) do + Inc(I); + if I <= SLen then + {$IFDEF CLR} + Result[I] := UpperCase(Result[I])[1]; + {$ELSE} + Result[I] := AnsiUpperCase(Result[I])[1]; + {$ENDIF CLR} + while (I <= SLen) and not (Result[I] in WordDelims) do + Inc(I); + end; +end; + +function WordCount(const S: string; const WordDelims: TSysCharSet): Integer; +var + SLen, I: Cardinal; +begin + Result := 0; + I := 1; + SLen := Length(S); + while I <= SLen do + begin + while (I <= SLen) and (S[I] in WordDelims) do + Inc(I); + if I <= SLen then + Inc(Result); + while (I <= SLen) and not (S[I] in WordDelims) do + Inc(I); + end; +end; + +function WordPosition(const N: Integer; const S: string; + const WordDelims: TSysCharSet): Integer; +var + Count, I: Integer; +begin + Count := 0; + I := 1; + Result := 0; + while (I <= Length(S)) and (Count <> N) do + begin + { skip over delimiters } + while (I <= Length(S)) and (S[I] in WordDelims) do + Inc(I); + { if we're not beyond end of S, we're at the start of a word } + if I <= Length(S) then + Inc(Count); + { if not finished, find the end of the current word } + if Count <> N then + while (I <= Length(S)) and not (S[I] in WordDelims) do + Inc(I) + else + Result := I; + end; +end; + +function ExtractWord(N: Integer; const S: string; + const WordDelims: TSysCharSet): string; +var + I: Integer; + Len: Integer; +begin + Len := 0; + I := WordPosition(N, S, WordDelims); + if I <> 0 then + { find the end of the current word } + while (I <= Length(S)) and not (S[I] in WordDelims) do + begin + { add the I'th character to result } + Inc(Len); + SetLength(Result, Len); + Result[Len] := S[I]; + Inc(I); + end; + SetLength(Result, Len); +end; + +function ExtractWordPos(N: Integer; const S: string; + const WordDelims: TSysCharSet; var Pos: Integer): string; +var + I, Len: Integer; +begin + Len := 0; + I := WordPosition(N, S, WordDelims); + Pos := I; + if I <> 0 then + { find the end of the current word } + while (I <= Length(S)) and not (S[I] in WordDelims) do + begin + { add the I'th character to result } + Inc(Len); + SetLength(Result, Len); + Result[Len] := S[I]; + Inc(I); + end; + SetLength(Result, Len); +end; + +function ExtractDelimited(N: Integer; const S: string; + const Delims: TSysCharSet): string; +var + CurWord: Integer; + I, Len, SLen: Integer; +begin + CurWord := 0; + I := 1; + Len := 0; + SLen := Length(S); + SetLength(Result, 0); + while (I <= SLen) and (CurWord <> N) do + begin + if S[I] in Delims then + Inc(CurWord) + else + begin + if CurWord = N - 1 then + begin + Inc(Len); + SetLength(Result, Len); + Result[Len] := S[I]; + end; + end; + Inc(I); + end; +end; + +function ExtractSubstr(const S: string; var Pos: Integer; + const Delims: TSysCharSet): string; +var + I: Integer; +begin + I := Pos; + while (I <= Length(S)) and not (S[I] in Delims) do + Inc(I); + Result := Copy(S, Pos, I - Pos); + if (I <= Length(S)) and (S[I] in Delims) then + Inc(I); + Pos := I; +end; + +function IsWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean; +var + Count, I: Integer; +begin + Result := False; + Count := WordCount(S, WordDelims); + for I := 1 to Count do + if ExtractWord(I, S, WordDelims) = W then + begin + Result := True; + Exit; + end; +end; + +function QuotedString(const S: string; Quote: Char): string; +begin + {$IFDEF CLR} + Result := QuotedStr(S, Quote); + {$ELSE} + Result := AnsiQuotedStr(S, Quote); + {$ENDIF CLR} +end; + +function ExtractQuotedString(const S: string; Quote: Char): string; +begin + Result := DequotedStr(S, Quote); +end; + +function Numb2USA(const S: string): string; +var + I, NA: Integer; +begin + I := Length(S); + Result := S; + NA := 0; + while (I > 0) do + begin + if ((Length(Result) - I + 1 - NA) mod 3 = 0) and (I <> 1) then + begin + Insert(',', Result, I); + Inc(NA); + end; + Dec(I); + end; +end; + +function CenterStr(const S: string; Len: Integer): string; +begin + if Length(S) < Len then + begin + Result := MakeStr(' ', (Len div 2) - (Length(S) div 2)) + S; + Result := Result + MakeStr(' ', Len - Length(Result)); + end + else + Result := S; +end; + +function Dec2Hex(N: Longint; A: Byte): string; +begin + Result := IntToHex(N, A); +end; + +function Hex2Dec(const S: string): Longint; +var + HexStr: string; +begin + if Pos('$', S) = 0 then + HexStr := '$' + S + else + HexStr := S; + Result := StrToIntDef(HexStr, 0); +end; + +function Dec2Numb(N: Int64; A, B: Byte): string; +var + C: Integer; + Number: Cardinal; +begin + if N = 0 then + Result := '0' + else + begin + Number := Cardinal(N); + Result := ''; + while Number > 0 do + begin + C := Number mod B; + if C > 9 then + C := C + 55 + else + C := C + 48; + Result := Chr(C) + Result; + Number := Number div B; + end; + end; + if Result <> '' then + Result := AddChar('0', Result, A); +end; + +function Numb2Dec(S: string; B: Byte): Int64; +var + I, P: Int64; +begin + I := Length(S); + Result := 0; + S := UpperCase(S); + P := 1; + while (I >= 1) do + begin + if S[I] > '@' then + Result := Result + (Ord(S[I]) - 55) * P + else + Result := Result + (Ord(S[I]) - 48) * P; + Dec(I); + P := P * B; + end; +end; + +function RomanToInt(const S: string): Longint; +const + RomanChars = ['C', 'D', 'I', 'L', 'M', 'V', 'X']; + RomanValues: array ['C'..'X'] of Word = + (100, 500, 0, 0, 0, 0, 1, 0, 0, 50, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 10); +var + Index, Next: Char; + I: Integer; + Negative: Boolean; +begin + Result := 0; + I := 0; + Negative := (Length(S) > 0) and (S[1] = '-'); + if Negative then + Inc(I); + while (I < Length(S)) do + begin + Inc(I); + Index := UpCase(S[I]); + if Index in RomanChars then + begin + if Succ(I) <= Length(S) then + Next := UpCase(S[I + 1]) + else + Next := #0; + if (Next in RomanChars) and (RomanValues[Index] < RomanValues[Next]) then + begin + Inc(Result, RomanValues[Next]); + Dec(Result, RomanValues[Index]); + Inc(I); + end + else + Inc(Result, RomanValues[Index]); + end + else + begin + Result := 0; + Exit; + end; + end; + if Negative then + Result := -Result; +end; + +function IntToRoman(Value: Longint): string; +label + A500, A400, A100, A90, A50, A40, A10, A9, A5, A4, A1; +begin + Result := ''; + while Value >= 1000 do + begin + Dec(Value, 1000); + Result := Result + 'M'; + end; + if Value < 900 then + goto A500 + else + begin + Dec(Value, 900); + Result := Result + 'CM'; + end; + goto A90; + A400: + if Value < 400 then + goto A100 + else + begin + Dec(Value, 400); + Result := Result + 'CD'; + end; + goto A90; + A500: + if Value < 500 then + goto A400 + else + begin + Dec(Value, 500); + Result := Result + 'D'; + end; + A100: + while Value >= 100 do + begin + Dec(Value, 100); + Result := Result + 'C'; + end; + A90: + if Value < 90 then + goto A50 + else + begin + Dec(Value, 90); + Result := Result + 'XC'; + end; + goto A9; + A40: + if Value < 40 then + goto A10 + else + begin + Dec(Value, 40); + Result := Result + 'XL'; + end; + goto A9; + A50: + if Value < 50 then + goto A40 + else + begin + Dec(Value, 50); + Result := Result + 'L'; + end; + A10: + while Value >= 10 do + begin + Dec(Value, 10); + Result := Result + 'X'; + end; + A9: + if Value < 9 then + goto A5 + else + Result := Result + 'IX'; + Exit; + A4: + if Value < 4 then + goto A1 + else + Result := Result + 'IV'; + Exit; + A5: + if Value < 5 then + goto A4 + else + begin + Dec(Value, 5); + Result := Result + 'V'; + end; + goto A1; + A1: + while Value >= 1 do + begin + Dec(Value); + Result := Result + 'I'; + end; +end; + +function IntToBin(Value: Longint; Digits, Spaces: Integer): string; +begin + Result := ''; + if Digits > 32 then + Digits := 32; + while Digits > 0 do + begin + if (Digits mod Spaces) = 0 then + Result := Result + ' '; + Dec(Digits); + Result := Result + IntToStr((Value shr Digits) and 1); + end; +end; + +function FindPart(const HelpWilds, InputStr: string): Integer; +var + I, J: Integer; + Diff: Integer; +begin + I := Pos('?', HelpWilds); + if I = 0 then + begin + { if no '?' in HelpWilds } + Result := Pos(HelpWilds, InputStr); + Exit; + end; + { '?' in HelpWilds } + Diff := Length(InputStr) - Length(HelpWilds); + if Diff < 0 then + begin + Result := 0; + Exit; + end; + { now move HelpWilds over InputStr } + for I := 0 to Diff do + begin + for J := 1 to Length(HelpWilds) do + begin + if (InputStr[I + J] = HelpWilds[J]) or (HelpWilds[J] = '?') then + begin + if J = Length(HelpWilds) then + begin + Result := I + 1; + Exit; + end; + end + else + Break; + end; + end; + Result := 0; +end; + +function IsWild(InputStr, Wilds: string; IgnoreCase: Boolean): Boolean; + + function SearchNext(var Wilds: string): Integer; + { looking for next *, returns position and string until position } + begin + Result := Pos('*', Wilds); + if Result > 0 then + Wilds := Copy(Wilds, 1, Result - 1); + end; + +var + CWild, CInputWord: Integer; { counter for positions } + I, LenHelpWilds: Integer; + MaxInputWord, MaxWilds: Integer; { Length of InputStr and Wilds } + HelpWilds: string; +begin + if Wilds = InputStr then + begin + Result := True; + Exit; + end; + repeat { delete '**', because '**' = '*' } + I := Pos('**', Wilds); + if I > 0 then + Wilds := Copy(Wilds, 1, I - 1) + '*' + Copy(Wilds, I + 2, MaxInt); + until I = 0; + if Wilds = '*' then + begin { for fast end, if Wilds only '*' } + Result := True; + Exit; + end; + MaxInputWord := Length(InputStr); + MaxWilds := Length(Wilds); + if IgnoreCase then + begin { upcase all letters } + {$IFDEF CLR} + InputStr := InputStr.ToUpper(); + Wilds := Wilds.ToUpper(); + {$ELSE} + InputStr := AnsiUpperCase(InputStr); + Wilds := AnsiUpperCase(Wilds); + {$ENDIF CLR} + end; + if (MaxWilds = 0) or (MaxInputWord = 0) then + begin + Result := False; + Exit; + end; + CInputWord := 1; + CWild := 1; + Result := True; + repeat + if InputStr[CInputWord] = Wilds[CWild] then + begin { equal letters } + { goto next letter } + Inc(CWild); + Inc(CInputWord); + Continue; + end; + if Wilds[CWild] = '?' then + begin { equal to '?' } + { goto next letter } + Inc(CWild); + Inc(CInputWord); + Continue; + end; + if Wilds[CWild] = '*' then + begin { handling of '*' } + HelpWilds := Copy(Wilds, CWild + 1, MaxWilds); + I := SearchNext(HelpWilds); + LenHelpWilds := Length(HelpWilds); + if I = 0 then + begin + { no '*' in the rest, compare the ends } + if HelpWilds = '' then + Exit; { '*' is the last letter } + { check the rest for equal Length and no '?' } + for I := 0 to LenHelpWilds - 1 do + begin + if (HelpWilds[LenHelpWilds - I] <> InputStr[MaxInputWord - I]) and + (HelpWilds[LenHelpWilds - I] <> '?') then + begin + Result := False; + Exit; + end; + end; + Exit; + end; + { handle all to the next '*' } + Inc(CWild, 1 + LenHelpWilds); + I := FindPart(HelpWilds, Copy(InputStr, CInputWord, MaxInt)); + if I = 0 then + begin + Result := False; + Exit; + end; + CInputWord := I + LenHelpWilds; + Continue; + end; + Result := False; + Exit; + until (CInputWord > MaxInputWord) or (CWild > MaxWilds); + { no completed evaluation } + if CInputWord <= MaxInputWord then + Result := False; + if (CWild <= MaxWilds) and (Wilds[MaxWilds] <> '*') then + Result := False; +end; + +function XorString(const Key, Src: ShortString): ShortString; +var + I: Integer; +begin + Result := Src; + if Length(Key) > 0 then + for I := 1 to Length(Src) do + Result[I] := AnsiChar(Chr(Byte(Key[1 + ((I - 1) mod Length(Key))]) xor Ord(Src[I]))); +end; + +function XorEncode(const Key, Source: string): string; +var + I: Integer; + C: Byte; +begin + Result := ''; + for I := 1 to Length(Source) do + begin + if Length(Key) > 0 then + C := Byte(Key[1 + ((I - 1) mod Length(Key))]) xor Byte(Source[I]) + else + C := Byte(Source[I]); + {$IFDEF CLR} + Result := Result + IntToHex(C, 2).ToLower(); + {$ELSE} + Result := Result + AnsiLowerCase(IntToHex(C, 2)); + {$ENDIF CLR} + end; +end; + +function XorDecode(const Key, Source: string): string; +var + I: Integer; + C: Char; +begin + Result := ''; + for I := 0 to Length(Source) div 2 - 1 do + begin + C := Chr(StrToIntDef('$' + Copy(Source, (I * 2) + 1, 2), Ord(' '))); + if Length(Key) > 0 then + C := Chr(Byte(Key[1 + (I mod Length(Key))]) xor Byte(C)); + Result := Result + C; + end; +end; + +function GetCmdLineArg(const Switch: string; ASwitchChars: TSysCharSet): string; +var + I: Integer; + S: string; +begin + I := 1; + while I <= ParamCount do + begin + S := ParamStr(I); + if (ASwitchChars = []) or ((S[1] in ASwitchChars) and (Length(S) > 1)) then + begin + {$IFDEF CLR} + if SameText(Copy(S, 2, MaxInt), Switch) then + {$ELSE} + if AnsiSameText(Copy(S, 2, MaxInt), Switch) then + {$ENDIF CLR} + begin + Inc(I); + if I <= ParamCount then + begin + Result := ParamStr(I); + Exit; + end; + end; + end; + Inc(I); + end; + Result := ''; +end; + +{ begin JvStrUtil } + +function FindNotBlankCharPos(const S: string): Integer; +begin + for Result := 1 to Length(S) do + if S[Result] <> ' ' then + Exit; + Result := Length(S) + 1; +end; + +function FindNotBlankCharPosW(const S: WideString): Integer; +begin + for Result := 1 to Length(S) do + if S[Result] <> ' ' then + Exit; + Result := Length(S) + 1; +end; + +// (rom) reimplemented + +function AnsiChangeCase(const S: string): string; +var + I: Integer; + Up: string; + Down: string; +begin + Result := S; + {$IFDEF CLR} + Up := S.ToUpper(); + Down := S.ToLower(); + {$ELSE} + Up := AnsiUpperCase(S); + Down := AnsiLowerCase(S); + {$ENDIF CLR} + for I := 1 to Length(Result) do + if Result[I] = Up[I] then + Result[I] := Down[I] + else + Result[I] := Up[I]; +end; + +function WideChangeCase(const S: string): string; +var + I: Integer; + Up: string; + Down: string; +begin + Result := S; + Up := WideUpperCase(S); + Down := WideLowerCase(S); + for I := 1 to Length(Result) do + if Result[I] = Up[I] then + Result[I] := Down[I] + else + Result[I] := Up[I]; +end; + +{ end JvStrUtil } +{ end JvStrUtils } + +{ begin JvFileUtil } + +function NormalDir(const DirName: string): string; +begin + Result := DirName; + {$IFDEF MSWINDOWS} + if (Result <> '') and + {$IFDEF CLR} + not (Result[Length(Result)] in [':', '\']) + {$ELSE} + not (AnsiLastChar(Result)^ in [':', '\']) + {$ENDIF CLR} + then + if (Length(Result) = 1) and (UpCase(Result[1]) in ['A'..'Z']) then + Result := Result + ':\' + else + Result := Result + '\'; + {$ENDIF MSWINDOWS} +end; + +function RemoveBackSlash(const DirName: string): string; +begin + Result := DirName; + if (Length(Result) > 1) and + {$IFDEF CLR} + (Result[Length(Result)] = '\') + {$ELSE} + (AnsiLastChar(Result)^ = '\') + {$ENDIF CLR} + then + if not ((Length(Result) = 3) and (UpCase(Result[1]) in ['A'..'Z']) and + (Result[2] = ':')) then + Delete(Result, Length(Result), 1); +end; + +function FileDateTime(const FileName: string): TDateTime; +{$IFNDEF COMPILER10_UP} +var + Age: Longint; +{$ENDIF !COMPILER10_UP} +begin + {$IFDEF COMPILER10_UP} + if not FileAge(Filename, Result) then + Result := NullDate; + {$ELSE} + Age := FileAge(FileName); + {$IFDEF MSWINDOWS} + // [roko] -1 is valid FileAge value on Linux + if Age = -1 then + Result := NullDate + else + {$ENDIF MSWINDOWS} + Result := FileDateToDateTime(Age); + {$ENDIF COMPILER10_UP} +end; + +function HasAttr(const FileName: string; Attr: Integer): Boolean; +var + FileAttr: Integer; +begin + FileAttr := FileGetAttr(FileName); + Result := (FileAttr >= 0) and (FileAttr and Attr = Attr); +end; + +function DeleteFilesEx(const FileMasks: array of string): Boolean; +var + I: Integer; +begin + Result := True; + for I := Low(FileMasks) to High(FileMasks) do + Result := Result and DeleteFiles(ExtractFilePath(FileMasks[I]), ExtractFileName(FileMasks[I])); +end; + +{$IFDEF MSWINDOWS} + +{$IFNDEF CLR} +function GetWindowsDir: string; +var + Buffer: array [0..MAX_PATH] of Char; +begin + SetString(Result, Buffer, GetWindowsDirectory(Buffer, SizeOf(Buffer))); +end; +{$ENDIF !CLR} + +function GetSystemDir: string; +{$IFDEF CLR} +begin + Result := System.Environment.SystemDirectory; +end; +{$ELSE} +var + Buffer: array [0..MAX_PATH] of Char; +begin + SetString(Result, Buffer, GetSystemDirectory(Buffer, SizeOf(Buffer))); +end; +{$ENDIF CLR} + +{$ENDIF MSWINDOWS} + +{$IFDEF UNIX} +function GetTempFileName(const Prefix: string): string; +var + P: PChar; +begin + P := tempnam(nil, Pointer(Prefix)); + Result := P; + if P <> nil then + Libc.free(P); +end; +{$ENDIF UNIX} + +function GenTempFileName(FileName: string): string; +var + TempDir: string; + {$IFDEF CLR} + TempFile: StringBuilder; + {$ELSE} + {$IFDEF MSWINDOWS} + TempFile: array [0..MAX_PATH] of Char; + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + TempFile: string; + {$ENDIF UNIX} + {$ENDIF CLR} + STempDir: TFileName; + Res: Integer; +begin + TempDir := GetTempDir; + if FileName <> '' then + begin + if Length(FileName) < 4 then + FileName := ExpandFileName(FileName); + if (Length(FileName) > 4) and (FileName[2] = ':') and + (Length(TempDir) > 4) and + (AnsiCompareFileName(TempDir, FileName) <> 0) then + begin + STempDir := ExtractFilePath(FileName); + MoveString(STempDir, TempDir, Length(STempDir) + 1); + end; + end; + {$IFDEF CLR} + TempFile := StringBuilder.Create(MAX_PATH); + {$ENDIF CLR} + {$IFDEF MSWINDOWS} + Res := GetTempFileName( + {$IFDEF CLR} + TempDir, { address of directory name for temporary file} + {$ELSE} + PChar(TempDir), { address of directory name for temporary file} + {$ENDIF CLR} + '~JV', { address of filename prefix} + 0, { number used to create temporary filename} + TempFile); { address of buffer that receives the new filename} + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + TempFile := GetTempFileName('~JV'); + Res := 1; + {$ENDIF UNIX} + if Res <> 0 then + Result := TempFile{$IFDEF CLR}.ToString(){$ENDIF} + else + Result := '~JVCLTemp.tmp'; + DeleteFile(Result); +end; + +function GenTempFileNameExt(FileName: string; const FileExt: string): string; +begin + Result := ChangeFileExt(GenTempFileName(FileName), FileExt); +end; + +function GetTempDir: string; +{$IFDEF CLR} +begin + Result := Path.GetTempPath; +end; +{$ELSE} +{$IFDEF MSWINDOWS} +var + TempDir: array [0..MAX_PATH] of Char; +begin + TempDir[GetTempPath(260, TempDir)] := #0; + Result := TempDir; +end; +{$ENDIF MSWINDOWS} +{$IFDEF UNIX} +begin + Result := ExtractFileDir(GetTempFileName('')); + if Result = '' then + Result := '/tmp'; // hard coded +end; +{$ENDIF UNIX} +{$ENDIF CLR} + +function ClearDir(const Dir: string): Boolean; +var + SearchRec: TSearchRec; + DosError: Integer; + Path: TFileName; +begin + Result := True; + Path := AddSlash(Dir); + DosError := FindFirst(Path + AllFilesMask, faAnyFile, SearchRec); + while DosError = 0 do + begin + if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then + begin + if (SearchRec.Attr and faDirectory) = faDirectory then + Result := Result and DeleteDir(Path + SearchRec.Name) + else + Result := Result and DeleteFile(Path + SearchRec.Name); + // if not Result then Exit; + end; + DosError := FindNext(SearchRec); + end; + FindClose(SearchRec); +end; + +function DeleteDir(const Dir: string): Boolean; +begin + ClearDir(Dir); + Result := RemoveDir(Dir); +end; + +function DeleteFiles(const Folder: TFileName; const Masks: string): Boolean; +var + SearchRec: TSearchRec; + DosError: Integer; + Path: TFileName; +begin + Result := False; + Path := AddSlash(Folder); + DosError := FindFirst(Path + AllFilesMask, faAnyFile and not faDirectory, SearchRec); + while DosError = 0 do + begin + if FileEquMasks(Path + SearchRec.Name, Masks) then + Result := DeleteFile(Path + SearchRec.Name); + DosError := FindNext(SearchRec); + end; + FindClose(SearchRec); +end; + +{$IFNDEF CLR} +function GetParameter: string; +var + FN, FN1: PChar; +begin + if ParamCount = 0 then + begin + Result := ''; + Exit + end; + FN := CmdLine; + if FN[0] = '"' then + begin + FN := StrScan(FN + 1, '"'); + if (FN[0] = #0) or (FN[1] = #0) then + Result := '' + else + begin + Inc(FN, 2); + if FN[0] = '"' then + begin + Inc(FN, 1); + FN1 := StrScan(FN + 1, '"'); + if FN1[0] <> #0 then + FN1[0] := #0; + end; + Result := FN; + end; + end + else + Result := Copy(CmdLine, Length(ParamStr(0)) + 1, 260); + while (Length(Result) > 0) and (Result[1] = ' ') do + Delete(Result, 1, 1); + Result := ReplaceString(Result, '"', ''); + if FileExists(Result) then + Result := GetLongFileName(Result); +end; +{$ENDIF !CLR} + +function GetLongFileName(const FileName: string): string; +{$IFDEF MSWINDOWS} +var + SearchRec: TSearchRec; +{$ENDIF MSWINDOWS} +begin + {$IFDEF MSWINDOWS} + if FileGetInfo(FileName, SearchRec) then + Result := ExtractFilePath(ExpandFileName(FileName)) + SearchRec.FindData.cFileName + else + Result := FileName; + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + Result := ExpandFileName(FileName); + {$ENDIF UNIX} +end; + +function FileEquMask(FileName, Mask: TFileName; CaseSensitive: Boolean): Boolean; +var + I: Integer; + C: Char; + Index: Integer; + LenFileName: Integer; +begin + if not CaseSensitive then + begin + FileName := AnsiUpperCase(ExtractFileName(FileName)); + Mask := AnsiUpperCase(Mask); + end; + Result := False; + {$IFDEF MSWINDOWS} + if Pos('.', FileName) = 0 then + FileName := FileName + '.'; + {$ENDIF MSWINDOWS} + LenFileName := Length(FileName); + I := 1; + Index := 1; + while I <= Length(Mask) do + begin + C := Mask[I]; + if (Index > LenFileName) and (C <> '*') then + Exit; + case C of + '*': + if I = Length(Mask) then + begin + Result := True; + Exit; + end + else + begin + Index := PosIdx(Mask[I + 1], FileName, Index); + if Index = 0 then + Exit; + end; + '?': + Inc(Index); + else + if C = FileName[Index] then + Inc(Index) + else + Exit; + end; + Inc(I); + end; + if Index > LenFileName then + Result := True; +end; + +function FileEquMasks(FileName, Masks: TFileName; CaseSensitive: Boolean): Boolean; +var + I: Integer; + Mask: string; +begin + Result := False; + I := 0; + Mask := Trim(SubStrBySeparator(Masks, I, PathSep)); + while Length(Mask) <> 0 do + if FileEquMask(FileName, Mask, CaseSensitive) then + begin + Result := True; + Break; + end + else + begin + Inc(I); + Mask := Trim(SubStrBySeparator(Masks, I, PathSep)); + end; +end; + +function ValidFileName(const FileName: string): Boolean; + + function HasAny(const Str, SubStr: string): Boolean; + var + I: Integer; + begin + Result := False; + for I := 1 to Length(SubStr) do + begin + if Pos(SubStr[I], Str) > 0 then + begin + Result := True; + Break; + end; + end; + end; + +begin + Result := (FileName <> '') and + {$IFDEF MSWINDOWS} + (not HasAny(FileName, '/<>"?*|')); + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + (not HasAny(FileName, '<>"?*|')); + {$ENDIF UNIX} + if Result then + Result := Pos(PathDelim, ExtractFileName(FileName)) = 0; +end; + +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} + +function FileLock(Handle: Integer; Offset, LockSize: Longint): Integer; overload; +begin + if LockFile(Handle, Offset, 0, LockSize, 0) then + Result := 0 + else + Result := GetLastError; +end; + +function FileUnlock(Handle: Integer; Offset, LockSize: Longint): Integer; overload; +begin + if UnlockFile(Handle, Offset, 0, LockSize, 0) then + Result := 0 + else + Result := GetLastError; +end; + +function FileLock(Handle: Integer; Offset, LockSize: Int64): Integer; overload; +begin + if LockFile(Handle, Int64Rec(Offset).Lo, Int64Rec(Offset).Hi, + Int64Rec(LockSize).Lo, Int64Rec(LockSize).Hi) then + Result := 0 + else + Result := GetLastError; +end; + +function FileUnlock(Handle: Integer; Offset, LockSize: Int64): Integer; overload; +begin + if UnlockFile(Handle, Int64Rec(Offset).Lo, Int64Rec(Offset).Hi, + Int64Rec(LockSize).Lo, Int64Rec(LockSize).Hi) then + Result := 0 + else + Result := GetLastError; +end; + +{$ENDIF MSWINDOWS} +{$ENDIF !CLR} + +function ShortToLongFileName(const ShortName: string): string; +{$IFDEF MSWINDOWS} +var + Temp: TWin32FindData; + SearchHandle: THandle; +begin + {$IFDEF CLR} + SearchHandle := FindFirstFile(ShortName, Temp); + {$ELSE} + SearchHandle := FindFirstFile(PChar(ShortName), Temp); + {$ENDIF CLR} + if SearchHandle <> INVALID_HANDLE_VALUE then + begin + Result := Temp.cFileName; + if Result = '' then + Result := Temp.cAlternateFileName; + end + else + Result := ''; + Windows.FindClose(SearchHandle); +end; +{$ENDIF MSWINDOWS} +{$IFDEF UNIX} +begin + if FileExists(ShortName) then + Result := ShortName + else + Result := ''; +end; +{$ENDIF UNIX} + +function LongToShortFileName(const LongName: string): string; +{$IFDEF MSWINDOWS} +var + Temp: TWin32FindData; + SearchHandle: THandle; +begin + {$IFDEF CLR} + SearchHandle := FindFirstFile(LongName, Temp); + {$ELSE} + SearchHandle := FindFirstFile(PChar(LongName), Temp); + {$ENDIF CLR} + if SearchHandle <> INVALID_HANDLE_VALUE then + begin + Result := Temp.cAlternateFileName; + if Result = '' then + Result := Temp.cFileName; + end + else + Result := ''; + Windows.FindClose(SearchHandle); +end; +{$ENDIF MSWINDOWS} +{$IFDEF UNIX} +begin + if FileExists(LongName) then + Result := LongName + else + Result := ''; +end; +{$ENDIF UNIX} + +function ShortToLongPath(const ShortName: string): string; +{$IFDEF CLR} +var + LastSlash: Integer; + TempPath: string; +begin + Result := ''; + TempPath := ShortName; + LastSlash := PosLastCharIdx(PathDelim, ShortName); + while LastSlash > 0 do + begin + Result := PathDelim + ShortToLongFileName(TempPath) + Result; + LastSlash := PosLastCharIdx(PathDelim, ShortName, LastSlash - 1); + TempPath := Copy(TempPath, 1, LastSlash); + end; +end; +{$ELSE} +var + LastSlash: PChar; + TempPathPtr: PChar; +begin + Result := ''; + TempPathPtr := PChar(ShortName); + LastSlash := StrRScan(TempPathPtr, PathDelim); + while LastSlash <> nil do + begin + Result := PathDelim + ShortToLongFileName(TempPathPtr) + Result; + if LastSlash <> nil then + begin + LastSlash^ := #0; + LastSlash := StrRScan(TempPathPtr, PathDelim); + end; + end; + Result := TempPathPtr + Result; +end; +{$ENDIF CLR} + +function LongToShortPath(const LongName: string): string; +{$IFDEF CLR} +begin + Result := ExtractShortPathName(LongName); +end; +{$ELSE} +var + LastSlash: PChar; + TempPathPtr: PChar; +begin + Result := ''; + TempPathPtr := PChar(LongName); + LastSlash := StrRScan(TempPathPtr, PathDelim); + while LastSlash <> nil do + begin + Result := PathDelim + LongToShortFileName(TempPathPtr) + Result; + if LastSlash <> nil then + begin + LastSlash^ := #0; + LastSlash := StrRScan(TempPathPtr, PathDelim); + end; + end; + Result := TempPathPtr + Result; +end; +{$ENDIF CLR} + +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} + +const + IID_IPersistFile: TGUID = + (D1: $0000010B; D2: $0000; D3: $0000; D4: ($C0, $00, $00, $00, $00, $00, $00, $46)); + +const + LinkExt = '.lnk'; + +procedure CreateFileLink(const FileName, DisplayName: string; Folder: Integer); +var + ShellLink: IShellLink; + PersistFile: IPersistFile; + ItemIDList: PItemIDList; + FileDestPath: array [0..MAX_PATH] of Char; + FileNameW: array [0..MAX_PATH] of WideChar; +begin + CoInitialize(nil); + try + OleCheck(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_SERVER, + IID_IShellLinkA, ShellLink)); + try + OleCheck(ShellLink.QueryInterface(IID_IPersistFile, PersistFile)); + try + OleCheck(SHGetSpecialFolderLocation(0, Folder, ItemIDList)); + SHGetPathFromIDList(ItemIDList, FileDestPath); + StrCat(FileDestPath, PChar('\' + DisplayName + LinkExt)); + ShellLink.SetPath(PChar(FileName)); + ShellLink.SetIconLocation(PChar(FileName), 0); + MultiByteToWideChar(CP_ACP, 0, FileDestPath, -1, FileNameW, MAX_PATH); + OleCheck(PersistFile.Save(FileNameW, True)); + finally + PersistFile := nil; + end; + finally + ShellLink := nil; + end; + finally + CoUninitialize; + end; +end; + +procedure DeleteFileLink(const DisplayName: string; Folder: Integer); +var + ShellLink: IShellLink; + ItemIDList: PItemIDList; + FileDestPath: array [0..MAX_PATH] of Char; +begin + CoInitialize(nil); + try + OleCheck(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_SERVER, + IID_IShellLinkA, ShellLink)); + try + OleCheck(SHGetSpecialFolderLocation(0, Folder, ItemIDList)); + SHGetPathFromIDList(ItemIDList, FileDestPath); + StrCat(FileDestPath, PChar('\' + DisplayName + LinkExt)); + DeleteFile(FileDestPath); + finally + ShellLink := nil; + end; + finally + CoUninitialize; + end; +end; + +{$ENDIF MSWINDOWS} +{$ENDIF !CLR} + +{ end JvFileUtil } + +function PtInRectInclusive(R: TRect; Pt: TPoint): Boolean; +begin + R.Right := R.Right + 1; + R.Bottom := R.Bottom + 1; + Result := PtInRect(R, Pt); +end; + +function PtInRectExclusive(R: TRect; Pt: TPoint): Boolean; +begin + R.Left := R.Left + 1; + R.Top := R.Top + 1; + Result := PtInRect(R, Pt); +end; + +function OpenObject(const Value: string): Boolean; overload; +begin + {$IFNDEF CLR} + Result := OpenObject(PChar(Value)); + {$ELSE} + Result := ShellExecute(0, 'open', Value, '', '', SW_SHOWNORMAL) > HINSTANCE_ERROR; + {$ENDIF !CLR} +end; + +{ (rb) Duplicate of JvFunctions.Exec } +{$IFNDEF CLR} +function OpenObject(Value: PChar): Boolean; overload; +begin + Result := ShellExecute(0, 'open', Value, nil, nil, SW_SHOWNORMAL) > HINSTANCE_ERROR; +end; +{$ENDIF !CLR} + +{$IFDEF MSWINDOWS} + +procedure RaiseLastWin32; overload; +begin + PError(''); +end; + +procedure RaiseLastWin32(const Text: string); overload; +begin + PError(Text); +end; + +{$IFDEF CLR} +[SuppressUnmanagedCodeSecurity, DllImport('version.dll', CharSet = CharSet.Auto, SetLastError = True, EntryPoint = 'VerQueryValue')] +function JvVerQueryValue([in] pBlock: TBytes; lpSubBlock: string; + out lplpBuffer: TVSFixedFileInfo; out puLen: UINT): BOOL; external; +{$ENDIF CLR} + +function GetFileVersion(const AFileName: string): Cardinal; +var + FileName: string; + InfoSize, Wnd: DWORD; + {$IFDEF CLR} + VerBuf: TBytes; + FI: TVSFixedFileInfo; + {$ELSE} + VerBuf: Pointer; + FI: PVSFixedFileInfo; + {$ENDIF CLR} + VerSize: DWORD; +begin + Result := 0; + // GetFileVersionInfo modifies the filename parameter data while parsing. + // Copy the string const into a local variable to create a writeable copy. + FileName := AFileName; + {$IFDEF CLR} + InfoSize := GetFileVersionInfoSize(FileName, Wnd); + {$ELSE} + UniqueString(FileName); + InfoSize := GetFileVersionInfoSize(PChar(FileName), Wnd); + {$ENDIF CLR} + if InfoSize <> 0 then + begin + {$IFDEF CLR} + if GetFileVersionInfo(FileName, Wnd, InfoSize, VerBuf) then + if JvVerQueryValue(VerBuf, '\', FI, VerSize) then + Result := FI.dwFileVersionMS; + {$ELSE} + GetMem(VerBuf, InfoSize); + try + if GetFileVersionInfo(PChar(FileName), Wnd, InfoSize, VerBuf) then + if VerQueryValue(VerBuf, '\', Pointer(FI), VerSize) then + Result := FI.dwFileVersionMS; + finally + FreeMem(VerBuf); + end; + {$ENDIF CLR} + end; +end; + +var + ShellVersion: Integer; + +function GetShellVersion: Cardinal; +begin + if ShellVersion = 0 then + ShellVersion := GetFileVersion('shell32.dll'); + Result := ShellVersion; +end; + +{$IFNDEF CLR} +procedure OpenCdDrive; +begin + mciSendString(PChar(RC_OpenCDDrive), nil, 0, Windows.GetForegroundWindow); +end; + +procedure CloseCdDrive; +begin + mciSendString(PChar(RC_CloseCDDrive), nil, 0, Windows.GetForegroundWindow); +end; + +{ (rb) Duplicate of JclFileUtils.DiskInDrive } + +function DiskInDrive(Drive: Char): Boolean; +var + DrvNum: Byte; + EMode: Word; +begin + DrvNum := Ord(Drive); + if DrvNum >= Ord('a') then + Dec(DrvNum, $20); + EMode := SetErrorMode(SEM_FAILCRITICALERRORS); + try + Result := DiskSize(DrvNum - $40) <> -1; + finally + SetErrorMode(EMode); + end; +end; + +{$ENDIF MSWINDOWS} + +procedure PError(const Text: string); +var + LastError: Integer; + St: string; +begin + LastError := GetLastError; + if LastError <> 0 then + begin + St := SysUtils.Format({$IFDEF COMPILER6_UP} SOSError {$ELSE} SWin32Error {$ENDIF}, + [LastError, SysErrorMessage(LastError)]); + if Text <> '' then + St := Text + ':' + St; + raise {$IFDEF COMPILER6_UP} EOSError{$ELSE} EWin32Error{$ENDIF}.Create(St); + end; +end; +{$ENDIF !CLR} + +procedure Exec(const FileName, Parameters, Directory: string); +begin + {$IFDEF CLR} + ShellExecute(Windows.GetForegroundWindow, 'open', FileName, Parameters, Directory, + SW_SHOWNORMAL); + {$ELSE} + {$IFDEF MSWINDOWS} + ShellExecute(Windows.GetForegroundWindow, 'open', PChar(FileName), PChar(Parameters), PChar(Directory), + SW_SHOWNORMAL); + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + ShellExecute(GetForegroundWindow, 'open', PChar(FileName), PChar(Parameters), PChar(Directory), + SW_SHOWNORMAL); + {$ENDIF UNIX} + {$ENDIF CLR} +end; +{$IFDEF UNIX} +// begin +// if Directory = '' then Directory := GetCurrentDir; +// Libc.system(PChar(Format('cd "%s" ; "%s" %s &', [Directory, FileName, Parameters]))); +// end; +{$ENDIF UNIX} + +{ (rb) Duplicate of JclMiscel.WinExec32AndWait } + +function ExecuteAndWait(const CommandLine, WorkingDirectory: string; Visibility: Integer): Integer; +{$IFDEF CLR} +var + Proc: Process; +begin + Result := 0; + Proc := Process.Create; + Proc.StartInfo.FileName := CommandLine; + + case Visibility of + SW_HIDE: + Proc.StartInfo.WindowStyle := ProcessWindowStyle.Hidden; + SW_SHOWMINIMIZED: + Proc.StartInfo.WindowStyle := ProcessWindowStyle.Minimized; + SW_SHOWMAXIMIZED: + Proc.StartInfo.WindowStyle := ProcessWindowStyle.Maximized; + else + Proc.StartInfo.WindowStyle := ProcessWindowStyle.Normal + end; + + if Proc.Start then + Proc.WaitForExit + else + Result := 1; + Proc.Close; +end; +{$ELSE} +{$IFDEF MSWINDOWS} +var + StartupInfo: TStartupInfo; + ProcessInfo: TProcessInformation; +begin + Result := 0; + FillChar(StartupInfo, SizeOf(StartupInfo), 0); + StartupInfo.cb := SizeOf(StartupInfo); + StartupInfo.dwFlags := STARTF_USESHOWWINDOW; + StartupInfo.wShowWindow := Visibility; + if not CreateProcess(nil, PChar(CommandLine), nil, nil, False, CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, + nil, Pointer(WorkingDirectory), StartupInfo, ProcessInfo) then + begin + WaitForSingleObject(ProcessInfo.hProcess, INFINITE); + + // required to avoid running resource leak. + CloseHandle(ProcessInfo.hProcess); + CloseHandle(ProcessInfo.hThread); + end + else + begin + Result := GetLastError; + end; +end; +{$ENDIF MSWINDOWS} +{$IFDEF UNIX} +begin + // ignores Visibility + { TODO : Untested } + if Libc.system(PChar(Format('kfmclient exec "%s"', [CommandLine]))) = -1 then + begin + if WorkingDirectory = '' then + Result := Libc.system(PChar(Format('cd "%s" ; %s', + [GetCurrentDir, CommandLine]))) + else + Result := Libc.system(PChar(Format('cd "%s" ; %s', + [WorkingDirectory, CommandLine]))); + end; +end; +{$ENDIF UNIX} +{$ENDIF CLR} + + + +function FirstInstance(const ATitle: string): Boolean; +{$IFDEF CLR} +var + Mux: System.Threading.Mutex; + IsNew: Boolean; +begin + Mux := System.Threading.Mutex.Create(False, ATitle, IsNew); + try + Result := IsNew; + finally + Mux.ReleaseMutex; + end; +end; +{$ELSE} +var + Mutex: THandle; +begin + Mutex := CreateMutex(nil, False, PChar(ATitle)); + try + Result := (Mutex <> 0) and (GetLastError <> ERROR_ALREADY_EXISTS); + finally + ReleaseMutex(Mutex); + end; +end; +{$ENDIF CLR} + +procedure RestoreOtherInstance(const MainFormClassName, MainFormCaption: string); +var + OtherWnd, OwnerWnd: HWND; +begin + {$IFDEF CLR} + OtherWnd := FindWindow(MainFormClassName, MainFormCaption); + {$ELSE} + OtherWnd := FindWindow(PChar(MainFormClassName), PChar(MainFormCaption)); + {$ENDIF CLR} + ShowWindow(OtherWnd, SW_SHOW); //in case the window was not visible before + + OwnerWnd := 0; + if OtherWnd <> 0 then + OwnerWnd := GetWindow(OtherWnd, GW_OWNER); + + if OwnerWnd <> 0 then + OtherWnd := OwnerWnd; + + if OtherWnd <> 0 then + begin + { (rb) Use JvVCLUtils.SwitchToWindow } + if IsIconic(OtherWnd) then + ShowWindow(OtherWnd, SW_RESTORE); + + SetForegroundWindow(OtherWnd); + end; +end; + +procedure HideTraybar; +begin + {$IFDEF CLR} + ShowWindow(FindWindow(RC_ShellName, nil), SW_HIDE); + {$ELSE} + ShowWindow(FindWindow(PChar(RC_ShellName), nil), SW_HIDE); + {$ENDIF CLR} +end; + +procedure ShowTraybar; +begin + {$IFDEF CLR} + ShowWindow(FindWindow(RC_ShellName, nil), SW_SHOW); + {$ELSE} + ShowWindow(FindWindow(PChar(RC_ShellName), nil), SW_SHOW); + {$ENDIF CLR} +end; + +{$IFNDEF CLR} +procedure ShowStartButton(Visible: Boolean); +var + Tray, Child: HWND; + C: array [0..127] of Char; + S: string; +begin + Tray := FindWindow(PChar(RC_ShellName), nil); + Child := GetWindow(Tray, GW_CHILD); + while Child <> 0 do + begin + if GetClassName(Child, C, SizeOf(C)) > 0 then + begin + S := StrPas(C); + if UpperCase(S) = 'BUTTON' then + if Visible then + ShowWindow(Child, SW_SHOWNORMAL) + else + ShowWindow(Child, SW_HIDE); + end; + Child := GetWindow(Child, GW_HWNDNEXT); + end; +end; +{$ENDIF !CLR} + +procedure MonitorOn; +begin + SendMessage(GetForegroundWindow, WM_SYSCOMMAND, SC_MONITORPOWER, -1); +end; + +procedure MonitorOff; +begin + SendMessage(GetForegroundWindow, WM_SYSCOMMAND, SC_MONITORPOWER, 2); +end; + +procedure LowPower; +begin + SendMessage(GetForegroundWindow, WM_SYSCOMMAND, SC_MONITORPOWER, 1); +end; + +procedure SendShift(H: THandle; Down: Boolean); +var + VKey, ScanCode: Word; + LParam: Cardinal; +begin + VKey := VK_SHIFT; + ScanCode := MapVirtualKey(VKey, 0); + LParam := Longint(ScanCode) shl 16 or 1; + if not Down then + LParam := LParam or $C0000000; + SendMessage(H, WM_KEYDOWN, VKey, LParam); +end; + +procedure SendCtrl(H: THandle; Down: Boolean); +var + VKey, ScanCode: Word; + LParam: Cardinal; +begin + VKey := VK_CONTROL; + ScanCode := MapVirtualKey(VKey, 0); + LParam := Longint(ScanCode) shl 16 or 1; + if not Down then + LParam := LParam or $C0000000; + SendMessage(H, WM_KEYDOWN, VKey, LParam); +end; + +function SendKey(const AppName: string; Key: Char): Boolean; +var + VKey, ScanCode: Word; + ConvKey: Longint; + LParam: Cardinal; + Shift, Ctrl: Boolean; + H: Windows.HWND; +begin + {$IFDEF CLR} + H := FindWindow(AppName, nil); + {$ELSE} + H := FindWindow(PChar(AppName), nil); + {$ENDIF CLR} + if H <> 0 then + begin + ConvKey := OemKeyScan(Ord(Key)); + Shift := (ConvKey and $00020000) <> 0; + Ctrl := (ConvKey and $00040000) <> 0; + ScanCode := ConvKey and $000000FF or $FF00; + VKey := Ord(Key); + LParam := Longint(ScanCode) shl 16 or 1; + if Shift then + SendShift(H, True); + if Ctrl then + SendCtrl(H, True); + SendMessage(H, WM_KEYDOWN, VKey, LParam); + SendMessage(H, WM_CHAR, VKey, LParam); + LParam := LParam or $C0000000; + SendMessage(H, WM_KEYUP, VKey, LParam); + if Shift then + SendShift(H, False); + if Ctrl then + SendCtrl(H, False); + Result := True; + end + else + Result := False; +end; + + + +{$IFDEF MSWINDOWS} + +{$IFNDEF CLR} +procedure RebuildIconCache; +var + Dummy: DWORD; +begin + SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, + Longint(PChar('WindowMetrics')), SMTO_NORMAL or SMTO_ABORTIFHUNG, 10000, Dummy); +end; + +procedure AssociateFileExtension(const IconPath, ProgramName, Path, Extension: string); +begin + with TRegistry.Create do + begin + RootKey := HKEY_CLASSES_ROOT; + OpenKey(ProgramName, True); + WriteString('', ProgramName); + if IconPath <> '' then + begin + OpenKey(RC_DefaultIcon, True); + WriteString('', IconPath); + end; + CloseKey; + OpenKey(ProgramName, True); + OpenKey('shell', True); + OpenKey('open', True); + OpenKey('command', True); + WriteString('', '"' + Path + '" "%1"'); + Free; + end; + with TRegistry.Create do + begin + RootKey := HKEY_CLASSES_ROOT; + OpenKey('.' + Extension, True); + WriteString('', ProgramName); + Free; + end; + RebuildIconCache; +end; + +procedure AssociateExtension(const IconPath, ProgramName, Path, Extension: string); +begin + AssociateFileExtension(IconPath, ProgramName, Path, Extension); +end; +{$ENDIF !CLR} + +function GetRecentDocs: TStringList; + +var + Path: string; + T: TSearchRec; + Res: Integer; + +begin + Result := TStringList.Create; + Path := IncludeTrailingPathDelimiter(GetRecentFolder); + //search for all files + Res := FindFirst(Path + '*.*', faAnyFile, T); + try + while Res = 0 do + begin + if (T.Name <> '.') and (T.Name <> '..') then + Result.Add(Path + T.Name); + Res := FindNext(T); + end; + finally + FindClose(T); + end; +end; + +{ (rb) Duplicate of JvWinDialogs.AddToRecentDocs } + +{$IFNDEF CLR} +procedure AddToRecentDocs(const FileName: string); +begin + SHAddToRecentDocs(SHARD_PATH, PChar(FileName)); +end; + +function EnumWindowsProc(Handle: THandle; LParam: TStrings): Boolean; stdcall; +var + St: array [0..256] of Char; + St2: string; +begin + if Windows.IsWindowVisible(Handle) then + begin + GetWindowText(Handle, St, SizeOf(St)); + St2 := St; + if St2 <> '' then + with TStrings(LParam) do + AddObject(St2, TObject(Handle)); + end; + Result := True; +end; + +procedure GetVisibleWindows(List: TStrings); +begin + List.BeginUpdate; + try + List.Clear; + EnumWindows(@EnumWindowsProc, Integer(List)); + finally + List.EndUpdate; + end; +end; +{$ENDIF !CLR} + +{$ENDIF MSWINDOWS} +// from JvComponentFunctions + +function StrPosNoCase(const psSub, psMain: string): Integer; +begin + Result := Pos(AnsiUpperCase(psSub), AnsiUpperCase(psMain)); +end; + +function StrRestOf(const Ps: string; const N: Integer): string; +begin + Result := Copy(Ps, N, {(Length(Ps) - N + 1)} MaxInt); +end; + +{!!!!!!!! use these because the JCL one is badly broken } + +{ I am using this one purely as an internal for StrReplace + + Replaces parts of a string with new text. iUpdatePos is the last update position + i.e. the position where substr was found + the length of the replacement string + 1. + Use 0 first time in } + +function StrReplaceInstance(const psSource, psSearch, psReplace: string; + var piUpdatePos: Integer; const pbCaseSens: Boolean): string; +var + liIndex: Integer; + lsCopy: string; +begin + Result := psSource; + if piUpdatePos >= Length(psSource) then + Exit; + if psSearch = '' then + Exit; + + Result := Copy(psSource, 1, piUpdatePos - 1); + lsCopy := StrRestOf(psSource, piUpdatePos); + + if pbCaseSens then + liIndex := Pos(psSearch, lsCopy) + else + liIndex := StrPosNoCase(psSearch, lsCopy); + if liIndex = 0 then + begin + Result := psSource; + piUpdatePos := Length(psSource) + 1; + Exit; + end; + + Result := Result + Copy(lsCopy, 1, liIndex - 1); + Result := Result + psReplace; + piUpdatePos := Length(Result) + 1; + Result := Result + StrRestOf(lsCopy, liIndex + Length(psSearch)); +end; + +function LStrReplace(const psSource, psSearch, psReplace: string; + const pbCaseSens: Boolean): string; +var + liUpdatePos: Integer; +begin + liUpdatePos := 0; + Result := psSource; + while liUpdatePos < Length(Result) do + Result := StrReplaceInstance(Result, psSearch, psReplace, liUpdatePos, pbCaseSens); +end; + +{ if it's not a decimal point then it must be a digit, space or Currency symbol + also always use $ for money } + +function CharIsMoney(const Ch: AnsiChar): Boolean; +begin + Result := CharIsDigit(Ch) or (Ch = AnsiSpace) or (Ch = '$') or (Ch = '-') or + (Pos(Ch, CurrencyString) > 0); +end; + +function StrToCurrDef(const Str: string; Def: Currency): Currency; +var + {$IFDEF CLR} + LStr: StringBuilder; + {$ELSE} + LStr: string; + {$ENDIF CLR} + I: Integer; +begin + {$IFDEF CLR} + LStr := StringBuilder.Create(Length(Str)); + {$ELSE} + LStr := ''; + {$ENDIF CLR} + for I := 1 to Length(Str) do + if Str[I] in ['0'..'9', '-', '+', AnsiChar(DecimalSeparator{$IFDEF CLR}[1]{$ENDIF})] then + {$IFDEF CLR} + LStr.Append(Str[I]); + {$ELSE} + LStr := LStr + Str[I]; + {$ENDIF CLR} + try + {$IFDEF CLR} + if not TryStrToCurr(LStr.ToString(), Result) then + {$ELSE} + if not TextToFloat(PChar(LStr), Result, fvCurrency) then + {$ENDIF CLR} + Result := Def; + except + Result := Def; + end; +end; + +// Note: before using StrToFloatDef, please be aware that it will ignore +// any character that is not a valid character for a float, which is different +// from what the one in Delphi 6 up is doing. This has been documented in Mantis +// issue# 2935: http://homepages.borland.com/jedi/issuetracker/view.php?id=2935 +function StrToFloatDef(const Str: string; Def: Extended): Extended; +var + {$IFDEF CLR} + LStr: StringBuilder; + d: Double; + b: Boolean; + {$ELSE} + LStr: string; + {$ENDIF CLR} + I: Integer; +begin + {$IFDEF CLR} + LStr := StringBuilder.Create; + {$ENDIF CLR} + for I := 1 to Length(Str) do + if Str[I] in ['0'..'9', '-', '+', 'e', 'E', AnsiChar(DecimalSeparator{$IFDEF CLR}[1]{$ENDIF})] then + {$IFDEF CLR} + LStr.Append(Str[I]); + {$ELSE} + LStr := LStr + Str[I]; + {$ENDIF CLR} + Result := Def; + {$IFDEF CLR} + if LStr.Length > 0 then + try + { the string '-' fails StrToFloat, but it can be interpreted as 0 } + if LStr[LStr.Length] = '-' then + LStr.Append('0'); + + { a string that ends in a '.' such as '12.' fails StrToFloat, + but as far as I am concerned, it may as well be interpreted as 12.0 } + if LStr[LStr.Length] = DecimalSeparator then + LStr.Append('0'); + + b := TryStrToFloat(LStr.ToString(), d); + Result := d; + if not b then + {$ELSE} + if LStr <> '' then + try + { the string '-' fails StrToFloat, but it can be interpreted as 0 } + if LStr[Length(LStr)] = '-' then + LStr := LStr + '0'; + + { a string that ends in a '.' such as '12.' fails StrToFloat, + but as far as I am concerned, it may as well be interpreted as 12.0 } + if LStr[Length(LStr)] = DecimalSeparator then + LStr := LStr + '0'; + if not TextToFloat(PChar(LStr), Result, fvExtended) then + {$ENDIF CLR} + Result := Def; + except + Result := Def; + end; +end; + +function IntToExtended(I: Integer): Extended; +begin + Result := I; +end; + +function GetChangedText(const Text: string; SelStart, SelLength: Integer; Key: Char): string; +begin + { take the original text, replace what will be overwritten with new value } + Result := Text; + + if SelLength > 0 then + Delete(Result, SelStart + 1, SelLength); + if Key <> #0 then + Insert(Key, Result, SelStart + 1); +end; + +{ "window" technique for years to translate 2 digits to 4 digits. + The window is 100 years wide + The pivot year is the lower edge of the window + A pivot year of 1900 is equivalent to putting 1900 before every 2-digit year + if pivot is 1940, then 40 is interpreted as 1940, 00 as 2000 and 39 as 2039 + The system default is 1950 + + Why the reimplementation? + JclDatetime.Make4DigitYear will fail after 2100, this won't + note that in this implementation pivot is a 4-digit year + I have made it accept JclDatetime.Make4DigitYear's 2 digit pivot years. + They are expanded by adding 1900. + + It is also better in that a valid 4-digit year will pass through unchanged, + not fail an assertion. +} + +function MakeYear4Digit(Year, Pivot: Integer): Integer; +var + Century: Integer; +begin + if Pivot < 0 then + {$IFDEF CLR} + raise Exception.Create(RsEPivotLessThanZero); + {$ELSE} + raise Exception.CreateRes(@RsEPivotLessThanZero); + {$ENDIF CLR} + + { map 100 to zero } + if Year = 100 then + Year := 0; + if Pivot = 100 then + Pivot := 0; + + // turn 2 digit pivot to 4 digit + if Pivot < 100 then + Pivot := Pivot + 1900; + + { turn 2 digit years to 4 digits } + if (Year >= 0) and (Year < 100) then + begin + Century := (Pivot div 100) * 100; + + Result := Year + Century; // give the result the same century as the pivot + if Result < Pivot then + // cannot be lower than the Pivot + Result := Result + 100; + end + else + Result := Year; +end; + +function StrIsInteger(const S: string): Boolean; +var + I: Integer; + Ch: AnsiChar; +begin + Result := S <> ''; + for I := 1 to Length(S) do + begin + Ch := AnsiChar(S[I]); + if (not CharIsNumber(Ch)) or (Ch = DecimalSeparator) then //Az + begin + Result := False; + Exit; + end; + end; +end; + +function StrIsFloatMoney(const Ps: string): Boolean; +var + I, liDots: Integer; + Ch: AnsiChar; +begin + Result := True; + liDots := 0; + + for I := 1 to Length(Ps) do + begin + { allow digits, space, Currency symbol and one decimal dot } + Ch := AnsiChar(Ps[I]); + + if Ch = DecimalSeparator then + begin + Inc(liDots); + if liDots > 1 then + begin + Result := False; + Break; + end; + end + else + if not CharIsMoney(Ch) then + begin + Result := False; + Break; + end; + end; +end; + +function StrIsDateTime(const Ps: string): Boolean; +const + MIN_DATE_TIME_LEN = 6; {2Jan02 } + MAX_DATE_TIME_LEN = 30; { 30 chars or so in '12 December 1999 12:23:23:00' } +var + I: Integer; + Ch: AnsiChar; + liColons, liSlashes, liSpaces, liDigits, liAlpha: Integer; + lbDisqualify: Boolean; +begin + if Length(Ps) < MIN_DATE_TIME_LEN then + begin + Result := False; + Exit; + end; + + if Length(Ps) > MAX_DATE_TIME_LEN then + begin + Result := False; + Exit; + end; + + lbDisqualify := False; + liColons := 0; + liSlashes := 0; + liSpaces := 0; + liDigits := 0; + liAlpha := 0; + + for I := 1 to Length(Ps) do + begin + Ch := AnsiChar(Ps[I]); + + if Ch = ':' then + Inc(liColons) + else + if Ch = AnsiForwardSlash then + Inc(liSlashes) + else + if Ch = AnsiSpace then + Inc(liSpaces) + else + if CharIsDigit(Ch) then + Inc(liDigits) + else + if CharIsAlpha(Ch) then + Inc(liAlpha) + else + begin + // no wierd punctuation in dates! + lbDisqualify := True; + Break; + end; + end; + + Result := False; + if not lbDisqualify then + { a date must have colons and slashes and spaces, but not to many of each } + if (liColons > 0) or (liSlashes > 0) or (liSpaces > 0) then + { only 2 slashes in "dd/mm/yy" or 3 colons in "hh:mm:ss:ms" or 6 spaces "yy mm dd hh mm ss ms" } + if (liSlashes <= 2) and (liColons <= 3) and (liSpaces <= 6) then + { must have some digits (min 3 digits, eg in "2 jan 02", max 16 dgits in "01/10/2000 10:10:10:10" + longest month name is 8 chars } + if (liDigits >= 3) and (liDigits <= 16) and (liAlpha <= 10) then + Result := True; + + { define in terms of results - if I can interpret it as a date, then I can } + if Result then + Result := (SafeStrToDateTime(PreformatDateString(Ps)) <> 0); +end; + +function PreformatDateString(Ps: string): string; +var + I: Integer; +begin + { turn any month names to numbers } + + { use the StrReplace in stringfunctions - + the one in JclStrings is badly broken and brings down the app } + + for I := Low(LongMonthNames) to High(LongMonthNames) do + Ps := LStrReplace(Ps, LongMonthNames[I], IntToStr(I), False); + + { now that 'January' is gone, catch 'Jan' } + for I := Low(ShortMonthNames) to High(ShortMonthNames) do + Ps := LStrReplace(Ps, ShortMonthNames[I], IntToStr(I), False); + + { remove redundant spaces } + Ps := LStrReplace(Ps, AnsiSpace + AnsiSpace, AnsiSpace, False); + + Result := Ps; +end; + +function BooleanToInteger(const B: Boolean): Integer; +begin + Result := Ord(B); +end; + +{ from my ConvertFunctions unit } + +function StringToBoolean(const Ps: string): Boolean; +const + TRUE_STRINGS: array [1..5] of string = ('True', 't', 'y', 'yes', '1'); +var + I: Integer; +begin + Result := False; + + for I := Low(TRUE_STRINGS) to High(TRUE_STRINGS) do + if AnsiSameText(Ps, TRUE_STRINGS[I]) then + begin + Result := True; + Break; + end; +end; + +function SafeStrToDateTime(const Ps: string): TDateTime; +begin + try + Result := StrToDateTime(PreformatDateString(Ps)); + except + on E: EConvertError do + Result := 0.0 + else + raise; + end; +end; + +function SafeStrToDate(const Ps: string): TDateTime; +begin + try + Result := StrToDate(PreformatDateString(Ps)); + except + on E: EConvertError do + Result := 0.0 + else + raise; + end; +end; + +function SafeStrToTime(const Ps: string): TDateTime; +begin + try + Result := StrToTime(Ps) + except + on E: EConvertError do + Result := 0.0 + else + raise; + end; +end; + +{!! from strFunctions } + +function StrDeleteChars(const Ps: string; const piPos: Integer; const piCount: Integer): string; +begin + Result := Copy(Ps, 1, piPos - 1) + StrRestOf(Ps, piPos + piCount); +end; + +function StrDelete(const psSub, psMain: string): string; +var + liPos: Integer; +begin + Result := psMain; + if psSub = '' then + Exit; + + liPos := StrIPos(psSub, psMain); + + while liPos > 0 do + begin + Result := StrDeleteChars(Result, liPos, Length(psSub)); + liPos := StrIPos(psSub, Result); + end; +end; + +function TimeOnly(pcValue: TDateTime): TTime; +begin + Result := Frac(pcValue); +end; + +function DateOnly(pcValue: TDateTime): TDate; +begin + Result := Trunc(pcValue); +end; + +{ have to do this as it depends what the datekind of the control is} + +function DateIsNull(const pdtValue: TDateTime; const pdtKind: TdtKind): Boolean; +begin + Result := False; + case pdtKind of + dtkDateOnly: + Result := pdtValue < 1; //if date only then anything less than 1 is considered null + dtkTimeOnly: + Result := Frac(pdtValue) = NullEquivalentDate; //if time only then anything without a remainder is null + dtkDateTime: + Result := pdtValue = NullEquivalentDate; + end; +end; + +function OSCheck(RetVal: Boolean): Boolean; +begin + if not RetVal then + RaiseLastOSError; + Result := RetVal; +end; + +function MinimizeFileName(const FileName: string; Canvas: TCanvas; MaxLen: Integer): string; +var + {$IFDEF CLR} + sb: StringBuilder; + {$ENDIF CLR} + R: TRect; +begin + Result := FileName; + R := Rect(0, 0, MaxLen, Canvas.TextHeight('Wq')); + {$IFDEF CLR} + sb := StringBuilder.Create(Result); + // DrawText() doesn't exist with StringBuilder parameter (2005) + if DrawTextEx(Canvas.Handle, sb, sb.Length, R, + DT_SINGLELINE or DT_MODIFYSTRING or DT_PATH_ELLIPSIS or DT_CALCRECT or + DT_NOPREFIX, nil) <= 0 then + {$ELSE} + UniqueString(Result); + if DrawText(Canvas.Handle, PChar(Result), Length(Result), R, + DT_SINGLELINE or DT_MODIFYSTRING or DT_PATH_ELLIPSIS or DT_CALCRECT or + DT_NOPREFIX) <= 0 then + {$ENDIF CLR} + Result := FileName; +end; + +function MinimizeText(const Text: string; Canvas: TCanvas; + MaxWidth: Integer): string; +var + I: Integer; +begin + Result := Text; + I := 1; + while (I <= Length(Text)) and (Canvas.TextWidth(Result) > MaxWidth) do + begin + Inc(I); + Result := Copy(Text, 1, Max(0, Length(Text) - I)) + '...'; + end; +end; + +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} + +function RunDLL32(const ModuleName, FuncName, CmdLine: string; WaitForCompletion: Boolean; CmdShow: Integer = + SW_SHOWDEFAULT): Boolean; +var + SI: TStartupInfo; + PI: TProcessInformation; + S: string; +begin + SI.cb := SizeOf(SI); + GetStartupInfo(SI); + SI.wShowWindow := CmdShow; + S := SysUtils.Format('rundll32.exe %s,%s %s', [ModuleName, FuncName, CmdLine]); + Result := CreateProcess(nil, PChar(S), nil, nil, False, 0, nil, nil, SI, PI); + try + if WaitForCompletion then + Result := WaitForSingleObject(PI.hProcess, INFINITE) <> WAIT_FAILED; + finally + CloseHandle(PI.hThread); + CloseHandle(PI.hProcess); + end; +end; + +procedure RunDll32Internal(Wnd: THandle; const DLLName, FuncName, CmdLine: string; CmdShow: Integer = SW_SHOWDEFAULT); +var + H: THandle; + P: TRunDLL32Proc; +begin + H := SafeLoadLibrary(DLLName, SEM_FAILCRITICALERRORS or SEM_NOOPENFILEERRORBOX); + if H <> 0 then + begin + try + P := GetProcAddress(H, PChar(FuncName)); + if Assigned(P) then + P(Wnd, H, PChar(CmdLine), CmdShow); + finally + FreeLibrary(H); + end; + end; +end; + +type + // (p3) from ShLwAPI + TDLLVersionInfo = packed record + cbSize: DWORD; + dwMajorVersion: DWORD; + dwMinorVersion: DWORD; + dwBuildNumber: DWORD; + dwPlatformId: DWORD; + end; + +function GetDLLVersion(const DLLName: string; var pdwMajor, pdwMinor: Integer): Boolean; +var + hDLL, hr: THandle; + pDllGetVersion: function(var Dvi: TDLLVersionInfo): Integer; stdcall; + Dvi: TDLLVersionInfo; +begin + hDLL := SafeLoadLibrary(DLLName); + if hDLL <> 0 then + begin + Result := True; + (* You must get this function explicitly + because earlier versions of the DLL's + don't implement this function. + That makes the lack of implementation + of the function a version marker in itself. *) + @pDllGetVersion := GetProcAddress(hDLL, PChar('DllGetVersion')); + if Assigned(pDllGetVersion) then + begin + FillChar(Dvi, SizeOf(Dvi), #0); + Dvi.cbSize := SizeOf(Dvi); + hr := pDllGetVersion(Dvi); + if hr = 0 then + begin + pdwMajor := Dvi.dwMajorVersion; + pdwMinor := Dvi.dwMinorVersion; + end; + end + else (* If GetProcAddress failed, the DLL is a version previous to the one shipped with IE 3.x. *) + begin + pdwMajor := 4; + pdwMinor := 0; + end; + FreeLibrary(hDLL); + Exit; + end; + Result := False; +end; + +{$ENDIF MSWINDOWS} +{from JvVCLUtils } + +{ Exceptions } + +procedure ResourceNotFound(ResID: PChar); +var + S: string; +begin + if LongRec(ResID).Hi = 0 then + S := IntToStr(LongRec(ResID).Lo) + else + S := StrPas(ResID); + raise EResNotFound.CreateResFmt(@SResNotFound, [S]); +end; +{$ENDIF !CLR} +*******************) + +function RectWidth(R: TRect): Integer; +begin + Result := Abs(R.Right - R.Left); +end; + +function RectHeight(R: TRect): Integer; +begin + Result := Abs(R.Bottom - R.Top); +end; + +function CompareRect(const R1, R2: TRect): Boolean; +begin + Result := (R1.Left = R2.Left) and (R1.Top = R2.Top) and + (R1.Right = R2.Right) and (R1.Bottom = R2.Bottom); +end; + +(****************** +{$IFDEF MSWINDOWS} +{ Service routines } + +{$IFNDEF CLR} +function LoadDLL(const LibName: string): THandle; +begin + Result := SafeLoadLibrary(LibName); + if Result <> 0 then + OSCheck(False); +end; + +function GetWindowsVersion: string; +const + sWindowsVersion = 'Windows %s %d.%.2d.%.3d %s'; +var + Ver: TOSVersionInfo; + Platfrm: string[4]; +begin + Ver.dwOSVersionInfoSize := SizeOf(Ver); + GetVersionEx(Ver); + with Ver do + begin + case dwPlatformId of + VER_PLATFORM_WIN32s: + Platfrm := '32s'; + VER_PLATFORM_WIN32_WINDOWS: + begin + dwBuildNumber := dwBuildNumber and $0000FFFF; + if (dwMajorVersion > 4) or ((dwMajorVersion = 4) and + (dwMinorVersion >= 10)) then + Platfrm := '98' + else + Platfrm := '95'; + end; + VER_PLATFORM_WIN32_NT: Platfrm := 'NT'; + end; + Result := Trim(SysUtils.Format(sWindowsVersion, [Platfrm, dwMajorVersion, + dwMinorVersion, dwBuildNumber, szCSDVersion])); + end; +end; + +{ RegisterServer procedure written by Vladimir Gaitanoff, 2:50/430.2 } + +function RegisterServer(const ModuleName: string): Boolean; +type + TCOMFunc = function: HRESULT; +const + S_OK = $00000000; +var + Handle: THandle; + DllRegServ: TCOMFunc; +begin + Handle := LoadDLL(ModuleName); + try + DllRegServ := GetProcAddress(Handle, 'DllRegisterServer'); + Result := Assigned(DllRegServ) and (DllRegServ() = S_OK); + finally + FreeLibrary(Handle); + end; +end; + +// UnregisterServer by Ralf Kaiser patterned on RegisterServer +function UnregisterServer(const ModuleName: string): Boolean; +type + TCOMFunc = function: HRESULT; +const + S_OK = $00000000; +var + Handle: THandle; + DllUnRegServ: TCOMFunc; + DllCanUnloadNow: TCOMFunc; +begin + Handle := LoadDLL(ModuleName); + try + DllUnRegServ := GetProcAddress(Handle, 'DllUnregisterServer'); + DllCanUnloadNow := GetProcAddress(Handle, 'DllCanUnloadNow'); + Result := Assigned(DllCanUnloadNow) and (DllCanUnloadNow() = S_OK) and + Assigned(DllUnRegServ) and (DllUnRegServ() = S_OK); + finally + FreeLibrary(Handle); + end; +end; + +procedure FreeUnusedOle; +begin + FreeLibrary(GetModuleHandle('OleAut32')); +end; +{$ENDIF !CLR} + +function GetEnvVar(const VarName: string): string; +begin + Result := GetEnvironmentVariable(VarName); +end; + +{$ENDIF MSWINDOWS} + +{$IFDEF UNIX} +function GetEnvVar(const VarName: string): string; +begin + Result := getenv(PChar(VarName)); +end; +{$ENDIF UNIX} + +{ Memory routines } + +{$IFNDEF CLR} +function AllocMemo(Size: Longint): Pointer; +begin + if Size > 0 then + Result := GlobalAllocPtr(HeapAllocFlags or GMEM_ZEROINIT, Size) + else + Result := nil; +end; + +function ReallocMemo(fpBlock: Pointer; Size: Longint): Pointer; +begin + Result := GlobalReallocPtr(fpBlock, Size, HeapAllocFlags or GMEM_ZEROINIT); +end; + +procedure FreeMemo(var fpBlock: Pointer); +begin + if fpBlock <> nil then + begin + GlobalFreePtr(fpBlock); + fpBlock := nil; + end; +end; + +function GetMemoSize(fpBlock: Pointer): Longint; +var + hMem: THandle; +begin + Result := 0; + if fpBlock <> nil then + begin + hMem := GlobalHandle(fpBlock); + if hMem <> 0 then + Result := GlobalSize(hMem); + end; +end; + +function CompareMem(fpBlock1, fpBlock2: Pointer; Size: Cardinal): Boolean; assembler; +asm + PUSH ESI + PUSH EDI + MOV ESI,fpBlock1 + MOV EDI,fpBlock2 + MOV ECX,Size + MOV EDX,ECX + XOR EAX,EAX + AND EDX,3 + SHR ECX,2 + REPE CMPSD + JNE @@2 + MOV ECX,EDX + REPE CMPSB + JNE @@2 +@@1: INC EAX +@@2: POP EDI + POP ESI +end; +{$ENDIF !CLR} + +{ Manipulate huge pointers routines by Ray Lischner, The Waite Group, Inc. } + +{$IFNDEF CLR} +procedure HugeInc(var HugePtr: Pointer; Amount: Longint); +begin + HugePtr := PChar(HugePtr) + Amount; +end; + +procedure HugeDec(var HugePtr: Pointer; Amount: Longint); +begin + HugePtr := PChar(HugePtr) - Amount; +end; + +function HugeOffset(HugePtr: Pointer; Amount: Longint): Pointer; +begin + Result := PChar(HugePtr) + Amount; +end; + +procedure HMemCpy(DstPtr, SrcPtr: Pointer; Amount: Longint); +begin + Move(SrcPtr^, DstPtr^, Amount); +end; + +procedure HugeMove(Base: Pointer; Dst, Src, Size: Longint); +var + SrcPtr, DstPtr: PChar; +begin + SrcPtr := PChar(Base) + Src * SizeOf(Pointer); + DstPtr := PChar(Base) + Dst * SizeOf(Pointer); + Move(SrcPtr^, DstPtr^, Size * SizeOf(Pointer)); +end; +{$ENDIF !CLR} + +{ String routines } + +{$IFNDEF CLR} +{ function GetParamStr copied from SYSTEM.PAS unit of Delphi 2.0 } + +function GetParamStr(P: PChar; var Param: string): PChar; +var + Len: Integer; + Buffer: array [Byte] of Char; +begin + while True do + begin + while (P[0] <> #0) and (P[0] <= ' ') do + Inc(P); + if (P[0] = '"') and (P[1] = '"') then + Inc(P, 2) + else + Break; + end; + Len := 0; + while P[0] > ' ' do + if P[0] = '"' then + begin + Inc(P); + while (P[0] <> #0) and (P[0] <> '"') do + begin + Buffer[Len] := P[0]; + Inc(Len); + Inc(P); + end; + if P[0] <> #0 then + Inc(P); + end + else + begin + Buffer[Len] := P[0]; + Inc(Len); + Inc(P); + end; + SetString(Param, Buffer, Len); + Result := P; +end; + +function ParamCountFromCommandLine(CmdLine: PChar): Integer; +var + S: string; + P: PChar; +begin + P := CmdLine; + Result := 0; + while True do + begin + P := GetParamStr(P, S); + if S = '' then + Break; + Inc(Result); + end; +end; + +function ParamStrFromCommandLine(CmdLine: PChar; Index: Integer): string; +var + P: PChar; +begin + P := CmdLine; + while True do + begin + P := GetParamStr(P, Result); + if (Index = 0) or (Result = '') then + Break; + Dec(Index); + end; +end; +{$ENDIF !CLR} + +procedure SplitCommandLine(const CmdLine: string; var ExeName, Params: string); +{$IFDEF CLR} +var + I, Len: Integer; +begin + ExeName := Trim(CmdLine); + Len := Length(ExeName); + if Len > 0 then + begin + if ExeName[1] = '"' then + begin + I := 2; + while (I < Len) do + begin + if ExeName[I] = '"' then + begin + if ExeName[I + 1] = '"' then + Inc(I) + else + Break; + end; + Inc(I); + end; + end + else + I := Pos(' ', ExeName); + + if (I = 0) or (I >= Len) then + Params := '' + else + begin + Params := Trim(Copy(ExeName, I + 1, MaxInt)); + Delete(ExeName, I, MaxInt); + end; + end + else + Params := ''; +end; +{$ELSE} +var + Buffer: PChar; + Cnt, I: Integer; + S: string; +begin + ExeName := ''; + Params := ''; + Buffer := StrPAlloc(CmdLine); + try + Cnt := ParamCountFromCommandLine(Buffer); + if Cnt > 0 then + begin + ExeName := ParamStrFromCommandLine(Buffer, 0); + for I := 1 to Cnt - 1 do + begin + S := ParamStrFromCommandLine(Buffer, I); + if Pos(' ', S) > 0 then + S := '"' + S + '"'; + Params := Params + S; + if I < Cnt - 1 then + Params := Params + ' '; + end; + end; + finally + StrDispose(Buffer); + end; +end; +{$ENDIF CLR} + +function AnsiUpperFirstChar(const S: AnsiString): AnsiString; +var + Temp: string[1]; +begin + Result := AnsiLowerCase(S); + if S <> '' then + begin + Temp := Result[1]; + Temp := AnsiUpperCase(Temp); + Result[1] := Temp[1]; + end; +end; + +{$IFNDEF CLR} +function StrPAlloc(const S: string): PChar; +begin + Result := StrPCopy(StrAlloc(Length(S) + 1), S); +end; + +function StringToPChar(var S: string): PChar; +begin + Result := PChar(S); +end; +{$ENDIF !CLR} + +function DropT(const S: string): string; +begin + if (UpCase(S[1]) = 'T') and (Length(S) > 1) then + Result := Copy(S, 2, MaxInt) + else + Result := S; +end; + +{$IFNDEF CLR} +function WindowClassName(Wnd: THandle): string; +var + Buffer: array [0..255] of Char; +begin + SetString(Result, Buffer, GetClassName(Wnd, Buffer, SizeOf(Buffer) - 1)); +end; +{$ENDIF !CLR} + + + +function GetAnimation: Boolean; +var + Info: TAnimationInfo; +begin + Info.cbSize := SizeOf(Info); + if SystemParametersInfo(SPI_GETANIMATION, Info.cbSize, {$IFNDEF CLR}@{$ENDIF}Info, 0) then + Result := Info.iMinAnimate <> 0 + else + Result := False; +end; + +procedure SetAnimation(Value: Boolean); +var + Info: TAnimationInfo; +begin + Info.cbSize := SizeOf(Info); + Info.iMinAnimate := Integer(Value); + SystemParametersInfo(SPI_SETANIMATION, Info.cbSize, {$IFNDEF CLR}@{$ENDIF}Info, 0); +end; + +procedure ShowWinNoAnimate(Handle: THandle; CmdShow: Integer); +var + Animation: Boolean; +begin + Animation := GetAnimation; + if Animation then + SetAnimation(False); + ShowWindow(Handle, CmdShow); + if Animation then + SetAnimation(True); +end; + +procedure SwitchToWindow(Wnd: THandle; Restore: Boolean); +begin + if Windows.IsWindowEnabled(Wnd) then + begin + SetForegroundWindow(Wnd); + if Restore and Windows.IsWindowVisible(Wnd) then + begin + if not IsZoomed(Wnd) then + SendMessage(Wnd, WM_SYSCOMMAND, SC_RESTORE, 0); + Windows.SetFocus(Wnd); + end; + end; +end; + +function GetWindowParent(Wnd: THandle): THandle; +begin + Result := GetWindowLong(Wnd, GWL_HWNDPARENT); +end; + +procedure ActivateWindow(Wnd: THandle); +begin + if Wnd <> 0 then + begin + ShowWinNoAnimate(Wnd, SW_SHOW); + SetForegroundWindow(Wnd); + end; +end; + +{$IFNDEF CLR} +{$IFDEF BCB} +function FindPrevInstance(const MainFormClass: ShortString; + const ATitle: string): THandle; +{$ELSE} +function FindPrevInstance(const MainFormClass, ATitle: string): THandle; +{$ENDIF BCB} +var + BufClass, BufTitle: PChar; +begin + Result := 0; + if (MainFormClass = '') and (ATitle = '') then + Exit; + BufClass := nil; + BufTitle := nil; + if MainFormClass <> '' then + BufClass := StrPAlloc(MainFormClass); + if ATitle <> '' then + BufTitle := StrPAlloc(ATitle); + try + Result := FindWindow(BufClass, BufTitle); + finally + StrDispose(BufTitle); + StrDispose(BufClass); + end; +end; + +function WindowsEnum(Handle: THandle; Param: Longint): BOOL; export; stdcall; +begin + if WindowClassName(Handle) = 'TAppBuilder' then + begin + Result := False; + PLongint(Param)^ := 1; + end + else + Result := True; +end; + +{$IFDEF BCB} +function ActivatePrevInstance(const MainFormClass: ShortString; + const ATitle: string): Boolean; +{$ELSE} +function ActivatePrevInstance(const MainFormClass, ATitle: string): Boolean; +{$ENDIF BCB} +var + PrevWnd, PopupWnd, ParentWnd: HWND; + IsDelphi: Longint; +begin + Result := False; + PrevWnd := FindPrevInstance(MainFormClass, ATitle); + if PrevWnd <> 0 then + begin + ParentWnd := GetWindowParent(PrevWnd); + while (ParentWnd <> GetDesktopWindow) and (ParentWnd <> 0) do + begin + PrevWnd := ParentWnd; + ParentWnd := GetWindowParent(PrevWnd); + end; + if WindowClassName(PrevWnd) = 'TApplication' then + begin + IsDelphi := 0; + EnumThreadWindows(GetWindowTask(PrevWnd), @WindowsEnum, + LPARAM(@IsDelphi)); + if Boolean(IsDelphi) then + Exit; + if IsIconic(PrevWnd) then + begin { application is minimized } + SendMessage(PrevWnd, WM_SYSCOMMAND, SC_RESTORE, 0); + Result := True; + Exit; + end + else + ShowWinNoAnimate(PrevWnd, SW_SHOWNOACTIVATE); + end + else + ActivateWindow(PrevWnd); + PopupWnd := GetLastActivePopup(PrevWnd); + if (PrevWnd <> PopupWnd) and Windows.IsWindowVisible(PopupWnd) and + Windows.IsWindowEnabled(PopupWnd) then + begin + SetForegroundWindow(PopupWnd); + end + else + ActivateWindow(PopupWnd); + Result := True; + end; +end; +{$ENDIF !CLR} + + +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} +function BrowseForFolderNative(const Handle: THandle; const Title: string; var Folder: string): Boolean; +var + BrowseInfo: TBrowseInfo; + Id: PItemIDList; + FN: array [0..MAX_PATH] of Char; +begin + with BrowseInfo do + begin + hwndOwner := Handle; + pidlRoot := nil; + pszDisplayName := FN; + lpszTitle := PChar(Title); + ulFlags := 0; + lpfn := nil; + end; + Id := SHBrowseForFolder(BrowseInfo); + Result := Id <> nil; + if Result then + begin + SHGetPathFromIDList(Id, FN); + Folder := FN; + end; +end; +{$ENDIF MSWINDOWS} +{$ENDIF !CLR} + +procedure FitRectToScreen(var Rect: TRect); +var + X, Y, Delta: Integer; +begin + X := GetSystemMetrics(SM_CXSCREEN); + Y := GetSystemMetrics(SM_CYSCREEN); + with Rect do + begin + if Right > X then + begin + Delta := Right - Left; + Right := X; + Left := Right - Delta; + end; + if Left < 0 then + begin + Delta := Right - Left; + Left := 0; + Right := Left + Delta; + end; + if Bottom > Y then + begin + Delta := Bottom - Top; + Bottom := Y; + Top := Bottom - Delta; + end; + if Top < 0 then + begin + Delta := Bottom - Top; + Top := 0; + Bottom := Top + Delta; + end; + end; +end; + +procedure CenterWindow(Wnd: THandle); +var + R: TRect; +begin + GetWindowRect(Wnd, R); + R := Rect((GetSystemMetrics(SM_CXSCREEN) - R.Right + R.Left) div 2, + (GetSystemMetrics(SM_CYSCREEN) - R.Bottom + R.Top) div 2, + R.Right - R.Left, R.Bottom - R.Top); + FitRectToScreen(R); + SetWindowPos(Wnd, 0, R.Left, R.Top, 0, 0, SWP_NOACTIVATE or + SWP_NOSIZE or SWP_NOZORDER); +end; + + +{ Delete the requested message from the queue, but throw back } +{ any WM_QUIT msgs that PeekMessage may also return. } +{ Copied from DbGrid.pas } +procedure KillMessage(Wnd: THandle; Msg: Cardinal); +var + M: TMsg; +begin + M.Message := 0; + if PeekMessage(M, Wnd, Msg, Msg, PM_REMOVE) and (M.Message = WM_QUIT) then + PostQuitMessage(M.WParam); +end; + + +procedure SetWindowTop(const Handle: THandle; const Top: Boolean); +const + TopFlag: array [Boolean] of Longword = (HWND_NOTOPMOST, HWND_TOPMOST); +begin + SetWindowPos(Handle, TopFlag[Top], 0, 0, 0, 0, SWP_NOMOVE or + SWP_NOSIZE or SWP_NOACTIVATE); +end; + +function MakeVariant(const Values: array of Variant): Variant; +begin + if High(Values) - Low(Values) > 1 then + Result := VarArrayOf(Values) + else + if High(Values) - Low(Values) = 1 then + Result := Values[Low(Values)] + else + Result := Null; +end; + +{$IFDEF MSWINDOWS} +{ Dialog units } + +function DialogUnitsToPixelsX(DlgUnits: Word): Word; +begin + Result := (DlgUnits * LoWord(GetDialogBaseUnits)) div 4; +end; + +function DialogUnitsToPixelsY(DlgUnits: Word): Word; +begin + Result := (DlgUnits * HiWord(GetDialogBaseUnits)) div 8; +end; + +function PixelsToDialogUnitsX(PixUnits: Word): Word; +begin + Result := PixUnits * 4 div LoWord(GetDialogBaseUnits); +end; + +function PixelsToDialogUnitsY(PixUnits: Word): Word; +begin + Result := PixUnits * 8 div HiWord(GetDialogBaseUnits); +end; + +{$ENDIF MSWINDOWS} + +function GetUniqueFileNameInDir(const Path, FileNameMask: string): string; +var + CurrentName: string; + I: Integer; +begin + Result := ''; + for I := 0 to MaxInt do + begin + CurrentName := SysUtils.Format(FileNameMask, [I]); + if not FileExists(NormalDir(Path) + CurrentName) then + begin + Result := CurrentName; + Exit; + end; + end; +end; + +{$IFNDEF CLR} + +procedure AntiAlias(Clip: TBitmap); +begin + AntiAliasRect(Clip, 0, 0, Clip.Width, Clip.Height); +end; + + + // (p3) duplicated from JvTypes to avoid JVCL dependencies +type + TJvRGBTriple = packed record + rgbBlue: Byte; + rgbGreen: Byte; + rgbRed: Byte; + end; + +type + PJvRGBArray = ^TJvRGBArray; + TJvRGBArray = array [0..32766] of TJvRGBTriple; + + +procedure AntiAliasRect(Clip: TBitmap; + XOrigin, YOrigin, XFinal, YFinal: Integer); +var + Tmp, X, Y: Integer; + Line0, Line1, Line2: PJvRGBArray; + OPF: TPixelFormat; +begin + // swap values + if XFinal < XOrigin then + begin + Tmp := XOrigin; + XOrigin := XFinal; + XFinal := Tmp; + end; + if YFinal < YOrigin then + begin + Tmp := YOrigin; + YOrigin := YFinal; + YFinal := Tmp; + end; + XOrigin := Max(1, XOrigin); + YOrigin := Max(1, YOrigin); + XFinal := Min(Clip.Width - 2, XFinal); + YFinal := Min(Clip.Height - 2, YFinal); + OPF := Clip.PixelFormat; + Clip.PixelFormat := pf24bit; + for Y := YOrigin to YFinal do + begin + Line0 := Clip.ScanLine[Y - 1]; + Line1 := Clip.ScanLine[Y]; + Line2 := Clip.ScanLine[Y + 1]; + for X := XOrigin to XFinal do + begin + Line1[X].rgbRed := (Line0[X].rgbRed + Line2[X].rgbRed + Line1[X - 1].rgbRed + Line1[X + 1].rgbRed) div 4; + Line1[X].rgbGreen := (Line0[X].rgbGreen + Line2[X].rgbGreen + Line1[X - 1].rgbGreen + Line1[X + 1].rgbGreen) div + 4; + Line1[X].rgbBlue := (Line0[X].rgbBlue + Line2[X].rgbBlue + Line1[X - 1].rgbBlue + Line1[X + 1].rgbBlue) div 4; + end; + end; + Clip.PixelFormat := OPF; +end; + +{$ENDIF !CLR} + + +{$IFNDEF CLR} + +procedure CopyRectDIBits(ACanvas: TCanvas; const DestRect: TRect; ABitmap: TBitmap; + const SourceRect: TRect); +var + Header, Bits: Pointer; + HeaderSize, BitsSize: Cardinal; + Bmp: TBitmap; +begin + if ABitmap.PixelFormat < pf15bit then + begin + Bmp := ABitmap; + // this function does not support palettes + ABitmap := TBitmap.Create; + ABitmap.Assign(Bmp); + ABitmap.PixelFormat := pf24bit; + end + else + Bmp := nil; + try + GetDIBSizes(ABitmap.Handle, HeaderSize, BitsSize); + { Do not use Delphi's memory manager. } + Header := VirtualAlloc(nil, HeaderSize, MEM_COMMIT, PAGE_READWRITE); + Bits := VirtualAlloc(nil, BitsSize, MEM_COMMIT, PAGE_READWRITE); + try + GetDIB(ABitmap.Handle, ABitmap.Palette, Header^, Bits^); + StretchDIBits(ACanvas.Handle, + DestRect.Left, DestRect.Top, + DestRect.Right - DestRect.Left, DestRect.Bottom - DestRect.Top, + SourceRect.Left, SourceRect.Top, + SourceRect.Right - SourceRect.Left, SourceRect.Bottom - SourceRect.Top, + Bits, TBitmapInfo(Header^), + DIB_RGB_COLORS, ACanvas.CopyMode); + finally + VirtualFree(Bits, 0, MEM_FREE); + VirtualFree(Header, 0, MEM_FREE); + end; + finally + if Bmp <> nil then + ABitmap.Free; + end; +end; +{$ENDIF !CLR} + +function IsTTFontSelected(const DC: HDC): Boolean; +var + Metrics: TTextMetric; +begin + GetTextMetrics(DC, Metrics); + Result := (Metrics.tmPitchAndFamily and TMPF_TRUETYPE) <> 0; +end; + +// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/fontext_6rlf.asp + +function IsTrueType(const FontName: string): Boolean; +var + Canvas: TCanvas; +begin + Canvas := TCanvas.Create; + try + Canvas.Handle := GetDC(HWND_DESKTOP); + Canvas.Font.Name := FontName; + Result := IsTTFontSelected(Canvas.Handle); + ReleaseDC(HWND_DESKTOP, Canvas.Handle); + Canvas.Handle := NullHandle; + finally + Canvas.Free; + end; +end; + + + +function TextToValText(const AValue: string): string; +var + I, J: Integer; +begin + Result := DelRSpace(AValue); + if DecimalSeparator <> ThousandSeparator then + Result := DelChars(Result, ThousandSeparator{$IFDEF CLR}[1]{$ENDIF}); + + if (DecimalSeparator <> '.') and (ThousandSeparator <> '.') then + Result := ReplaceStr(Result, '.', DecimalSeparator); + if (DecimalSeparator <> ',') and (ThousandSeparator <> ',') then + Result := ReplaceStr(Result, ',', DecimalSeparator); + + J := 1; + for I := 1 to Length(Result) do + if Result[I] in ['0'..'9', '-', '+', + AnsiChar(DecimalSeparator{$IFDEF CLR}[1]{$ENDIF}), AnsiChar(ThousandSeparator{$IFDEF CLR}[1]{$ENDIF})] then + begin + Result[J] := Result[I]; + Inc(J); + end; + SetLength(Result, J - 1); + + if Result = '' then + Result := '0' + else + if Result = '-' then + Result := '-0'; +end; + +******************** NOT CONVERTED *) + +function DrawText(Canvas: TCanvas; const Text: string; Len: Integer; var R: TRect; WinFlags: Integer): Integer; overload; +begin + Result := DrawText(Canvas, PChar(Text), Len, R, WinFlags and not DT_MODIFYSTRING); +end; + +function DrawText(Canvas: TCanvas; Text: PAnsiChar; Len: Integer; var R: TRect; WinFlags: Integer): Integer; +begin + //TODO: Patch with referenced one by Luiz Americo when GDK used + Result := LCLIntf.DrawText(Canvas.Handle, Text, Len, R, WinFlags); +end; + +(******************** NOT CONVERTED + +function DrawText(DC: HDC; const Text: TCaption; Len: Integer; var R: TRect; WinFlags: Integer): Integer; overload; +begin + {$IFDEF CLR} + Result := Windows.DrawText(DC, Text, Len, R, WinFlags and not DT_MODIFYSTRING); // make sure the string cannot be modified + {$ELSE} + Result := Windows.DrawText(DC, PChar(Text), Len, R, WinFlags and not DT_MODIFYSTRING); // make sure the string cannot be modified + {$ENDIF CLR} +end; + +function DrawTextEx(Canvas: TCanvas; const Text: string; cchText: Integer; var p4: TRect; dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; +begin + Result := Windows.DrawTextEx(Canvas.Handle, PChar(Text), cchText, p4, dwDTFormat and not DT_MODIFYSTRING, DTParams); +end; + +function DrawTextEx(Canvas: TCanvas; lpchText: PChar; cchText: Integer; var p4: TRect; dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; +begin + Result := Windows.DrawTextEx(Canvas.Handle, lpchText, cchText, p4, dwDTFormat, DTParams); +end; + +{$IFDEF COMPILER6_UP} + +function DrawText(Canvas: TCanvas; const Text: WideString; Len: Integer; var R: TRect; WinFlags: Integer): Integer; overload; +begin + Result := DrawTextW(Canvas, Text, Len, R, WinFlags and not DT_MODIFYSTRING); +end; + +function DrawTextEx(Canvas: TCanvas; const Text: WideString; cchText: Integer; var p4: TRect; dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; overload; +begin + Result := DrawTextExW(Canvas, Text, cchText, p4, dwDTFormat and not DT_MODIFYSTRING, DTParams); +end; + +{$ENDIF COMPILER6_UP} + +function DrawTextW(Canvas: TCanvas; const Text: WideString; Len: Integer; var R: TRect; WinFlags: Integer): Integer; overload; +begin + Result := DrawTextW(Canvas, PWideChar(Text), Len, R, WinFlags and not DT_MODIFYSTRING); +end; + +function DrawTextW(Canvas: TCanvas; Text: PWideChar; Len: Integer; var R: TRect; WinFlags: Integer): Integer; +begin + Result := Windows.DrawTextW(Canvas.Handle, Text, Len, R, WinFlags); +end; + +function DrawTextExW(Canvas: TCanvas; lpchText: PWideChar; cchText: Integer; var p4: TRect; dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; +begin + Result := Windows.DrawTextExW(Canvas.Handle, lpchText, cchText, p4, dwDTFormat, DTParams); +end; + +function DrawTextExW(Canvas: TCanvas; const Text: WideString; cchText: Integer; var p4: TRect; dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; +begin + Result := Windows.DrawTextExW(Canvas.Handle, PWideChar(Text), cchText, p4, dwDTFormat and not DT_MODIFYSTRING, DTParams); +end; + +const + // (p3) move to interface? + ROP_DSna = $00220326; // RasterOp_NotAndROP + {$EXTERNALSYM ROP_DSna} + ROP_DSno = MERGEPAINT; + {$EXTERNALSYM ROP_DSno} + ROP_DPSnoo = PATPAINT; + {$EXTERNALSYM ROP_DPSnoo} + ROP_D = $00AA0029; // RasterOp_NopROP + {$EXTERNALSYM ROP_D} + ROP_Dn = DSTINVERT; // DSTINVERT + {$EXTERNALSYM ROP_Dn} + ROP_SDna = SRCERASE; // SRCERASE + {$EXTERNALSYM ROP_SDna} + ROP_SDno = $00DD0228; // RasterOp_OrNotROP + {$EXTERNALSYM ROP_SDno} + ROP_DSan = $007700E6; // RasterOp_NandROP + {$EXTERNALSYM ROP_DSan} + ROP_DSon = $001100A6; // NOTSRCERASE + {$EXTERNALSYM ROP_DSon} + +function RasterOpToWinRop(Rop: RasterOp): Cardinal; +begin + case Rop of + RasterOp_ClearROP: + Result := BLACKNESS; + RasterOp_NotROP: + Result := DSTINVERT; + RasterOp_NotOrROP: + Result := MERGEPAINT; + RasterOp_NotCopyROP: + Result := NOTSRCCOPY; + RasterOp_NorROP: + Result := NOTSRCERASE; + RasterOp_AndROP: + Result := SRCAND; + RasterOp_CopyROP: + Result := SRCCOPY; + RasterOp_AndNotROP: + Result := SRCERASE; + RasterOp_XorROP: + Result := SRCINVERT; + RasterOp_OrROP: + Result := SRCPAINT; + RasterOp_SetROP: + Result := WHITENESS; + RasterOp_NotAndROP: + Result := ROP_DSna; + RasterOp_NopROP: + Result := ROP_D; + RasterOp_OrNotROP: + Result := ROP_SDno; + RasterOp_NandROP: + Result := ROP_DSan; + else + Result := 0; + end; +end; + +function BitBlt(DestCanvas: TCanvas; X, Y, Width, Height: Integer; SrcCanvas: TCanvas; + XSrc, YSrc: Integer; WinRop: Cardinal; IgnoreMask: Boolean = True): LongBool; +begin + // NB! IgnoreMask is not supported in VCL! + Result := Windows.BitBlt(DestCanvas.Handle, X, Y, Width, Height, SrcCanvas.Handle, + XSrc, YSrc, WinRop); +end; + +function BitBlt(DestDC: HDC; X, Y, Width, Height: Integer; SrcDC: HDC; + XSrc, YSrc: Integer; Rop: RasterOp; IgnoreMask: Boolean): LongBool; +begin + Result := Windows.BitBlt(DestDC, X, Y, Width, Height, SrcDC, XSrc, YSrc, RasterOpToWinRop(Rop)); +end; + +function BitBlt(DestDC: HDC; X, Y, Width, Height: Integer; SrcDC: HDC; + XSrc, YSrc: Integer; WinRop: Cardinal; IgnoreMask: Boolean): LongBool; +begin + Result := Windows.BitBlt(DestDC, X, Y, Width, Height, SrcDC, XSrc, YSrc, WinRop); +end; + +function BitBlt(DestDC: HDC; X, Y, Width, Height: Integer; SrcDC: HDC; XSrc, YSrc: Integer; WinRop: Cardinal): LongBool; +begin + Result := Windows.BitBlt(DestDC, X, Y, Width, Height, SrcDC, XSrc, YSrc, WinRop); +end; + + + + + +function IsEqualGUID(const IID1, IID2: TGUID): Boolean; +begin + {$IFDEF COMPILER5} + Result := CompareMem(@IID1, @IID2, SizeOf(IID1)); + {$ELSE} + Result := SysUtils.IsEqualGUID(IID1, IID2); + {$ENDIF COMPILER5} +end; + +{Color functions} +procedure RGBToHSV(R, G, B: Integer; var H, S, V: Integer); + +var + Delta: Integer; + Min, Max: Integer; + + function GetMax(I, J, K: Integer): Integer; + begin + if J > I then + I := J; + if K > I then + I := K; + Result := I; + end; + + function GetMin(I, J, K: Integer): Integer; + begin + if J < I then + I := J; + if K < I then + I := K; + Result := I; + end; + + +begin + Min := GetMin(R, G, B); + Max := GetMax(R, G, B); + V := Max; + Delta := Max - Min; + if Max = 0 then + S := 0 + else + S := (255 * Delta) div Max; + if S = 0 then + H := 0 + else + begin + if R = Max then + H := (60 * (G - B)) div Delta + else + if G = Max then + H := 120 + (60 * (B - R)) div Delta + else + H := 240 + (60 * (R - G)) div Delta; + if H < 0 then + H := H + 360; + end; +end; + +function RGBToBGR(Value: Cardinal): Cardinal; +begin + Result := + ((Value and $00FF0000) shr 16) or + (Value and $0000FF00) or + ((Value and $000000FF) shl 16); +end; + +function ColorToPrettyName(Value: TColor): string; +var + Index: Integer; +begin + for Index := Low(ColorValues) to High(ColorValues) do + if Value = ColorValues[Index].Value then + begin + Result := ColorValues[Index].Description; + Exit; + end; + for Index := Low(StandardColorValues) to High(StandardColorValues) do + if Value = StandardColorValues[Index].Value then + begin + Result := StandardColorValues[Index].Description; + Exit; + end; + for Index := Low(SysColorValues) to High(SysColorValues) do + if Value = SysColorValues[Index].Value then + begin + Result := SysColorValues[Index].Description; + Exit; + end; + Result := ColorToString(Value); +end; + +function PrettyNameToColor(const Value: string): TColor; +var + Index: Integer; + ColorResult: Integer; +begin + for Index := Low(ColorValues) to High(ColorValues) do + begin + if CompareText(Value, ColorValues[Index].Description) = 0 then + begin + Result := ColorValues[Index].Value; + Exit; + end; + end; + for Index := Low(StandardColorValues) to High(StandardColorValues) do + begin + if CompareText(Value, StandardColorValues[Index].Description) = 0 then + begin + Result := StandardColorValues[Index].Value; + Exit; + end; + end; + for Index := Low(SysColorValues) to High(SysColorValues) do + begin + if CompareText(Value, SysColorValues[Index].Description) = 0 then + begin + Result := SysColorValues[Index].Value; + Exit; + end; + end; + if IdentToColor(Value, ColorResult) then + Result := ColorResult + else + Result := clNone; +end; + +{$IFNDEF CLR} +function StartsText(const SubStr, S: string): Boolean; +begin + Result := AnsiStartsText(SubStr, S); +end; + +function EndsText(const SubStr, S: string): Boolean; +begin + Result := AnsiEndsText(SubStr, S); +end; + +function DequotedStr(const S: string; QuoteChar: Char = ''''): string; +begin + Result := AnsiDequotedStr(S, QuoteChar); +end; + +function AnsiDequotedStr(const S: AnsiString; AQuote: AnsiChar): AnsiString; +var + P: PChar; +begin + P := PChar(S); + Result := AnsiExtractQuotedStr(P, AQuote); +end; +{$ENDIF !CLR} + +{$IFNDEF BCB} +{$IFDEF COMPILER5} +{ These functions simply call their JvVCL5Utils equivalents } + +function TryStrToInt(const S: string; out Value: Integer): Boolean; +begin + Result := JvVCL5Utils.TryStrToInt(S, Value); +end; + +function TryStrToDateTime(const S: string; out Date: TDateTime): Boolean; +begin + Result := JvVCL5Utils.TryStrToDateTime(S, Date); +end; + +function StrToDateTimeDef(const S: string; Default: TDateTime): TDateTime; +begin + Result := JvVCL5Utils.StrToDateTimeDef(S, Default); +end; + +// function StrToFloatDef(const Str: string; Default: Extended): Extended; +procedure RaiseLastOSError; +begin + JvVCL5Utils.RaiseLastOSError; +end; + +function IncludeTrailingPathDelimiter(const APath: string): string; +begin + Result := JvVCL5Utils.IncludeTrailingPathDelimiter(APath); +end; + +function ExcludeTrailingPathDelimiter(const APath: string): string; +begin + Result := JvVCL5Utils.ExcludeTrailingPathDelimiter(APath); +end; + +function DirectoryExists(const Name: string): Boolean; +begin + Result := JvVCL5Utils.DirectoryExists(Name); +end; + +function ForceDirectories(Dir: string): Boolean; +begin + Result := JvVCL5Utils.ForceDirectories(Dir); +end; + +function SameFileName(const FN1, FN2: string): Boolean; +begin + Result := JvVCL5Utils.SameFileName(FN1, FN2); +end; + +function WideCompareText(const S1, S2: WideString): Integer; +begin + Result := JvVCL5Utils.WideCompareText(S1, S2); +end; + +function WideUpperCase(const S: WideString): WideString; +begin + Result := JvVCL5Utils.WideUpperCase(S); +end; + +function WideLowerCase(const S: WideString): WideString; +begin + Result := JvVCL5Utils.WideLowerCase(S); +end; + +function CompareDateTime(const A, B: TDateTime): Integer; +begin + Result := JvVCL5Utils.CompareDateTime(A, B); +end; + +// StrUtils +function AnsiStartsText(const SubText, Text: string): Boolean; +begin + Result := JvVCL5Utils.AnsiStartsText(SubText, Text); +end; + +function AnsiEndsText(const SubText, Text: string): Boolean; +begin + Result := JvVCL5Utils.AnsiEndsText(SubText, Text); +end; + +function AnsiStartsStr(const SubStr, Str: string): Boolean; +begin + Result := JvVCL5Utils.AnsiStartsStr(SubStr, Str); +end; + +function AnsiEndsStr(const SubStr, Str: string): Boolean; +begin + Result := JvVCL5Utils.AnsiEndsStr(SubStr, Str); +end; + +// Variants +function VarIsStr(const V: Variant): Boolean; +begin + Result := JvVCL5Utils.VarIsStr(V); +end; + +{$ENDIF COMPILER5} +{$ENDIF !BCB} + +procedure CollectionQuickSort(List: Classes.TCollection; L, R: Integer; SortProc: TCollectionSortProc); +var + I, J, pix: Integer; + P, t1, t2: TCollectionItem; +begin + List.BeginUpdate; + repeat + I := L; + J := R; + pix := (L+R) shr 1; + if pix > List.Count - 1 then + pix := List.Count - 1; + P := List.Items[pix]; + + repeat + while SortProc(List.Items[I], P) < 0 do + Inc(I); + while SortProc(List.Items[J], P) > 0 do + Dec(J); + + if I <= J then + begin + t1 := List.Items[I]; + t2 := List.Items[J]; + t1.Index := J; + t2.Index := I; + + if pix = I then + pix := J + else + if pix = J then + pix := I; + + P := List.Items[pix]; + Inc(I); + Dec(J); + end; + until I > J; + if L < J then + CollectionQuickSort(List, L, J, SortProc); + L := I; + until I >= R; + List.EndUpdate; +end; + +procedure CollectionSort(Collection: Classes.TCollection; SortProc: TCollectionSortProc); +begin + if Assigned(Collection) and Assigned(SortProc) and (Collection.Count >= 2) then + CollectionQuickSort(Collection, 0, Collection.Count - 1, SortProc); +end; + +{$IFDEF COMPILER5} +function SecondsBetween(const Now: TDateTime; const FTime: TDateTime): Integer; +begin + Result := Trunc(86400 * (FTime - Now)); +end; +{$ENDIF COMPILER5} + +{ TIntegerList } + +function TIntegerList.Add(Value: Integer): Integer; +begin + Result := inherited Add(Pointer(Value)); +end; + +{$IFDEF COMPILER5} +procedure TIntegerList.Assign(Source: TList); +var + I: Integer; +begin + Clear; + Capacity := Source.Count; + for I := 0 to Source.Count - 1 do + Add(Integer(Source[I])); +end; +{$ENDIF COMPILER5} + +procedure TIntegerList.DoChange(Item: Integer; Action: TListNotification); +begin + if Assigned(OnChange) then + OnChange(Self, Item, Action); +end; + +function TIntegerList.Extract(Item: Integer): Integer; +begin + Result := Integer(inherited Extract(Pointer(Item))); +end; + +function TIntegerList.First: Integer; +begin + Result := Integer(inherited First); +end; + +function TIntegerList.GetItem(Index: Integer): Integer; +begin + Result := Integer(inherited Items[Index]); +end; + +function TIntegerList.IndexOf(Item: Integer): Integer; +begin + Result := inherited IndexOf(Pointer(Item)); +end; + +procedure TIntegerList.Insert(Index, Item: Integer); +begin + inherited Insert(Index, Pointer(Item)); +end; + +function TIntegerList.Last: Integer; +begin + Result := Integer(inherited Last); +end; + +procedure TIntegerList.Notify(Ptr: Pointer; Action: TListNotification); +begin + DoChange(Integer(Ptr), Action); +end; + +procedure TIntegerList.ReadData(Reader: TReader); +begin + FLoading := True; + try + Clear; + Reader.ReadListBegin; + while not Reader.EndOfList do + begin + Add(Reader.ReadInteger); + end; + Reader.ReadListEnd; + finally + FLoading := False; + end; +end; + +function TIntegerList.Remove(Item: Integer): Integer; +begin + Result := Integer(inherited Remove(Pointer(Item))); +end; + +procedure TIntegerList.SetItem(Index: Integer; const Value: Integer); +begin + inherited Items[Index] := Pointer(Value); +end; + +procedure TIntegerList.WriteData(Writer: TWriter); +var + I: Integer; +begin + Writer.WriteListBegin; + for I := 0 to Count - 1 do + Writer.WriteInteger(Items[I]); + Writer.WriteListEnd; +end; + +******************** NOT CONVERTED *) + +end. + + diff --git a/components/jvcllaz/run/JvJVCLUtils.pas b/components/jvcllaz/run/JvJVCLUtils.pas new file mode 100644 index 000000000..828bbc95e --- /dev/null +++ b/components/jvcllaz/run/JvJVCLUtils.pas @@ -0,0 +1,7694 @@ +{----------------------------------------------------------------------------- +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: JvJVCLUtils.PAS, released on 2002-09-24. + +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. + +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: +-----------------------------------------------------------------------------} +// $Id: JvJVCLUtils.pas 11413 2007-07-11 20:23:46Z ahuser $ + +// Initial port to Lazarus by Sergio Samayoa - september 2007. +// Conversion is done in incremental way: as types / classes / routines +// are needed they are converted. + +{$mode objfpc}{$H+} + +unit JvJVCLUtils; + +interface +uses + Classes, Graphics, JvTypes; + +(******************** NOT CONVERTED +// Transform an icon to a bitmap +function IconToBitmap(Ico: HICON): TBitmap; +// Transform an icon to a bitmap using an image list +function IconToBitmap2(Ico: HICON; Size: Integer = 32; + TransparentColor: TColor = clNone): TBitmap; +function IconToBitmap3(Ico: HICON; Size: Integer = 32; + TransparentColor: TColor = clNone): TBitmap; + +// bitmap manipulation functions +// NOTE: Dest bitmap must be freed by caller! +// get red channel bitmap +procedure GetRBitmap(var Dest: TBitmap; const Source: TBitmap); +// get green channel bitmap +procedure GetGBitmap(var Dest: TBitmap; const Source: TBitmap); +// get blue channel bitmap +procedure GetBBitmap(var Dest: TBitmap; const Source: TBitmap); +// get monochrome bitmap +procedure GetMonochromeBitmap(var Dest: TBitmap; const Source: TBitmap); +// get hue bitmap (h part of hsv) +procedure GetHueBitmap(var Dest: TBitmap; const Source: TBitmap); +// get saturation bitmap (s part of hsv) +procedure GetSaturationBitmap(var Dest: TBitmap; const Source: TBitmap); +// get value bitmap (V part of HSV) +procedure GetValueBitmap(var Dest: TBitmap; const Source: TBitmap); + +// hides / shows the a forms caption area +procedure HideFormCaption(FormHandle: THandle; Hide: Boolean); + +{$IFDEF MSWINDOWS} + +type + TJvWallpaperStyle = (wpTile, wpCenter, wpStretch); + +// set the background wallpaper (two versions) +{$IFNDEF CLR} +procedure SetWallpaper(const Path: string); overload; +{$ENDIF !CLR} +procedure SetWallpaper(const Path: string; Style: TJvWallpaperStyle); overload; + +(-* (rom) to be deleted. Use ScreenShot from JCL +{$IFDEF VCL} +// screen capture functions +function CaptureScreen(IncludeTaskBar: Boolean = True): TBitmap; overload; +function CaptureScreen(Rec: TRect): TBitmap; overload; +function CaptureScreen(WndHandle: Longword): TBitmap; overload; +{$ENDIF VCL} +*-) + +{$ENDIF MSWINDOWS} + +procedure RGBToHSV(R, G, B: Integer; var H, S, V: Integer); + +{ from JvVCLUtils } + +procedure CopyParentImage(Control: TControl; Dest: TCanvas); +{ Windows resources (bitmaps and icons) VCL-oriented routines } +procedure DrawBitmapTransparent(Dest: TCanvas; DstX, DstY: Integer; + Bitmap: TBitmap; TransparentColor: TColor); +procedure DrawBitmapRectTransparent(Dest: TCanvas; DstX, DstY: Integer; + SrcRect: TRect; Bitmap: TBitmap; TransparentColor: TColor); +procedure StretchBitmapRectTransparent(Dest: TCanvas; DstX, DstY, DstW, + DstH: Integer; SrcRect: TRect; Bitmap: TBitmap; TransparentColor: TColor); +{$IFNDEF CLR} +function MakeBitmap(ResID: PChar): TBitmap; +function MakeBitmapID(ResID: Word): TBitmap; +function MakeModuleBitmap(Module: THandle; ResID: PChar): TBitmap; +{$ENDIF !CLR} +function CreateTwoColorsBrushPattern(Color1, Color2: TColor): TBitmap; +function CreateDisabledBitmap_NewStyle(FOriginal: TBitmap; BackColor: TColor): + TBitmap; +function CreateDisabledBitmapEx(FOriginal: TBitmap; OutlineColor, BackColor, + HighLightColor, ShadowColor: TColor; DrawHighlight: Boolean): TBitmap; +function CreateDisabledBitmap(FOriginal: TBitmap; OutlineColor: TColor): + TBitmap; +procedure AssignBitmapCell(Source: TGraphic; Dest: TBitmap; Cols, Rows, + Index: Integer); +function ChangeBitmapColor(Bitmap: TBitmap; Color, NewColor: TColor): TBitmap; +procedure ImageListDrawDisabled(Images: TCustomImageList; Canvas: TCanvas; + X, Y, Index: Integer; HighLightColor, GrayColor: TColor; + DrawHighlight: Boolean); + +{$IFNDEF CLR} +function MakeIcon(ResID: PChar): TIcon; +function MakeIconID(ResID: Word): TIcon; +function MakeModuleIcon(Module: THandle; ResID: PChar): TIcon; +{$ENDIF !CLR} +function CreateBitmapFromIcon(Icon: TIcon; BackColor: TColor): TBitmap; +function CreateIconFromBitmap(Bitmap: TBitmap; TransparentColor: TColor): TIcon; +function CreateRotatedFont(Font: TFont; Angle: Integer): HFONT; + +{$IFNDEF CLR} +// launches the specified CPL file +// format: [,@n] or [,,m] or [,@n,m] +// where @n = zero-based index of the applet to start (if there is more than one +// m is the zero-based index of the tab to display + +procedure LaunchCpl(const FileName: string); + +// for Win 2000 and XP +procedure ShowSafeRemovalDialog; + +{ + GetControlPanelApplets retrieves information about all control panel applets in a specified folder. + APath is the Path to the folder to search and AMask is the filename mask (containing wildcards if necessary) to use. + + The information is returned in the Strings and Images lists according to the following rules: + The Display Name and Path to the CPL file is returned in Strings with the following format: + '=' + You can access the DisplayName by using the Strings.Names array and the Path by accessing the Strings.Values array + Strings.Objects can contain either of two values depending on if Images is nil or not: + * If Images is nil then Strings.Objects contains the image for the applet as a TBitmap. Note that the caller (you) + is responsible for freeing the bitmaps in this case + * If Images <> nil, then the Strings.Objects array contains the index of the image in the Images array for the selected item. + To access and use the ImageIndex, typecast Strings.Objects to an int: + Tmp.Name := Strings.Name[I]; + Tmp.ImageIndex := Integer(Strings.Objects[I]); + The function returns True if any Control Panel Applets were found (i.e Strings.Count is > 0 when returning) +} + +function GetControlPanelApplets(const APath, AMask: string; Strings: TStrings; + Images: TCustomImageList = nil): Boolean; +{ GetControlPanelApplet works like GetControlPanelApplets, with the difference that it only loads and searches one cpl file (according to AFilename). + Note though, that some CPL's contains multiple applets, so the Strings and Images lists can contain multiple return values. + The function returns True if any Control Panel Applets were found in AFilename (i.e if items were added to Strings) +} +function GetControlPanelApplet(const AFileName: string; Strings: TStrings; + Images: TCustomImageList = nil): Boolean; + +{$ENDIF !CLR} + +function PointInPolyRgn(const P: TPoint; const Points: array of TPoint): Boolean; +function PaletteColor(Color: TColor): Longint; +procedure PaintInverseRect(const RectOrg, RectEnd: TPoint); +procedure DrawInvertFrame(ScreenRect: TRect; Width: Integer); + +procedure ShowMDIClientEdge(ClientHandle: THandle; ShowEdge: Boolean); + +function GetTickCount64: Int64; +procedure Delay(MSecs: Int64); +procedure CenterControl(Control: TControl); + +procedure MergeForm(AControl: TWinControl; AForm: TForm; Align: TAlign; + Show: Boolean); +function GetAveCharSize(Canvas: TCanvas): TPoint; +******************** NOT CONVERTED *) + +{ Gradient filling routine } + +type + TFillDirection = (fdTopToBottom, fdBottomToTop, fdLeftToRight, fdRightToLeft); + +procedure GradientFillRect(Canvas: TCanvas; ARect: TRect; StartColor, + EndColor: TColor; Direction: TFillDirection; Colors: Byte); + +(******************** NOT CONVERTED +procedure StartWait; +procedure StopWait; +{$IFNDEF CLR} +function DefineCursor(Instance: THandle; ResID: PChar): TCursor; +{$ENDIF !CLR} +function GetNextFreeCursorIndex(StartHint: Integer; PreDefined: Boolean): + Integer; +function WaitCursor: IInterface; +function ScreenCursor(ACursor: TCursor): IInterface; +{$IFDEF MSWINDOWS} +// loads the more modern looking drag cursors from OLE32.DLL +function LoadOLEDragCursors: Boolean; +// set some default cursor from JVCL +{$ENDIF MSWINDOWS} +procedure SetDefaultJVCLCursors; + +{$IFNDEF CLR} +function LoadAniCursor(Instance: THandle; ResID: PChar): HCURSOR; +{$ENDIF !CLR} + +{ Windows API level routines } + +procedure StretchBltTransparent(DstDC: HDC; DstX, DstY, DstW, DstH: Integer; + SrcDC: HDC; SrcX, SrcY, SrcW, Srch: Integer; + Palette: HPALETTE; TransparentColor: TColorRef); +procedure DrawTransparentBitmap(DC: HDC; Bitmap: HBITMAP; + DstX, DstY: Integer; TransparentColor: TColorRef); +function PaletteEntries(Palette: HPALETTE): Integer; +procedure ShadeRect(DC: HDC; const Rect: TRect); + +function ScreenWorkArea: TRect; + +{ Grid drawing } + +type + TVertAlignment = (vaTopJustify, vaCenterJustify, vaBottomJustify); + +procedure WriteText(ACanvas: TCanvas; ARect: TRect; DX, DY: Integer; + const Text: string; Alignment: TAlignment; WordWrap: Boolean; ARightToLeft: + Boolean = False); +procedure DrawCellText(Control: TCustomControl; ACol, ARow: Longint; + const S: string; const ARect: TRect; Align: TAlignment; + VertAlign: TVertAlignment); overload; +procedure DrawCellTextEx(Control: TCustomControl; ACol, ARow: Longint; + const S: string; const ARect: TRect; Align: TAlignment; + VertAlign: TVertAlignment; WordWrap: Boolean); overload; +procedure DrawCellText(Control: TCustomControl; ACol, ARow: Longint; + const S: string; const ARect: TRect; Align: TAlignment; + VertAlign: TVertAlignment; ARightToLeft: Boolean); overload; +procedure DrawCellTextEx(Control: TCustomControl; ACol, ARow: Longint; + const S: string; const ARect: TRect; Align: TAlignment; + VertAlign: TVertAlignment; WordWrap: Boolean; ARightToLeft: Boolean); +overload; +procedure DrawCellBitmap(Control: TCustomControl; ACol, ARow: Longint; + Bmp: TGraphic; Rect: TRect); + +type + TJvDesktopCanvas = class(TCanvas) + private + FDC: HDC; + protected + procedure CreateHandle; override; + public + destructor Destroy; override; + procedure SetOrigin(X, Y: Integer); + procedure FreeHandle; + end; + + { end from JvVCLUtils } + + { begin JvUtils } + {**** other routines - } + { FindByTag returns the control with specified class, + ComponentClass, from WinContol.Controls property, + having Tag property value, equaled to Tag parameter } +function FindByTag(WinControl: TWinControl; ComponentClass: TComponentClass; + const Tag: Integer): TComponent; +{ ControlAtPos2 equal to TWinControl.ControlAtPos function, + but works better } +function ControlAtPos2(Parent: TWinControl; X, Y: Integer): TControl; +{ RBTag searches WinControl.Controls for checked + RadioButton and returns its Tag property value } +function RBTag(Parent: TWinControl): Integer; +{ FindFormByClass returns first form with specified + class, FormClass, owned by Application global variable } +function FindFormByClass(FormClass: TFormClass): TForm; +function FindFormByClassName(const FormClassName: string): TForm; +{ AppMinimized returns True, if Application is minimized } +function AppMinimized: Boolean; +function IsForegroundTask: Boolean; + +{ MessageBox is Application.MessageBox with string (not PChar) parameters. + if Caption parameter = '', it replaced with Application.Title } +function MessageBox(const Msg, Caption: string; const Flags: Integer): Integer; +function MsgBox(const Caption, Text: string; Flags: Integer): Integer; overload; +function MsgBox(Handle: THandle; const Caption, Text: string; Flags: Integer): Integer; overload; +function MsgDlg(const Msg: string; AType: TMsgDlgType; AButtons: TMsgDlgButtons; HelpCtx: Longint): Word; +function MsgDlg2(const Msg, ACaption: string; DlgType: TMsgDlgType; + Buttons: TMsgDlgButtons; HelpContext: Integer; Control: TWinControl): Integer; +function MsgDlgDef(const Msg, ACaption: string; DlgType: TMsgDlgType; + Buttons: TMsgDlgButtons; DefButton: TMsgDlgBtn; HelpContext: Integer; + Control: TWinControl): Integer; + +(-***** Utility MessageBox based dialogs *-) +// returns True if user clicked Yes +function MsgYesNo(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0): Boolean; +// returns True if user clicked Retry +function MsgRetryCancel(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0): Boolean; +// returns IDABORT, IDRETRY or IDIGNORE +function MsgAbortRetryIgnore(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0): Integer; +// returns IDYES, IDNO or IDCANCEL +function MsgYesNoCancel(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0): Integer; +// returns True if user clicked OK +function MsgOKCancel(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0): Boolean; + +// dialog without icon +procedure MsgOK(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0); +// dialog with info icon +procedure MsgInfo(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0); +// dialog with warning icon +procedure MsgWarn(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0); +// dialog with question icon +procedure MsgQuestion(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0); +// dialog with error icon +procedure MsgError(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0); +// dialog with custom icon (must be available in the app resource) +procedure MsgAbout(Handle: Integer; const Msg, Caption: string; const IcoName: string = 'MAINICON'; Flags: DWORD = MB_OK); + +{**** Windows routines } + +{ LoadIcoToImage loads two icons from resource named NameRes, + into two image lists ALarge and ASmall} +procedure LoadIcoToImage(ALarge, ASmall: ImgList.TCustomImageList; + const NameRes: string); + +{ Works like InputQuery but displays 2 edits. If PasswordChar <> #0, the second edit's PasswordChar is set } +function DualInputQuery(const ACaption, Prompt1, Prompt2: string; + var AValue1, AValue2: string; PasswordChar: Char = #0): Boolean; + +{ Works like InputQuery but set the edit's PasswordChar to PasswordChar. If PasswordChar = #0, works exactly like InputQuery } +function InputQueryPassword(const ACaption, APrompt: string; PasswordChar: Char; var Value: string): Boolean; + +{ returns the sum of pc.Left, pc.Width and piSpace} +function ToRightOf(const pc: TControl; piSpace: Integer = 0): Integer; +{ sets the top of pc to be in the middle of pcParent } +procedure CenterHeight(const pc, pcParent: TControl); +procedure CenterHor(Parent: TControl; MinLeft: Integer; Controls: array of TControl); +procedure EnableControls(Control: TWinControl; const Enable: Boolean); +procedure EnableMenuItems(MenuItem: TMenuItem; const Tag: Integer; const Enable: Boolean); +procedure ExpandWidth(Parent: TControl; MinWidth: Integer; Controls: array of TControl); +function PanelBorder(Panel: TCustomPanel): Integer; +function Pixels(Control: TControl; APixels: Integer): Integer; + +type + TMenuAnimation = (maNone, maRandom, maUnfold, maSlide); + +procedure ShowMenu(Form: TForm; MenuAni: TMenuAnimation); + +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} +{ TargetFileName - if FileName is ShortCut returns filename ShortCut linked to } +function TargetFileName(const FileName: TFileName): TFileName; +{ return filename ShortCut linked to } +function ResolveLink(const HWND: THandle; const LinkFile: TFileName; + var FileName: TFileName): HRESULT; +{$ENDIF MSWINDOWS} + +type + TProcObj = procedure of object; + +procedure ExecAfterPause(Proc: TProcObj; Pause: Integer); +{$ENDIF !CLR} + +{ end JvUtils } + +{ begin JvAppUtils} +function GetFirstParentForm(Control: TControl): TCustomForm; +function GetDefaultSection(Component: TComponent): string; +function GetDefaultIniName: string; + +type + TOnGetDefaultIniName = function: string; + TPlacementOption = (fpState, fpSize, fpLocation, fpActiveControl); + TPlacementOptions = set of TPlacementOption; + TPlacementOperation = (poSave, poRestore); + +var + OnGetDefaultIniName: TOnGetDefaultIniName = nil; + DefCompanyName: string = ''; + RegUseAppTitle: Boolean = False; + +function GetDefaultIniRegKey: string; +function FindForm(FormClass: TFormClass): TForm; +function FindShowForm(FormClass: TFormClass; const Caption: string): TForm; +function ShowDialog(FormClass: TFormClass): Boolean; +function InstantiateForm(FormClass: TFormClass; var Reference): TForm; + +procedure SaveFormPlacement(Form: TForm; const AppStorage: TJvCustomAppStorage; Options: TPlacementOptions); +procedure RestoreFormPlacement(Form: TForm; const AppStorage: TJvCustomAppStorage; Options: TPlacementOptions); + +procedure SaveMDIChildren(MainForm: TForm; const AppStorage: TJvCustomAppStorage); +procedure RestoreMDIChildren(MainForm: TForm; const AppStorage: TJvCustomAppStorage); +procedure RestoreGridLayout(Grid: TCustomGrid; const AppStorage: TJvCustomAppStorage); +procedure SaveGridLayout(Grid: TCustomGrid; const AppStorage: TJvCustomAppStorage); + +function StrToIniStr(const Str: string): string; +function IniStrToStr(const Str: string): string; + +// Ini Utilitie Functions +// Added by RDB + +function FontStylesToString(Styles: TFontStyles): string; +function StringToFontStyles(const Styles: string): TFontStyles; + +function FontToString(Font: TFont): string; +function StringToFont(const Str: string): TFont; + +function RectToStr(Rect: TRect): string; +function StrToRect(const Str: string; const Def: TRect): TRect; +function PointToStr(P: TPoint): string; +function StrToPoint(const Str: string; const Def: TPoint): TPoint; + +{ +function IniReadString(IniFile: TObject; const Section, Ident, + Default: string): string; +procedure IniWriteString(IniFile: TObject; const Section, Ident, + Value: string); +function IniReadInteger(IniFile: TObject; const Section, Ident: string; + Default: Longint): Longint; +procedure IniWriteInteger(IniFile: TObject; const Section, Ident: string; + Value: Longint); +function IniReadBool(IniFile: TObject; const Section, Ident: string; + Default: Boolean): Boolean; +procedure IniWriteBool(IniFile: TObject; const Section, Ident: string; + Value: Boolean); +procedure IniReadSections(IniFile: TObject; Strings: TStrings); +procedure IniEraseSection(IniFile: TObject; const Section: string); +procedure IniDeleteKey(IniFile: TObject; const Section, Ident: string); +} + +procedure AppBroadcast(Msg, wParam: Longint; lParam: Longint); +procedure AppTaskbarIcons(AppOnly: Boolean); + +{ Internal using utilities } + +procedure InternalSaveFormPlacement(Form: TForm; const AppStorage: TJvCustomAppStorage; + const StorePath: string; Options: TPlacementOptions = [fpState, fpSize, fpLocation]); +procedure InternalRestoreFormPlacement(Form: TForm; const AppStorage: TJvCustomAppStorage; + const StorePath: string; Options: TPlacementOptions = [fpState, fpSize, fpLocation]); +procedure InternalSaveGridLayout(Grid: TCustomGrid; const AppStorage: TJvCustomAppStorage; const StorePath: string); +procedure InternalRestoreGridLayout(Grid: TCustomGrid; const AppStorage: TJvCustomAppStorage; const StorePath: string); +procedure InternalSaveMDIChildren(MainForm: TForm; const AppStorage: TJvCustomAppStorage; const StorePath: string); +procedure InternalRestoreMDIChildren(MainForm: TForm; const AppStorage: TJvCustomAppStorage; const StorePath: string); + +{ end JvAppUtils } +{ begin JvGraph } +type + TMappingMethod = (mmHistogram, mmQuantize, mmTrunc784, mmTrunc666, + mmTripel, mmGrayscale); + +function GetBitmapPixelFormat(Bitmap: TBitmap): TPixelFormat; + +function GetPaletteBitmapFormat(Bitmap: TBitmap): TPixelFormat; +{$IFNDEF CLR} +procedure SetBitmapPixelFormat(Bitmap: TBitmap; PixelFormat: TPixelFormat; + Method: TMappingMethod); +function BitmapToMemoryStream(Bitmap: TBitmap; PixelFormat: TPixelFormat; + Method: TMappingMethod): TMemoryStream; +procedure GrayscaleBitmap(Bitmap: TBitmap); + +function BitmapToMemory(Bitmap: TBitmap; Colors: Integer): TStream; +procedure SaveBitmapToFile(const FileName: string; Bitmap: TBitmap; + Colors: Integer); +{$ENDIF !CLR} + +function ScreenPixelFormat: TPixelFormat; +function ScreenColorCount: Integer; + +var + DefaultMappingMethod: TMappingMethod = mmHistogram; + +function GetWorkareaRect(Monitor: TMonitor): TRect; +function FindMonitor(Handle: HMONITOR): TMonitor; + +procedure TileImage(Canvas: TCanvas; Rect: TRect; Image: TGraphic); +function ZoomImage(ImageW, ImageH, MaxW, MaxH: Integer; Stretch: Boolean): TPoint; + +type + TJvGradientOptions = class(TPersistent) + private + FStartColor: TColor; + FEndColor: TColor; + FDirection: TFillDirection; + FStepCount: Byte; + FVisible: Boolean; + FOnChange: TNotifyEvent; + procedure SetStartColor(Value: TColor); + procedure SetEndColor(Value: TColor); + procedure SetDirection(Value: TFillDirection); + procedure SetStepCount(Value: Byte); + procedure SetVisible(Value: Boolean); + protected + procedure Changed; dynamic; + public + constructor Create; + procedure Assign(Source: TPersistent); override; + procedure Draw(Canvas: TCanvas; Rect: TRect); + published + property Direction: TFillDirection read FDirection write SetDirection default fdTopToBottom; + property EndColor: TColor read FEndColor write SetEndColor default clGray; + property StartColor: TColor read FStartColor write SetStartColor default clSilver; + property StepCount: Byte read FStepCount write SetStepCount default 64; + property Visible: Boolean read FVisible write SetVisible default False; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + end; +{ end JvGraph } + +type + // equivalent of TPoint, but that can be a published property + TJvPoint = class(TPersistent) + private + FY: Longint; + FX: Longint; + FOnChange: TNotifyEvent; + procedure SetX(Value: Longint); + procedure SetY(Value: Longint); + protected + procedure DoChange; + public + procedure Assign(Source: TPersistent); overload; override; + procedure Assign(Source: TPoint); reintroduce; overload; + procedure CopyToPoint(var Point: TPoint); + property OnChange: TNotifyEvent read FOnChange write FOnChange; + published + property X: Longint read FX write SetX default 0; + property Y: Longint read FY write SetY default 0; + end; + + // equivalent of TRect, but that can be a published property + TJvRect = class(TPersistent) + private + FTopLeft: TJvPoint; + FBottomRight: TJvPoint; + FOnChange: TNotifyEvent; + function GetBottom: Integer; + function GetLeft: Integer; + function GetRight: Integer; + function GetTop: Integer; + procedure SetBottom(Value: Integer); + procedure SetLeft(Value: Integer); + procedure SetRight(Value: Integer); + procedure SetTop(Value: Integer); + procedure SetBottomRight(Value: TJvPoint); + procedure SetTopLeft(Value: TJvPoint); + procedure PointChange(Sender: TObject); + function GetHeight: Integer; + function GetWidth: Integer; + procedure SetHeight(Value: Integer); + procedure SetWidth(Value: Integer); + protected + procedure DoChange; + public + constructor Create; + destructor Destroy; override; + procedure Assign(Source: TPersistent); overload; override; + procedure Assign(Source: TRect); reintroduce; overload; + procedure CopyToRect(var Rect: TRect); + property TopLeft: TJvPoint read FTopLeft write SetTopLeft; + property BottomRight: TJvPoint read FBottomRight write SetBottomRight; + property Width: Integer read GetWidth write SetWidth; + property Height: Integer read GetHeight write SetHeight; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + published + property Left: Integer read GetLeft write SetLeft default 0; + property Top: Integer read GetTop write SetTop default 0; + property Right: Integer read GetRight write SetRight default 0; + property Bottom: Integer read GetBottom write SetBottom default 0; + end; + + TJvSize = class(TPersistent) + private + FWidth: Longint; + FHeight: Longint; + FOnChange: TNotifyEvent; + procedure SetWidth(Value: Longint); + procedure SetHeight(Value: Longint); + protected + procedure DoChange; + public + procedure Assign(Source: TPersistent); overload; override; + procedure Assign(Source: TSize); reintroduce; overload; + procedure CopyToSize(var Size: TSize); + property OnChange: TNotifyEvent read FOnChange write FOnChange; + published + property Width: Longint read FWidth write SetWidth default 0; + property Height: Longint read FHeight write SetHeight default 0; + end; + +{ begin JvCtrlUtils } + +//------------------------------------------------------------------------------ +// ToolBarMenu +//------------------------------------------------------------------------------ + +procedure JvCreateToolBarMenu(AForm: TForm; AToolBar: TToolBar; + AMenu: TMainMenu = nil); + +//------------------------------------------------------------------------------ +// ListView functions +//------------------------------------------------------------------------------ + +type + {$IFDEF CLR} + TJvLVItemStateData = record + Caption: string; + Data: TObject; + Focused: Boolean; + Selected: Boolean; + end; + PJvLVItemStateData = TJvLVItemStateData; + {$ELSE} + PJvLVItemStateData = ^TJvLVItemStateData; + TJvLVItemStateData = record + Caption: string; + Data: Pointer; + Focused: Boolean; + Selected: Boolean; + end; + {$ENDIF CLR} + +{ listview functions } +function ConvertStates(const State: Integer): TItemStates; + +function ChangeHasDeselect(const peOld, peNew: TItemStates): Boolean; +function ChangeHasSelect(const peOld, peNew: TItemStates): Boolean; + +function ChangeHasDefocus(const peOld, peNew: TItemStates): Boolean; +function ChangeHasFocus(const peOld, peNew: TItemStates): Boolean; + +function GetListItemColumn(const pcItem: TListItem; piIndex: Integer): string; + +procedure JvListViewToStrings(ListView: TListView; Strings: TStrings; + SelectedOnly: Boolean = False; Headers: Boolean = True); + +function JvListViewSafeSubItemString(Item: TListItem; SubItemIndex: Integer): string; + +procedure JvListViewSortClick(Column: TListColumn; + AscendingSortImage: Integer = -1; DescendingSortImage: Integer = -1); + +procedure JvListViewCompare(ListView: TListView; Item1, Item2: TListItem; + var Compare: Integer); + +procedure JvListViewSelectAll(ListView: TListView; Deselect: Boolean = False); + +function JvListViewSaveState(ListView: TListView): TJvLVItemStateData; + +function JvListViewRestoreState(ListView: TListView; Data: TJvLVItemStateData; + MakeVisible: Boolean = True; FocusFirst: Boolean = False): Boolean; + + +function JvListViewGetOrderedColumnIndex(Column: TListColumn): Integer; +procedure JvListViewSetSystemImageList(ListView: TListView); + + +//------------------------------------------------------------------------------ +// MessageBox +//------------------------------------------------------------------------------ + +function JvMessageBox(const Text, Caption: string; Flags: DWORD): Integer; overload; +function JvMessageBox(const Text: string; Flags: DWORD): Integer; overload; + +{ end JvCtrlUtils } +********************) + +procedure UpdateTrackFont(TrackFont, Font: TFont; TrackOptions: TJvTrackFontOptions); +(******************** +// Returns the size of the image +// used for checkboxes and radiobuttons. +// Originally from Mike Lischke +function GetDefaultCheckBoxSize: TSize; + +function CanvasMaxTextHeight(Canvas: TCanvas): Integer; + +{$IFDEF MSWINDOWS} +// AllocateHWndEx works like Classes.AllocateHWnd but does not use any virtual memory pages +function AllocateHWndEx(Method: TWndMethod; const AClassName: string = ''): THandle; +// DeallocateHWndEx works like Classes.DeallocateHWnd but does not use any virtual memory pages +procedure DeallocateHWndEx(Wnd: THandle); + +function JvMakeObjectInstance(Method: TWndMethod): {$IFDEF CLR}TFNWndProc{$ELSE}Pointer{$ENDIF}; +procedure JvFreeObjectInstance(ObjectInstance: {$IFDEF CLR}TFNWndProc{$ELSE}Pointer{$ENDIF}); +{$ENDIF MSWINDOWS} + +function GetAppHandle: THandle; +// DrawArrow draws a standard arrow in any of four directions and with the specifed color. +// Rect is the area to draw the arrow in and also defines the size of the arrow +// Note that this procedure might shrink Rect so that it's width and height is always +// the same and the width and height are always even, i.e calling with +// Rect(0,0,12,12) (odd) is the same as calling with Rect(0,0,11,11) (even) +// Direction defines the direction of the arrow. If Direction is akLeft, the arrow point is +// pointing to the left +procedure DrawArrow(Canvas: TCanvas; Rect: TRect; Color: TColor = clBlack; Direction: TAnchorKind = akBottom); + +function IsPositiveResult(Value: TModalResult): Boolean; +function IsNegativeResult(Value: TModalResult): Boolean; +function IsAbortResult(const Value: TModalResult): Boolean; +function StripAllFromResult(const Value: TModalResult): TModalResult; +// returns either BrightColor or DarkColor depending on the luminance of AColor +// This function gives the same result (AFAIK) as the function used in Windows to +// calculate the desktop icon text color based on the desktop background color +function SelectColorByLuminance(AColor, DarkColor, BrightColor: TColor): TColor; + +// (peter3) implementation moved from JvHTControls. +type + TJvHTMLCalcType = (htmlShow, htmlCalcWidth, htmlCalcHeight); + +procedure HTMLDrawTextEx(Canvas: TCanvas; Rect: TRect; + const State: TOwnerDrawState; const Text: string; var Width: Integer; + CalcType: TJvHTMLCalcType; MouseX, MouseY: Integer; var MouseOnLink: Boolean; + var LinkName: string; Scale: Integer = 100); +function HTMLDrawText(Canvas: TCanvas; Rect: TRect; + const State: TOwnerDrawState; const Text: string; Scale: Integer = 100): string; +function HTMLTextWidth(Canvas: TCanvas; Rect: TRect; + const State: TOwnerDrawState; const Text: string; Scale: Integer = 100): Integer; +function HTMLPlainText(const Text: string): string; +function HTMLTextHeight(Canvas: TCanvas; const Text: string; Scale: Integer = 100): Integer; +function HTMLPrepareText(const Text: string): string; + +// This type is used to allow an easy migration from a TBitmap property to a +// TPicture property. It is, for instance, used in TJvXPButton so that users +// migrating to the JVCL can still open their applications and benefit +// automatically from the change of format. The whole point is that a TPicture +// can also contain an Icon, which could be a valid source for a button glyph. +type + TJvPicture = class (TPicture) + private + procedure ReadBitmapData(Stream: TStream); + protected + procedure DefineProperties(Filer: TFiler); override; + end; + +{ +Documentation: +************* + +WHAT IT IS: + These are helper functions to register graphic formats than can + later be recognized from a stream, thus allowing to rely on the actual + content of a file rather than from its filename extension. + This is used in TJvDBImage and TJvImage. + +IMAGE FORMATS: + The implementation is simple: Just register image signatures with + RegisterGraphicSignature procedure and the methods takes care + of the correct instantiation of the TGraphic object. The signatures + register at unit's initialization are: BMP, WMF, EMF, ICO, JPG. + If you got some other image library (such as GIF, PCX, TIFF, ANI or PNG), + just register the signature: + + RegisterGraphicSignature(, , ) + + or + + RegisterGraphicSignature([], , ) + + This means: + When (or byte values) found at the graphic + class to use is + + For example (actual code of the initialization section): + + RegisterGraphicSignature([$D7, $CD], 0, TMetaFile); // WMF + RegisterGraphicSignature([1, 0], 0, TMetaFile); // EMF + RegisterGraphicSignature('JFIF', 6, TJPEGImage); + + You can also unregister signature. IF you want use TGIFImage instead of + TJvGIFImage, you can unregister with: + + UnregisterGraphicSignature('GIF', 0); + + or just + + UnregisterGraphicSignature(TJvGIFImage); // must add JvGIF unit in uses clause + + then: + RegisterGraphicSignature('GIF', 0, TGIFImage); // must add GIFImage to uses clause + + If you dont like the signature registration there is a new event called + OnGetGraphicClass. The event gets the following parameters: + + Sender: TObject; + Stream: TMemoryStream; + var GraphicClass: TGraphicClass) + + The memory stream containing the blob data is sent in Stream to allow the user + to inspect the contents and figure out which graphic class is. + + The graphic class to be used must implement LoadFromStream and SaveToStream + methods in order to work properly. +} + +type + TJvGetGraphicClassEvent = procedure(Sender: TObject; AStream: TMemoryStream; + var GraphicClass: TGraphicClass) of object; + +procedure RegisterGraphicSignature(const ASignature: string; AOffset: Integer; + AGraphicClass: TGraphicClass); overload; +procedure RegisterGraphicSignature(const ASignature: array of Byte; AOffset: Integer; + AGraphicClass: TGraphicClass); overload; + +procedure UnregisterGraphicSignature(AGraphicClass: TGraphicClass); overload; +procedure UnregisterGraphicSignature(const ASignature: string; AOffset: Integer); overload; +procedure UnregisterGraphicSignature(const ASignature: array of Byte; AOffset: Integer); overload; + +function GetGraphicClass(AStream: TStream): TGraphicClass; +function GetGraphicObject(AStream: TStream): TGraphic; overload; +function GetGraphicObject(AStream: TStream; ASender: TObject; AOnProc: TJvGetGraphicClassEvent): TGraphic; overload; +********************) + +implementation + +(******************** +uses + SysConst, + Consts, + {$IFDEF MSWINDOWS} + CommCtrl, MMSystem, ShlObj, ActiveX, + {$ENDIF MSWINDOWS} + Math, jpeg, Contnrs, + JclSysInfo, + JvConsts, JvProgressUtils, JvResources; + +{$R JvConsts.res} + +const + {$IFDEF MSWINDOWS} + RC_ControlRegistry = 'Control Panel\Desktop'; + RC_WallPaperStyle = 'WallpaperStyle'; + RC_WallpaperRegistry = 'Wallpaper'; + RC_TileWallpaper = 'TileWallpaper'; + RC_RunCpl = 'rundll32.exe shell32,Control_RunDLL '; + {$ENDIF MSWINDOWS} + +function GetAppHandle: THandle; +begin + Result := Application.Handle; +end; + +type + TWaitCursor = class(TInterfacedObject, IInterface) + private + FCursor: TCursor; + public + constructor Create(ACursor: TCursor); + destructor Destroy; override; + end; + +constructor TWaitCursor.Create(ACursor: TCursor); +begin + inherited Create; + FCursor := Screen.Cursor; + Screen.Cursor := ACursor; +end; + +destructor TWaitCursor.Destroy; +begin + Screen.Cursor := FCursor; + inherited Destroy; +end; + + + + + +function IconToBitmap(Ico: HICON): TBitmap; +var + Pic: TPicture; +begin + Pic := TPicture.Create; + try + Pic.Icon.Handle := Ico; + Result := TBitmap.Create; + Result.Height := Pic.Icon.Height; + Result.Width := Pic.Icon.Width; + Result.Canvas.Draw(0, 0, Pic.Icon); + finally + Pic.Free; + end; +end; + +function IconToBitmap2(Ico: HICON; Size: Integer = 32; + TransparentColor: TColor = clNone): TBitmap; +begin + // (p3) this seems to generate "better" bitmaps... + with TImageList.CreateSize(Size, Size) do + try + Masked := True; + BkColor := TransparentColor; + ImageList_AddIcon(Handle, Ico); + Result := TBitmap.Create; + Result.PixelFormat := pf24bit; + if TransparentColor <> clNone then + Result.TransparentColor := TransparentColor; + Result.Transparent := TransparentColor <> clNone; + GetBitmap(0, Result); + finally + Free; + end; +end; + +function IconToBitmap3(Ico: HICON; Size: Integer = 32; + TransparentColor: TColor = clNone): TBitmap; +var + Icon: TIcon; + Tmp: TBitmap; +begin + Icon := TIcon.Create; + Tmp := TBitmap.Create; + try + Icon.Handle := CopyIcon(Ico); + Result := TBitmap.Create; + Result.Width := Icon.Width; + Result.Height := Icon.Height; + Result.PixelFormat := pf24bit; + // fill the bitmap with the transparent color + Result.Canvas.Brush.Color := TransparentColor; + Result.Canvas.FillRect(Rect(0, 0, Result.Width, Result.Height)); + Result.Canvas.Draw(0, 0, Icon); + Result.TransparentColor := TransparentColor; + Tmp.Assign(Result); + // Result.Width := Size; + // Result.Height := Size; + Result.Canvas.StretchDraw(Rect(0, 0, Result.Width, Result.Height), Tmp); + Result.Transparent := True; + finally + Icon.Free; + Tmp.Free; + end; +end; + + +procedure RGBToHSV(R, G, B: Integer; var H, S, V: Integer); + +var + Delta: Integer; + Min, Max: Integer; + + function GetMax(I, J, K: Integer): Integer; + begin + if J > I then + I := J; + if K > I then + I := K; + Result := I; + end; + + function GetMin(I, J, K: Integer): Integer; + begin + if J < I then + I := J; + if K < I then + I := K; + Result := I; + end; + +begin + Min := GetMin(R, G, B); + Max := GetMax(R, G, B); + V := Max; + Delta := Max - Min; + if Max = 0 then + S := 0 + else + S := (255 * Delta) div Max; + if S = 0 then + H := 0 + else + begin + if R = Max then + H := (60 * (G - B)) div Delta + else + if G = Max then + H := 120 + (60 * (B - R)) div Delta + else + H := 240 + (60 * (R - G)) div Delta; + if H < 0 then + H := H + 360; + end; +end; + + + +(-* (rom) to be deleted. Use ScreenShot from JCL +{$IFDEF VCL} + +function CaptureScreen(Rec: TRect): TBitmap; +const + NumColors = 256; +var + R: TRect; + C: TCanvas; + LP: PLogPalette; + TmpPalette: HPALETTE; + Size: Integer; +begin + Result := TBitmap.Create; + Result.Width := Rec.Right - Rec.Left; + Result.Height := Rec.Bottom - Rec.Top; + R := Rec; + C := TCanvas.Create; + try + C.Handle := GetDC(HWND_DESKTOP); + Result.Canvas.CopyRect(Rect(0, 0, Rec.Right - Rec.Left, Rec.Bottom - + Rec.Top), C, R); + Size := SizeOf(TLogPalette) + (Pred(NumColors) * SizeOf(TPaletteEntry)); + LP := AllocMem(Size); + try + LP^.palVersion := $300; + LP^.palNumEntries := NumColors; + GetSystemPaletteEntries(C.Handle, 0, NumColors, LP^.palPalEntry); + TmpPalette := CreatePalette(LP^); + Result.Palette := TmpPalette; + DeleteObject(TmpPalette); + finally + FreeMem(LP, Size); + end + finally + ReleaseDC(HWND_DESKTOP, C.Handle); + C.Free; + end; +end; + +function CaptureScreen(IncludeTaskBar: Boolean): TBitmap; +var + R: TRect; +begin + if IncludeTaskBar then + R := Rect(0, 0, Screen.Width, Screen.Height) + else + SystemParametersInfo(SPI_GETWORKAREA, 0, Pointer(@R), 0); + Result := CaptureScreen(R); +end; + +function CaptureScreen(WndHandle: Longword): TBitmap; +var + R: TRect; + WP: TWindowPlacement; +begin + if GetWindowRect(WndHandle, R) then + begin + GetWindowPlacement(WndHandle, @WP); + if IsIconic(WndHandle) then + ShowWindow(WndHandle, SW_RESTORE); + BringWindowToTop(WndHandle); + Result := CaptureScreen(R); + SetWindowPlacement(WndHandle, @WP); + end + else + Result := nil; +end; +{$ENDIF VCL} +*-) + +{$IFDEF MSWINDOWS} + +{$IFNDEF CLR} +procedure SetWallpaper(const Path: string); +begin + SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, PChar(Path), SPIF_UPDATEINIFILE); +end; +{$ENDIF !CLR} + +procedure SetWallpaper(const Path: string; Style: TJvWallpaperStyle); +begin + with TRegistry.Create do + begin + OpenKey(RC_ControlRegistry, False); + case Style of + wpTile: + begin + WriteString(RC_TileWallpaper, '1'); + WriteString(RC_WallPaperStyle, '0'); + end; + wpCenter: + begin + WriteString(RC_TileWallpaper, '0'); + WriteString(RC_WallPaperStyle, '0'); + end; + wpStretch: + begin + WriteString(RC_TileWallpaper, '0'); + WriteString(RC_WallPaperStyle, '2'); + end; + end; + WriteString(RC_WallpaperRegistry, Path); + Free; + end; + SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, nil, SPIF_SENDWININICHANGE); +end; + +{$ENDIF MSWINDOWS} + +type + TGetXBitmapMode =(gxRed, gxGreen, gxBlue, gxHue, gxSaturation, gxValue); + +procedure GetXBitmap(var Dest: TBitmap; const Source: TBitmap; Mode: TGetXBitmapMode); +var + I, J, H, S, V: Integer; + {$IFDEF CLR} + Line: array of TJvRGBTriple; + {$ELSE} + Line: PJvRGBArray; + {$ENDIF CLR} +begin + if not Assigned(Dest) then + Dest := TBitmap.Create; + Dest.Assign(Source); + Dest.PixelFormat := pf24bit; + for J := Dest.Height - 1 downto 0 do + begin + {$IFDEF CLR} + Marshal.PtrToStructure(Dest.ScanLine[J], Line); + {$ELSE} + Line := Dest.ScanLine[J]; + {$ENDIF CLR} + case Mode of + gxRed: + for I := Dest.Width - 1 downto 0 do + begin + Line[I].rgbGreen := 0; + Line[I].rgbBlue := 0; + end; + gxGreen: + for I := Dest.Width - 1 downto 0 do + begin + Line[I].rgbRed := 0; + Line[I].rgbBlue := 0; + end; + gxBlue: + for I := Dest.Width - 1 downto 0 do + begin + Line[I].rgbRed := 0; + Line[I].rgbGreen := 0; + end; + gxHue: + for I := Dest.Width - 1 downto 0 do + with Line[I] do + begin + RGBToHSV(rgbRed, rgbGreen, rgbBlue, H, S, V); + rgbRed := H; + rgbGreen := H; + rgbBlue := H; + end; + gxSaturation: + for I := Dest.Width - 1 downto 0 do + with Line[I] do + begin + RGBToHSV(rgbRed, rgbGreen, rgbBlue, H, S, V); + rgbRed := S; + rgbGreen := S; + rgbBlue := S; + end; + gxValue: + for I := Dest.Width - 1 downto 0 do + with Line[I] do + begin + RGBToHSV(rgbRed, rgbGreen, rgbBlue, H, S, V); + rgbRed := V; + rgbGreen := V; + rgbBlue := V; + end; + end; + end; + Dest.PixelFormat := Source.PixelFormat; +end; + +procedure GetRBitmap(var Dest: TBitmap; const Source: TBitmap); +begin + GetXBitmap(Dest, Source, gxRed); +end; + +procedure GetBBitmap(var Dest: TBitmap; const Source: TBitmap); +begin + GetXBitmap(Dest, Source, gxBlue); +end; + +procedure GetGBitmap(var Dest: TBitmap; const Source: TBitmap); +begin + GetXBitmap(Dest, Source, gxGreen); +end; + +procedure GetMonochromeBitmap(var Dest: TBitmap; const Source: TBitmap); +begin + if not Assigned(Dest) then + Dest := TBitmap.Create; + Dest.Assign(Source); + Dest.Monochrome := True; +end; + +procedure GetHueBitmap(var Dest: TBitmap; const Source: TBitmap); +begin + GetXBitmap(Dest, Source, gxHue); +end; + +procedure GetSaturationBitmap(var Dest: TBitmap; const Source: TBitmap); +begin + GetXBitmap(Dest, Source, gxSaturation); +end; + +procedure GetValueBitmap(var Dest: TBitmap; const Source: TBitmap); +begin + GetXBitmap(Dest, Source, gxValue); +end; + + +{ (rb) Duplicate of JvAppUtils.AppTaskbarIcons } + +procedure HideFormCaption(FormHandle: THandle; Hide: Boolean); +begin + if Hide then + SetWindowLong(FormHandle, GWL_STYLE, + GetWindowLong(FormHandle, GWL_STYLE) and not WS_CAPTION) + else + SetWindowLong(FormHandle, GWL_STYLE, + GetWindowLong(FormHandle, GWL_STYLE) or WS_CAPTION); +end; + + +{$IFNDEF CLR} + + +procedure LaunchCpl(const FileName: string); +begin + // rundll32.exe shell32,Control_RunDLL '; + RunDLL32('shell32.dll', 'Control_RunDLL', FileName, True); + // WinExec(PChar(RC_RunCpl + FileName), SW_SHOWNORMAL); +end; + +procedure ShowSafeRemovalDialog; +begin + LaunchCpl('HOTPLUG.DLL'); +end; + +const + {$EXTERNALSYM WM_CPL_LAUNCH} + WM_CPL_LAUNCH = (WM_USER + 1000); + {$EXTERNALSYM WM_CPL_LAUNCHED} + WM_CPL_LAUNCHED = (WM_USER + 1001); + + { (p3) just define enough to make the Cpl unnecessary for us (for the benefit of PE users) } + cCplAddress = 'CPlApplet'; + CPL_INIT = 1; + {$EXTERNALSYM CPL_INIT} + CPL_GETCOUNT = 2; + {$EXTERNALSYM CPL_GETCOUNT} + CPL_INQUIRE = 3; + {$EXTERNALSYM CPL_INQUIRE} + CPL_EXIT = 7; + {$EXTERNALSYM CPL_EXIT} + CPL_NEWINQUIRE = 8; + {$EXTERNALSYM CPL_NEWINQUIRE} + +type + TCPLApplet = function(hwndCPl: THandle; uMsg: DWORD; + lParam1, lParam2: Longint): Longint; stdcall; + + TCPLInfo = packed record + idIcon: Integer; + idName: Integer; + idInfo: Integer; + lData: Longint; + end; + + TNewCPLInfoA = packed record + dwSize: DWORD; + dwFlags: DWORD; + dwHelpContext: DWORD; + lData: Longint; + HICON: HICON; + szName: array [0..31] of AnsiChar; + szInfo: array [0..63] of AnsiChar; + szHelpFile: array [0..127] of AnsiChar; + end; + TNewCPLInfoW = packed record + dwSize: DWORD; + dwFlags: DWORD; + dwHelpContext: DWORD; + lData: Longint; + HICON: HICON; + szName: array [0..31] of WideChar; + szInfo: array [0..63] of WideChar; + szHelpFile: array [0..127] of WideChar; + end; + +function GetControlPanelApplet(const AFileName: string; Strings: TStrings; + Images: TCustomImageList = nil): Boolean; +var + hLib: HMODULE; // Library Handle to *.cpl file + hIco: HICON; + CplCall: TCPLApplet; // Pointer to CPlApplet() function + I: Longint; + TmpCount, Count: Longint; + S: WideString; + // the three types of information that can be returned + CPLInfo: TCPLInfo; + InfoW: TNewCPLInfoW; + InfoA: TNewCPLInfoA; + HWND: THandle; +begin + Result := False; + hLib := SafeLoadLibrary(AFileName); + if hLib = 0 then + Exit; + HWND := GetForegroundWindow; + TmpCount := Strings.Count; + Strings.BeginUpdate; + try + @CplCall := GetProcAddress(hLib, PChar(cCplAddress)); + if not Assigned(CplCall) then + Exit; + CplCall(HWND, CPL_INIT, 0, 0); // Init the *.cpl file + try + Count := CplCall(HWND, CPL_GETCOUNT, 0, 0); + for I := 0 to Count - 1 do + begin + FillChar(InfoW, SizeOf(InfoW), 0); + FillChar(InfoA, SizeOf(InfoA), 0); + FillChar(CPLInfo, SizeOf(CPLInfo), 0); + S := ''; + CplCall(HWND, CPL_NEWINQUIRE, I, Longint(@InfoW)); + if InfoW.dwSize = SizeOf(InfoW) then + begin + hIco := InfoW.HICON; + S := WideString(InfoW.szName); + end + else + begin + if InfoW.dwSize = SizeOf(InfoA) then + begin + Move(InfoW, InfoA, SizeOf(InfoA)); + hIco := CopyIcon(InfoA.HICON); + S := string(InfoA.szName); + end + else + begin + CplCall(HWND, CPL_INQUIRE, I, Longint(@CPLInfo)); + LoadStringA(hLib, CPLInfo.idName, InfoA.szName, + SizeOf(InfoA.szName)); + hIco := LoadImage(hLib, PChar(CPLInfo.idIcon), IMAGE_ICON, 16, 16, + LR_DEFAULTCOLOR); + S := string(InfoA.szName); + end; + end; + if S <> '' then + begin + S := Format('%s=%s,@%d', [S, AFileName, I]); + if Images <> nil then + begin + hIco := CopyIcon(hIco); + ImageList_AddIcon(Images.Handle, hIco); + Strings.AddObject(S, TObject(Images.Count - 1)); + end + else + Strings.AddObject(S, IconToBitmap2(hIco, 16, clMenu)); + // (p3) not sure this is really needed... + // DestroyIcon(hIco); + end; + end; + Result := TmpCount < Strings.Count; + finally + CplCall(HWND, CPL_EXIT, 0, 0); + end; + finally + FreeLibrary(hLib); + Strings.EndUpdate; + end; +end; + +function GetControlPanelApplets(const APath, AMask: string; Strings: TStrings; + Images: TCustomImageList = nil): Boolean; +var + H: THandle; + F: TSearchRec; +begin + Result := False; + if Strings = nil then + Exit; + H := FindFirst(IncludeTrailingPathDelimiter(APath) + AMask, faAnyFile, F); + if Images <> nil then + begin + Images.Clear; + Images.BkColor := clMenu; + end; + Strings.BeginUpdate; + try + Strings.Clear; + while H = 0 do + begin + if F.Attr and faDirectory = 0 then + // if (F.Name <> '.') and (F.Name <> '..') then + GetControlPanelApplet(APath + F.Name, Strings, Images); + H := FindNext(F); + end; + SysUtils.FindClose(F); + Result := Strings.Count > 0; + finally + Strings.EndUpdate; + end; +end; + +{$ENDIF !CLR} + +{ imported from VCLFunctions } + +procedure CenterHeight(const pc, pcParent: TControl); +begin + pc.Top := //pcParent.Top + + ((pcParent.Height - pc.Height) div 2); +end; + +function ToRightOf(const pc: TControl; piSpace: Integer): Integer; +begin + if pc <> nil then + Result := pc.Left + pc.Width + piSpace + else + Result := piSpace; +end; + +{ compiled from ComCtrls.pas's implmentation section } + +function HasFlag(A, B: Integer): Boolean; +begin + Result := (A and B) <> 0; +end; + +function ConvertStates(const State: Integer): TItemStates; +begin + Result := []; + if HasFlag(State, LVIS_ACTIVATING) then + Include(Result, isActivating); + if HasFlag(State, LVIS_CUT) then + Include(Result, isCut); + if HasFlag(State, LVIS_DROPHILITED) then + Include(Result, isDropHilited); + if HasFlag(State, LVIS_FOCUSED) then + Include(Result, IsFocused); + if HasFlag(State, LVIS_SELECTED) then + Include(Result, isSelected); +end; + +function ChangeHasSelect(const peOld, peNew: TItemStates): Boolean; +begin + Result := (not (isSelected in peOld)) and (isSelected in peNew); +end; + +function ChangeHasDeselect(const peOld, peNew: TItemStates): Boolean; +begin + Result := (isSelected in peOld) and (not (isSelected in peNew)); +end; + +function ChangeHasFocus(const peOld, peNew: TItemStates): Boolean; +begin + Result := (not (IsFocused in peOld)) and (IsFocused in peNew); +end; + +function ChangeHasDefocus(const peOld, peNew: TItemStates): Boolean; +begin + Result := (IsFocused in peOld) and (not (IsFocused in peNew)); +end; + +function GetListItemColumn(const pcItem: TListItem; piIndex: Integer): string; +begin + if pcItem = nil then + begin + Result := ''; + Exit; + end; + + if (piIndex < 0) or (piIndex > pcItem.SubItems.Count) then + begin + Result := ''; + Exit; + end; + + if piIndex = 0 then + Result := pcItem.Caption + else + Result := pcItem.SubItems[piIndex - 1]; +end; + +{from JvVCLUtils } + +{ Bitmaps } + + + + +// see above for VisualCLX version of CopyParentImage +type + TJvParentControl = class(TWinControl); + +procedure CopyParentImage(Control: TControl; Dest: TCanvas); +var + I, Count, SaveIndex: Integer; + DC: HDC; + R, SelfR, CtlR: TRect; + ViewPortOrg: TPoint; +begin + if (Control = nil) or (Control.Parent = nil) then + Exit; + Count := Control.Parent.ControlCount; + DC := Dest.Handle; + with Control.Parent do + ControlState := ControlState + [csPaintCopy]; + try + // The view port may already be set. This is especially true when + // a control using CopyParentImage is placed inside a control that + // calls it as well. Best example is a TJvSpeeButton in a TJvPanel, + // both with Transparent set to True (discovered while working on + // Mantis 3624) + GetViewPortOrgEx(DC, ViewPortOrg); + + with Control do + begin + SelfR := Bounds(Left, Top, Width, Height); + + ViewPortOrg.X := ViewPortOrg.X-Left; + ViewPortOrg.Y := ViewPortOrg.Y-Top; + end; + + // Copy parent control image + SaveIndex := SaveDC(DC); + try + SetViewPortOrgEx(DC, ViewPortOrg.X, ViewPortOrg.Y, nil); + IntersectClipRect(DC, 0, 0, Control.Parent.ClientWidth, + Control.Parent.ClientHeight); + {$IFDEF CLR} + Control.Parent.Perform(WM_ERASEBKGND, DC, 0); + Control.Parent.GetType.InvokeMember('PaintWindow', + BindingFlags.Instance or BindingFlags.InvokeMethod or BindingFlags.NonPublic, + nil, Control.Parent, [DC]); + {$ELSE} + with TJvParentControl(Control.Parent) do + begin + Perform(WM_ERASEBKGND, DC, 0); + PaintWindow(DC); + end; + {$ENDIF CLR} + finally + RestoreDC(DC, SaveIndex); + end; + + // Copy images of control's siblings + // Note: while working on Mantis 3624 it was decided that there was no + // real reason to limit this to controls derived from TGraphicControl. + for I := 0 to Count - 1 do + begin + if Control.Parent.Controls[I] = Control then + Break + else + if (Control.Parent.Controls[I] <> nil) then + begin + with Control.Parent.Controls[I] do + begin + CtlR := Bounds(Left, Top, Width, Height); + if IntersectRect(R, SelfR, CtlR) and Visible then + begin + ControlState := ControlState + [csPaintCopy]; + SaveIndex := SaveDC(DC); + try + SetViewPortOrgEx(DC, Left + ViewPortOrg.X, Top + ViewPortOrg.Y, nil); + IntersectClipRect(DC, 0, 0, Width, Height); + Perform(WM_PAINT, DC, 0); + finally + RestoreDC(DC, SaveIndex); + ControlState := ControlState - [csPaintCopy]; + end; + end; + end; + end; + end; + finally + with Control.Parent do + ControlState := ControlState - [csPaintCopy]; + end; +end; + + + +{$IFNDEF CLR} +function MakeModuleBitmap(Module: THandle; ResID: PChar): TBitmap; +begin + Result := TBitmap.Create; + try + if Module <> 0 then + begin + if LongRec(ResID).Hi = 0 then + Result.LoadFromResourceID(Module, LongRec(ResID).Lo) + else + Result.LoadFromResourceName(Module, StrPas(ResID)); + end + else + begin + Result.Handle := LoadBitmap(Module, ResID); + if Result.Handle = 0 then + ResourceNotFound(ResID); + end; + except + Result.Free; + Result := nil; + end; +end; + +function MakeBitmap(ResID: PChar): TBitmap; +begin + Result := MakeModuleBitmap(HInstance, ResID); +end; + +function MakeBitmapID(ResID: Word): TBitmap; +begin + Result := MakeModuleBitmap(HInstance, MakeIntResource(ResID)); +end; +{$ENDIF !CLR} + +procedure AssignBitmapCell(Source: TGraphic; Dest: TBitmap; + Cols, Rows, Index: Integer); +var + CellWidth, CellHeight: Integer; +begin + if (Source <> nil) and (Dest <> nil) then + begin + if Cols <= 0 then + Cols := 1; + if Rows <= 0 then + Rows := 1; + if Index < 0 then + Index := 0; + CellWidth := Source.Width div Cols; + CellHeight := Source.Height div Rows; + with Dest do + begin + Width := CellWidth; + Height := CellHeight; + end; + if Source is TBitmap then + begin + Dest.Canvas.CopyRect(Bounds(0, 0, CellWidth, CellHeight), + TBitmap(Source).Canvas, Bounds((Index mod Cols) * CellWidth, + (Index div Cols) * CellHeight, CellWidth, CellHeight)); + Dest.TransparentColor := TBitmap(Source).TransparentColor; + end + else + begin + Dest.Canvas.Brush.Color := clSilver; + Dest.Canvas.FillRect(Bounds(0, 0, CellWidth, CellHeight)); + Dest.Canvas.Draw(-(Index mod Cols) * CellWidth, + -(Index div Cols) * CellHeight, Source); + end; + Dest.Transparent := Source.Transparent; + end; +end; + +{ Transparent bitmap } + + + +procedure StretchBltTransparent(DstDC: HDC; DstX, DstY, DstW, DstH: Integer; + SrcDC: HDC; SrcX, SrcY, SrcW, Srch: Integer; Palette: HPALETTE; + TransparentColor: TColorRef); +var + Color: TColorRef; + bmAndBack, bmAndObject, bmAndMem, bmSave: HBITMAP; + bmBackOld, bmObjectOld, bmMemOld, bmSaveOld: HBITMAP; + MemDC, BackDC, ObjectDC, SaveDC: HDC; + palDst, palMem, palSave, palObj: HPALETTE; +begin + { Create some DCs to hold temporary data } + BackDC := CreateCompatibleDC(DstDC); + ObjectDC := CreateCompatibleDC(DstDC); + MemDC := CreateCompatibleDC(DstDC); + SaveDC := CreateCompatibleDC(DstDC); + { Create a bitmap for each DC } + bmAndObject := CreateBitmap(SrcW, Srch, 1, 1, nil); + bmAndBack := CreateBitmap(SrcW, Srch, 1, 1, nil); + bmAndMem := CreateCompatibleBitmap(DstDC, DstW, DstH); + bmSave := CreateCompatibleBitmap(DstDC, SrcW, Srch); + { Each DC must select a bitmap object to store pixel data } + bmBackOld := SelectObject(BackDC, bmAndBack); + bmObjectOld := SelectObject(ObjectDC, bmAndObject); + bmMemOld := SelectObject(MemDC, bmAndMem); + bmSaveOld := SelectObject(SaveDC, bmSave); + { Select palette } + palDst := 0; + palMem := 0; + palSave := 0; + palObj := 0; + if Palette <> 0 then + begin + palDst := SelectPalette(DstDC, Palette, True); + RealizePalette(DstDC); + palSave := SelectPalette(SaveDC, Palette, False); + RealizePalette(SaveDC); + palObj := SelectPalette(ObjectDC, Palette, False); + RealizePalette(ObjectDC); + palMem := SelectPalette(MemDC, Palette, True); + RealizePalette(MemDC); + end; + { Set proper mapping mode } + SetMapMode(SrcDC, GetMapMode(DstDC)); + SetMapMode(SaveDC, GetMapMode(DstDC)); + { Save the bitmap sent here } + BitBlt(SaveDC, 0, 0, SrcW, Srch, SrcDC, SrcX, SrcY, SRCCOPY); + { Set the background color of the source DC to the color, } + { contained in the parts of the bitmap that should be transparent } + Color := SetBkColor(SaveDC, PaletteColor(TransparentColor)); + { Create the object mask for the bitmap by performing a BitBlt() } + { from the source bitmap to a monochrome bitmap } + BitBlt(ObjectDC, 0, 0, SrcW, Srch, SaveDC, 0, 0, SRCCOPY); + { Set the background color of the source DC back to the original } + SetBkColor(SaveDC, Color); + { Create the inverse of the object mask } + BitBlt(BackDC, 0, 0, SrcW, Srch, ObjectDC, 0, 0, NOTSRCCOPY); + { Copy the background of the main DC to the destination } + BitBlt(MemDC, 0, 0, DstW, DstH, DstDC, DstX, DstY, SRCCOPY); + { Mask out the places where the bitmap will be placed } + StretchBlt(MemDC, 0, 0, DstW, DstH, ObjectDC, 0, 0, SrcW, Srch, SRCAND); + { Mask out the transparent colored pixels on the bitmap } + BitBlt(SaveDC, 0, 0, SrcW, Srch, BackDC, 0, 0, SRCAND); + { XOR the bitmap with the background on the destination DC } + StretchBlt(MemDC, 0, 0, DstW, DstH, SaveDC, 0, 0, SrcW, Srch, SRCPAINT); + { Copy the destination to the screen } + BitBlt(DstDC, DstX, DstY, DstW, DstH, MemDC, 0, 0, SRCCOPY); + { Restore palette } + if Palette <> 0 then + begin + SelectPalette(MemDC, palMem, False); + SelectPalette(ObjectDC, palObj, False); + SelectPalette(SaveDC, palSave, False); + SelectPalette(DstDC, palDst, True); + end; + { Delete the memory bitmaps } + DeleteObject(SelectObject(BackDC, bmBackOld)); + DeleteObject(SelectObject(ObjectDC, bmObjectOld)); + DeleteObject(SelectObject(MemDC, bmMemOld)); + DeleteObject(SelectObject(SaveDC, bmSaveOld)); + { Delete the memory DCs } + DeleteDC(MemDC); + DeleteDC(BackDC); + DeleteDC(ObjectDC); + DeleteDC(SaveDC); +end; + + + +procedure DrawTransparentBitmapRect(DC: HDC; Bitmap: HBITMAP; DstX, DstY, + DstW, DstH: Integer; SrcRect: TRect; TransparentColor: TColorRef); +var + hdcTemp: HDC; +begin + hdcTemp := CreateCompatibleDC(DC); + try + SelectObject(hdcTemp, Bitmap); + with SrcRect do + StretchBltTransparent(DC, DstX, DstY, DstW, DstH, hdcTemp, + Left, Top, Right - Left, Bottom - Top, 0, TransparentColor); + finally + DeleteDC(hdcTemp); + end; +end; + +procedure DrawTransparentBitmap(DC: HDC; Bitmap: HBITMAP; + DstX, DstY: Integer; TransparentColor: TColorRef); +var + BM: tagBITMAP; +begin + {$IFDEF CLR} + GetObject(Bitmap, Marshal.SizeOf(BM), BM); + {$ELSE} + GetObject(Bitmap, SizeOf(BM), @BM); + {$ENDIF CLR} + DrawTransparentBitmapRect(DC, Bitmap, DstX, DstY, BM.bmWidth, BM.bmHeight, + Rect(0, 0, BM.bmWidth, BM.bmHeight), TransparentColor); +end; + +procedure StretchBitmapTransparent(Dest: TCanvas; Bitmap: TBitmap; + TransparentColor: TColor; DstX, DstY, DstW, DstH, SrcX, SrcY, + SrcW, Srch: Integer); +var + CanvasChanging: TNotifyEvent; +begin + if DstW <= 0 then + DstW := Bitmap.Width; + if DstH <= 0 then + DstH := Bitmap.Height; + if (SrcW <= 0) or (Srch <= 0) then + begin + SrcX := 0; + SrcY := 0; + SrcW := Bitmap.Width; + Srch := Bitmap.Height; + end; + if not Bitmap.Monochrome then + SetStretchBltMode(Dest.Handle, STRETCH_DELETESCANS); + CanvasChanging := Bitmap.Canvas.OnChanging; + Bitmap.Canvas.Lock; + try + Bitmap.Canvas.OnChanging := nil; + if TransparentColor = clNone then + begin + StretchBlt(Dest.Handle, DstX, DstY, DstW, DstH, Bitmap.Canvas.Handle, + SrcX, SrcY, SrcW, Srch, Cardinal(Dest.CopyMode)); + end + else + begin + if TransparentColor = clDefault then + TransparentColor := Bitmap.Canvas.Pixels[0, Bitmap.Height - 1]; + if Bitmap.Monochrome then + TransparentColor := clWhite + else + TransparentColor := ColorToRGB(TransparentColor); + StretchBltTransparent(Dest.Handle, DstX, DstY, DstW, DstH, + Bitmap.Canvas.Handle, SrcX, SrcY, SrcW, Srch, + Bitmap.Palette, TransparentColor); + end; + finally + Bitmap.Canvas.OnChanging := CanvasChanging; + Bitmap.Canvas.Unlock; + end; +end; + +procedure StretchBitmapRectTransparent(Dest: TCanvas; DstX, DstY, + DstW, DstH: Integer; SrcRect: TRect; Bitmap: TBitmap; + TransparentColor: TColor); +begin + with SrcRect do + StretchBitmapTransparent(Dest, Bitmap, TransparentColor, + DstX, DstY, DstW, DstH, Left, Top, Right - Left, Bottom - Top); +end; + +procedure DrawBitmapRectTransparent(Dest: TCanvas; DstX, DstY: Integer; + SrcRect: TRect; Bitmap: TBitmap; TransparentColor: TColor); +begin + with SrcRect do + StretchBitmapTransparent(Dest, Bitmap, TransparentColor, + DstX, DstY, Right - Left, Bottom - Top, Left, Top, Right - Left, + Bottom - Top); +end; + +procedure DrawBitmapTransparent(Dest: TCanvas; DstX, DstY: Integer; + Bitmap: TBitmap; TransparentColor: TColor); +begin + StretchBitmapTransparent(Dest, Bitmap, TransparentColor, DstX, DstY, + Bitmap.Width, Bitmap.Height, 0, 0, Bitmap.Width, Bitmap.Height); +end; + +{ CreateDisabledBitmap. Creating TBitmap object with disable button glyph + image. You must destroy it outside by calling TBitmap.Free method. } + +function CreateDisabledBitmap_NewStyle(FOriginal: TBitmap; BackColor: TColor): + TBitmap; +var + MonoBmp: TBitmap; + R: TRect; + DestDC, SrcDC: HDC; +begin + R := Rect(0, 0, FOriginal.Width, FOriginal.Height); + Result := TBitmap.Create; + try + Result.Width := FOriginal.Width; + Result.Height := FOriginal.Height; + Result.Canvas.Brush.Color := BackColor; + Result.Canvas.FillRect(R); + + MonoBmp := TBitmap.Create; + try + MonoBmp.Width := FOriginal.Width; + MonoBmp.Height := FOriginal.Height; + MonoBmp.Canvas.Brush.Color := clWhite; + MonoBmp.Canvas.FillRect(R); + DrawBitmapTransparent(MonoBmp.Canvas, 0, 0, FOriginal, BackColor); + MonoBmp.Monochrome := True; + + SrcDC := MonoBmp.Canvas.Handle; + { Convert Black to clBtnHighlight } + Result.Canvas.Brush.Color := clBtnHighlight; + DestDC := Result.Canvas.Handle; + SetTextColor(DestDC, clWhite); + SetBkColor(DestDC, clBlack); + BitBlt(DestDC, 1, 1, FOriginal.Width, FOriginal.Height, SrcDC, 0, 0, + ROP_DSPDxax); + { Convert Black to clBtnShadow } + Result.Canvas.Brush.Color := clBtnShadow; + DestDC := Result.Canvas.Handle; + SetTextColor(DestDC, clWhite); + SetBkColor(DestDC, clBlack); + BitBlt(DestDC, 0, 0, FOriginal.Width, FOriginal.Height, SrcDC, 0, 0, + ROP_DSPDxax); + finally + MonoBmp.Free; + end; + except + Result.Free; + raise; + end; +end; + +function CreateDisabledBitmapEx(FOriginal: TBitmap; OutlineColor, BackColor, + HighLightColor, ShadowColor: TColor; DrawHighlight: Boolean): TBitmap; +var + MonoBmp: TBitmap; + IRect: TRect; +begin + IRect := Rect(0, 0, FOriginal.Width, FOriginal.Height); + Result := TBitmap.Create; + try + Result.Width := FOriginal.Width; + Result.Height := FOriginal.Height; + MonoBmp := TBitmap.Create; + try + with MonoBmp do + begin + Width := FOriginal.Width; + Height := FOriginal.Height; + Canvas.CopyRect(IRect, FOriginal.Canvas, IRect); + HandleType := bmDDB; + Canvas.Brush.Color := OutlineColor; + if Monochrome then + begin + Canvas.Font.Color := clWhite; + Monochrome := False; + Canvas.Brush.Color := clWhite; + end; + Monochrome := True; + end; + with Result.Canvas do + begin + Brush.Color := BackColor; + FillRect(IRect); + if DrawHighlight then + begin + Brush.Color := HighLightColor; + SetTextColor(Handle, clBlack); + SetBkColor(Handle, clWhite); + BitBlt(Handle, 1, 1, RectWidth(IRect), RectHeight(IRect), + MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax); + end; + Brush.Color := ShadowColor; + SetTextColor(Handle, clBlack); + SetBkColor(Handle, clWhite); + BitBlt(Handle, 0, 0, RectWidth(IRect), RectHeight(IRect), + MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax); + end; + finally + MonoBmp.Free; + end; + except + Result.Free; + raise; + end; +end; + +function CreateDisabledBitmap(FOriginal: TBitmap; OutlineColor: TColor): + TBitmap; +begin + Result := CreateDisabledBitmapEx(FOriginal, OutlineColor, + clBtnFace, clBtnHighlight, clBtnShadow, True); +end; + +{ ChangeBitmapColor. This function create new TBitmap object. + You must destroy it outside by calling TBitmap.Free method. } + +function ChangeBitmapColor(Bitmap: TBitmap; Color, NewColor: TColor): TBitmap; +var + R: TRect; +begin + Result := TBitmap.Create; + try + with Result do + begin + Height := Bitmap.Height; + Width := Bitmap.Width; + R := Bounds(0, 0, Width, Height); + with Canvas do + begin + Brush.Color := NewColor; + FillRect(R); + BrushCopy( R, Bitmap, R, Color); + end; + end; + except + Result.Free; + raise; + end; +end; + +procedure ImageListDrawDisabled(Images: TCustomImageList; Canvas: TCanvas; + X, Y, Index: Integer; HighLightColor, GrayColor: TColor; + DrawHighlight: Boolean); +var + Bmp: TBitmap; + SaveColor: TColor; +begin + SaveColor := Canvas.Brush.Color; + Bmp := TBitmap.Create; + try + Bmp.Width := Images.Width; + Bmp.Height := Images.Height; + with Bmp.Canvas do + begin + Brush.Color := clWhite; + FillRect(Rect(0, 0, Images.Width, Images.Height)); + ImageList_Draw(Images.Handle, Index, Handle, 0, 0, ILD_MASK); + end; + Bmp.Monochrome := True; + if DrawHighlight then + begin + Canvas.Brush.Color := HighLightColor; + SetTextColor(Canvas.Handle, clWhite); + SetBkColor(Canvas.Handle, clBlack); + BitBlt(Canvas.Handle, X + 1, Y + 1, Images.Width, + Images.Height, Bmp.Canvas.Handle, 0, 0, ROP_DSPDxax); + end; + Canvas.Brush.Color := GrayColor; + SetTextColor(Canvas.Handle, clWhite); + SetBkColor(Canvas.Handle, clBlack); + BitBlt(Canvas.Handle, X, Y, Images.Width, + Images.Height, Bmp.Canvas.Handle, 0, 0, ROP_DSPDxax); + finally + Bmp.Free; + Canvas.Brush.Color := SaveColor; + end; +end; + +{ Brush Pattern } + +function CreateTwoColorsBrushPattern(Color1, Color2: TColor): TBitmap; +var + X, Y: Integer; +begin + Result := TBitmap.Create; + Result.Width := 8; + Result.Height := 8; + with Result.Canvas do + begin + Brush.Style := bsSolid; + Brush.Color := Color1; + FillRect(Rect(0, 0, Result.Width, Result.Height)); + for Y := 0 to 7 do + for X := 0 to 7 do + if (Y mod 2) = (X mod 2) then { toggles between even/odd pixles } + Pixels[X, Y] := Color2; { on even/odd rows } + end; +end; + +{ Icons } + +{$IFNDEF CLR} +function MakeIcon(ResID: PChar): TIcon; +begin + Result := MakeModuleIcon(HInstance, ResID); +end; + +function MakeIconID(ResID: Word): TIcon; +begin + Result := MakeModuleIcon(HInstance, MakeIntResource(ResID)); +end; + +function MakeModuleIcon(Module: THandle; ResID: PChar): TIcon; +begin + Result := TIcon.Create; + Result.Handle := LoadIcon(Module, ResID); + if Result.Handle = 0 then + begin + Result.Free; + Result := nil; + end; +end; +{$ENDIF !CLR} + +{ Create TBitmap object from TIcon } + +function CreateBitmapFromIcon(Icon: TIcon; BackColor: TColor): TBitmap; +var + IWidth, IHeight: Integer; +begin + IWidth := Icon.Width; + IHeight := Icon.Height; + Result := TBitmap.Create; + try + Result.Width := IWidth; + Result.Height := IHeight; + with Result.Canvas do + begin + Brush.Color := BackColor; + FillRect(Rect(0, 0, IWidth, IHeight)); + Draw(0, 0, Icon); + end; + Result.TransparentColor := BackColor; + Result.Transparent := True; + except + Result.Free; + raise; + end; +end; + +function CreateIconFromBitmap(Bitmap: TBitmap; TransparentColor: TColor): TIcon; + +begin + with TImageList.CreateSize(Bitmap.Width, Bitmap.Height) do + try + if TransparentColor = clDefault then + TransparentColor := Bitmap.TransparentColor; + AllocBy := 1; + AddMasked(Bitmap, TransparentColor); + Result := TIcon.Create; + try + GetIcon(0, Result); + except + Result.Free; + raise; + end; + finally + Free; + end; +end; + +type + TCustomControlAccessProtected = class(TCustomControl); + + + +procedure PaintInverseRect(const RectOrg, RectEnd: TPoint); +var + DC: Windows.HDC; + R: TRect; +begin + DC := Windows.GetDC(HWND_DESKTOP); + try + R := Rect(RectOrg.X, RectOrg.Y, RectEnd.X, RectEnd.Y); + Windows.InvertRect(DC, R); + finally + Windows.ReleaseDC(HWND_DESKTOP, DC); + end; +end; + +procedure DrawInvertFrame(ScreenRect: TRect; Width: Integer); +var + DC: Windows.HDC; + I: Integer; +begin + DC := Windows.GetDC(HWND_DESKTOP); + try + for I := 1 to Width do + begin + Windows.DrawFocusRect(DC, ScreenRect); + //InflateRect(ScreenRect, -1, -1); + end; + finally + Windows.ReleaseDC(HWND_DESKTOP, DC); + end; +end; + + + + + +function PointInPolyRgn(const P: TPoint; const Points: array of TPoint): + Boolean; +{$IFNDEF CLR} +type + PPoints = ^TPoints; + TPoints = array [0..0] of TPoint; +{$ENDIF CLR} +var + Rgn: HRGN; +begin + {$IFDEF CLR} + Rgn := CreatePolygonRgn(Points, Length(Points), WINDING); + {$ELSE} + Rgn := CreatePolygonRgn(PPoints(@Points)^, High(Points) + 1, WINDING); + {$ENDIF CLR} + try + Result := PtInRegion(Rgn, P.X, P.Y); + finally + DeleteObject(Rgn); + end; +end; + +function PaletteColor(Color: TColor): Longint; +begin + Result := ColorToRGB(Color) or PaletteMask; +end; + + + +function CreateRotatedFont(Font: TFont; Angle: Integer): HFONT; +var + LogFont: TLogFont; +begin + {$IFNDEF CLR} + FillChar(LogFont, SizeOf(LogFont), 0); + {$ENDIF !CLR} + with LogFont do + begin + lfHeight := Font.Height; + lfWidth := 0; + lfEscapement := Angle * 10; + lfOrientation := 0; + if fsBold in Font.Style then + lfWeight := FW_BOLD + else + lfWeight := FW_NORMAL; + lfItalic := Ord(fsItalic in Font.Style); + lfUnderline := Ord(fsUnderline in Font.Style); + lfStrikeOut := Byte(fsStrikeOut in Font.Style); + lfCharSet := Byte(Font.Charset); + {$IFDEF CLR} + if SameText(Font.Name, 'Default') then + lfFaceName := DefFontData.Name + else + lfFaceName := Font.Name; + {$ELSE} + if SameText(Font.Name, 'Default') then + StrPCopy(lfFaceName, DefFontData.Name) + else + StrPCopy(lfFaceName, Font.Name); + {$ENDIF CLR} + lfQuality := DEFAULT_QUALITY; + lfOutPrecision := OUT_TT_PRECIS; + lfClipPrecision := CLIP_DEFAULT_PRECIS; + case Font.Pitch of + fpVariable: + lfPitchAndFamily := VARIABLE_PITCH; + fpFixed: + lfPitchAndFamily := FIXED_PITCH; + else + lfPitchAndFamily := DEFAULT_PITCH; + end; + end; + Result := CreateFontIndirect(LogFont); +end; + +function PaletteEntries(Palette: HPALETTE): Integer; +begin + {$IFDEF CLR} + GetObject(Palette, 4, Result); + {$ELSE} + GetObject(Palette, SizeOf(Integer), @Result); + {$ENDIF CLR} +end; + + +procedure Delay(MSecs: Int64); +var + FirstTickCount, Now: Int64; +begin + FirstTickCount := GetTickCount64; + repeat + Application.ProcessMessages; + { allowing access to other controls, etc. } + Now := GetTickCount64; + until (Now - FirstTickCount >= MSecs); +end; + +function GetTickCount64: Int64; +var + QFreq, QCount: Int64; +begin + Result := GetTickCount; + if QueryPerformanceFrequency(QFreq) then + begin + QueryPerformanceCounter(QCount); + if QFreq <> 0 then + Result := (QCount div QFreq) * 1000; + end; +end; + +procedure CenterControl(Control: TControl); +var + X, Y: Integer; +begin + X := Control.Left; + Y := Control.Top; + if Control is TForm then + begin + with Control do + begin + if (TForm(Control).FormStyle = fsMDIChild) and + (Application.MainForm <> nil) then + begin + X := (Application.MainForm.ClientWidth - Width) div 2; + Y := (Application.MainForm.ClientHeight - Height) div 2; + end + else + begin + X := (Screen.Width - Width) div 2; + Y := (Screen.Height - Height) div 2; + end; + end; + end + else + if Control.Parent <> nil then + begin + with Control do + begin + Parent.HandleNeeded; + X := (Parent.ClientWidth - Width) div 2; + Y := (Parent.ClientHeight - Height) div 2; + end; + end; + if X < 0 then + X := 0; + if Y < 0 then + Y := 0; + with Control do + SetBounds(X, Y, Width, Height); +end; + +procedure MergeForm(AControl: TWinControl; AForm: TForm; Align: TAlign; + Show: Boolean); +var + R: TRect; + AutoScroll: Boolean; +begin + AutoScroll := AForm.AutoScroll; + AForm.Hide; + {$IFDEF CLR} + AForm.GetType.InvokeMember('DestroyHandle', + BindingFlags.NonPublic or BindingFlags.InvokeMethod or BindingFlags.Instance, + nil, AForm, []); + {$ELSE} + TCustomControlAccessProtected(AForm).DestroyHandle; + {$ENDIF CLR} + with AForm do + begin + BorderStyle := bsNone; + BorderIcons := []; + Parent := AControl; + end; + AControl.DisableAlign; + try + if Align <> alNone then + AForm.Align := Align + else + begin + R := AControl.ClientRect; + AForm.SetBounds(R.Left + AForm.Left, R.Top + AForm.Top, AForm.Width, + AForm.Height); + end; + AForm.AutoScroll := AutoScroll; + AForm.Visible := Show; + finally + AControl.EnableAlign; + end; +end; + + +{ ShowMDIClientEdge function has been copied from Inprise's FORMS.PAS unit, + Delphi 4 version } + +procedure ShowMDIClientEdge(ClientHandle: THandle; ShowEdge: Boolean); +var + Style: Longint; +begin + if ClientHandle <> 0 then + begin + Style := GetWindowLong(ClientHandle, GWL_EXSTYLE); + if ShowEdge then + if Style and WS_EX_CLIENTEDGE = 0 then + Style := Style or WS_EX_CLIENTEDGE + else + Exit + else + if Style and WS_EX_CLIENTEDGE <> 0 then + Style := Style and not WS_EX_CLIENTEDGE + else + Exit; + SetWindowLong(ClientHandle, GWL_EXSTYLE, Style); + SetWindowPos(ClientHandle, 0, 0, 0, 0, 0, + SWP_FRAMECHANGED or SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER); + end; +end; + +{ Shade rectangle } + +procedure ShadeRect(DC: HDC; const Rect: TRect); +const + HatchBits: array [0..7] of Word = ($11, $22, $44, $88, $11, $22, $44, $88); +var + Bitmap: HBITMAP; + SaveBrush: HBRUSH; + SaveTextColor, SaveBkColor: TColorRef; + {$IFDEF CLR} + Mem: IntPtr; + {$ENDIF CLR} +begin + {$IFDEF CLR} + Marshal.AllocHGlobal(Length(HatchBits)); + try + Marshal.StructureToPtr(HatchBits, Mem, True); + Bitmap := CreateBitmap(8, 8, 1, 1, Mem); + finally + Marshal.DestroyStructure(Mem, TypeOf(HatchBits)); + end; + {$ELSE} + Bitmap := CreateBitmap(8, 8, 1, 1, @HatchBits); + {$ENDIF CLR} + SaveBrush := SelectObject(DC, CreatePatternBrush(Bitmap)); + try + SaveTextColor := SetTextColor(DC, clWhite); + SaveBkColor := SetBkColor(DC, clBlack); + with Rect do + PatBlt(DC, Left, Top, Right - Left, Bottom - Top, $00A000C9); + SetBkColor(DC, SaveBkColor); + SetTextColor(DC, SaveTextColor); + finally + DeleteObject(SelectObject(DC, SaveBrush)); + DeleteObject(Bitmap); + end; +end; + + +function ScreenWorkArea: TRect; +begin + {$IFDEF MSWINDOWS} + if not SystemParametersInfo(SPI_GETWORKAREA, 0, {$IFNDEF CLR}@{$ENDIF}Result, 0) then + {$ENDIF MSWINDOWS} + with Screen do + Result := Bounds(0, 0, Width, Height); +end; + +{ Standard Windows MessageBox function } + +function MsgBox(const Caption, Text: string; Flags: Integer): Integer; + +begin + {$IFDEF CLR} + Result := Application.MessageBox(Text, Caption, Flags); + {$ELSE} + Result := Application.MessageBox(PChar(Text), PChar(Caption), Flags); + {$ENDIF CLR} +end; + + + +function MsgDlg(const Msg: string; AType: TMsgDlgType; AButtons: TMsgDlgButtons; + HelpCtx: Longint): Word; +begin + Result := MessageDlg(Msg, AType, AButtons, HelpCtx); +end; + + +function MsgBox(Handle: THandle; const Caption, Text: string; Flags: Integer): Integer; +begin + {$IFDEF CLR} + Result := Windows.MessageBox(Handle, Text, Caption, Flags); + {$ELSE} + {$IFDEF MSWINDOWS} + Result := Windows.MessageBox(Handle, PChar(Text), PChar(Caption), Flags); + {$ENDIF MSWINDOWS} + {$IFDEF UNIX} + Result := MsgBox(Caption, Text, Flags); + {$ENDIF UNIX} + {$ENDIF CLR} +end; +*******************) + +{ Gradient fill procedure - displays a gradient beginning with a chosen } +{ color and ending with another chosen color. Based on TGradientFill } +{ component source code written by Curtis White, cwhite att teleport dott com. } + +procedure GradientFillRect(Canvas: TCanvas; ARect: TRect; StartColor, + EndColor: TColor; Direction: TFillDirection; Colors: Byte); +// 25.09.2007 - SESS - Implemented using TCanvas.GradientFill(), +// "Colors" parameter just ignored +var + gd: TGradientDirection; + c: TColor; +begin + case Direction of + fdTopToBottom: + gd := gdVertical; + fdBottomToTop: + begin + gd := gdVertical; + c := StartColor; + StartColor := EndColor; + EndColor := c; + end; + fdLeftToRight: + gd := gdHorizontal; + fdRightToLeft: + begin + gd := gdHorizontal; + c := StartColor; + StartColor := EndColor; + EndColor := c; + end; + end; + Canvas.GradientFill(ARect, StartColor, EndColor, gd); +end; + +(******************** NOT CONVERTED +function GetAveCharSize(Canvas: TCanvas): TPoint; +var + I: Integer; + Buffer: array [0..51] of Char; + {$IFDEF CLR} + Size: TSize; + {$ENDIF CLR} +begin + for I := 0 to 25 do + Buffer[I] := Chr(I + Ord('A')); + for I := 0 to 25 do + Buffer[I + 26] := Chr(I + Ord('a')); + {$IFDEF CLR} + GetTextExtentPoint32(Canvas.Handle, Buffer, 52, Size); + Result.X := Size.cx; + Result.Y := Size.cy; + {$ELSE} + GetTextExtentPoint32(Canvas.Handle, Buffer, 52, TSize(Result)); + {$ENDIF CLR} + Result.X := Result.X div 52; +end; + +{ Cursor routines } + +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} +function LoadAniCursor(Instance: THandle; ResID: PChar): HCURSOR; +{ Unfortunately I don't know how we can load animated cursor from + executable resource directly. So I write this routine using temporary + file and LoadCursorFromFile function. } +var + S: TFileStream; + Path, FileName: array[0..MAX_PATH] of Char; + RSrc: HRSRC; + Res: THandle; + Data: Pointer; +begin + Integer(Result) := 0; + RSrc := FindResource(Instance, ResID, RT_ANICURSOR); + if RSrc <> 0 then + begin + OSCheck(GetTempPath(MAX_PATH, Path) <> 0); + OSCheck(GetTempFileName(Path, 'ANI', 0, FileName) <> 0); + try + Res := LoadResource(Instance, RSrc); + try + Data := LockResource(Res); + if Data <> nil then + try + S := TFileStream.Create(StrPas(FileName), fmCreate); + try + S.WriteBuffer(Data^, SizeOfResource(Instance, RSrc)); + finally + S.Free; + end; + Result := LoadCursorFromFile(FileName); + finally + UnlockResource(Res); + end; + finally + FreeResource(Res); + end; + finally + Windows.DeleteFile(FileName); + end; + end; +end; +{$ENDIF MSWINDOWS} +{$ENDIF !CLR} + +function GetNextFreeCursorIndex(StartHint: Integer; PreDefined: Boolean): + Integer; +begin + Result := StartHint; + if PreDefined then + begin + if Result >= crSizeAll then + Result := crSizeAll - 1; + end + else + if Result <= crDefault then + Result := crDefault + 1; + while (Screen.Cursors[Result] <> Screen.Cursors[crDefault]) do + begin + if PreDefined then + Dec(Result) + else + Inc(Result); + if (Result < Low(TCursor)) or (Result > High(TCursor)) then + {$IFDEF CLR} + raise EOutOfResources.Create(SOutOfResources); + {$ELSE} + raise EOutOfResources.CreateRes(@SOutOfResources); + {$ENDIF CLR} + end; +end; + +{$IFNDEF CLR} +function DefineCursor(Instance: THandle; ResID: PChar): TCursor; +var + Handle: HCURSOR; +begin + Handle := LoadCursor(Instance, ResID); + if Handle = 0 then + Handle := LoadAniCursor(Instance, ResID); + if Integer(Handle) = 0 then + ResourceNotFound(ResID); + try + Result := GetNextFreeCursorIndex(crJVCLFirst, False); + Screen.Cursors[Result] := Handle; + except + DestroyCursor(Handle); + raise; + end; +end; +{$ENDIF !CLR} + +var + WaitCount: Integer = 0; + SaveCursor: TCursor = crDefault; + +const + FWaitCursor: TCursor = crHourGlass; + +procedure StartWait; +begin + if WaitCount = 0 then + begin + SaveCursor := Screen.Cursor; + Screen.Cursor := FWaitCursor; + end; + Inc(WaitCount); +end; + +procedure StopWait; +begin + if WaitCount > 0 then + begin + Dec(WaitCount); + if WaitCount = 0 then + Screen.Cursor := SaveCursor; + end; +end; + +function WaitCursor: IInterface; +begin + Result := ScreenCursor(crHourGlass); +end; + +function ScreenCursor(ACursor: TCursor): IInterface; +begin + Result := TWaitCursor.Create(ACursor); +end; + +{$IFDEF MSWINDOWS} + +var + OLEDragCursorsLoaded: Boolean = False; + +function LoadOLEDragCursors: Boolean; +{$IFDEF CLR} +type + PChar = Integer; +{$ENDIF CLR} +const + cOle32DLL = 'ole32.dll'; +var + Handle: Cardinal; +begin + if OLEDragCursorsLoaded then + begin + Result := True; + Exit; + end; + OLEDragCursorsLoaded := True; + + Result := False; + if Screen <> nil then + begin + Handle := GetModuleHandle(cOle32DLL); + if Handle = 0 then + Handle := LoadLibraryEx(cOle32DLL, 0, LOAD_LIBRARY_AS_DATAFILE); + if Handle <> 0 then // (p3) don't free the lib handle! + try + Screen.Cursors[crNoDrop] := LoadCursor(Handle, PChar(1)); + Screen.Cursors[crDrag] := LoadCursor(Handle, PChar(2)); + Screen.Cursors[crMultiDrag] := LoadCursor(Handle, PChar(3)); + Screen.Cursors[crMultiDragLink] := LoadCursor(Handle, PChar(4)); + Screen.Cursors[crDragAlt] := LoadCursor(Handle, PChar(5)); + Screen.Cursors[crMultiDragAlt] := LoadCursor(Handle, PChar(6)); + Screen.Cursors[crMultiDragLinkAlt] := LoadCursor(Handle, PChar(7)); + Result := True; + except + end; + end; +end; + +{$ENDIF MSWINDOWS} + +procedure SetDefaultJVCLCursors; +begin + if Screen <> nil then + begin + // dynamically assign the first available cursor id to our cursor defines + crMultiDragLink := GetNextFreeCursorIndex(crJVCLFirst, False); + Screen.Cursors[crMultiDragLink] := Screen.Cursors[crMultiDrag]; + crDragAlt := GetNextFreeCursorIndex(crJVCLFirst, False); + Screen.Cursors[crDragAlt] := Screen.Cursors[crDrag]; + crMultiDragAlt := GetNextFreeCursorIndex(crJVCLFirst, False); + Screen.Cursors[crMultiDragAlt] := Screen.Cursors[crMultiDrag]; + crMultiDragLinkAlt := GetNextFreeCursorIndex(crJVCLFirst, False); + Screen.Cursors[crMultiDragLinkAlt] := Screen.Cursors[crMultiDrag]; + { begin RxLib } + crHand := GetNextFreeCursorIndex(crJVCLFirst, False); + Screen.Cursors[crHand] := LoadCursor(HInstance, 'JvHANDCURSOR'); + crDragHand := GetNextFreeCursorIndex(crJVCLFirst, False); + Screen.Cursors[crDragHand] := LoadCursor(hInstance, 'JvDRAGCURSOR'); + { end RxLib } + end; +end; + +{ Grid drawing } + +var + DrawBitmap: TBitmap = nil; + +procedure UsesBitmap; +begin + if DrawBitmap = nil then + DrawBitmap := TBitmap.Create; +end; + +procedure WriteText(ACanvas: TCanvas; ARect: TRect; DX, DY: Integer; + const Text: string; Alignment: TAlignment; WordWrap: Boolean; + ARightToLeft: Boolean = False); +const + AlignFlags: array [TAlignment] of Integer = + (DT_LEFT or DT_EXPANDTABS or DT_NOPREFIX, + DT_RIGHT or DT_EXPANDTABS or DT_NOPREFIX, + DT_CENTER or DT_EXPANDTABS or DT_NOPREFIX); + WrapFlags: array [Boolean] of Integer = (0, DT_WORDBREAK); + + RTL: array [Boolean] of Integer = (0, DT_RTLREADING); +var + B, R: TRect; + I, Left: Integer; +begin + UsesBitmap; + I := ColorToRGB(ACanvas.Brush.Color); + if not WordWrap and (Integer(GetNearestColor(ACanvas.Handle, I)) = I) and + (Pos(Cr, Text) = 0) then + begin { Use ExtTextOut for solid colors } + { In BiDi, because we changed the window origin, the text that does not + change alignment, actually gets its alignment changed. } + if (ACanvas.CanvasOrientation = coRightToLeft) and (not ARightToLeft) then + ChangeBiDiModeAlignment(Alignment); + case Alignment of + taLeftJustify: + Left := ARect.Left + DX; + taRightJustify: + Left := ARect.Right - ACanvas.TextWidth(Text) - 3; + else { taCenter } + Left := ARect.Left + (ARect.Right - ARect.Left) shr 1 - + (ACanvas.TextWidth(Text) shr 1); + end; + ACanvas.TextRect(ARect, Left, ARect.Top + DY, Text); + end + else + begin { Use FillRect and DrawText for dithered colors } + DrawBitmap.Canvas.Lock; + try + with DrawBitmap, ARect do { Use offscreen bitmap to eliminate flicker and } + begin { brush origin tics in painting / scrolling. } + Width := Max(Width, Right - Left); + Height := Max(Height, Bottom - Top); + R := Rect(DX, DY, Right - Left - 1, Bottom - Top - 1); + B := Rect(0, 0, Right - Left, Bottom - Top); + end; + with DrawBitmap.Canvas do + begin + Font := ACanvas.Font; + Font.Color := ACanvas.Font.Color; + Brush := ACanvas.Brush; + Brush.Style := bsSolid; + FillRect(B); + SetBkMode(Handle, Transparent); + if (ACanvas.CanvasOrientation = coRightToLeft) then + ChangeBiDiModeAlignment(Alignment); + DrawText(DrawBitmap.Canvas, Text, Length(Text), R, + //Windows.DrawText(Handle, PChar(Text), Length(Text), R, + AlignFlags[Alignment] or RTL[ARightToLeft] or WrapFlags[WordWrap]); + end; + ACanvas.CopyRect(ARect, DrawBitmap.Canvas, B); + finally + DrawBitmap.Canvas.Unlock; + end; + end; +end; + +procedure DrawCellTextEx(Control: TCustomControl; ACol, ARow: Longint; + const S: string; const ARect: TRect; Align: TAlignment; + VertAlign: TVertAlignment; WordWrap: Boolean; ARightToLeft: Boolean); overload; +const + MinOffs = 2; +var + H: Integer; +begin + case VertAlign of + vaTopJustify: + H := MinOffs; + vaCenterJustify: + with TCustomControlAccessProtected(Control) do + H := Max(1, (ARect.Bottom - ARect.Top - Canvas.TextHeight('W')) div 2); + else {vaBottomJustify} + begin + with TCustomControlAccessProtected(Control) do + H := Max(MinOffs, ARect.Bottom - ARect.Top - Canvas.TextHeight('W')); + end; + end; + WriteText(TCustomControlAccessProtected(Control).Canvas, ARect, MinOffs, + H, S, Align, WordWrap, ARightToLeft); +end; + +procedure DrawCellText(Control: TCustomControl; ACol, ARow: Longint; + const S: string; const ARect: TRect; Align: TAlignment; + VertAlign: TVertAlignment; ARightToLeft: Boolean); overload; +begin + DrawCellTextEx(Control, ACol, ARow, S, ARect, Align, VertAlign, + Align = taCenter, ARightToLeft); +end; + +procedure DrawCellTextEx(Control: TCustomControl; ACol, ARow: Longint; + const S: string; const ARect: TRect; Align: TAlignment; + VertAlign: TVertAlignment; WordWrap: Boolean); overload; +const + MinOffs = 2; +var + H: Integer; +begin + case VertAlign of + vaTopJustify: + H := MinOffs; + vaCenterJustify: + with TCustomControlAccessProtected(Control) do + H := Max(1, (ARect.Bottom - ARect.Top - Canvas.TextHeight('W')) div 2); + else {vaBottomJustify} + begin + with TCustomControlAccessProtected(Control) do + H := Max(MinOffs, ARect.Bottom - ARect.Top - Canvas.TextHeight('W')); + end; + end; + WriteText(TCustomControlAccessProtected(Control).Canvas, ARect, MinOffs, H, S, Align, WordWrap); +end; + +procedure DrawCellText(Control: TCustomControl; ACol, ARow: Longint; + const S: string; const ARect: TRect; Align: TAlignment; + VertAlign: TVertAlignment); overload; +begin + DrawCellTextEx(Control, ACol, ARow, S, ARect, Align, VertAlign, Align = taCenter); +end; + +procedure DrawCellBitmap(Control: TCustomControl; ACol, ARow: Longint; + Bmp: TGraphic; Rect: TRect); +begin + Rect.Top := (Rect.Bottom + Rect.Top - Bmp.Height) div 2; + Rect.Left := (Rect.Right + Rect.Left - Bmp.Width) div 2; + TCustomControlAccessProtected(Control).Canvas.Draw(Rect.Left, Rect.Top, Bmp); +end; + +//=== { TJvDesktopCanvas } =================================================== + +destructor TJvDesktopCanvas.Destroy; +begin + FreeHandle; + inherited Destroy; +end; + +procedure TJvDesktopCanvas.CreateHandle; +begin + if FDC = 0 then + FDC := GetWindowDC(GetDesktopWindow); + Handle := FDC; +end; + +procedure TJvDesktopCanvas.FreeHandle; +begin + if FDC <> 0 then + begin + Handle := 0; + ReleaseDC(GetDesktopWindow, FDC); + FDC := 0; + end; +end; + +procedure TJvDesktopCanvas.SetOrigin(X, Y: Integer); +var + FOrigin: TPoint; +begin + SetWindowOrgEx(Handle, -X, -Y, {$IFNDEF CLR}@{$ENDIF}FOrigin); +end; + +// (rom) moved to file end to minimize W- switch impact at end of function + +{ end JvVCLUtils } +{ begin JvUtils } + +function FindByTag(WinControl: TWinControl; ComponentClass: TComponentClass; + const Tag: Integer): TComponent; +var + I: Integer; +begin + for I := 0 to WinControl.ControlCount - 1 do + begin + Result := WinControl.Controls[I]; + if (Result is ComponentClass) and (Result.Tag = Tag) then + Exit; + end; + Result := nil; +end; + +function ControlAtPos2(Parent: TWinControl; X, Y: Integer): TControl; +var + I: Integer; + P: TPoint; +begin + P := Point(X, Y); + for I := Parent.ControlCount - 1 downto 0 do + begin + Result := Parent.Controls[I]; + with Result do + if PtInRect(BoundsRect, P) then + Exit; + end; + Result := nil; +end; + +function RBTag(Parent: TWinControl): Integer; +var + RB: TRadioButton; + I: Integer; +begin + RB := nil; + with Parent do + for I := 0 to ControlCount - 1 do + if (Controls[I] is TRadioButton) and + (Controls[I] as TRadioButton).Checked then + begin + RB := Controls[I] as TRadioButton; + Break; + end; + if RB <> nil then + Result := RB.Tag + else + Result := 0; +end; + +function FindFormByClass(FormClass: TFormClass): TForm; +var + I: Integer; +begin + Result := nil; + for I := 0 to Application.ComponentCount - 1 do + if Application.Components[I].ClassName = FormClass.ClassName then + begin + Result := Application.Components[I] as TForm; + Break; + end; +end; + +function FindFormByClassName(const FormClassName: string): TForm; +var + I: Integer; +begin + Result := nil; + for I := 0 to Application.ComponentCount - 1 do + if Application.Components[I].ClassName = FormClassName then + begin + Result := Application.Components[I] as TForm; + Break; + end; +end; + +function AppMinimized: Boolean; +begin + Result := IsIconic(GetAppHandle); +end; + +{$IFDEF MSWINDOWS} + +{ Check if this is the active Windows task } +{ Copied from implementation of FORMS.PAS } +type + {$IFNDEF CLR} + PCheckTaskInfo = ^TCheckTaskInfo; + {$ENDIF !CLR} + TCheckTaskInfo = record + FocusWnd: Windows.HWND; + Found: Boolean; + end; +{$IFDEF CLR} + PCheckTaskInfo = TCheckTaskInfo; + +var + CheckTaskHashLock: TObject = nil; + CheckTaskInfo: PCheckTaskInfo; +{$ENDIF CLR} + +function CheckTaskWindow(Window: HWND; Data: Longint): LongBool; {$IFNDEF CLR}stdcall;{$ENDIF} +begin + Result := True; + {$IFDEF CLR} + if CheckTaskInfo.FocusWnd = Window then + begin + CheckTaskInfo.Found := True; + {$ELSE} + if PCheckTaskInfo(Data).FocusWnd = Window then + begin + PCheckTaskInfo(Data).Found := True; + {$ENDIF CLR} + Result := False; + end; +end; + +function IsForegroundTask: Boolean; +var + Info: TCheckTaskInfo; +begin + Info.FocusWnd := Windows.GetActiveWindow; + Info.Found := False; + + {$IFDEF CLR} + if CheckTaskHashLock = nil then + CheckTaskHashLock := TObject.Create; + Monitor.Enter(CheckTaskHashLock); + try + CheckTaskInfo := Info; + EnumThreadWindows(GetCurrentThreadId, CheckTaskWindow, 0); + Info := CheckTaskInfo; + finally + Monitor.Exit(CheckTaskHashLock); + end; + {$ELSE} + EnumThreadWindows(GetCurrentThreadId, @CheckTaskWindow, Longint(@Info)); + {$ENDIF CLR} + Result := Info.Found; +end; + +{$ENDIF MSWINDOWS} + +{$IFDEF UNIX} +function IsForegroundTask: Boolean; +begin + Result := Application.Active; +end; +{$ENDIF UNIX} + +function MessageBox(const Msg, Caption: string; const Flags: Integer): Integer; +{$IFDEF CLR} +begin + if Caption = '' then + Result := Application.MessageBox(Msg, Caption, Flags) + else + Result := Application.MessageBox(Msg, Application.Title, Flags); +end; +{$ELSE} +begin + if Caption = '' then + Result := Application.MessageBox(PChar(Msg), PChar(Caption), Flags) + else + Result := Application.MessageBox(PChar(Msg), PChar(Application.Title), Flags); +end; +{$ENDIF CLR} + +const + NoHelp = 0; { for MsgDlg2 } + MsgDlgCharSet: Integer = DEFAULT_CHARSET; + +function MsgDlgDef1(const Msg, ACaption: string; DlgType: TMsgDlgType; + Buttons: TMsgDlgButtons; DefButton: TMsgDlgBtn; UseDefButton: Boolean; + AHelpContext: Integer; Control: TWinControl): Integer; +const + ButtonNames: array [TMsgDlgBtn] of string = + ('Yes', 'No', 'OK', 'Cancel', 'Abort', 'Retry', 'Ignore', 'All', 'NoToAll', + 'YesToAll', 'Help'); +var + P: TPoint; + I: Integer; + Btn: TButton; + StayOnTop: Boolean; +begin + if AHelpContext <> 0 then + Buttons := Buttons + [mbHelp]; + StayOnTop := False; + with CreateMessageDialog(Msg, DlgType, Buttons) do + try + Font.Charset := MsgDlgCharSet; + if (Screen.ActiveForm <> nil) and + (Screen.ActiveForm.FormStyle = fsStayOnTop) then + begin + StayOnTop := True; + SetWindowTop(Screen.ActiveForm.Handle, False); + end; + if ACaption <> '' then + Caption := ACaption; + if Control = nil then + begin + Left := (Screen.Width - Width) div 2; + Top := (Screen.Height - Height) div 2; + end + else + begin + P := Point((Control.Width - Width) div 2, + (Control.Height - Height) div 2); + P := Control.ClientToScreen(P); + Left := P.X; + Top := P.Y + end; + if Left < 0 then + Left := 0 + else + if Left > Screen.Width then + Left := Screen.Width - Width; + if Top < 0 then + Top := 0 + else + if Top > Screen.Height then + Top := Screen.Height - Height; + HelpContext := AHelpContext; + + Btn := FindComponent(ButtonNames[DefButton]) as TButton; + if UseDefButton and (Btn <> nil) then + begin + for I := 0 to ComponentCount - 1 do + if Components[I] is TButton then + (Components[I] as TButton).Default := False; + Btn.Default := True; + ActiveControl := Btn; + end; + Btn := FindComponent(ButtonNames[mbIgnore]) as TButton; + if Btn <> nil then + begin + // Btn.Width := Btn.Width * 5 div 4; {To shift the Help button Help [translated] } + end; + Result := ShowModal; + finally + Free; + if (Screen.ActiveForm <> nil) and StayOnTop then + SetWindowTop(Screen.ActiveForm.Handle, True); + end; +end; + +function MsgDlgDef(const Msg, ACaption: string; DlgType: TMsgDlgType; + Buttons: TMsgDlgButtons; DefButton: TMsgDlgBtn; HelpContext: Integer; + Control: TWinControl): Integer; +begin + Result := MsgDlgDef1(Msg, ACaption, DlgType, Buttons, DefButton, True, + HelpContext, Control); +end; + +function MsgDlg2(const Msg, ACaption: string; DlgType: TMsgDlgType; + Buttons: TMsgDlgButtons; HelpContext: Integer; + Control: TWinControl): Integer; +begin + Result := MsgDlgDef1(Msg, ACaption, DlgType, Buttons, mbHelp, False, + HelpContext, Control); +end; + +function MsgYesNo(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0): Boolean; +begin + Result := MsgBox(Handle, Caption, Msg, MB_YESNO or Flags) = IDYES; +end; + +function MsgRetryCancel(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0): Boolean; +begin + Result := MsgBox(Handle, Caption, Msg, MB_RETRYCANCEL or Flags) = IDRETRY; +end; + +function MsgAbortRetryIgnore(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0): Integer; +begin + Result := MsgBox(Handle, Caption, Msg, MB_ABORTRETRYIGNORE or Flags); +end; + +function MsgYesNoCancel(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0): Integer; +begin + Result := MsgBox(Handle, Caption, Msg, MB_YESNOCANCEL or Flags); +end; + +function MsgOKCancel(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0): Boolean; +begin + Result := MsgBox(Handle, Caption, Msg, MB_OKCANCEL or Flags) = IDOK; +end; + +procedure MsgOK(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0); +begin + MsgBox(Handle, Caption, Msg, MB_OK or Flags); +end; + +procedure MsgInfo(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0); +begin + MsgOK(Handle, Msg, Caption, MB_ICONINFORMATION or Flags); +end; + +procedure MsgWarn(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0); +begin + MsgOK(Handle, Msg, Caption, MB_ICONWARNING or Flags); +end; + +procedure MsgQuestion(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0); +begin + MsgOK(Handle, Msg, Caption, MB_ICONQUESTION or Flags); +end; + +procedure MsgError(Handle: Integer; const Msg, Caption: string; Flags: DWORD = 0); +begin + MsgOK(Handle, Msg, Caption, MB_ICONERROR or Flags); +end; + +function FindIcon(hInstance: DWORD; const IconName: string): Boolean; +begin + {$IFDEF CLR} + Result := (IconName <> '') and + (FindResource(hInstance, IconName, RT_GROUP_ICON) <> 0) or + (FindResource(hInstance, IconName, RT_ICON) <> 0) + {$ELSE} + if Win32Platform = VER_PLATFORM_WIN32_NT then + Result := (IconName <> '') and + (FindResourceW(hInstance, PWideChar(WideString(IconName)), PWideChar(RT_GROUP_ICON)) <> 0) or + (FindResourceW(hInstance, PWideChar(WideString(IconName)), PWideChar(RT_ICON)) <> 0) + else + Result := (IconName <> '') and + (FindResourceA(hInstance, PChar(IconName), RT_GROUP_ICON) <> 0) or + (FindResourceA(hInstance, PChar(IconName), RT_ICON) <> 0); + {$ENDIF CLR} +end; + +{$IFNDEF CLR} +type + TMsgBoxParamsRec = record + case Boolean of + False: (ParamsA: TMsgBoxParamsA); + True: (ParamsW: TMsgBoxParamsW); + end; +{$ENDIF !CLR} + +procedure MsgAbout(Handle: Integer; const Msg, Caption: string; const IcoName: string = 'MAINICON'; Flags: DWORD = MB_OK); +{$IFDEF CLR} +var + Params: TMsgBoxParams; +begin + Params.hInstance := hInstance; + with Params do + begin + cbSize := Marshal.SizeOf(Params); + hwndOwner := Handle; + lpszText := Msg; + lpszCaption := Caption; + dwStyle := Flags; + if FindIcon(hInstance, IcoName) then + begin + dwStyle := dwStyle or MB_USERICON; + lpszIcon := IcoName; + end + else + dwStyle := dwStyle or MB_ICONINFORMATION; + dwContextHelpId := 0; + lpfnMsgBoxCallback := nil; + dwLanguageId := GetUserDefaultLangID; + end; + MessageBoxIndirect(Params); +end; +{$ELSE} +var + Params: TMsgBoxParamsRec; +begin + if Win32Platform = VER_PLATFORM_WIN32_NT then + begin + Params.ParamsW.hInstance := hInstance; + with Params.ParamsW do + begin + cbSize := SizeOf(TMsgBoxParamsW); + hwndOwner := Handle; + lpszText := PWideChar(WideString(Msg)); + lpszCaption := PWideChar(WideString(Caption)); + dwStyle := Flags; + if FindIcon(hInstance, IcoName) then + begin + dwStyle := dwStyle or MB_USERICON; + lpszIcon := PWideChar(WideString(IcoName)); + end + else + dwStyle := dwStyle or MB_ICONINFORMATION; + dwContextHelpId := 0; + lpfnMsgBoxCallback := nil; + dwLanguageId := GetUserDefaultLangID; + MessageBoxIndirectW(Params.ParamsW); + end + end + else + begin + Params.ParamsA.hInstance := hInstance; + with Params.ParamsA do + begin + cbSize := SizeOf(TMsgBoxParamsA); + hwndOwner := Handle; + lpszText := PChar(Msg); + lpszCaption := PChar(Caption); + dwStyle := Flags; + if FindIcon(hInstance, IcoName) then + begin + dwStyle := dwStyle or MB_USERICON; + lpszIcon := PChar(IcoName); + end + else + dwStyle := dwStyle or MB_ICONINFORMATION; + dwContextHelpId := 0; + lpfnMsgBoxCallback := nil; + dwLanguageId := GetUserDefaultLangID; + MessageBoxIndirectA(Params.ParamsA); + end; + end; +end; +{$ENDIF CLR} + +procedure LoadIcoToImage(ALarge, ASmall: ImgList.TCustomImageList; const NameRes: string); +var + Ico: TIcon; +begin + Ico := TIcon.Create; + if ALarge <> nil then + begin + {$IFDEF CLR} + Ico.Handle := LoadImage(HInstance, NameRes, IMAGE_ICON, 32, 32, 0); + {$ELSE} + Ico.Handle := LoadImage(HInstance, PChar(NameRes), IMAGE_ICON, 32, 32, 0); + {$ENDIF CLR} + ALarge.AddIcon(Ico); + end; + if ASmall <> nil then + begin + {$IFDEF CLR} + Ico.Handle := LoadImage(HInstance, NameRes, IMAGE_ICON, 16, 16, 0); + {$ELSE} + Ico.Handle := LoadImage(HInstance, PChar(NameRes), IMAGE_ICON, 16, 16, 0); + {$ENDIF CLR} + ASmall.AddIcon(Ico); + end; + Ico.Free; +end; + +function DualInputQuery(const ACaption, Prompt1, Prompt2: string; + var AValue1, AValue2: string; PasswordChar: Char = #0): Boolean; +var + AForm: TForm; + ALabel1, ALabel2: TLabel; + AEdit1, AEdit2: TEdit; + ASize, I: Integer; +begin + Result := False; + AForm := CreateMessageDialog(Prompt1, mtCustom, [mbOK, mbCancel]); + ASize := 0; + if AForm <> nil then + try + AForm.Caption := ACaption; + ALabel1 := AForm.FindComponent('Message') as TLabel; + for I := 0 to AForm.ControlCount - 1 do + if AForm.Controls[I] is TButton then + TButton(AForm.Controls[I]).Anchors := [akRight, akBottom]; + if ALabel1 <> nil then + begin + AEdit1 := TEdit.Create(AForm); + AEdit1.Left := ALabel1.Left; + AEdit1.Width := AForm.ClientWidth - AEdit1.Left * 2; + AEdit1.Top := ALabel1.Top + ALabel1.Height + 2; + AEdit1.Parent := AForm; + AEdit1.Anchors := [akLeft, akTop, akRight]; + AEdit1.Text := AValue1; + ALabel1.Caption := Prompt1; + ALabel1.FocusControl := AEdit1; + Inc(ASize, AEdit1.Height + 2); + + ALabel2 := TLabel.Create(AForm); + ALabel2.Left := ALabel1.Left; + ALabel2.Top := AEdit1.Top + AEdit1.Height + 7; + ALabel2.Caption := Prompt2; + ALabel2.Parent := AForm; + Inc(ASize, ALabel2.Height + 7); + + AEdit2 := TEdit.Create(AForm); + AEdit2.Left := ALabel1.Left; + AEdit2.Width := AForm.ClientWidth - AEdit2.Left * 2; + AEdit2.Top := ALabel2.Top + ALabel2.Height + 2; + AEdit2.Parent := AForm; + AEdit2.Anchors := [akLeft, akTop, akRight]; + AEdit2.Text := AValue1; + if PasswordChar <> #0 then + AEdit2.PasswordChar := PasswordChar; + ALabel2.FocusControl := AEdit2; + + Inc(ASize, AEdit2.Height + 8); + AForm.ClientHeight := AForm.ClientHeight + ASize; + AForm.ClientWidth := 320; + AForm.ActiveControl := AEdit1; + Result := AForm.ShowModal = mrOk; + if Result then + begin + AValue1 := AEdit1.Text; + AValue2 := AEdit2.Text; + end; + end; + finally + AForm.Free; + end; +end; + +function InputQueryPassword(const ACaption, APrompt: string; PasswordChar: Char; var Value: string): Boolean; +var + AForm: TForm; + ALabel: TLabel; + AEdit: TEdit; + ASize: Integer; +begin + Result := False; + AForm := CreateMessageDialog(APrompt, mtCustom, [mbOK, mbCancel]); + if AForm <> nil then + try + AForm.Caption := ACaption; + ALabel := AForm.FindComponent('Message') as TLabel; + for ASize := 0 to AForm.ControlCount - 1 do + if AForm.Controls[ASize] is TButton then + TButton(AForm.Controls[ASize]).Anchors := [akRight, akBottom]; + ASize := 0; + if ALabel <> nil then + begin + AEdit := TEdit.Create(AForm); + AEdit.Left := ALabel.Left; + AEdit.Width := AForm.ClientWidth - AEdit.Left * 2; + AEdit.Top := ALabel.Top + ALabel.Height + 2; + AEdit.Parent := AForm; + AEdit.Anchors := [akLeft, akTop, akRight]; + AEdit.Text := Value; + AEdit.PasswordChar := PasswordChar; + ALabel.Caption := APrompt; + ALabel.FocusControl := AEdit; + Inc(ASize, AEdit.Height + 2); + + AForm.ClientHeight := AForm.ClientHeight + ASize; + AForm.ClientWidth := 320; + AForm.ActiveControl := AEdit; + Result := AForm.ShowModal = mrOk; + if Result then + Value := AEdit.Text; + end; + finally + AForm.Free; + end; +end; + + +procedure CenterHor(Parent: TControl; MinLeft: Integer; Controls: array of TControl); +var + I: Integer; +begin + for I := Low(Controls) to High(Controls) do + Controls[I].Left := Max(MinLeft, (Parent.Width - Controls[I].Width) div 2); +end; + +procedure EnableControls(Control: TWinControl; const Enable: Boolean); +var + I: Integer; +begin + for I := 0 to Control.ControlCount - 1 do + Control.Controls[I].Enabled := Enable; +end; + +procedure EnableMenuItems(MenuItem: TMenuItem; const Tag: Integer; const Enable: Boolean); +var + I: Integer; +begin + for I := 0 to MenuItem.Count - 1 do + if MenuItem[I].Tag <> Tag then + MenuItem[I].Enabled := Enable; +end; + +procedure ExpandWidth(Parent: TControl; MinWidth: Integer; Controls: array of TControl); +var + I: Integer; +begin + for I := Low(Controls) to High(Controls) do + Controls[I].Width := Max(MinWidth, Parent.ClientWidth - 2 * Controls[I].Left); +end; + +function PanelBorder(Panel: TCustomPanel): Integer; +begin + Result := TPanel(Panel).BorderWidth; + if TPanel(Panel).BevelOuter <> bvNone then + Inc(Result, TPanel(Panel).BevelWidth); + if TPanel(Panel).BevelInner <> bvNone then + Inc(Result, TPanel(Panel).BevelWidth); +end; + +function Pixels(Control: TControl; APixels: Integer): Integer; +var + Form: TForm; +begin + Result := APixels; + if Control is TForm then + Form := TForm(Control) + else + Form := TForm(GetParentForm(Control)); + if Form.Scaled then + Result := Result * Form.PixelsPerInch div 96; +end; + +procedure ShowMenu(Form: TForm; MenuAni: TMenuAnimation); +var + I: Integer; + H: Integer; + W: Integer; +begin + case MenuAni of + maNone: + Form.Show; + maRandom: + ; + maUnfold: + begin + H := Form.Height; + Form.Height := 0; + Form.Show; + for I := 0 to H div 10 do + if Form.Height < H then + Form.Height := Form.Height + 10; + end; + maSlide: + begin + H := Form.Height; + W := Form.Width; + Form.Height := 0; + Form.Width := 0; + Form.Show; + for I := 0 to Max(H div 5, W div 5) do + begin + if Form.Height < H then + Form.Height := Form.Height + 5; + if Form.Width < W then + Form.Width := Form.Width + 5; + end; + // CS_SAVEBITS + end; + end; +end; + +{$IFNDEF CLR} +{$IFDEF MSWINDOWS} + +function TargetFileName(const FileName: TFileName): TFileName; +begin + Result := FileName; + if SameFileName(ExtractFileExt(FileName), '.lnk') then + if ResolveLink(GetAppHandle, FileName, Result) <> 0 then + {$IFDEF CLR} + raise EJVCLException.CreateFmt(RsECantGetShortCut, [FileName]); + {$ELSE} + raise EJVCLException.CreateResFmt(@RsECantGetShortCut, [FileName]); + {$ENDIF CLR} +end; + +function ResolveLink(const HWND: THandle; const LinkFile: TFileName; + var FileName: TFileName): HRESULT; +var + psl: IShellLink; + WLinkFile: array [0..MAX_PATH] of WideChar; + wfd: TWin32FindData; + ppf: IPersistFile; + wnd: Windows.HWND; +begin + wnd := HWND; + Pointer(psl) := nil; + Pointer(ppf) := nil; + Result := CoInitialize(nil); + if Succeeded(Result) then + begin + // Get a Pointer to the IShellLink interface. + Result := CoCreateInstance(CLSID_ShellLink, nil, + CLSCTX_INPROC_SERVER, IShellLink, psl); + if Succeeded(Result) then + begin + + // Get a Pointer to the IPersistFile interface. + Result := psl.QueryInterface(IPersistFile, ppf); + if Succeeded(Result) then + begin + StringToWideChar(LinkFile, WLinkFile, SizeOf(WLinkFile) - 1); + // Load the shortcut. + Result := ppf.Load(WLinkFile, STGM_READ); + if Succeeded(Result) then + begin + // Resolve the link. + Result := psl.Resolve(wnd, SLR_ANY_MATCH); + if Succeeded(Result) then + begin + // Get the path to the link target. + SetLength(FileName, MAX_PATH); + Result := psl.GetPath(PChar(FileName), MAX_PATH, wfd, + SLGP_UNCPRIORITY); + if not Succeeded(Result) then + Exit; + SetLength(FileName, Length(PChar(FileName))); + end; + end; + // Release the Pointer to the IPersistFile interface. + ppf._Release; + end; + // Release the Pointer to the IShellLink interface. + psl._Release; + end; + CoUninitialize; + end; + Pointer(psl) := nil; + Pointer(ppf) := nil; +end; + +{$ENDIF MSWINDOWS} + +var + ProcList: TList = nil; + +type + TJvProcItem = class(TObject) + private + FProcObj: TProcObj; + public + constructor Create(AProcObj: TProcObj); + end; + +constructor TJvProcItem.Create(AProcObj: TProcObj); +begin + inherited Create; + FProcObj := AProcObj; +end; + +procedure TmrProc(hwnd: THandle; uMsg: Integer; idEvent: Integer; dwTime: Integer); stdcall; +var + Pr: TProcObj; +begin + if ProcList[idEvent] <> nil then + begin + Pr := TJvProcItem(ProcList[idEvent]).FProcObj; + TJvProcItem(ProcList[idEvent]).Free; + end + else + Pr := nil; + ProcList.Delete(idEvent); + KillTimer(hwnd, idEvent); + if ProcList.Count <= 0 then + begin + ProcList.Free; + ProcList := nil; + end; + if Assigned(Pr) then + Pr; +end; + +procedure ExecAfterPause(Proc: TProcObj; Pause: Integer); +var + Num: Integer; + I: Integer; +begin + if ProcList = nil then + ProcList := TList.Create; + Num := -1; + for I := 0 to ProcList.Count - 1 do + if @TJvProcItem(ProcList[I]).FProcObj = @Proc then + begin + Num := I; + Break; + end; + if Num <> -1 then + KillTimer(GetAppHandle, Num) + else + Num := ProcList.Add(TJvProcItem.Create(Proc)); + SetTimer(GetAppHandle, Num, Pause, @TmrProc); +end; +{$ENDIF !CLR} + +{ end JvUtils } + +{ begin JvApputils } + +function GetFirstParentForm(Control: TControl): TCustomForm; +begin + while not (Control is TCustomForm) and (Control.Parent <> nil) do + Control := Control.Parent; + if Control is TCustomForm then + Result := TCustomForm(Control) else + Result := nil; +end; + +function GetDefaultSection(Component: TComponent): string; +var + F: TCustomForm; + Owner: TComponent; +begin + if Component <> nil then + begin + if Component is TCustomForm then + Result := Component.ClassName + else + begin + Result := Component.Name; + if Component is TControl then + begin + // GetParentForm will not stop at the first TCustomForm it finds. + // Starting with Delphi 2005, we can pass False as the second parameter + // to stop at the FIRST parent that is a TCustomForm, but this is not + // available in earlier versions of Delphi. Hence the creation and + // use of GetFirstParentForm. + // This is required to fix Mantis 3785. Indeed with GetParentForm, the + // returned form would be the top most form. + // Say, you have a control in Form2, with an instance of Form2 docked + // in Form1. When loading, F would Form1, because the parent chain + // is completely set. But when destroying, the parent chain would be + // already broken, and F would then be Form2, thus returning a different + // section name than the one returned when loading. + F := GetFirstParentForm(TControl(Component)); + if F <> nil then + Result := F.ClassName + Result + else + begin + if TControl(Component).Parent <> nil then + Result := TControl(Component).Parent.Name + Result; + end; + end + else + begin + Owner := Component.Owner; + if Owner is TForm then + Result := Format('%s.%s', [Owner.ClassName, Result]); + end; + end; + end + else + Result := ''; +end; + +function GetDefaultIniName: string; +begin + if Assigned(OnGetDefaultIniName) then + Result := OnGetDefaultIniName + else + {$IFDEF UNIX} + Result := GetEnvironmentVariable('HOME') + PathDelim + + '.' + ExtractFileName(Application.ExeName); + {$ENDIF UNIX} + {$IFDEF MSWINDOWS} + Result := ExtractFileName(ChangeFileExt(Application.ExeName, '.ini')); + {$ENDIF MSWINDOWS} +end; + +function GetDefaultIniRegKey: string; +begin + if RegUseAppTitle and (Application.Title <> '') then + Result := Application.Title + else + Result := ExtractFileName(ChangeFileExt(Application.ExeName, '')); + if DefCompanyName <> '' then + Result := DefCompanyName + '\' + Result; + Result := 'Software\' + Result; +end; + +function FindForm(FormClass: TFormClass): TForm; +var + I: Integer; +begin + Result := nil; + for I := 0 to Screen.FormCount - 1 do + begin + if Screen.Forms[I] is FormClass then + begin + Result := Screen.Forms[I]; + Break; + end; + end; +end; + +function InternalFindShowForm(FormClass: TFormClass; + const Caption: string; Restore: Boolean): TForm; +var + I: Integer; +begin + Result := nil; + for I := 0 to Screen.FormCount - 1 do + begin + if Screen.Forms[I] is FormClass then + if (Caption = '') or (Caption = Screen.Forms[I].Caption) then + begin + Result := Screen.Forms[I]; + Break; + end; + end; + if Result = nil then + begin + Application.CreateForm(FormClass, Result); + if Caption <> '' then + Result.Caption := Caption; + end; + with Result do + begin + if Restore and (WindowState = wsMinimized) then + WindowState := wsNormal; + Show; + end; +end; + +function FindShowForm(FormClass: TFormClass; const Caption: string): TForm; +begin + Result := InternalFindShowForm(FormClass, Caption, True); +end; + +function ShowDialog(FormClass: TFormClass): Boolean; +var + Dlg: TForm; +begin + Application.CreateForm(FormClass, Dlg); + try + Result := Dlg.ShowModal in [mrOk, mrYes]; + finally + Dlg.Free; + end; +end; + +function InstantiateForm(FormClass: TFormClass; var Reference): TForm; +begin + if TForm(Reference) = nil then + Application.CreateForm(FormClass, Reference); + Result := TForm(Reference); +end; + +// (rom) use StrStringToEscaped, StrEscapedToString from JclStrings.pas + +function StrToIniStr(const Str: string): string; +var + N: Integer; +begin + Result := Str; + repeat + N := Pos(CrLf, Result); + if N > 0 then + Result := Copy(Result, 1, N - 1) + '\n' + Copy(Result, N + 2, Length(Result)); + until N = 0; + repeat + N := Pos(#10#13, Result); + if N > 0 then + Result := Copy(Result, 1, N - 1) + '\n' + Copy(Result, N + 2, Length(Result)); + until N = 0; +end; + +function IniStrToStr(const Str: string): string; +var + N: Integer; +begin + Result := Str; + repeat + N := Pos('\n', Result); + if N > 0 then + Result := Copy(Result, 1, N - 1) + CrLf + Copy(Result, N + 2, Length(Result)); + until N = 0; +end; + +{ The following strings should not be localized } +const + siFlags = 'Flags'; + siShowCmd = 'ShowCmd'; + siMinMaxPos = 'MinMaxPos'; + siNormPos = 'NormPos'; + siPixels = 'PixelsPerInch'; + siMDIChild = 'MDI Children'; + siListCount = 'Count'; + siItem = 'Item%d'; + +(-* +function IniReadString(IniFile: TObject; const Section, Ident, + Default: string): string; +begin + {$IFDEF MSWINDOWS} + if IniFile is TRegIniFile then + Result := TRegIniFile(IniFile).ReadString(Section, Ident, Default) + else + {$ENDIF MSWINDOWS} + if IniFile is TCustomIniFile then + Result := TCustomIniFile(IniFile).ReadString(Section, Ident, Default) + else + Result := Default; +end; + +procedure IniWriteString(IniFile: TObject; const Section, Ident, + Value: string); +var + S: string; +begin + {$IFDEF MSWINDOWS} + if IniFile is TRegIniFile then + TRegIniFile(IniFile).WriteString(Section, Ident, Value) + else + {$ENDIF MSWINDOWS} + begin + S := Value; + if S <> '' then + begin + if ((S[1] = '"') and (S[Length(S)] = '"')) or + ((S[1] = '''') and (S[Length(S)] = '''')) then + S := '"' + S + '"'; + end; + if IniFile is TCustomIniFile then + TCustomIniFile(IniFile).WriteString(Section, Ident, S); + end; +end; + +function IniReadInteger(IniFile: TObject; const Section, Ident: string; + Default: Longint): Longint; +begin + {$IFDEF MSWINDOWS} + if IniFile is TRegIniFile then + Result := TRegIniFile(IniFile).ReadInteger(Section, Ident, Default) + else + {$ENDIF MSWINDOWS} + if IniFile is TCustomIniFile then + Result := TCustomIniFile(IniFile).ReadInteger(Section, Ident, Default) + else + Result := Default; +end; + +procedure IniWriteInteger(IniFile: TObject; const Section, Ident: string; + Value: Longint); +begin + {$IFDEF MSWINDOWS} + if IniFile is TRegIniFile then + TRegIniFile(IniFile).WriteInteger(Section, Ident, Value) + else + {$ENDIF MSWINDOWS} + if IniFile is TCustomIniFile then + TCustomIniFile(IniFile).WriteInteger(Section, Ident, Value); +end; + +function IniReadBool(IniFile: TObject; const Section, Ident: string; + Default: Boolean): Boolean; +begin + {$IFDEF MSWINDOWS} + if IniFile is TRegIniFile then + Result := TRegIniFile(IniFile).ReadBool(Section, Ident, Default) + else + {$ENDIF MSWINDOWS} + if IniFile is TCustomIniFile then + Result := TCustomIniFile(IniFile).ReadBool(Section, Ident, Default) + else + Result := Default; +end; + +procedure IniWriteBool(IniFile: TObject; const Section, Ident: string; + Value: Boolean); +begin + {$IFDEF MSWINDOWS} + if IniFile is TRegIniFile then + TRegIniFile(IniFile).WriteBool(Section, Ident, Value) + else + {$ENDIF MSWINDOWS} + if IniFile is TCustomIniFile then + TCustomIniFile(IniFile).WriteBool(Section, Ident, Value); +end; + +procedure IniEraseSection(IniFile: TObject; const Section: string); +begin + {$IFDEF MSWINDOWS} + if IniFile is TRegIniFile then + TRegIniFile(IniFile).EraseSection(Section) + else + {$ENDIF MSWINDOWS} + if IniFile is TCustomIniFile then + TCustomIniFile(IniFile).EraseSection(Section); +end; + +procedure IniDeleteKey(IniFile: TObject; const Section, Ident: string); +begin + {$IFDEF MSWINDOWS} + if IniFile is TRegIniFile then + TRegIniFile(IniFile).DeleteKey(Section, Ident) + else + {$ENDIF MSWINDOWS} + if IniFile is TCustomIniFile then + TCustomIniFile(IniFile).DeleteKey(Section, Ident); +end; + +procedure IniReadSections(IniFile: TObject; Strings: TStrings); +begin + if IniFile is TCustomIniFile then + TCustomIniFile(IniFile).ReadSections(Strings) + {$IFDEF MSWINDOWS} + else + if IniFile is TRegIniFile then + TRegIniFile(IniFile).ReadSections(Strings); + {$ENDIF MSWINDOWS} +end; +*-) + +{$HINTS OFF} +type + {*******************************************************} + { !! ATTENTION Nasty implementation } + {*******************************************************} + { } + { This class definition was copied from FORMS.PAS. } + { It is needed to access some private fields of TForm. } + { } + { Any changes in the underlying classes may cause } + { errors in this implementation! } + { } + {*******************************************************} + + TJvHackForm = class(TScrollingWinControl) + private + FActiveControl: TWinControl; + FFocusedControl: TWinControl; + FBorderIcons: TBorderIcons; + FBorderStyle: TFormBorderStyle; + FSizeChanging: Boolean; + FWindowState: TWindowState; { !! } + end; + + TComponentAccessProtected = class(TComponent); +{$HINTS ON} + +function CrtResString: string; +begin + Result := Format('(%dx%d)', [GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN)]); +end; + +function ReadPosStr(AppStorage: TJvCustomAppStorage; const Path: string): string; +begin + if AppStorage.ValueStored(Path + CrtResString) then + Result := AppStorage.ReadString(Path + CrtResString) + else + Result := AppStorage.ReadString(Path); +end; + +procedure WritePosStr(AppStorage: TJvCustomAppStorage; const Path, Value: string); +begin + AppStorage.WriteString(Path + CrtResString, Value); + AppStorage.WriteString(Path, Value); +end; + +procedure InternalSaveMDIChildren(MainForm: TForm; + const AppStorage: TJvCustomAppStorage; const StorePath: string); +var + I: Integer; +begin + if (MainForm = nil) or (MainForm.FormStyle <> fsMDIForm) then + {$IFDEF CLR} + raise EInvalidOperation.Create(SNoMDIForm); + {$ELSE} + raise EInvalidOperation.CreateRes(@SNoMDIForm); + {$ENDIF CLR} + AppStorage.DeleteSubTree(AppStorage.ConcatPaths([StorePath, siMDIChild])); + if MainForm.MDIChildCount > 0 then + begin + AppStorage.WriteInteger(AppStorage.ConcatPaths([StorePath, siMDIChild, + siListCount]), MainForm.MDIChildCount); + for I := 0 to MainForm.MDIChildCount - 1 do + AppStorage.WriteString(AppStorage.ConcatPaths([StorePath, siMDIChild, + Format(siItem, [I])]), MainForm.MDIChildren[I].ClassName); + end; +end; + +procedure InternalRestoreMDIChildren(MainForm: TForm; + const AppStorage: TJvCustomAppStorage; const StorePath: string); +var + I: Integer; + Count: Integer; + FormClass: TFormClass; +begin + if (MainForm = nil) or (MainForm.FormStyle <> fsMDIForm) then + {$IFDEF CLR} + raise EInvalidOperation.Create(SNoMDIForm); + {$ELSE} + raise EInvalidOperation.CreateRes(@SNoMDIForm); + {$ENDIF CLR} + StartWait; + try + Count := AppStorage.ReadInteger(AppStorage.ConcatPaths([StorePath, siMDIChild, + siListCount]), 0); + if Count > 0 then + begin + for I := 0 to Count - 1 do + begin + FormClass := + TFormClass(GetClass(AppStorage.ReadString(AppStorage.ConcatPaths([StorePath, + siMDIChild, Format(siItem, [I])]), ''))); + if FormClass <> nil then + InternalFindShowForm(FormClass, '', False); + end; + end; + finally + StopWait; + end; +end; + +procedure SaveMDIChildren(MainForm: TForm; const AppStorage: TJvCustomAppStorage); +begin + InternalSaveMDIChildren(MainForm, AppStorage, ''); +end; + +procedure RestoreMDIChildren(MainForm: TForm; const AppStorage: TJvCustomAppStorage); +begin + InternalRestoreMDIChildren(MainForm, AppStorage, ''); +end; + +procedure InternalSaveFormPlacement(Form: TForm; const AppStorage: TJvCustomAppStorage; + const StorePath: string; Options: TPlacementOptions = [fpState, fpSize, fpLocation]); +var + Placement: TWindowPlacement; +begin + if Options = [fpActiveControl] then + Exit; + {$IFDEF CLR} + Placement.Length := Marshal.SizeOf(Placement); + GetWindowPlacement(Form.Handle, Placement); + {$ELSE} + Placement.Length := SizeOf(TWindowPlacement); + GetWindowPlacement(Form.Handle, @Placement); + {$ENDIF CLR} + with Placement, TForm(Form) do + begin + if (Form = Application.MainForm) and AppMinimized then + ShowCmd := SW_SHOWMINIMIZED; + if (FormStyle = fsMDIChild) and (WindowState = wsMinimized) then + Flags := Flags or WPF_SETMINPOSITION; + if fpState in Options then + AppStorage.WriteInteger(StorePath + '\' + siShowCmd, ShowCmd); + if [fpSize, fpLocation] * Options <> [] then + begin + AppStorage.WriteInteger(StorePath + '\' + siFlags, Flags); + AppStorage.WriteInteger(StorePath + '\' + siPixels, Screen.PixelsPerInch); + WritePosStr(AppStorage, StorePath + '\' + siMinMaxPos, Format('%d,%d,%d,%d', + [ptMinPosition.X, ptMinPosition.Y, ptMaxPosition.X, ptMaxPosition.Y])); + WritePosStr(AppStorage, StorePath + '\' + siNormPos, Format('%d,%d,%d,%d', + [rcNormalPosition.Left, rcNormalPosition.Top, rcNormalPosition.Right, + rcNormalPosition.Bottom])); + end; + end; +end; + +procedure InternalRestoreFormPlacement(Form: TForm; const AppStorage: TJvCustomAppStorage; + const StorePath: string; Options: TPlacementOptions = [fpState, fpSize, fpLocation]); +const + Delims = [',', ' ']; +var + PosStr: string; + Placement: TWindowPlacement; + WinState: TWindowState; + DataFound: Boolean; + + procedure ChangePosition(APosition: TPosition); + begin + {$IFDEF CLR} + Form.GetType.InvokeMember('SetDesigning', + BindingFlags.NonPublic or BindingFlags.InvokeMethod or BindingFlags.Instance, + nil, Form, [True]); + try + Form.Position := APosition; + finally + Form.GetType.InvokeMember('SetDesigning', + BindingFlags.NonPublic or BindingFlags.InvokeMethod or BindingFlags.Instance, + nil, Form, [False]); + end; + {$ELSE} + TComponentAccessProtected(Form).SetDesigning(True); + try + Form.Position := APosition; + finally + TComponentAccessProtected(Form).SetDesigning(False); + end; + {$ENDIF CLR} + end; + +begin + if Options = [fpActiveControl] then + Exit; + {$IFDEF CLR} + Placement.Length := Marshal.SizeOf(Placement); + GetWindowPlacement(Form.Handle, Placement); + {$ELSE} + Placement.Length := SizeOf(TWindowPlacement); + GetWindowPlacement(Form.Handle, @Placement); + {$ENDIF CLR} + with Placement, TForm(Form) do + begin + if not IsWindowVisible(Form.Handle) then + ShowCmd := SW_HIDE; + if [fpSize, fpLocation] * Options <> [] then + begin + DataFound := False; + AppStorage.ReadInteger(StorePath + '\' + siFlags, Flags); + PosStr := ReadPosStr(AppStorage, StorePath + '\' + siMinMaxPos); + if PosStr <> '' then + begin + DataFound := True; + if fpLocation in Options then + begin + ptMinPosition.X := StrToIntDef(ExtractWord(1, PosStr, Delims), 0); + ptMinPosition.Y := StrToIntDef(ExtractWord(2, PosStr, Delims), 0); + end; + if fpSize in Options then + begin + ptMaxPosition.X := StrToIntDef(ExtractWord(3, PosStr, Delims), 0); + ptMaxPosition.Y := StrToIntDef(ExtractWord(4, PosStr, Delims), 0); + end; + end; + PosStr := ReadPosStr(AppStorage, StorePath + '\' + siNormPos); + if PosStr <> '' then + begin + DataFound := True; + if fpLocation in Options then + begin + rcNormalPosition.Left := StrToIntDef(ExtractWord(1, PosStr, Delims), Left); + rcNormalPosition.Top := StrToIntDef(ExtractWord(2, PosStr, Delims), Top); + end + else + begin + rcNormalPosition.Left := Left; + rcNormalPosition.Top := Top; + end; + if fpSize in Options then + begin + rcNormalPosition.Right := rcNormalPosition.Left +StrToIntDef(ExtractWord(3, PosStr, Delims), Width)-StrToIntDef(ExtractWord(1, PosStr, Delims), Left); + rcNormalPosition.Bottom := rcNormalPosition.Top +StrToIntDef(ExtractWord(4, PosStr, Delims), Height)-StrToIntDef(ExtractWord(2, PosStr, Delims), Top); + end + else + if fpLocation in Options then + begin + rcNormalPosition.Right := rcNormalPosition.Left + Width; + rcNormalPosition.Bottom := rcNormalPosition.Top + Height; + end; + end; + DataFound := DataFound and (Screen.PixelsPerInch = AppStorage.ReadInteger( + StorePath + '\' + siPixels, Screen.PixelsPerInch)); + if DataFound then + begin + if not (BorderStyle in [bsSizeable, bsSizeToolWin]) then + rcNormalPosition := Rect(rcNormalPosition.Left, + rcNormalPosition.Top, rcNormalPosition.Left + Width, rcNormalPosition.Top + Height); + if rcNormalPosition.Right > rcNormalPosition.Left then + begin + if not (csDesigning in ComponentState) then + begin + if (fpSize in Options) and (fpLocation in Options) then + ChangePosition(poDesigned) + else + if fpSize in Options then + begin + {.$IFDEF DELPHI????_UP} // Change to the right version 5 or 6 ? + if Position = poDefault then + ChangePosition(poDefaultPosOnly); + {.ENDIF} + end + else + if fpLocation in Options then // obsolete but better to read + {.$IFDEF DELPHI????_UP} // Change to the right version 5 or 6 ? + if Position = poDefault then + ChangePosition(poDefaultSizeOnly) + else + {.ENDIF} + if Position <> poDesigned then + ChangePosition(poDesigned); + end; + SetWindowPlacement(Handle, {$IFNDEf CLR}@{$ENDIF}Placement); + end; + end; + end; + if fpState in Options then + begin + WinState := wsNormal; + { default maximize MDI main form } + if ((Application.MainForm = Form) or + (Application.MainForm = nil)) and ((FormStyle = fsMDIForm) or + ((FormStyle = fsNormal) and (Position = poDefault))) then + WinState := wsMaximized; + ShowCmd := AppStorage.ReadInteger(StorePath + '\' + siShowCmd, SW_HIDE); + case ShowCmd of + SW_SHOWNORMAL, SW_RESTORE, SW_SHOW: + WinState := wsNormal; + SW_MINIMIZE, SW_SHOWMINIMIZED, SW_SHOWMINNOACTIVE: + WinState := wsMinimized; + SW_MAXIMIZE: + WinState := wsMaximized; + end; + if (WinState = wsMinimized) and ((Form = Application.MainForm) or + (Application.MainForm = nil)) then + begin + {$IFDEF CLR} + SetPrivateField(Form, 'FWindowState', wsNormal); + {$ELSE} + TJvHackForm(Form).FWindowState := wsNormal; + {$ENDIF CLR} + PostMessage(Application.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0); + Exit; + end; + if FormStyle in [fsMDIChild, fsMDIForm] then + {$IFDEF CLR} + SetPrivateField(Form, 'FWindowState', WinState) + {$ELSE} + TJvHackForm(Form).FWindowState := WinState + {$ENDIF CLR} + else + WindowState := WinState; + end; + Update; + end; +end; + +procedure InternalSaveGridLayout(Grid: TCustomGrid; + const AppStorage: TJvCustomAppStorage; const StorePath: string); +var + I: Longint; +begin + for I := 0 to TDrawGrid(Grid).ColCount - 1 do + AppStorage.WriteInteger(AppStorage.ConcatPaths([StorePath, Format(siItem, [I])]), + TDrawGrid(Grid).ColWidths[I]); +end; + +procedure InternalRestoreGridLayout(Grid: TCustomGrid; + const AppStorage: TJvCustomAppStorage; const StorePath: string); +var + I: Longint; +begin + for I := 0 to TDrawGrid(Grid).ColCount - 1 do + TDrawGrid(Grid).ColWidths[I] := + AppStorage.ReadInteger(AppStorage.ConcatPaths([StorePath, + Format(siItem, [I])]), TDrawGrid(Grid).ColWidths[I]); +end; + +procedure RestoreGridLayout(Grid: TCustomGrid; const AppStorage: TJvCustomAppStorage); +begin + InternalRestoreGridLayout(Grid, AppStorage, GetDefaultSection(Grid)); +end; + +procedure SaveGridLayout(Grid: TCustomGrid; const AppStorage: TJvCustomAppStorage); +begin + InternalSaveGridLayout(Grid, AppStorage, GetDefaultSection(Grid)); +end; + +procedure SaveFormPlacement(Form: TForm; const AppStorage: TJvCustomAppStorage; Options: TPlacementOptions); +begin + InternalSaveFormPlacement(Form, AppStorage, GetDefaultSection(Form), Options); +end; + +procedure RestoreFormPlacement(Form: TForm; const AppStorage: TJvCustomAppStorage; Options: TPlacementOptions); +begin + InternalRestoreFormPlacement(Form, AppStorage, GetDefaultSection(Form), Options); +end; + + + +procedure AppBroadcast(Msg, wParam: Longint; lParam: Longint); +var + I: Integer; +begin + for I := 0 to Screen.FormCount - 1 do + SendMessage(Screen.Forms[I].Handle, Msg, wParam, lParam); +end; + +procedure AppTaskbarIcons(AppOnly: Boolean); +var + Style: Longint; +begin + Style := GetWindowLong(Application.Handle, GWL_STYLE); + if AppOnly then + Style := Style or WS_CAPTION + else + Style := Style and not WS_CAPTION; + SetWindowLong(Application.Handle, GWL_STYLE, Style); + if AppOnly then + SwitchToWindow(Application.Handle, False); +end; + + + +{ end JvAppUtils } +{ begin JvGraph } +// (rom) moved here to make JvMaxMin obsolete + +function MaxFloat(const Values: array of Extended): Extended; +var + I: Cardinal; +begin + Result := Values[Low(Values)]; + for I := Low(Values) + 1 to High(Values) do + if Values[I] > Result then + Result := Values[I]; +end; + +procedure InvalidBitmap; +begin + {$IFDEF CLR} + raise EInvalidGraphic.Create(SInvalidBitmap); + {$ELSE} + raise EInvalidGraphic.CreateRes(@SInvalidBitmap); + {$ENDIF CLR} +end; + +function WidthBytes(I: Longint): Longint; +begin + Result := ((I + 31) div 32) * 4; +end; + +function PixelFormatToColors(PixelFormat: TPixelFormat): Integer; +begin + case PixelFormat of + pf1bit: + Result := 2; + pf4bit: + Result := 16; + pf8bit: + Result := 256; + else + Result := 0; + end; +end; + + + +function ScreenPixelFormat: TPixelFormat; +var + DC: HDC; +begin + DC := CreateIC('DISPLAY', nil, nil, nil); + try + case GetDeviceCaps(DC, PLANES) * GetDeviceCaps(DC, BITSPIXEL) of + 1: + Result := pf1bit; + 4: + Result := pf4bit; + 8: + Result := pf8bit; + 15: + Result := pf15bit; + 16: + Result := pf16bit; + 24: + Result := pf24bit; + 32: + Result := pf32bit; + else + Result := pfDevice; + end; + finally + DeleteDC(DC); + end; +end; + +function ScreenColorCount: Integer; +begin + Result := PixelFormatToColors(ScreenPixelFormat); +end; + + +function GetWorkareaRect(Monitor: TMonitor): TRect; +var + MonInfo: TMonitorInfo; +begin + MonInfo.cbSize := SizeOf(MonInfo); + GetMonitorInfo(Monitor.Handle, @MonInfo); + Result := MonInfo.rcWork; +end; + +function FindMonitor(Handle: HMONITOR): TMonitor; +var + I: Integer; +begin + Result := nil; + for I := 0 to Screen.MonitorCount - 1 do + if Screen.Monitors[I].Handle = Handle then + begin + Result := Screen.Monitors[I]; + Break; + end; +end; + +{ Quantizing } +{ Quantizing procedures based on free C source code written by + Joe C. Oliphant, CompuServe 71742, 1451, joe_oliphant att csufresno dott edu } + +const + MAX_COLORS = 4096; + +type + TTriple = array [0..2] of Byte; + + {$IFDEF CLR} + TQColor = class; + PQColor = TQColor; + TQColor = class + RGB: TTriple; + NewColorIndex: Byte; + Count: Longint; + PNext: PQColor; + end; + + PQColorArray = array of TQColor; + TQColorArray = array [0..MAX_COLORS - 1] of TQColor; + + PQColorList = array of PQColor; + TQColorList = array [0..MaxListSize - 1] of PQColor; + + TNewColor = record + RGBMin: TTriple; + RGBWidth: TTriple; + NumEntries: Longint; + Count: Longint; + QuantizedColors: PQColor; + end; + PNewColor = TNewColor; + + PNewColorArray = array of TNewColor; + TNewColorArray = array [Byte] of TNewColor; + {$ELSE} + PQColor = ^TQColor; + TQColor = record + RGB: TTriple; + NewColorIndex: Byte; + Count: Longint; + PNext: PQColor; + end; + + PQColorArray = ^TQColorArray; + TQColorArray = array [0..MAX_COLORS - 1] of TQColor; + + PQColorList = ^TQColorList; + TQColorList = array [0..MaxListSize - 1] of PQColor; + + PNewColor = ^TNewColor; + TNewColor = record + RGBMin: TTriple; + RGBWidth: TTriple; + NumEntries: Longint; + Count: Longint; + QuantizedColors: PQColor; + end; + + PNewColorArray = ^TNewColorArray; + TNewColorArray = array [Byte] of TNewColor; + {$ENDIF CLR} + +procedure PInsert(ColorList: PQColorList; {$IFDEF CLR}Offset: Integer;{$ENDIF} + Number: Integer; SortRGBAxis: Integer); +var + Q1, Q2: PQColor; + I, J: Integer; + Temp: PQColor; +begin + for I := 1 to Number - 1 do + begin + Temp := ColorList[{$IFDEF CLR}Offset +{$ENDIF}I]; + J := I - 1; + while J >= 0 do + begin + Q1 := Temp; + Q2 := ColorList[{$IFDEF CLR}Offset +{$ENDIF}J]; + if Q1.RGB[SortRGBAxis] - Q2.RGB[SortRGBAxis] > 0 then + Break; + ColorList[{$IFDEF CLR}Offset +{$ENDIF}J + 1] := ColorList[{$IFDEF CLR}Offset +{$ENDIF}J]; + Dec(J); + end; + ColorList[{$IFDEF CLR}Offset +{$ENDIF}J + 1] := Temp; + end; +end; + +procedure PSort(ColorList: PQColorList; {$IFDEF CLR}Offset: Integer;{$ENDIF} + Number: Integer; SortRGBAxis: Integer); +var + Q1, Q2: PQColor; + I, J, N, Nr: Integer; + Temp, Part: PQColor; +begin + if Number < 8 then + begin + PInsert(ColorList, {$IFDEF CLR}Offset, {$ENDIF} Number, SortRGBAxis); + Exit; + end; + Part := ColorList[{$IFDEF CLR}Offset +{$ENDIF} Number div 2]; + I := -1; + J := Number; + repeat + repeat + Inc(I); + Q1 := ColorList[{$IFDEF CLR}Offset +{$ENDIF} I]; + Q2 := Part; + N := Q1.RGB[SortRGBAxis] - Q2.RGB[SortRGBAxis]; + until N >= 0; + repeat + Dec(J); + Q1 := ColorList[{$IFDEF CLR}Offset +{$ENDIF} J]; + Q2 := Part; + N := Q1.RGB[SortRGBAxis] - Q2.RGB[SortRGBAxis]; + until N <= 0; + if I >= J then + Break; + Temp := ColorList[{$IFDEF CLR}Offset +{$ENDIF} I]; + ColorList[{$IFDEF CLR}Offset +{$ENDIF} I] := ColorList[{$IFDEF CLR}Offset +{$ENDIF} J]; + ColorList[{$IFDEF CLR}Offset +{$ENDIF} J] := Temp; + until False; + Nr := Number - I; + if I < Number div 2 then + begin + {$IFDEF CLR} + PSort(ColorList, Offset, I, SortRGBAxis); + PSort(ColorList, Offset + I, Nr, SortRGBAxis); + {$ELSE} + PSort(ColorList, I, SortRGBAxis); + PSort(PQColorList(@ColorList[I]), Nr, SortRGBAxis); + {$ENDIF CLR} + end + else + begin + {$IFDEF CLR} + PSort(ColorList, Offset + I, Nr, SortRGBAxis); + PSort(ColorList, Offset, I, SortRGBAxis); + {$ELSE} + PSort(PQColorList(@ColorList[I]), Nr, SortRGBAxis); + PSort(ColorList, I, SortRGBAxis); + {$ENDIF CLR} + end; +end; + +{$IFDEF CLR} +function DivideMap(var NewColorSubdiv: PNewColorArray; ColorMapSize: Integer; + var NewColormapSize: Integer; var LPSTR: PQColorArray; Offset: Integer): Integer; +{$ELSE} +function DivideMap(NewColorSubdiv: PNewColorArray; ColorMapSize: Integer; + var NewColormapSize: Integer; LPSTR: Pointer): Integer; +{$ENDIF CLR} +var + I, J: Integer; + MaxSize, Index: Integer; + NumEntries, MinColor, MaxColor: Integer; + Sum, Count: Longint; + QuantizedColor: PQColor; + SortArray: PQColorList; + SortRGBAxis: Integer; +begin + Index := 0; + SortRGBAxis := 0; + while ColorMapSize > NewColormapSize do + begin + MaxSize := -1; + for I := 0 to NewColormapSize - 1 do + begin + for J := 0 to 2 do + begin + if (NewColorSubdiv[I].RGBWidth[J] > MaxSize) and + (NewColorSubdiv[I].NumEntries > 1) then + begin + MaxSize := NewColorSubdiv[I].RGBWidth[J]; + Index := I; + SortRGBAxis := J; + end; + end; + end; + if MaxSize = -1 then + begin + Result := 1; + Exit; + end; + SortArray := PQColorList(LPSTR); + J := 0; + QuantizedColor := NewColorSubdiv[Index].QuantizedColors; + while (J < NewColorSubdiv[Index].NumEntries) and + (QuantizedColor <> nil) do + begin + SortArray[{$IFDEF CLR}Offset +{$ENDIF} J] := QuantizedColor; + Inc(J); + QuantizedColor := QuantizedColor.PNext; + end; + PSort(SortArray, {$IFDEF CLR}Offset,{$ENDIF} NewColorSubdiv[Index].NumEntries, SortRGBAxis); + for J := 0 to NewColorSubdiv[Index].NumEntries - 2 do + SortArray[{$IFDEF CLR}Offset +{$ENDIF} J].PNext := SortArray[{$IFDEF CLR}Offset +{$ENDIF} J + 1]; + SortArray[{$IFDEF CLR}Offset +{$ENDIF} NewColorSubdiv[Index].NumEntries - 1].PNext := nil; + NewColorSubdiv[Index].QuantizedColors := SortArray[{$IFDEF CLR}Offset +{$ENDIF} 0]; + QuantizedColor := SortArray[{$IFDEF CLR}Offset +{$ENDIF} 0]; + Sum := NewColorSubdiv[Index].Count div 2 - QuantizedColor.Count; + NumEntries := 1; + Count := QuantizedColor.Count; + Dec(Sum, QuantizedColor.PNext.Count); + while (Sum >= 0) and (QuantizedColor.PNext <> nil) and + (QuantizedColor.PNext.PNext <> nil) do + begin + QuantizedColor := QuantizedColor.PNext; + Inc(NumEntries); + Inc(Count, QuantizedColor.Count); + Dec(Sum, QuantizedColor.PNext.Count); + end; + MaxColor := (QuantizedColor.RGB[SortRGBAxis]) shl 4; + MinColor := (QuantizedColor.PNext.RGB[SortRGBAxis]) shl 4; + NewColorSubdiv[NewColormapSize].QuantizedColors := QuantizedColor.PNext; + QuantizedColor.PNext := nil; + NewColorSubdiv[NewColormapSize].Count := Count; + Dec(NewColorSubdiv[Index].Count, Count); + NewColorSubdiv[NewColormapSize].NumEntries := NewColorSubdiv[Index].NumEntries - NumEntries; + NewColorSubdiv[Index].NumEntries := NumEntries; + for J := 0 to 2 do + begin + NewColorSubdiv[NewColormapSize].RGBMin[J] := + NewColorSubdiv[Index].RGBMin[J]; + NewColorSubdiv[NewColormapSize].RGBWidth[J] := + NewColorSubdiv[Index].RGBWidth[J]; + end; + NewColorSubdiv[NewColormapSize].RGBWidth[SortRGBAxis] := + NewColorSubdiv[NewColormapSize].RGBMin[SortRGBAxis] + + NewColorSubdiv[NewColormapSize].RGBWidth[SortRGBAxis] - + MinColor; + NewColorSubdiv[NewColormapSize].RGBMin[SortRGBAxis] := MinColor; + NewColorSubdiv[Index].RGBWidth[SortRGBAxis] := MaxColor - NewColorSubdiv[Index].RGBMin[SortRGBAxis]; + Inc(NewColormapSize); + end; + Result := 1; +end; + +{$IFNDEF CLR} +function Quantize(const Bmp: TBitmapInfoHeader; gptr, Data8: Pointer; + var ColorCount: Integer; var OutputColormap: TRGBPalette): Integer; +type + PWord = ^Word; +var + P: PByteArray; + LineBuffer, Data: Pointer; + LineWidth: Longint; + TmpLineWidth, NewLineWidth: Longint; + I, J: Longint; + Index: Word; + NewColormapSize, NumOfEntries: Integer; + Mems: Longint; + cRed, cGreen, cBlue: Longint; + LPSTR, Temp, Tmp: Pointer; + NewColorSubdiv: PNewColorArray; + ColorArrayEntries: PQColorArray; + QuantizedColor: PQColor; +begin + LineWidth := WidthBytes(Longint(Bmp.biWidth) * Bmp.biBitCount); + Mems := (Longint(SizeOf(TQColor)) * (MAX_COLORS)) + + (Longint(SizeOf(TNewColor)) * 256) + LineWidth + + (Longint(SizeOf(PQColor)) * (MAX_COLORS)); + LPSTR := AllocMemo(Mems); + try + Temp := AllocMemo(Longint(Bmp.biWidth) * Longint(Bmp.biHeight) * + SizeOf(Word)); + try + ColorArrayEntries := PQColorArray(LPSTR); + NewColorSubdiv := PNewColorArray(HugeOffset(LPSTR, + Longint(SizeOf(TQColor)) * (MAX_COLORS))); + LineBuffer := HugeOffset(LPSTR, (Longint(SizeOf(TQColor)) * (MAX_COLORS)) + + + (Longint(SizeOf(TNewColor)) * 256)); + for I := 0 to MAX_COLORS - 1 do + begin + ColorArrayEntries^[I].RGB[0] := I shr 8; + ColorArrayEntries^[I].RGB[1] := (I shr 4) and $0F; + ColorArrayEntries^[I].RGB[2] := I and $0F; + ColorArrayEntries^[I].Count := 0; + end; + Tmp := Temp; + for I := 0 to Bmp.biHeight - 1 do + begin + HMemCpy(LineBuffer, HugeOffset(gptr, (Bmp.biHeight - 1 - I) * + LineWidth), LineWidth); + P := LineBuffer; + for J := 0 to Bmp.biWidth - 1 do + begin + Index := (Longint(P^[2] and $F0) shl 4) + + Longint(P^[1] and $F0) + (Longint(P^[0] and $F0) shr 4); + Inc(ColorArrayEntries^[Index].Count); + P := HugeOffset(P, 3); + PWord(Tmp)^ := Index; + Tmp := HugeOffset(Tmp, 2); + end; + end; + for I := 0 to 255 do + begin + NewColorSubdiv^[I].QuantizedColors := nil; + NewColorSubdiv^[I].Count := 0; + NewColorSubdiv^[I].NumEntries := 0; + for J := 0 to 2 do + begin + NewColorSubdiv^[I].RGBMin[J] := 0; + NewColorSubdiv^[I].RGBWidth[J] := 255; + end; + end; + I := 0; + while I < MAX_COLORS do + begin + if ColorArrayEntries^[I].Count > 0 then + Break; + Inc(I); + end; + QuantizedColor := @ColorArrayEntries^[I]; + NewColorSubdiv^[0].QuantizedColors := @ColorArrayEntries^[I]; + NumOfEntries := 1; + Inc(I); + while I < MAX_COLORS do + begin + if ColorArrayEntries^[I].Count > 0 then + begin + QuantizedColor^.PNext := @ColorArrayEntries^[I]; + QuantizedColor := @ColorArrayEntries^[I]; + Inc(NumOfEntries); + end; + Inc(I); + end; + QuantizedColor^.PNext := nil; + NewColorSubdiv^[0].NumEntries := NumOfEntries; + NewColorSubdiv^[0].Count := Longint(Bmp.biWidth) * Longint(Bmp.biHeight); + NewColormapSize := 1; + DivideMap(NewColorSubdiv, ColorCount, NewColormapSize, + HugeOffset(LPSTR, Longint(SizeOf(TQColor)) * (MAX_COLORS) + + Longint(SizeOf(TNewColor)) * 256 + LineWidth)); + if NewColormapSize < ColorCount then + begin + for I := NewColormapSize to ColorCount - 1 do + FillChar(OutputColormap[I], SizeOf(TRGBQuad), 0); + end; + for I := 0 to NewColormapSize - 1 do + begin + J := NewColorSubdiv^[I].NumEntries; + if J > 0 then + begin + QuantizedColor := NewColorSubdiv^[I].QuantizedColors; + cRed := 0; + cGreen := 0; + cBlue := 0; + while QuantizedColor <> nil do + begin + QuantizedColor^.NewColorIndex := I; + Inc(cRed, QuantizedColor^.RGB[0]); + Inc(cGreen, QuantizedColor^.RGB[1]); + Inc(cBlue, QuantizedColor^.RGB[2]); + QuantizedColor := QuantizedColor^.PNext; + end; + with OutputColormap[I] do + begin + rgbRed := (Longint(cRed shl 4) or $0F) div J; + rgbGreen := (Longint(cGreen shl 4) or $0F) div J; + rgbBlue := (Longint(cBlue shl 4) or $0F) div J; + rgbReserved := 0; + if (rgbRed <= $10) and (rgbGreen <= $10) and (rgbBlue <= $10) then + FillChar(OutputColormap[I], SizeOf(TRGBQuad), 0); { clBlack } + end; + end; + end; + TmpLineWidth := Longint(Bmp.biWidth) * SizeOf(Word); + NewLineWidth := WidthBytes(Longint(Bmp.biWidth) * 8); + FillChar(Data8^, NewLineWidth * Bmp.biHeight, #0); + for I := 0 to Bmp.biHeight - 1 do + begin + LineBuffer := HugeOffset(Temp, (Bmp.biHeight - 1 - I) * TmpLineWidth); + Data := HugeOffset(Data8, I * NewLineWidth); + for J := 0 to Bmp.biWidth - 1 do + begin + PByte(Data)^ := ColorArrayEntries^[PWord(LineBuffer)^].NewColorIndex; + LineBuffer := HugeOffset(LineBuffer, 2); + Data := HugeOffset(Data, 1); + end; + end; + finally + FreeMemo(Temp); + end; + finally + FreeMemo(LPSTR); + end; + ColorCount := NewColormapSize; + Result := 0; +end; + +{ + Procedures to truncate to lower bits-per-pixel, grayscale, tripel and + histogram conversion based on freeware C source code of GBM package by + Andy Key (nyangau att interalpha dott co dott uk). The home page of GBM + author is at http://www.interalpha.net/customer/nyangau/. +} + +{ Truncate to lower bits per pixel } + +type + TTruncLine = procedure(Src, Dest: Pointer; CX: Integer); + + { For 6Rx6Gx6B, 7Rx8Gx4B palettes etc. } + +const + Scale04: array [0..3] of Byte = (0, 85, 170, 255); + Scale06: array [0..5] of Byte = (0, 51, 102, 153, 204, 255); + Scale07: array [0..6] of Byte = (0, 43, 85, 128, 170, 213, 255); + Scale08: array [0..7] of Byte = (0, 36, 73, 109, 146, 182, 219, 255); + + { For 6Rx6Gx6B, 7Rx8Gx4B palettes etc. } + +var + TruncTablesInitialized: Boolean = False; + TruncIndex04: array [Byte] of Byte; + TruncIndex06: array [Byte] of Byte; + TruncIndex07: array [Byte] of Byte; + TruncIndex08: array [Byte] of Byte; + + { These functions initialises this module } + +procedure InitTruncTables; + + function NearestIndex(Value: Byte; const Bytes: array of Byte): Byte; + var + B, I: Byte; + Diff, DiffMin: Word; + begin + Result := 0; + B := Bytes[0]; + DiffMin := Abs(Value - B); + for I := 1 to High(Bytes) do + begin + B := Bytes[I]; + Diff := Abs(Value - B); + if Diff < DiffMin then + begin + DiffMin := Diff; + Result := I; + end; + end; + end; + +var + I: Integer; +begin + if not TruncTablesInitialized then + begin + TruncTablesInitialized := True; + // (rom) secured because it is called in initialization section + // (ahuser) moved from initialization section to "on demand" initialization + try + { For 7 Red X 8 Green X 4 Blue palettes etc. } + for I := 0 to 255 do + begin + TruncIndex04[I] := NearestIndex(Byte(I), Scale04); + TruncIndex06[I] := NearestIndex(Byte(I), Scale06); + TruncIndex07[I] := NearestIndex(Byte(I), Scale07); + TruncIndex08[I] := NearestIndex(Byte(I), Scale08); + end; + except + end; + end; +end; + +procedure Trunc(const Header: TBitmapInfoHeader; Src, Dest: Pointer; + DstBitsPerPixel: Integer; TruncLineProc: TTruncLine); +var + SrcScanline, DstScanline: Longint; + Y: Integer; +begin + SrcScanline := (Header.biWidth * 3 + 3) and not 3; + DstScanline := ((Header.biWidth * DstBitsPerPixel + 31) div 32) * 4; + for Y := 0 to Header.biHeight - 1 do + TruncLineProc(HugeOffset(Src, Y * SrcScanline), + HugeOffset(Dest, Y * DstScanline), Header.biWidth); +end; + +{ return 6Rx6Gx6B palette + This function makes the palette for the 6 red X 6 green X 6 blue palette. + 216 palette entrys used. Remaining 40 Left blank. +} + +procedure TruncPal6R6G6B(var Colors: TRGBPalette); +var + I, R, G, B: Byte; +begin + FillChar(Colors, SizeOf(TRGBPalette), $80); + I := 0; + for R := 0 to 5 do + for G := 0 to 5 do + for B := 0 to 5 do + begin + Colors[I].rgbRed := Scale06[R]; + Colors[I].rgbGreen := Scale06[G]; + Colors[I].rgbBlue := Scale06[B]; + Colors[I].rgbReserved := 0; + Inc(I); + end; +end; + +{ truncate to 6Rx6Gx6B one line } + +procedure TruncLine6R6G6B(Src, Dest: Pointer; CX: Integer); +var + X: Integer; + R, G, B: Byte; +begin + InitTruncTables; + for X := 0 to CX - 1 do + begin + B := TruncIndex06[Byte(Src^)]; + Src := HugeOffset(Src, 1); + G := TruncIndex06[Byte(Src^)]; + Src := HugeOffset(Src, 1); + R := TruncIndex06[Byte(Src^)]; + Src := HugeOffset(Src, 1); + PByte(Dest)^ := 6 * (6 * R + G) + B; + Dest := HugeOffset(Dest, 1); + end; +end; + +{ truncate to 6Rx6Gx6B } + +procedure Trunc6R6G6B(const Header: TBitmapInfoHeader; + const Data24, Data8: Pointer); +begin + Trunc(Header, Data24, Data8, 8, TruncLine6R6G6B); +end; + +{ return 7Rx8Gx4B palette + This function makes the palette for the 7 red X 8 green X 4 blue palette. + 224 palette entrys used. Remaining 32 Left blank. + Colours calculated to match those used by 8514/A PM driver. +} + +procedure TruncPal7R8G4B(var Colors: TRGBPalette); +var + I, R, G, B: Byte; +begin + FillChar(Colors, SizeOf(TRGBPalette), $80); + I := 0; + for R := 0 to 6 do + for G := 0 to 7 do + for B := 0 to 3 do + begin + Colors[I].rgbRed := Scale07[R]; + Colors[I].rgbGreen := Scale08[G]; + Colors[I].rgbBlue := Scale04[B]; + Colors[I].rgbReserved := 0; + Inc(I); + end; +end; + +{ truncate to 7Rx8Gx4B one line } + +procedure TruncLine7R8G4B(Src, Dest: Pointer; CX: Integer); +var + X: Integer; + R, G, B: Byte; +begin + InitTruncTables; + for X := 0 to CX - 1 do + begin + B := TruncIndex04[Byte(Src^)]; + Src := HugeOffset(Src, 1); + G := TruncIndex08[Byte(Src^)]; + Src := HugeOffset(Src, 1); + R := TruncIndex07[Byte(Src^)]; + Src := HugeOffset(Src, 1); + PByte(Dest)^ := 4 * (8 * R + G) + B; + Dest := HugeOffset(Dest, 1); + end; +end; + +{ truncate to 7Rx8Gx4B } + +procedure Trunc7R8G4B(const Header: TBitmapInfoHeader; + const Data24, Data8: Pointer); +begin + Trunc(Header, Data24, Data8, 8, TruncLine7R8G4B); +end; + +{ Grayscale support } + +procedure GrayPal(var Colors: TRGBPalette); +var + I: Byte; +begin + FillChar(Colors, SizeOf(TRGBPalette), 0); + for I := 0 to 255 do + FillChar(Colors[I], 3, I); +end; + +procedure GrayScale(const Header: TBitmapInfoHeader; Data24, Data8: Pointer); +var + SrcScanline, DstScanline: Longint; + Y, X: Integer; + Src, Dest: PByte; + R, G, B: Byte; +begin + SrcScanline := (Header.biWidth * 3 + 3) and not 3; + DstScanline := (Header.biWidth + 3) and not 3; + for Y := 0 to Header.biHeight - 1 do + begin + Src := Data24; + Dest := Data8; + for X := 0 to Header.biWidth - 1 do + begin + B := Src^; + Src := HugeOffset(Src, 1); + G := Src^; + Src := HugeOffset(Src, 1); + R := Src^; + Src := HugeOffset(Src, 1); + Dest^ := Byte(Longint(Word(R) * 77 + Word(G) * 150 + Word(B) * 29) shr 8); + Dest := HugeOffset(Dest, 1); + end; + Data24 := HugeOffset(Data24, SrcScanline); + Data8 := HugeOffset(Data8, DstScanline); + end; +end; + +{ Tripel conversion } + +procedure TripelPal(var Colors: TRGBPalette); +var + I: Byte; +begin + FillChar(Colors, SizeOf(TRGBPalette), 0); + for I := 0 to $40 do + begin + Colors[I].rgbRed := I shl 2; + Colors[I + $40].rgbGreen := I shl 2; + Colors[I + $80].rgbBlue := I shl 2; + end; +end; + +procedure Tripel(const Header: TBitmapInfoHeader; Data24, Data8: Pointer); +var + SrcScanline, DstScanline: Longint; + Y, X: Integer; + Src, Dest: PByte; + R, G, B: Byte; +begin + SrcScanline := (Header.biWidth * 3 + 3) and not 3; + DstScanline := (Header.biWidth + 3) and not 3; + for Y := 0 to Header.biHeight - 1 do + begin + Src := Data24; + Dest := Data8; + for X := 0 to Header.biWidth - 1 do + begin + B := Src^; + Src := HugeOffset(Src, 1); + G := Src^; + Src := HugeOffset(Src, 1); + R := Src^; + Src := HugeOffset(Src, 1); + case ((X + Y) mod 3) of + 0: Dest^ := Byte(R shr 2); + 1: Dest^ := Byte($40 + (G shr 2)); + 2: Dest^ := Byte($80 + (B shr 2)); + end; + Dest := HugeOffset(Dest, 1); + end; + Data24 := HugeOffset(Data24, SrcScanline); + Data8 := HugeOffset(Data8, DstScanline); + end; +end; + +{ Histogram/Frequency-of-use method of color reduction } + +const + MAX_N_COLS = 2049; + MAX_N_HASH = 5191; + +function Hash(R, G, B: Byte): Word; +begin + Result := Word(Longint(Longint(R + G) * Longint(G + B) * Longint(B + R)) mod MAX_N_HASH); +end; + +type + PFreqRecord = ^TFreqRecord; + TFreqRecord = record + B: Byte; + G: Byte; + R: Byte; + Frequency: Longint; + Nearest: Byte; + end; + + PHist = ^THist; + THist = record + ColCount: Longint; + Rm: Byte; + Gm: Byte; + BM: Byte; + Freqs: array [0..MAX_N_COLS - 1] of TFreqRecord; + HashTable: array [0..MAX_N_HASH - 1] of Word; + end; + +function CreateHistogram(R, G, B: Byte): PHist; +{ create empty histogram } +begin + GetMem(Result, SizeOf(THist)); + with Result^ do + begin + Rm := R; + Gm := G; + BM := B; + ColCount := 0; + end; + FillChar(Result^.HashTable, MAX_N_HASH * SizeOf(Word), 255); +end; + +procedure ClearHistogram(var Hist: PHist; R, G, B: Byte); +begin + with Hist^ do + begin + Rm := R; + Gm := G; + BM := B; + ColCount := 0; + end; + FillChar(Hist^.HashTable, MAX_N_HASH * SizeOf(Word), 255); +end; + +procedure DeleteHistogram(var Hist: PHist); +begin + FreeMem(Hist, SizeOf(THist)); + Hist := nil; +end; + +function AddToHistogram(var Hist: THist; const Header: TBitmapInfoHeader; + Data24: Pointer): Boolean; +{ add bitmap data to histogram } +var + Step24: Integer; + HashColor, Index: Word; + Rm, Gm, BM, R, G, B: Byte; + X, Y, ColCount: Longint; +begin + Step24 := ((Header.biWidth * 3 + 3) and not 3) - Header.biWidth * 3; + Rm := Hist.Rm; + Gm := Hist.Gm; + BM := Hist.BM; + ColCount := Hist.ColCount; + for Y := 0 to Header.biHeight - 1 do + begin + for X := 0 to Header.biWidth - 1 do + begin + B := Byte(Data24^) and BM; + Data24 := HugeOffset(Data24, 1); + G := Byte(Data24^) and Gm; + Data24 := HugeOffset(Data24, 1); + R := Byte(Data24^) and Rm; + Data24 := HugeOffset(Data24, 1); + HashColor := Hash(R, G, B); + repeat + Index := Hist.HashTable[HashColor]; + if (Index = $FFFF) or ((Hist.Freqs[Index].R = R) and + (Hist.Freqs[Index].G = G) and (Hist.Freqs[Index].B = B)) then + Break; + Inc(HashColor); + if HashColor = MAX_N_HASH then + HashColor := 0; + until False; + { Note: loop will always be broken out of } + { We don't allow HashTable to fill up above half full } + if Index = $FFFF then + begin + { Not found in Hash table } + if ColCount = MAX_N_COLS then + begin + Result := False; + Exit; + end; + Hist.Freqs[ColCount].Frequency := 1; + Hist.Freqs[ColCount].B := B; + Hist.Freqs[ColCount].G := G; + Hist.Freqs[ColCount].R := R; + Hist.HashTable[HashColor] := ColCount; + Inc(ColCount); + end + else + begin + { Found in Hash table, update index } + Inc(Hist.Freqs[Index].Frequency); + end; + end; + Data24 := HugeOffset(Data24, Step24); + end; + Hist.ColCount := ColCount; + Result := True; +end; + +procedure PalHistogram(var Hist: THist; var Colors: TRGBPalette; + ColorsWanted: Integer); +{ work out a palette from Hist } +var + I, J: Longint; + MinDist, Dist: Longint; + MaxJ, MinJ: Longint; + DeltaB, DeltaG, DeltaR: Longint; + MaxFreq: Longint; +begin + I := 0; + MaxJ := 0; + MinJ := 0; + { Now find the ColorsWanted most frequently used ones } + while (I < ColorsWanted) and (I < Hist.ColCount) do + begin + MaxFreq := 0; + for J := 0 to Hist.ColCount - 1 do + if Hist.Freqs[J].Frequency > MaxFreq then + begin + MaxJ := J; + MaxFreq := Hist.Freqs[J].Frequency; + end; + Hist.Freqs[MaxJ].Nearest := Byte(I); + Hist.Freqs[MaxJ].Frequency := 0; { Prevent later use of Freqs[MaxJ] } + Colors[I].rgbBlue := Hist.Freqs[MaxJ].B; + Colors[I].rgbGreen := Hist.Freqs[MaxJ].G; + Colors[I].rgbRed := Hist.Freqs[MaxJ].R; + Colors[I].rgbReserved := 0; + Inc(I); + end; + { Unused palette entries will be medium grey } + while I <= 255 do + begin + Colors[I].rgbRed := $80; + Colors[I].rgbGreen := $80; + Colors[I].rgbBlue := $80; + Colors[I].rgbReserved := 0; + Inc(I); + end; + { For the rest, find the closest one in the first ColorsWanted } + for I := 0 to Hist.ColCount - 1 do + begin + if Hist.Freqs[I].Frequency <> 0 then + begin + MinDist := 3 * 256 * 256; + for J := 0 to ColorsWanted - 1 do + begin + DeltaB := Hist.Freqs[I].B - Colors[J].rgbBlue; + DeltaG := Hist.Freqs[I].G - Colors[J].rgbGreen; + DeltaR := Hist.Freqs[I].R - Colors[J].rgbRed; + Dist := Longint(DeltaR * DeltaR) + Longint(DeltaG * DeltaG) + + Longint(DeltaB * DeltaB); + if Dist < MinDist then + begin + MinDist := Dist; + MinJ := J; + end; + end; + Hist.Freqs[I].Nearest := Byte(MinJ); + end; + end; +end; + +procedure MapHistogram(var Hist: THist; const Header: TBitmapInfoHeader; + Data24, Data8: Pointer); +{ map bitmap data to Hist palette } +var + Step24: Integer; + Step8: Integer; + HashColor, Index: Longint; + Rm, Gm, BM, R, G, B: Byte; + X, Y: Longint; +begin + Step24 := ((Header.biWidth * 3 + 3) and not 3) - Header.biWidth * 3; + Step8 := ((Header.biWidth + 3) and not 3) - Header.biWidth; + Rm := Hist.Rm; + Gm := Hist.Gm; + BM := Hist.BM; + for Y := 0 to Header.biHeight - 1 do + begin + for X := 0 to Header.biWidth - 1 do + begin + B := Byte(Data24^) and BM; + Data24 := HugeOffset(Data24, 1); + G := Byte(Data24^) and Gm; + Data24 := HugeOffset(Data24, 1); + R := Byte(Data24^) and Rm; + Data24 := HugeOffset(Data24, 1); + HashColor := Hash(R, G, B); + repeat + Index := Hist.HashTable[HashColor]; + if (Hist.Freqs[Index].R = R) and (Hist.Freqs[Index].G = G) and + (Hist.Freqs[Index].B = B) then + Break; + Inc(HashColor); + if HashColor = MAX_N_HASH then + HashColor := 0; + until False; + PByte(Data8)^ := Hist.Freqs[Index].Nearest; + Data8 := HugeOffset(Data8, 1); + end; + Data24 := HugeOffset(Data24, Step24); + Data8 := HugeOffset(Data8, Step8); + end; +end; + +procedure Histogram(const Header: TBitmapInfoHeader; var Colors: TRGBPalette; + Data24, Data8: Pointer; ColorsWanted: Integer; Rm, Gm, BM: Byte); +{ map single bitmap to frequency optimised palette } +var + Hist: PHist; +begin + Hist := CreateHistogram(Rm, Gm, BM); + try + repeat + if AddToHistogram(Hist^, Header, Data24) then + Break + else + begin + if Gm > Rm then + Gm := Gm shl 1 + else + if Rm > BM then + Rm := Rm shl 1 + else + BM := BM shl 1; + ClearHistogram(Hist, Rm, Gm, BM); + end; + until False; + { Above loop will always be exited as if masks get rough } + { enough, ultimately number of unique colours < MAX_N_COLS } + PalHistogram(Hist^, Colors, ColorsWanted); + MapHistogram(Hist^, Header, Data24, Data8); + finally + DeleteHistogram(Hist); + end; +end; + +{ expand to 24 bits-per-pixel } + +(-* +procedure ExpandTo24Bit(const Header: TBitmapInfoHeader; Colors: TRGBPalette; + Data, NewData: Pointer); +var + Scanline, NewScanline: Longint; + Y, X: Integer; + Src, Dest: Pointer; + C: Byte; +begin + if Header.biBitCount = 24 then + begin + Exit; + end; + Scanline := ((Header.biWidth * Header.biBitCount + 31) div 32) * 4; + NewScanline := ((Header.biWidth * 3 + 3) and not 3); + for Y := 0 to Header.biHeight - 1 do + begin + Src := HugeOffset(Data, Y * Scanline); + Dest := HugeOffset(NewData, Y * NewScanline); + case Header.biBitCount of + 1: + begin + C := 0; + for X := 0 to Header.biWidth - 1 do + begin + if (X and 7) = 0 then + begin + C := Byte(Src^); + Src := HugeOffset(Src, 1); + end + else C := C shl 1; + PByte(Dest)^ := Colors[C shr 7].rgbBlue; + Dest := HugeOffset(Dest, 1); + PByte(Dest)^ := Colors[C shr 7].rgbGreen; + Dest := HugeOffset(Dest, 1); + PByte(Dest)^ := Colors[C shr 7].rgbRed; + Dest := HugeOffset(Dest, 1); + end; + end; + 4: + begin + X := 0; + while X < Header.biWidth - 1 do + begin + C := Byte(Src^); + Src := HugeOffset(Src, 1); + PByte(Dest)^ := Colors[C shr 4].rgbBlue; + Dest := HugeOffset(Dest, 1); + PByte(Dest)^ := Colors[C shr 4].rgbGreen; + Dest := HugeOffset(Dest, 1); + PByte(Dest)^ := Colors[C shr 4].rgbRed; + Dest := HugeOffset(Dest, 1); + PByte(Dest)^ := Colors[C and 15].rgbBlue; + Dest := HugeOffset(Dest, 1); + PByte(Dest)^ := Colors[C and 15].rgbGreen; + Dest := HugeOffset(Dest, 1); + PByte(Dest)^ := Colors[C and 15].rgbRed; + Dest := HugeOffset(Dest, 1); + Inc(X, 2); + end; + if X < Header.biWidth then + begin + C := Byte(Src^); + PByte(Dest)^ := Colors[C shr 4].rgbBlue; + Dest := HugeOffset(Dest, 1); + PByte(Dest)^ := Colors[C shr 4].rgbGreen; + Dest := HugeOffset(Dest, 1); + PByte(Dest)^ := Colors[C shr 4].rgbRed; + {Dest := HugeOffset(Dest, 1);} + end; + end; + 8: + begin + for X := 0 to Header.biWidth - 1 do + begin + C := Byte(Src^); + Src := HugeOffset(Src, 1); + PByte(Dest)^ := Colors[C].rgbBlue; + Dest := HugeOffset(Dest, 1); + PByte(Dest)^ := Colors[C].rgbGreen; + Dest := HugeOffset(Dest, 1); + PByte(Dest)^ := Colors[C].rgbRed; + Dest := HugeOffset(Dest, 1); + end; + end; + end; + end; +end; +*-) +{$ENDIF !CLR} + + +{ DIB utility routines } + +function GetPaletteBitmapFormat(Bitmap: TBitmap): TPixelFormat; +var + PalSize: Integer; +begin + Result := pfDevice; + if Bitmap.Palette <> 0 then + begin + GetObject(Bitmap.Palette, SizeOf(Integer), {$IFNDEF CLR}@{$ENDIF}PalSize); + if PalSize > 0 then + begin + if PalSize <= 2 then + Result := pf1bit + else + if PalSize <= 16 then + Result := pf4bit + else + if PalSize <= 256 then + Result := pf8bit; + end; + end; +end; + + +function GetBitmapPixelFormat(Bitmap: TBitmap): TPixelFormat; +begin + Result := Bitmap.PixelFormat; +end; + +function BytesPerScanLine(PixelsPerScanline, BitsPerPixel, + Alignment: Longint): Longint; +begin + Dec(Alignment); + Result := ((PixelsPerScanline * BitsPerPixel) + Alignment) and not Alignment; + Result := Result div 8; +end; + +{$IFNDEF CLR} + + +procedure InitializeBitmapInfoHeader(Bitmap: HBITMAP; var BI: TBitmapInfoHeader; + PixelFormat: TPixelFormat); +var + DS: TDIBSection; + Bytes: Integer; +begin + DS.dsbmih.biSize := 0; + { Retrieve the info for the current bitmap, thus with the current bit size/PixelFormat } + Bytes := GetObject(Bitmap, SizeOf(DS), @DS); + if Bytes = 0 then + InvalidBitmap + else + if (Bytes >= (SizeOf(DS.dsbm) + SizeOf(DS.dsbmih))) and + (DS.dsbmih.biSize >= DWORD(SizeOf(DS.dsbmih))) then + BI := DS.dsbmih + else + begin + FillChar(BI, SizeOf(BI), 0); + with BI, DS.dsbm do + begin + biSize := SizeOf(BI); + biWidth := bmWidth; + biHeight := bmHeight; + end; + end; + case PixelFormat of + pf1bit: + BI.biBitCount := 1; + pf4bit: + BI.biBitCount := 4; + pf8bit: + BI.biBitCount := 8; + pf24bit: + BI.biBitCount := 24; + else + BI.biBitCount := DS.dsbm.bmBitsPixel * DS.dsbm.bmPlanes; + end; + BI.biPlanes := 1; + { Calculate the size of the image with the new bit count; better would be to + call GetDIBits, see http://support.microsoft.com/default.aspx?scid=kb;EN-US;80080 + } + BI.biSizeImage := BytesPerScanLine(BI.biWidth, BI.biBitCount, 32) * + Abs(BI.biHeight); + BI.biClrUsed := 0; + BI.biClrImportant := 0; +end; + +procedure InternalGetDIBSizes(Bitmap: HBITMAP; var InfoHeaderSize: Integer; + var ImageSize: Longint; BitCount: TPixelFormat); +var + BI: TBitmapInfoHeader; +begin + InitializeBitmapInfoHeader(Bitmap, BI, BitCount); + if BI.biBitCount > 8 then + begin + InfoHeaderSize := SizeOf(TBitmapInfoHeader); + if (BI.biCompression and BI_BITFIELDS) <> 0 then + Inc(InfoHeaderSize, 12); + end + else + InfoHeaderSize := SizeOf(TBitmapInfoHeader) + SizeOf(TRGBQuad) * (1 shl BI.biBitCount); + ImageSize := BI.biSizeImage; +end; + +function GetDInColors(const BI: TBitmapInfoHeader): Integer; +begin + if (BI.biClrUsed = 0) and (BI.biBitCount <= 8) then + Result := 1 shl BI.biBitCount + else + Result := BI.biClrUsed; +end; + +function InternalGetDIB(Bitmap: HBITMAP; Palette: HPALETTE; + var BitmapInfo; var Bits; PixelFormat: TPixelFormat): Boolean; +var + OldPal: HPALETTE; + DC: HDC; +begin + InitializeBitmapInfoHeader(Bitmap, TBitmapInfoHeader(BitmapInfo), PixelFormat); + with TBitmapInfoHeader(BitmapInfo) do + biHeight := Abs(biHeight); + OldPal := 0; + DC := CreateScreenCompatibleDC; + try + if Palette <> 0 then + begin + OldPal := SelectPalette(DC, Palette, False); + RealizePalette(DC); + end; + Result := GetDIBits(DC, Bitmap, 0, TBitmapInfoHeader(BitmapInfo).biHeight, + @Bits, TBitmapInfo(BitmapInfo), DIB_RGB_COLORS) <> 0; + + TBitmapInfoHeader(BitmapInfo).biClrUsed := GetDInColors(TBitmapInfoHeader(BitmapInfo)); + finally + if OldPal <> 0 then + SelectPalette(DC, OldPal, False); + DeleteDC(DC); + end; +end; + +function DIBFromBit(Src: HBITMAP; Pal: HPALETTE; PixelFormat: TPixelFormat; + var Length: Longint): Pointer; +var + HeaderSize: Integer; + ImageSize: Longint; + FileHeader: PBitmapFileHeader; + BI: PBitmapInfoHeader; + Bits: Pointer; +begin + if Src = 0 then + InvalidBitmap; + InternalGetDIBSizes(Src, HeaderSize, ImageSize, PixelFormat); + Length := SizeOf(TBitmapFileHeader) + HeaderSize + ImageSize; + Result := AllocMemo(Length); + try + FillChar(Result^, Length, 0); + FileHeader := Result; + with FileHeader^ do + begin + bfType := $4D42; + bfSize := Length; + bfOffBits := SizeOf(FileHeader^) + HeaderSize; + end; + BI := PBitmapInfoHeader(Longint(FileHeader) + SizeOf(FileHeader^)); + Bits := Pointer(Longint(BI) + HeaderSize); + InternalGetDIB(Src, Pal, BI^, Bits^, PixelFormat); + except + FreeMemo(Result); + raise; + end; +end; + +{ Change bits per pixel in a General Bitmap } + +function BitmapToMemoryStream(Bitmap: TBitmap; PixelFormat: TPixelFormat; + Method: TMappingMethod): TMemoryStream; +var + FileHeader: PBitmapFileHeader; + BI, NewBI: PBitmapInfoHeader; + Bits: Pointer; + NewPalette: PRGBPalette; + NewHeaderSize: Integer; + ImageSize, Length, Len: Longint; + P, InitData: Pointer; + ColorCount: Integer; + SourceBitmapFormat: TPixelFormat; +begin + Result := nil; + if Bitmap.Handle = 0 then + InvalidBitmap; + SourceBitmapFormat := GetBitmapPixelFormat(Bitmap); + if (SourceBitmapFormat = PixelFormat) and + (Method <> mmGrayscale) then + begin + Result := TMemoryStream.Create; + try + Bitmap.SaveToStream(Result); + Result.Position := 0; + except + Result.Free; + raise; + end; + Exit; + end; + case PixelFormat of + pf1bit, pf4bit, pf24bit: + begin + P := DIBFromBit(Bitmap.Handle, Bitmap.Palette, PixelFormat, Length); + try + Result := TMemoryStream.Create; + try + Result.Write(P^, Length); + Result.Position := 0; + except + Result.Free; + raise; + end; + finally + FreeMemo(P); + end; + end; + pf8bit: + begin + { pf8bit - expand to 24bit first } + InitData := DIBFromBit(Bitmap.Handle, Bitmap.Palette, pf24bit, Len); + try + BI := PBitmapInfoHeader(Longint(InitData) + SizeOf(TBitmapFileHeader)); + if BI^.biBitCount <> 24 then + raise EJVCLException.CreateRes(@RsEBitCountNotImplemented); + Bits := Pointer(Longint(BI) + SizeOf(TBitmapInfoHeader)); + InternalGetDIBSizes(Bitmap.Handle, NewHeaderSize, ImageSize, PixelFormat); + Length := SizeOf(TBitmapFileHeader) + NewHeaderSize; + P := AllocMemo(Length); + try + FillChar(P^, Length, #0); + NewBI := PBitmapInfoHeader(Longint(P) + SizeOf(TBitmapFileHeader)); + if NewHeaderSize <= SizeOf(TBitmapInfoHeader) then + NewPalette := nil + else + NewPalette := PRGBPalette(Longint(NewBI) + SizeOf(TBitmapInfoHeader)); + FileHeader := PBitmapFileHeader(P); + InitializeBitmapInfoHeader(Bitmap.Handle, NewBI^, PixelFormat); + if Assigned(NewPalette) then + case Method of + mmQuantize: + begin + ColorCount := 256; + Quantize(BI^, Bits, Bits, ColorCount, NewPalette^); + NewBI^.biClrImportant := ColorCount; + end; + mmTrunc784: + begin + TruncPal7R8G4B(NewPalette^); + Trunc7R8G4B(BI^, Bits, Bits); + NewBI^.biClrImportant := 224; + end; + mmTrunc666: + begin + TruncPal6R6G6B(NewPalette^); + Trunc6R6G6B(BI^, Bits, Bits); + NewBI^.biClrImportant := 216; + end; + mmTripel: + begin + TripelPal(NewPalette^); + Tripel(BI^, Bits, Bits); + end; + mmHistogram: + begin + Histogram(BI^, NewPalette^, Bits, Bits, + PixelFormatToColors(PixelFormat), 255, 255, 255); + end; + mmGrayscale: + begin + GrayPal(NewPalette^); + GrayScale(BI^, Bits, Bits); + end; + end; + with FileHeader^ do + begin + bfType := $4D42; + bfSize := Length; + bfOffBits := SizeOf(FileHeader^) + NewHeaderSize; + end; + Result := TMemoryStream.Create; + try + Result.Write(P^, Length); + Result.Write(Bits^, ImageSize); + Result.Position := 0; + except + Result.Free; + raise; + end; + finally + FreeMemo(P); + end; + finally + FreeMemo(InitData); + end; + end + else + raise EJVCLException.CreateRes(@RsEPixelFormatNotImplemented) + end; +end; + +function BitmapToMemory(Bitmap: TBitmap; Colors: Integer): TStream; +var + PixelFormat: TPixelFormat; +begin + if Colors <= 2 then + PixelFormat := pf1bit + else + if Colors <= 16 then + PixelFormat := pf4bit + else + if Colors <= 256 then + PixelFormat := pf8bit + else + PixelFormat := pf24bit; + Result := BitmapToMemoryStream(Bitmap, PixelFormat, DefaultMappingMethod); +end; + +procedure SaveBitmapToFile(const FileName: string; Bitmap: TBitmap; + Colors: Integer); +var + Memory: TStream; +begin + if Bitmap.Monochrome then + Colors := 2; + Memory := BitmapToMemory(Bitmap, Colors); + try + TMemoryStream(Memory).SaveToFile(FileName); + finally + Memory.Free; + end; +end; + +procedure SetBitmapPixelFormat(Bitmap: TBitmap; PixelFormat: TPixelFormat; + Method: TMappingMethod); +var + M: TMemoryStream; +begin + if (Bitmap.Handle = 0) or ((GetBitmapPixelFormat(Bitmap) = PixelFormat) and (Method <> mmGrayscale)) then + Exit; + M := BitmapToMemoryStream(Bitmap, PixelFormat, Method); + try + Bitmap.LoadFromStream(M); + finally + M.Free; + end; +end; + +procedure GrayscaleBitmap(Bitmap: TBitmap); +begin + SetBitmapPixelFormat(Bitmap, pf8bit, mmGrayscale); +end; + + +{$ENDIF CLR} + +function ZoomImage(ImageW, ImageH, MaxW, MaxH: Integer; Stretch: Boolean): + TPoint; +var + Zoom: Double; +begin + Result := Point(0, 0); + if (MaxW <= 0) or (MaxH <= 0) or (ImageW <= 0) or (ImageH <= 0) then + Exit; + with Result do + if Stretch then + begin + Zoom := MaxFloat([ImageW / MaxW, ImageH / MaxH]); + if Zoom > 0 then + begin + X := Round(ImageW * 0.98 / Zoom); + Y := Round(ImageH * 0.98 / Zoom); + end + else + begin + X := ImageW; + Y := ImageH; + end; + end + else + begin + X := MaxW; + Y := MaxH; + end; +end; + +procedure TileImage(Canvas: TCanvas; Rect: TRect; Image: TGraphic); +var + X, Y: Integer; + SaveIndex: Integer; +begin + if (Image.Width = 0) or (Image.Height = 0) then + Exit; + SaveIndex := SaveDC(Canvas.Handle); + try + with Rect do + IntersectClipRect(Canvas.Handle, Left, Top, Right, Bottom); + for X := 0 to (RectWidth(Rect) div Image.Width) do + for Y := 0 to (RectHeight(Rect) div Image.Height) do + Canvas.Draw(Rect.Left + X * Image.Width, + Rect.Top + Y * Image.Height, Image); + finally + RestoreDC(Canvas.Handle, SaveIndex); + end; +end; + +//=== { TJvGradientOptions } ================================================= + +constructor TJvGradientOptions.Create; +begin + inherited Create; + FStartColor := clSilver; + FEndColor := clGray; + FStepCount := 64; + FDirection := fdTopToBottom; +end; + +procedure TJvGradientOptions.Assign(Source: TPersistent); +begin + if Source is TJvGradientOptions then + begin + with TJvGradientOptions(Source) do + begin + Self.FStartColor := StartColor; + Self.FEndColor := EndColor; + Self.FStepCount := StepCount; + Self.FDirection := Direction; + Self.FVisible := Visible; + end; + Changed; + end + else + inherited Assign(Source); +end; + +procedure TJvGradientOptions.Changed; +begin + if Assigned(FOnChange) then + FOnChange(Self); +end; + +procedure TJvGradientOptions.Draw(Canvas: TCanvas; Rect: TRect); +begin + GradientFillRect(Canvas, Rect, FStartColor, FEndColor, FDirection, FStepCount); +end; + +procedure TJvGradientOptions.SetStartColor(Value: TColor); +begin + if Value <> FStartColor then + begin + FStartColor := Value; + Changed; + end; +end; + +procedure TJvGradientOptions.SetEndColor(Value: TColor); +begin + if Value <> FEndColor then + begin + FEndColor := Value; + Changed; + end; +end; + +procedure TJvGradientOptions.SetDirection(Value: TFillDirection); +begin + if Value <> FDirection then + begin + FDirection := Value; + Changed; + end; +end; + +procedure TJvGradientOptions.SetStepCount(Value: Byte); +begin + if Value <> FStepCount then + begin + FStepCount := Value; + Changed; + end; +end; + +procedure TJvGradientOptions.SetVisible(Value: Boolean); +begin + if FVisible <> Value then + begin + FVisible := Value; + Changed; + end; +end; +{ end JvGraph } + +{ begin JvCtrlUtils } + +//=== ToolBarMenu ============================================================ + +procedure JvCreateToolBarMenu(AForm: TForm; AToolBar: TToolBar; + AMenu: TMainMenu); +var + I, TotalWidth: Integer; + Button: TToolButton; +begin + if AForm.FormStyle = fsMDIForm then + {$IFDEF CLR} + raise EJVCLException.Create(RsENotForMdi); + {$ELSE} + raise EJVCLException.CreateRes(@RsENotForMdi); + {$ENDIF CLR} + if AMenu = nil then + AMenu := AForm.Menu; + if AMenu = nil then + Exit; + with AToolBar do + begin + TotalWidth := BorderWidth; + for I := ButtonCount - 1 downto 0 do + Buttons[I].Free; + ShowCaptions := True; + end; + with AMenu do + for I := Items.Count - 1 downto 0 do + begin + Button := TToolButton.Create(AToolBar); + Button.Parent := AToolBar; + Button.AutoSize := True; + Button.Caption := Items[I].Caption; + Button.Grouped := True; + Button.MenuItem := Items[I]; + Inc(TotalWidth, Button.Width + AToolBar.BorderWidth); + end; + AToolBar.Width := TotalWidth; + AForm.Menu := nil; +end; + +//=== ListView functions ===================================================== + +procedure JvListViewToStrings(ListView: TListView; Strings: TStrings; + SelectedOnly: Boolean; Headers: Boolean); +var + R, C: Integer; + ColWidths: array of Word; + S: string; + + procedure AddLine; + begin + Strings.Add(TrimRight(S)); + end; + + function StrPadRight(const S: string; Len: Integer): string; + begin + Result := S; + if Len > Length(S) then + Result := Result + MakeStr(' ', Len - Length(S)) + end; + + function StrPadLeft(const S: string; Len: Integer): string; + begin + Result := S; + if Len > Length(S) then + Result := MakeStr(' ', Len - Length(S)) + Result; + end; + + function MakeCellStr(const Text: string; Index: Integer): string; + begin + with ListView.Columns[Index] do + if Alignment = taLeftJustify then + Result := StrPadRight(Text, ColWidths[Index] + 1) + else + Result := StrPadLeft(Text, ColWidths[Index]) + ' '; + end; + +begin + SetLength(S, 256); + with ListView do + begin + SetLength(ColWidths, Columns.Count); + if Headers then + for C := 0 to Columns.Count - 1 do + ColWidths[C] := Length(Trim(Columns[C].Caption)); + for R := 0 to Items.Count - 1 do + if not SelectedOnly or Items[R].Selected then + begin + ColWidths[0] := Max(ColWidths[0], Length(Trim(Items[R].Caption))); + for C := 0 to Items[R].SubItems.Count - 1 do + ColWidths[C + 1] := Max(ColWidths[C + 1], + Length(Trim(Items[R].SubItems[C]))); + end; + Strings.BeginUpdate; + try + if Headers then + with Columns do + begin + S := ''; + for C := 0 to Count - 1 do + S := S + MakeCellStr(Items[C].Caption, C); + AddLine; + S := ''; + for C := 0 to Count - 1 do + S := S + StringOfChar('-', ColWidths[C]) + ' '; + AddLine; + end; + for R := 0 to Items.Count - 1 do + if not SelectedOnly or Items[R].Selected then + with Items[R] do + begin + S := MakeCellStr(Caption, 0); + for C := 0 to Min(SubItems.Count, Columns.Count - 1) - 1 do + S := S + MakeCellStr(SubItems[C], C + 1); + AddLine; + end; + finally + Strings.EndUpdate; + end; + end; +end; + +function JvListViewSafeSubItemString(Item: TListItem; SubItemIndex: Integer): string; +begin + if Item.SubItems.Count > SubItemIndex then + Result := Item.SubItems[SubItemIndex] + else + Result := ''; +end; + +procedure JvListViewSortClick(Column: TListColumn; AscendingSortImage: Integer; + DescendingSortImage: Integer); +var + ListView: TListView; + I: Integer; +begin + ListView := TListColumns(Column.Collection).Owner as TListView; + ListView.Columns.BeginUpdate; + try + with ListView.Columns do + for I := 0 to Count - 1 do + Items[I].ImageIndex := -1; + if ListView.Tag and $FF = Column.Index then + ListView.Tag := ListView.Tag xor $100 + else + ListView.Tag := Column.Index; + if ListView.Tag and $100 = 0 then + Column.ImageIndex := AscendingSortImage + else + Column.ImageIndex := DescendingSortImage; + finally + ListView.Columns.EndUpdate; + end; +end; + +procedure JvListViewCompare(ListView: TListView; Item1, Item2: TListItem; + var Compare: Integer); +var + ColIndex: Integer; + + function FmtStrToInt(S: string): Integer; + var + I: Integer; + begin + I := 1; + while I <= Length(S) do + if not (S[I] in (DigitChars + ['-'])) then + Delete(S, I, 1) + else + Inc(I); + Result := StrToInt(S); + end; + +begin + with ListView do + begin + ColIndex := Tag and $FF - 1; + if Columns[ColIndex + 1].Alignment = taLeftJustify then + begin + if ColIndex = -1 then + {$IFDEF CLR} + Compare := CompareText(Item1.Caption, Item2.Caption) + else + Compare := CompareText(Item1.SubItems[ColIndex], Item2.SubItems[ColIndex]); + {$ELSE} + Compare := AnsiCompareText(Item1.Caption, Item2.Caption) + else + Compare := AnsiCompareText(Item1.SubItems[ColIndex], Item2.SubItems[ColIndex]); + {$ENDIF CLR} + end + else + begin + if ColIndex = -1 then + Compare := FmtStrToInt(Item1.Caption) - FmtStrToInt(Item2.Caption) + else + Compare := FmtStrToInt(Item1.SubItems[ColIndex]) - + FmtStrToInt(Item2.SubItems[ColIndex]); + end; + if Tag and $100 <> 0 then + Compare := -Compare; + end; +end; + +procedure JvListViewSelectAll(ListView: TListView; Deselect: Boolean); +var + I: Integer; + H: THandle; + Data: Integer; + SaveOnSelectItem: TLVSelectItemEvent; +begin + with ListView do + if MultiSelect then + begin + Items.BeginUpdate; + SaveOnSelectItem := OnSelectItem; + WaitCursor; + try + H := Handle; + OnSelectItem := nil; + if Deselect then + Data := 0 + else + Data := LVIS_SELECTED; + for I := 0 to Items.Count - 1 do + ListView_SetItemState(H, I, Data, LVIS_SELECTED); + finally + OnSelectItem := SaveOnSelectItem; + Items.EndUpdate; + end; + end; +end; + +function JvListViewSaveState(ListView: TListView): TJvLVItemStateData; +var + TempItem: TListItem; +begin + with Result do + begin + Focused := Assigned(ListView.ItemFocused); + Selected := Assigned(ListView.Selected); + if Focused then + TempItem := ListView.ItemFocused + else + if Selected then + TempItem := ListView.Selected + else + TempItem := nil; + if TempItem <> nil then + begin + Caption := TempItem.Caption; + Data := TempItem.Data; + end + else + begin + Caption := ''; + Data := nil; + end; + end; +end; + +function JvListViewRestoreState(ListView: TListView; Data: TJvLVItemStateData; + MakeVisible: Boolean; FocusFirst: Boolean): Boolean; +var + TempItem: TListItem; +begin + with ListView do + begin + TempItem := FindCaption(0, Data.Caption, False, True, False); + Result := TempItem <> nil; + if Result then + begin + TempItem.Focused := Data.Focused; + TempItem.Selected := Data.Selected; + end + else + if FocusFirst and (Items.Count > 0) then + begin + TempItem := Items[0]; + TempItem.Focused := True; + TempItem.Selected := True; + end; + if MakeVisible and (TempItem <> nil) then + TempItem.MakeVisible(True); + end; +end; + + + +function JvListViewGetOrderedColumnIndex(Column: TListColumn): Integer; +var + {$IFDEF CLR} + ColumnOrder: TIntegerDynArray; + {$ELSE} + ColumnOrder: array of Integer; + {$ENDIF CLR} + Columns: TListColumns; + I: Integer; +begin + Result := -1; + Columns := TListColumns(Column.Collection); + SetLength(ColumnOrder, Columns.Count); + {$IFDEF CLR} + ListView_GetColumnOrderArray(Columns.Owner.Handle, Columns.Count, ColumnOrder); + {$ELSE} + ListView_GetColumnOrderArray(Columns.Owner.Handle, Columns.Count, PInteger(ColumnOrder)); + {$ENDIF CLR} + for I := 0 to High(ColumnOrder) do + if ColumnOrder[I] = Column.Index then + begin + Result := I; + Break; + end; +end; + +procedure JvListViewSetSystemImageList(ListView: TListView); +var + FileInfo: TSHFileInfo; + ImageListHandle: THandle; +begin + {$IFNDEF CLR} + FillChar(FileInfo, SizeOf(FileInfo), 0); + {$ENDIF !CLR} + ImageListHandle := SHGetFileInfo('', 0, FileInfo, SizeOf(FileInfo), + SHGFI_SYSICONINDEX or SHGFI_SMALLICON); + SendMessage(ListView.Handle, LVM_SETIMAGELIST, LVSIL_SMALL, ImageListHandle); + {$IFNDEF CLR} + FillChar(FileInfo, SizeOf(FileInfo), 0); + {$ENDIF !CLR} + ImageListHandle := SHGetFileInfo('', 0, FileInfo, SizeOf(FileInfo), + SHGFI_SYSICONINDEX or SHGFI_LARGEICON); + SendMessage(ListView.Handle, LVM_SETIMAGELIST, LVSIL_NORMAL, ImageListHandle); +end; + + +//== MessageBox ============================================================== + +function JvMessageBox(const Text, Caption: string; Flags: DWORD): Integer; +begin + Result := MsgBox(Text, Caption, Flags); +end; + +function JvMessageBox(const Text: string; Flags: DWORD): Integer; +begin + Result := MsgBox(Text, Application.Title, Flags); +end; +********************) + +procedure UpdateTrackFont(TrackFont, Font: TFont; TrackOptions: TJvTrackFontOptions); +begin + if hoFollowFont in TrackOptions then + begin + if not (hoPreserveCharSet in TrackOptions) then + TrackFont.Charset := Font.Charset; + if not (hoPreserveColor in TrackOptions) then + TrackFont.Color := Font.Color; + if not (hoPreserveHeight in TrackOptions) then + TrackFont.Height := Font.Height; + if not (hoPreserveName in TrackOptions) then + TrackFont.Name := Font.Name; + if not (hoPreservePitch in TrackOptions) then + TrackFont.Pitch := Font.Pitch; + if not (hoPreserveStyle in TrackOptions) then + TrackFont.Style := Font.Style; + end; +end; + +(******************** + +{ end JvCtrlUtils } + +function GetDefaultCheckBoxSize: TSize; +begin + with TBitmap.Create do + try + {$IFDEF CLR} + Handle := LoadBitmap(0, OBM_CHECKBOXES); + {$ELSE} + Handle := LoadBitmap(0, PChar(OBM_CHECKBOXES)); + {$ENDIF CLR} + Result.cx := Width div 4; + Result.cy := Height div 3; + finally + Free; + end; +end; + +function CanvasMaxTextHeight(Canvas: TCanvas): Integer; +var + tt: TTextMetric; +begin + // (ahuser) Qt returns different values for TextHeight('Ay') and TextHeigth(#1..#255) + GetTextMetrics(Canvas.Handle, tt); + Result := tt.tmHeight; +end; + +{$IFDEF MSWINDOWS} + +//=== AllocateHWndEx ========================================================= + +{$IFNDEF CLR} +const + cUtilWindowExClass: TWndClass = ( + style: 0; + lpfnWndProc: nil; + cbClsExtra: 0; + cbWndExtra: SizeOf(TMethod); + hInstance: 0; + hIcon: 0; + hCursor: 0; + hbrBackground: 0; + lpszMenuName: nil; + lpszClassName: 'TPUtilWindowEx'); + +function StdWndProc(Window: THandle; Message, WParam: WPARAM; + LParam: LPARAM): LRESULT; stdcall; +var + Msg: Messages.TMessage; + WndProc: TWndMethod; +begin + TMethod(WndProc).Code := Pointer(GetWindowLong(Window, 0)); + TMethod(WndProc).Data := Pointer(GetWindowLong(Window, SizeOf(Pointer))); + if Assigned(WndProc) then + begin + Msg.Msg := Message; + Msg.WParam := WParam; + Msg.LParam := LParam; + Msg.Result := 0; + WndProc(Msg); + Result := Msg.Result; + end + else + Result := DefWindowProc(Window, Message, WParam, LParam); +end; +{$ENDIF !CLR} + +function AllocateHWndEx(Method: TWndMethod; const AClassName: string = ''): THandle; +{$IFDEF CLR} +begin + Result := AllocateHWnd(Method); +end; +{$ELSE} +var + TempClass: TWndClass; + UtilWindowExClass: TWndClass; + ClassRegistered: Boolean; +begin + UtilWindowExClass := cUtilWindowExClass; + UtilWindowExClass.hInstance := HInstance; + UtilWindowExClass.lpfnWndProc := @DefWindowProc; + if AClassName <> '' then + UtilWindowExClass.lpszClassName := PChar(AClassName); + + ClassRegistered := Windows.GetClassInfo(HInstance, UtilWindowExClass.lpszClassName, + TempClass); + if not ClassRegistered or (TempClass.lpfnWndProc <> @DefWindowProc) then + begin + if ClassRegistered then + Windows.UnregisterClass(UtilWindowExClass.lpszClassName, HInstance); + Windows.RegisterClass(UtilWindowExClass); + end; + Result := Windows.CreateWindowEx(Windows.WS_EX_TOOLWINDOW, UtilWindowExClass.lpszClassName, + '', Windows.WS_POPUP, 0, 0, 0, 0, 0, 0, HInstance, nil); + + if Assigned(Method) then + begin + Windows.SetWindowLong(Result, 0, Longint(TMethod(Method).Code)); + Windows.SetWindowLong(Result, SizeOf(TMethod(Method).Code), Longint(TMethod(Method).Data)); + Windows.SetWindowLong(Result, GWL_WNDPROC, Longint(@StdWndProc)); + end; +end; +{$ENDIF CLR} + +procedure DeallocateHWndEx(Wnd: THandle); +begin + {$IFDEF CLR} + DeallocateHWnd(Wnd); + {$ELSE} + Windows.DestroyWindow(Wnd); + {$ENDIF CLR} +end; + +function JvMakeObjectInstance(Method: TWndMethod): {$IFDEF CLR}TFNWndProc{$ELSE}Pointer{$ENDIF}; +begin + Result := MakeObjectInstance(Method); +end; + +procedure JvFreeObjectInstance(ObjectInstance: {$IFDEF CLR}TFNWndProc{$ELSE}Pointer{$ENDIF}); +begin + if Assigned(ObjectInstance) then + FreeObjectInstance(ObjectInstance); +end; + +{$ENDIF MSWINDOWS} + +procedure InitScreenCursors; +begin + try + if Screen <> nil then + begin + // now only available through SetDefaultJVCLCursors + { (ahuser) if used in VisualCLX mode Application.Destroy crashes } + Screen.Cursors[crMultiDragLink] := Screen.Cursors[crMultiDrag]; + Screen.Cursors[crDragAlt] := Screen.Cursors[crDrag]; + Screen.Cursors[crMultiDragAlt] := Screen.Cursors[crMultiDrag]; + Screen.Cursors[crMultiDragLinkAlt] := Screen.Cursors[crMultiDrag]; + end; + except + end; +end; + +const + Lefts = ['[', '{', '(']; + Rights = [']', '}', ')']; + +{ Utilities routines } + +function FontStylesToString(Styles: TFontStyles): string; +begin + Result := ''; + if fsBold in Styles then + Result := Result + 'B'; + if fsItalic in Styles then + Result := Result + 'I'; + if fsUnderline in Styles then + Result := Result + 'U'; + if fsStrikeOut in Styles then + Result := Result + 'S'; +end; + +function StringToFontStyles(const Styles: string): TFontStyles; +begin + Result := []; + if Pos('B', UpperCase(Styles)) > 0 then + Include(Result, fsBold); + if Pos('I', UpperCase(Styles)) > 0 then + Include(Result, fsItalic); + if Pos('U', UpperCase(Styles)) > 0 then + Include(Result, fsUnderline); + if Pos('S', UpperCase(Styles)) > 0 then + Include(Result, fsStrikeOut); +end; + + + +function FontToString(Font: TFont): string; +begin + with Font do + Result := Format('%s,%d,%s,%d,%s,%d', [Name, Size, + FontStylesToString(Style), Ord(Pitch), ColorToString(Color), Charset]); +end; + +function StringToFont(const Str: string): TFont; +const + Delims = [',', ';']; +var + Pos: Integer; + I: Byte; + S: string; +begin + Result := TFont.Create; + try + Pos := 1; + I := 0; + while Pos <= Length(Str) do + begin + Inc(I); + S := Trim(ExtractSubstr(Str, Pos, Delims)); + case I of + 1: + Result.Name := S; + 2: + Result.Size := StrToIntDef(S, Result.Size); + 3: + Result.Style := StringToFontStyles(S); + 4: + Result.Pitch := TFontPitch(StrToIntDef(S, Ord(Result.Pitch))); + 5: + Result.Color := StringToColor(S); + 6: + Result.Charset := TFontCharset(StrToIntDef(S, Result.Charset)); + end; + end; + finally + end; +end; + + + +function RectToStr(Rect: TRect): string; +begin + with Rect do + Result := Format('[%d,%d,%d,%d]', [Left, Top, Right, Bottom]); +end; + +function StrToRect(const Str: string; const Def: TRect): TRect; +var + S: string; + Temp: string[10]; + I: Integer; +begin + Result := Def; + S := Str; + if (S[1] in Lefts) and (S[Length(S)] in Rights) then + begin + Delete(S, 1, 1); + SetLength(S, Length(S) - 1); + end; + I := Pos(',', S); + if I > 0 then + begin + Temp := Trim(Copy(S, 1, I - 1)); + Result.Left := StrToIntDef(Temp, Def.Left); + Delete(S, 1, I); + I := Pos(',', S); + if I > 0 then + begin + Temp := Trim(Copy(S, 1, I - 1)); + Result.Top := StrToIntDef(Temp, Def.Top); + Delete(S, 1, I); + I := Pos(',', S); + if I > 0 then + begin + Temp := Trim(Copy(S, 1, I - 1)); + Result.Right := StrToIntDef(Temp, Def.Right); + Delete(S, 1, I); + Temp := Trim(S); + Result.Bottom := StrToIntDef(Temp, Def.Bottom); + end; + end; + end; +end; + +function PointToStr(P: TPoint): string; +begin + with P do + Result := Format('[%d,%d]', [X, Y]); +end; + +function StrToPoint(const Str: string; const Def: TPoint): TPoint; +var + S: string; + Temp: string[10]; + I: Integer; +begin + Result := Def; + S := Str; + if (S[1] in Lefts) and (S[Length(Str)] in Rights) then + begin + Delete(S, 1, 1); + SetLength(S, Length(S) - 1); + end; + I := Pos(',', S); + if I > 0 then + begin + Temp := Trim(Copy(S, 1, I - 1)); + Result.X := StrToIntDef(Temp, Def.X); + Delete(S, 1, I); + Temp := Trim(S); + Result.Y := StrToIntDef(Temp, Def.Y); + end; +end; + +procedure DrawArrow(Canvas: TCanvas; Rect: TRect; Color: TColor = clBlack; Direction: TAnchorKind = akBottom); +var + I, Size: Integer; +begin + Size := Rect.Right - Rect.Left; + if Odd(Size) then + begin + Dec(Size); + Dec(Rect.Right); + end; + // set to center by dejoy + if RectHeight(Rect) > Size then + Rect.Top := Rect.Top + (RectHeight(Rect) - (Size div 2)) div 2; + + Rect.Bottom := Rect.Top + Size; + Canvas.Pen.Color := Color; + case Direction of + akLeft: + for I := 0 to Size div 2 do + begin + Canvas.MoveTo(Rect.Right - I, Rect.Top + I); + Canvas.LineTo(Rect.Right - I, Rect.Bottom - I); + end; + akRight: + for I := 0 to Size div 2 do + begin + Canvas.MoveTo(Rect.Left + I, Rect.Top + I); + Canvas.LineTo(Rect.Left + I, Rect.Bottom - I); + end; + akTop: + for I := 0 to Size div 2 do + begin + Canvas.MoveTo(Rect.Left + I, Rect.Bottom - I); + Canvas.LineTo(Rect.Right - I, Rect.Bottom - I); + end; + akBottom: + for I := 0 to Size div 2 do + begin + Canvas.MoveTo(Rect.Left + I, Rect.Top + I); + Canvas.LineTo(Rect.Right - I, Rect.Top + I); + end; + end; +end; + +function IsPositiveResult(Value: TModalResult): Boolean; +begin + Result := Value in [mrOk, mrYes, mrAll, mrYesToAll]; +end; + +function IsNegativeResult(Value: TModalResult): Boolean; +begin + Result := Value in [mrNo, mrNoToAll]; +end; + +function IsAbortResult(const Value: TModalResult): Boolean; +begin + Result := Value in [mrCancel, mrAbort]; +end; + +function StripAllFromResult(const Value: TModalResult): TModalResult; +begin + case Value of + mrAll: + Result := mrOk; + mrNoToAll: + Result := mrNo; + mrYesToAll: + Result := mrYes; + else + Result := Value; + end; +end; + +//=== { TJvPoint } =========================================================== + +procedure TJvPoint.Assign(Source: TPersistent); +begin + if Source is TJvPoint then + begin + FX := TJvPoint(Source).X; + FY := TJvPoint(Source).Y; + DoChange; + end + else + inherited Assign(Source); +end; + +procedure TJvPoint.Assign(Source: TPoint); +begin + X := Source.X; + Y := Source.Y; +end; + +procedure TJvPoint.CopyToPoint(var Point: TPoint); +begin + Point.X := X; + Point.Y := Y; +end; + +procedure TJvPoint.DoChange; +begin + if Assigned(FOnChange) then + FOnChange(Self); +end; + +procedure TJvPoint.SetX(Value: Longint); +begin + FX := Value; + DoChange; +end; + +procedure TJvPoint.SetY(Value: Longint); +begin + FY := Value; + DoChange; +end; + +//=== { TJvRect } ============================================================ + +procedure TJvRect.Assign(Source: TRect); +begin + TopLeft.Assign(Source.TopLeft); + BottomRight.Assign(Source.BottomRight); +end; + +procedure TJvRect.CopyToRect(var Rect: TRect); +begin + TopLeft.CopyToPoint(Rect.TopLeft); + BottomRight.CopyToPoint(Rect.BottomRight); +end; + +constructor TJvRect.Create; +begin + inherited Create; + FTopLeft := TJvPoint.Create; + FBottomRight := TJvPoint.Create; + FTopLeft.OnChange := PointChange; + FBottomRight.OnChange := PointChange; +end; + +destructor TJvRect.Destroy; +begin + FTopLeft.Free; + FBottomRight.Free; + inherited Destroy; +end; + +procedure TJvRect.Assign(Source: TPersistent); +begin + if Source is TJvRect then + begin + TopLeft.Assign(TJvRect(Source).TopLeft); + BottomRight.Assign(TJvRect(Source).BottomRight); + DoChange; + end + else + inherited Assign(Source); +end; + +procedure TJvRect.DoChange; +begin + if Assigned(FOnChange) then + FOnChange(Self); +end; + +function TJvRect.GetBottom: Integer; +begin + Result := FBottomRight.Y; +end; + +function TJvRect.GetLeft: Integer; +begin + Result := FTopLeft.X; +end; + +function TJvRect.GetRight: Integer; +begin + Result := FBottomRight.X; +end; + +function TJvRect.GetTop: Integer; +begin + Result := FTopLeft.Y; +end; + +procedure TJvRect.PointChange(Sender: TObject); +begin + DoChange; +end; + +procedure TJvRect.SetBottom(Value: Integer); +begin + FBottomRight.Y := Value; +end; + +procedure TJvRect.SetBottomRight(Value: TJvPoint); +begin + FBottomRight.Assign(Value); +end; + +procedure TJvRect.SetLeft(Value: Integer); +begin + FTopLeft.X := Value; +end; + +procedure TJvRect.SetRight(Value: Integer); +begin + FBottomRight.X := Value; +end; + +procedure TJvRect.SetTop(Value: Integer); +begin + FTopLeft.Y := Value; +end; + +procedure TJvRect.SetTopLeft(Value: TJvPoint); +begin + FTopLeft.Assign(Value); +end; + +function TJvRect.GetHeight: Integer; +begin + Result := FBottomRight.Y - FTopLeft.Y; +end; + +function TJvRect.GetWidth: Integer; +begin + Result := FBottomRight.X - FTopLeft.X; +end; + +procedure TJvRect.SetHeight(Value: Integer); +begin + FBottomRight.Y := FTopLeft.Y + Value; +end; + +procedure TJvRect.SetWidth(Value: Integer); +begin + FBottomRight.X := FTopLeft.X + Value; +end; + + { TJvSize } + +procedure TJvSize.Assign(Source: TPersistent); +begin + if Source is TJvSize then + begin + FWidth := (Source as TJvSize).Width; + FHeight := (Source as TJvSize).Height; + DoChange; + end + else + begin + inherited Assign(Source); + end; +end; + +procedure TJvSize.Assign(Source: TSize); +begin + FWidth := Source.cx; + FHeight := Source.cy; + DoChange; +end; + +procedure TJvSize.CopyToSize(var Size: TSize); +begin + Size.cx := Width; + Size.cy := Height; +end; + +procedure TJvSize.DoChange; +begin + if Assigned(OnChange) then + OnChange(Self); +end; + +procedure TJvSize.SetHeight(Value: Integer); +begin + if FHeight <> Value then + begin + FHeight := Value; + DoChange; + end; +end; + +procedure TJvSize.SetWidth(Value: Integer); +begin + if FWidth <> Value then + begin + FWidth := Value; + DoChange; + end; +end; + +function SelectColorByLuminance(AColor, DarkColor, BrightColor: TColor): TColor; +var + ACol: Longint; +begin + ACol := ColorToRGB(AColor) and $00FFFFFF; + if ((2.99 * GetRValue(ACol) + 5.87 * GetGValue(ACol) + 1.14 * GetBValue(ACol)) > $400) then + Result := DarkColor + else + Result := BrightColor; +end; + +const + cBR = '
'; + cHR = '
'; + cTagBegin = '<'; + cTagEnd = '>'; + cLT = '<'; + cGT = '>'; + cQuote = '"'; + cCENTER = 'CENTER'; + cRIGHT = 'RIGHT'; + cHREF = 'HREF'; + cIND = 'IND'; + cCOLOR = 'COLOR'; + cBGCOLOR = 'BGCOLOR'; + +// moved from JvHTControls and renamed +function HTMLPrepareText(const Text: string): string; +type + THtmlCode = packed record + Html: string[10]; + Text: Char; + end; +const + Conversions: array [0..6] of THtmlCode = + ( + (Html: '&'; Text: '&'), + (Html: '"'; Text: '"'), + (Html: '®'; Text: '®'), + (Html: '©'; Text: '©'), + (Html: '™'; Text: '™'), + (Html: '€'; Text: '€'), + (Html: ' '; Text: ' ') + ); +var + I: Integer; +begin + Result := Text; + for I := Low(Conversions) to High(Conversions) do + with Conversions[I] do + Result := StringReplace(Result, Html, Text, [rfReplaceAll, rfIgnoreCase]); + Result := StringReplace(Result, sLineBreak, '', [rfReplaceAll, rfIgnoreCase]); // only
can be new line + Result := StringReplace(Result, cBR, sLineBreak, [rfReplaceAll, rfIgnoreCase]); + Result := StringReplace(Result, cHR, cHR + sLineBreak, [rfReplaceAll, rfIgnoreCase]); // fixed

+end; + +function HTMLBeforeTag(var Str: string; DeleteToTag: Boolean = False): string; +begin + if Pos(cTagBegin, Str) > 0 then + begin + Result := Copy(Str, 1, Pos(cTagBegin, Str)-1); + if DeleteToTag then + Delete(Str, 1, Pos(cTagBegin, Str)-1); + end + else + begin + Result := Str; + if DeleteToTag then + Str := ''; + end; +end; + +function GetChar(const Str: string; Pos: Word; Up: Boolean = False): Char; +begin + if Length(Str) >= Pos then + Result := Str[Pos] + else + Result := ' '; + if Up then + Result := UpCase(Result); +end; + +function HTMLDeleteTag(const Str: string): string; +begin + Result := Str; + if (GetChar(Result, 1) = cTagBegin) and (Pos(cTagEnd, Result) > 1) then + Delete(Result, 1, Pos(cTagEnd, Result)); +end; + +procedure HTMLDrawTextEx(Canvas: TCanvas; Rect: TRect; + const State: TOwnerDrawState; const Text: string; var Width: Integer; + CalcType: TJvHTMLCalcType; MouseX, MouseY: Integer; var MouseOnLink: Boolean; + var LinkName: string; Scale: Integer = 100); +const + DefaultLeft = 0; // (ahuser) was 2 +var + vText, vM, TagPrp, Prp, TempLink: string; + vCount: Integer; + vStr: TStringList; + Selected: Boolean; + Alignment: TAlignment; + Trans, IsLink: Boolean; + CurLeft: Integer; + // for begin and end + OldFontStyles: TFontStyles; + OldFontColor: TColor; + OldBrushColor: TColor; + OldBrushStyle: TBrushStyle; + OldAlignment: TAlignment; + OldFont: TFont; + OldWidth: Integer; + // for font style + RemFontColor, + RemBrushColor: TColor; + RemFontSize: Integer; + + function ExtractPropertyValue(const Tag: string; PropName: string): string; + var + I: Integer; + begin + Result := ''; + PropName := UpperCase(PropName); + if Pos(PropName, UpperCase(Tag)) > 0 then + begin + Result := Copy(Tag, Pos(PropName, UpperCase(Tag)) + Length(PropName), Length(Tag)); + if Pos('"', Result) <> 0 then + begin + Result := Copy(Result, Pos('"', Result) + 1, Length(Result)); + Result := Copy(Result, 1, Pos('"', Result) - 1); + end + else + if Pos('''', Result) <> 0 then + begin + Result := Copy(Result, Pos('''', Result) + 1, Length(Result)); + Result := Copy(Result, 1, Pos('''', Result) - 1); + end + else + begin + Result := Trim(Result); + Delete(Result, 1, 1); + Result := Trim(Result); + I := 1; + while (I < Length(Result)) and (Result[I+1] <> ' ') do + Inc(I); + Result := Copy(Result, 1, I); + end; + end; + end; + + procedure Style(const Style: TFontStyle; const Include: Boolean); + begin + if Assigned(Canvas) then + if Include then + Canvas.Font.Style := Canvas.Font.Style + [Style] + else + Canvas.Font.Style := Canvas.Font.Style - [Style]; + end; + + function CalcPos(const Str: string): Integer; + begin + case Alignment of + taRightJustify: + Result := (Rect.Right {- Rect.Left}) - HTMLTextWidth(Canvas, Rect, State, Str, Scale); + taCenter: + Result := (Rect.Right {- Rect.Left} - HTMLTextWidth(Canvas, Rect, State, Str)) div 2; + else + Result := DefaultLeft; + end; + if Result <= 0 then + Result := DefaultLeft; + end; + + procedure Draw(const M: string); + var + Width, Height: Integer; + R: TRect; + begin + R := Rect; + Inc(R.Left, CurLeft); + if Assigned(Canvas) then + begin + Width := Canvas.TextWidth(M); + Height := CanvasMaxTextHeight(Canvas); + if IsLink and not MouseOnLink then + if (MouseY >= R.Top) and (MouseY <= R.Top + Height) and + (MouseX >= R.Left) and (MouseX <= R.Left + Width) and + ((MouseY > 0) or (MouseX > 0)) then + begin + MouseOnLink := True; + Canvas.Font.Color := clRed; // hover link + LinkName := TempLink; + end; + if CalcType = htmlShow then + begin + if Trans then + Canvas.Brush.Style := bsClear; // for transparent + Canvas.TextOut(R.Left, R.Top, M); + end; + CurLeft := CurLeft + Width; + end; + end; + + procedure NewLine(Always: Boolean = False); + begin + if Assigned(Canvas) then + if Always or (vCount < vStr.Count - 1) then + begin + Width := Max(Width, CurLeft); + CurLeft := DefaultLeft; + Rect.Top := Rect.Top + CanvasMaxTextHeight(Canvas); + end; + end; + +begin + // (p3) remove warnings + OldFontColor := 0; + OldBrushColor := 0; + OldBrushStyle := bsClear; + RemFontSize := 0; + RemFontColor := 0; + RemBrushColor := 0; + OldAlignment := taLeftJustify; + OldFont := TFont.Create; + + if Canvas <> nil then + begin + OldFontStyles := Canvas.Font.Style; + OldFontColor := Canvas.Font.Color; + OldBrushColor := Canvas.Brush.Color; + OldBrushStyle := Canvas.Brush.Style; + OldAlignment := Alignment; + RemFontColor := Canvas.Font.Color; + RemBrushColor := Canvas.Brush.Color; + RemFontSize := Canvas.Font.size; + end; + try + Alignment := taLeftJustify; + IsLink := False; + MouseOnLink := False; + vText := Text; + vStr := TStringList.Create; + vStr.Text := HTMLPrepareText(vText); + LinkName := ''; + TempLink := ''; + + Selected := (odSelected in State) or (odDisabled in State); + Trans := (Canvas.Brush.Style = bsClear) and not selected; + + Width := DefaultLeft; + CurLeft := DefaultLeft; + + vM := ''; + for vCount := 0 to vStr.Count - 1 do + begin + vText := vStr[vCount]; + CurLeft := CalcPos(vText); + while Length(vText) > 0 do + begin + vM := HTMLBeforeTag(vText, True); + vM := StringReplace(vM, '<', cLT, [rfReplaceAll, rfIgnoreCase]); // <--+ this must be here + vM := StringReplace(vM, '>', cGT, [rfReplaceAll, rfIgnoreCase]); // <--/ + if GetChar(vText, 1) = cTagBegin then + begin + Draw(vM); + if Pos(cTagEnd, vText) = 0 then + Insert(cTagEnd, vText, 2); + if GetChar(vText, 2) = '/' then + begin + case GetChar(vText, 3, True) of + 'A': + begin + IsLink := False; + Canvas.Font.Assign(OldFont); + end; + 'B': + Style(fsBold, False); + 'I': + Style(fsItalic, False); + 'U': + Style(fsUnderline, False); + 'S': + Style(fsStrikeOut, False); + 'F': + begin + if not Selected then // restore old colors + begin + Canvas.Font.Color := RemFontColor; + Canvas.Brush.Color := RemBrushColor; + Canvas.Font.Size := RemFontSize; + Trans := True; + end; + end; + end + end + else + begin + case GetChar(vText, 2, True) of + 'A': + begin + if GetChar(vText, 3, True) = 'L' then // ALIGN + begin + TagPrp := UpperCase(Copy(vText, 2, Pos(cTagEnd, vText)-2)); + if Pos(cCENTER, TagPrp) > 0 then + Alignment := taCenter + else + if Pos(cRIGHT, TagPrp) > 0 then + Alignment := taRightJustify + else + Alignment := taLeftJustify; + CurLeft := DefaultLeft; + if CalcType = htmlShow then + CurLeft := CalcPos(vText); + end + else + begin // A HREF + TagPrp := Copy(vText, 2, Pos(cTagEnd, vText)-2); + if Pos(cHREF, UpperCase(TagPrp)) > 0 then + begin + IsLink := True; + OldFont.Assign(Canvas.Font); + if not Selected then + Canvas.Font.Color := clBlue; + TempLink := ExtractPropertyValue(TagPrp, cHREF); + end; + end; + end; + 'B': + Style(fsBold, True); + 'I': + if GetChar(vText, 3, True) = 'N' then //IND="%d" + begin + TagPrp := Copy(vText, 2, Pos(cTagEnd, vText)-2); + CurLeft := StrToInt(ExtractPropertyValue(TagPrp, cIND)); // ex IND="10" + if odReserved1 in State then + CurLeft := Round((CurLeft * Scale) div 100); + end + else + Style(fsItalic, True); // ITALIC + 'U': + Style(fsUnderline, True); + 'S': + Style(fsStrikeOut, True); + 'H': + if (GetChar(vText, 3, True) = 'R') and Assigned(Canvas) then // HR + begin + if odDisabled in State then // only when disabled + Canvas.Pen.Color := Canvas.Font.Color; + OldWidth := Canvas.Pen.Width; + TagPrp := UpperCase(Copy(vText, 2, Pos(cTagEnd, vText)-2)); + Canvas.Pen.Width := StrToIntDef(ExtractPropertyValue(TagPrp, 'SIZE'),1); // ex HR="10" + if odReserved1 in State then + Canvas.Pen.Width := Round((Canvas.Pen.Width * Scale) div 100); + if CalcType = htmlShow then + begin + Canvas.MoveTo(Rect.Left ,Rect.Top + CanvasMaxTextHeight(Canvas)); + Canvas.LineTo(Rect.Right,Rect.Top + CanvasMaxTextHeight(Canvas)); + end; + Rect.Top := Rect.Top + 1 + Canvas.Pen.Width; + Canvas.Pen.Width := OldWidth; + NewLine(HTMLDeleteTag(vText) <> ''); + end; + 'F': + if (Pos(cTagEnd, vText) > 0) and (not Selected) and Assigned(Canvas) {and (CalcType = htmlShow)} then // F from FONT + begin + TagPrp := UpperCase(Copy(vText, 2, Pos(cTagEnd, vText)-2)); + RemFontColor := Canvas.Font.Color; + RemBrushColor := Canvas.Brush.Color; + + if Pos(cCOLOR, TagPrp) > 0 then + begin + Prp := ExtractPropertyValue(TagPrp, cCOLOR); + if Prp[1] = '#' then + Prp[1] := '$'; + Canvas.Font.Color := StringToColor(Prp); + end; + if Pos(cBGCOLOR, TagPrp) > 0 then + begin + Prp := ExtractPropertyValue(TagPrp, cBGCOLOR); + if Prp[1] = '#' then + Prp[1] := '$'; + if UpperCase(Prp) = 'CLNONE' then + Trans := True + else + begin + Canvas.Brush.Color := StringToColor(Prp); + Trans := False; + end; + end; + if Pos('SIZE', TagPrp) > 0 then + begin + Prp := ExtractPropertyValue(TagPrp, 'SIZE'); + Canvas.Font.Size := StrToIntDef(Prp,2) * Canvas.Font.Size div 2; + end; + end; + end; + end; + vText := HTMLDeleteTag(vText); + vM := ''; + end; + end; + Draw(vM); + NewLine; + vM := ''; + end; + finally + if Canvas <> nil then + begin + Canvas.Font.Style := OldFontStyles; + Canvas.Font.Color := OldFontColor; + Canvas.Brush.Color := OldBrushColor; + Canvas.Brush.Style := OldBrushStyle; + Alignment := OldAlignment; + { Canvas.Font.Color := RemFontColor; + Canvas.Brush.Color:= RemBrushColor;} + end; + FreeAndNil(vStr); + FreeAndNil(OldFont); + end; + if CalcType = htmlCalcHeight then + Width := Rect.Top + CanvasMaxTextHeight(Canvas) + else + Width := Max(Width, CurLeft - DefaultLeft); +end; + +function HTMLDrawText(Canvas: TCanvas; Rect: TRect; + const State: TOwnerDrawState; const Text: string; Scale: Integer = 100): string; +var + W: Integer; + S: Boolean; + St: string; +begin + HTMLDrawTextEx(Canvas, Rect, State, Text, W, htmlShow, 0, 0, S, St, Scale); +end; + +function HTMLPlainText(const Text: string): string; +var + S: string; +begin + Result := ''; + S := HTMLPrepareText(Text); + while Pos(cTagBegin, S) > 0 do + begin + Result := Result + Copy(S, 1, Pos(cTagBegin, S)-1); + if Pos(cTagEnd, S) > 0 then + Delete(S, 1, Pos(cTagEnd, S)) + else + Delete(S, 1, Pos(cTagBegin, S)); + end; + Result := Result + S; +end; + +function HTMLTextWidth(Canvas: TCanvas; Rect: TRect; + const State: TOwnerDrawState; const Text: string; Scale: Integer = 100): Integer; +var + S: Boolean; + St: string; +begin + HTMLDrawTextEx(Canvas, Rect, State, Text, Result, htmlCalcWidth, 0, 0, S, St); +end; + +function HTMLTextHeight(Canvas: TCanvas; const Text: string; Scale: Integer = 100): Integer; +var + S: Boolean; + St: string; + R: TRect; +begin + R := Rect(0, 0, 0, 0); + HTMLDrawTextEx(Canvas, R, [], Text, Result, htmlCalcHeight, 0, 0, S, St, Scale); + if Result = 0 then + Result := CanvasMaxTextHeight(Canvas); + Inc(Result); +end; + +{ TJvPicture } +procedure TJvPicture.ReadBitmapData(Stream: TStream); +var + Size: Longint; +begin + Stream.Read(Size, SizeOf(Size)); + Bitmap.LoadFromStream(Stream); +end; + +type + TAccessReader = class(TReader) + end; + +procedure TJvPicture.DefineProperties(Filer: TFiler); +var + SavedPosition: Integer; + Reader: TReader; + VType : TValueType; + WasBitmap : Boolean; + Count : Longint; + NameLength: Byte; +begin + if Filer is TReader then + begin + // When we are reading, we must detect if the data is a valid TPicture + // data or just a TBitmap data. This is done by having a sneak peak at + // what's in the reader stream. If we find a NameLength tag that is + // greater than 63 (it's built-in limit, see TPicture.DefineProperties) + // then it must be a TBitmap and we then tell the bitmap to load itself + // from the Filter. + // Note: the test must be done here, before any call to the + // DefineBinaryProperty of the Reader. If not, then the FPropName field + // would be put back to blank and prevent the inherited DefineProperties + // from working correctly. + Reader := Filer as TReader; + WasBitmap := False; + SavedPosition := Reader.Position; + + VType := Reader.ReadValue; + if VType = vaBinary then + begin + Reader.Read(Count, SizeOf(Count)); + Reader.Read(NameLength, SizeOf(NameLength)); + WasBitmap := NameLength > 63; + end; + + Reader.Position := SavedPosition; + + if WasBitmap then + Filer.DefineBinaryProperty('Data', ReadBitmapData, nil, True) + else + inherited DefineProperties(Filer); + end + else + begin + inherited DefineProperties(Filer); + end; +end; + +//=== { TGraphicSignature } ================================================== + +// Code to manage graphic's signatures. +type + TGraphicSignature = class(TObject) + public + Signature: string; + Offset: Integer; + GraphicClass: TGraphicClass; + constructor Create(const ASignature: string; AOffset: Integer; AGraphicClass: TGraphicClass); + function CheckSignature(AStream: TStream): Boolean; + end; + +constructor TGraphicSignature.Create(const ASignature: string; AOffset: Integer; AGraphicClass: TGraphicClass); +begin + inherited Create; + Signature := ASignature; + Offset := AOffset; + GraphicClass := AGraphicClass; +end; + +function TGraphicSignature.CheckSignature(AStream: TStream): Boolean; +var + Buffer: string; + Count: Integer; + BytesRead: Integer; +begin + Result := False; + try + Count := Length(Signature); + SetLength(Buffer, Count); + AStream.Position := Offset; + BytesRead := AStream.Read(Buffer[1], Count); + Result := (BytesRead = Count) and (Buffer = Signature); + except + // Ignore any error... + end; +end; + +var + GraphicSignatures: TObjectList = nil; + +procedure GraphicSignaturesNeeded; +begin + if not Assigned(GraphicSignatures) then + begin + GraphicSignatures := TObjectList.Create; + + RegisterGraphicSignature('BM', 0, TBitmap); + RegisterGraphicSignature([0, 0, 1, 0], 0, TIcon); + RegisterGraphicSignature([$D7, $CD], 0, TMetafile); // WMF + RegisterGraphicSignature([1, 0], 0, TMetafile); // EMF + RegisterGraphicSignature('JFIF', 6, TJPEGImage); + RegisterGraphicSignature('Exif', 6 , TJPEGImage); + // NB! Registering these will add a requirement on having the JvMM package installed + // Let users register these manually + // RegisterGraphicSignature([$0A], 0, TJvPcx); + // RegisterGraphicSignature('ACON', 8, TJvAni); + // JvCursorImage cannot be registered because it doesn't support + // LoadFromStream/SaveToStream but here's the signature for future reference: + // RegisterGraphicSignature([0, 0, 2, 0], 0, TJvCursorImage); + {$IFDEF USE_JV_GIF} + // RegisterGraphicSignature('GIF', 0, TJvGIFImage); + {$ENDIF USE_JV_GIF} +// RegisterGraphicSignature('GIF', 0, TGIFGraphic); +// RegisterGraphicSignature('PNG', 1, TPNGGraphic); + end; +end; + +procedure RegisterGraphicSignature(const ASignature: string; AOffset: Integer; AGraphicClass: TGraphicClass); +var + GraphicSignature: TGraphicSignature; +begin + // Avoid bad signatures + if (ASignature = '') or (AOffset < 0) or (AGraphicClass = nil) then + {$IFDEF CLR} + raise EJVCLException.Create(RsEBadGraphicSignature); + {$ELSE} + raise EJVCLException.CreateRes(@RsEBadGraphicSignature); + {$ENDIF CLR} + GraphicSignaturesNeeded; + // Should raise an exception if empty signature, negative offset or null class. + GraphicSignature := TGraphicSignature.Create(ASignature, AOffset, AGraphicClass); + try + GraphicSignatures.Add(GraphicSignature); + except + GraphicSignature.Free; + end; +end; + +procedure RegisterGraphicSignature(const ASignature: array of Byte; AOffset: Integer; AGraphicClass: TGraphicClass); +var + Signature: string; +begin + SetLength(Signature, Length(ASignature)); + Move(ASignature[Low(ASignature)], Signature[1], Length(ASignature)); + RegisterGraphicSignature(Signature, AOffset, AGraphicClass); +end; + +procedure UnregisterGraphicSignature(AGraphicClass: TGraphicClass); overload; +var + I: Integer; +begin + if Assigned(GraphicSignatures) then + for I := GraphicSignatures.Count - 1 downto 0 do + if TGraphicSignature(GraphicSignatures[I]).GraphicClass = AGraphicClass then + GraphicSignatures.Delete(I); +end; + +procedure UnregisterGraphicSignature(const ASignature: string; AOffset: Integer); +var + I: Integer; +begin + if Assigned(GraphicSignatures) then + for I := GraphicSignatures.Count - 1 downto 0 do + with TGraphicSignature(GraphicSignatures[I]) do + if (Signature = ASignature) and (Offset = AOffset) then + GraphicSignatures.Delete(I); +end; + +procedure UnregisterGraphicSignature(const ASignature: array of Byte; AOffset: Integer); +var + Signature: string; +begin + SetLength(Signature, Length(ASignature)); + Move(ASignature[Low(ASignature)], Signature[1], Length(ASignature)); + UnregisterGraphicSignature(Signature, AOffset); +end; + +function GetGraphicClass(AStream: TStream): TGraphicClass; +var + P: Integer; + I: Integer; + S: TGraphicSignature; +begin + Result := nil; + GraphicSignaturesNeeded; + if Assigned(GraphicSignatures) then + begin + P := AStream.Position; + try + for I := 0 to GraphicSignatures.Count - 1 do + begin + S := TGraphicSignature(GraphicSignatures[I]); + if S.CheckSignature(AStream) then + begin + Result := S.GraphicClass; + Exit; + end; + end; + finally + AStream.Position := P; + end; + end; +end; + +function GetGraphicObject(AStream: TStream): TGraphic; +var + LOnProc: TJvGetGraphicClassEvent; +begin + LOnProc := nil; + Result := GetGraphicObject(AStream, nil, LOnProc); +end; + +function GetGraphicObject(AStream: TStream; ASender: TObject; AOnProc: TJvGetGraphicClassEvent): TGraphic; overload; +var + GraphicClass: TGraphicClass; +begin + // Figure out which Graphic class is... + GraphicClass := GetGraphicClass(AStream); + // Call user event + if Assigned(AOnProc) and (AStream is TMemoryStream) then + AOnProc(ASender, TMemoryStream(AStream), GraphicClass); + // If we got one, load it.. + if Assigned(GraphicClass) then + begin + Result := GraphicClass.Create; + Result.LoadFromStream(AStream); + end + else // nope. + Result := nil; +end; + +initialization + InitScreenCursors; + +finalization + FreeAndNil(DrawBitmap); + FreeAndNil(GraphicSignatures); +******************** NOT CONVERTED *) + +end. + diff --git a/components/jvcllaz/run/JvNavigationPane.pas b/components/jvcllaz/run/JvNavigationPane.pas new file mode 100644 index 000000000..372786eb9 --- /dev/null +++ b/components/jvcllaz/run/JvNavigationPane.pas @@ -0,0 +1,5192 @@ +{----------------------------------------------------------------------------- +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: JvNavigationPane.PAS, released on 2004-03-28. + +The Initial Developer of the Original Code is Peter Thornqvist +Portions created by Peter Thornqvist are Copyright (C) 2004 Peter Thornqvist. +All Rights Reserved. + +Contributor(s): + +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: +-----------------------------------------------------------------------------} +// $Id: JvNavigationPane.pas 11400 2007-06-28 21:24:06Z ahuser $ + +// Initial port to Lazarus by Sergio Samayoa - september 2007. +// TODO: LM_NCPAINT isnt fired by lazarus, see what we can do about. +// +// 26.09.2007: +// BUG: (I think is of the JVCL base class) - also in Delphi +// - Made some panels iconic. +// - Click on popup button of the pane (TJvNavIconButton) +// - Don't select any menu option, just click and hold for a second any of +// the iconized pages. +// - Page isn't selected but button remains as down. +// +// LM_NCPAINT isn't fired in LCL (reply on forums from Luiz Americo). +// Also changing "BorderWidth" does nothing. This is inherited from TControl. +// This means that TJvExControl descendatns should deflate its bound by BorderWidth +// before painting itself and at last (after LM_PAINT) "send" LM_NCPAINT. +// This property should afect also the positioning if the controls inside. + +{$mode objfpc}{$H+} + +unit JvNavigationPane; + +interface + +uses + SysUtils, Classes, Controls, ExtCtrls, Graphics, ImgList, JvButton, + JvComponent, JvExExtCtrls, JvPageList, JvTypes, LCLIntf, LCLType, LMessages, Menus; + +const + CM_PARENTSTYLEMANAGERCHANGE = CM_BASE + 1; + CM_PARENTSTYLEMANAGERCHANGED = CM_BASE + 2; + +type + TJvCustomNavigationPane = class; + TJvNavIconButton = class; + TJvNavStyleLink = class; + TJvNavPaneStyleManager = class; + TMsgStyleManagerChange = record + Msg: Cardinal; + Sender: TControl; + StyleManager: TJvNavPaneStyleManager; + Result: Longint; + end; + + TJvNavPanelHeader = class(TJvCustomControl) + private + FColorFrom: TColor; + FColorTo: TColor; + FImages: TCustomImageList; + FImageIndex: TImageIndex; + FChangeLink: TChangeLink; + FStyleManager: TJvNavPaneStyleManager; + FStyleLink: TJvNavStyleLink; + FWordWrap: Boolean; + FAlignment: TAlignment; + FParentStyleManager: Boolean; + procedure WMEraseBkgnd(var Msg: TLMEraseBkgnd); message LM_ERASEBKGND; + procedure SetColorFrom(const Value: TColor); + procedure SetColorTo(const Value: TColor); + procedure SetImageIndex(const Value: TImageIndex); + procedure SetImages(const Value: TCustomImageList); + procedure DoImagesChange(Sender: TObject); + procedure SetStyleManager(const Value: TJvNavPaneStyleManager); + procedure DoStyleChange(Sender: TObject); + procedure SetAlignment(const Value: TAlignment); + procedure SetWordWrap(const Value: Boolean); + procedure ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); message CM_PARENTSTYLEMANAGERCHANGED; + procedure ParentStyleManagerChange(var Msg: TLMessage); message CM_PARENTSTYLEMANAGERCHANGE; + procedure CMControlChange(var Msg: TLMessage); message CM_CONTROLCHANGE; + procedure SetParentStyleManager(const Value: Boolean); + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure TextChanged; override; + procedure Paint; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property Align; + property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify; + property Anchors; + property Caption; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property OnStartDock; + property OnEndDock; + property OnUnDock; + property Enabled; + property Font; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowHint; + property Visible; + property WordWrap: Boolean read FWordWrap write SetWordWrap default False; + property ColorFrom: TColor read FColorFrom write SetColorFrom default TColor($D0835C); + property ColorTo: TColor read FColorTo write SetColorTo default TColor($903B09); + property Images: TCustomImageList read FImages write SetImages; + property ImageIndex: TImageIndex read FImageIndex write SetImageIndex default -1; + property StyleManager: TJvNavPaneStyleManager read FStyleManager write SetStyleManager; + // (p3) must be published after StyleManager + property ParentStyleManager: Boolean read FParentStyleManager write SetParentStyleManager default True; + property Height default 27; + property Width default 225; + property OnClick; + property OnContextPopup; + property OnDragDrop; + property OnDragOver; + property OnEndDrag; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnStartDrag; + end; + + TJvNavPanelDivider = class(TJvExSplitter) + private + FColorFrom: TColor; + FColorTo: TColor; + FFrameColor: TColor; + FStyleManager: TJvNavPaneStyleManager; + FStyleLink: TJvNavStyleLink; + FAlignment: TAlignment; + FParentStyleManager: Boolean; + procedure SetColorFrom(const Value: TColor); + procedure SetColorTo(const Value: TColor); + procedure SetFrameColor(const Value: TColor); + procedure SetStyleManager(const Value: TJvNavPaneStyleManager); + procedure DoStyleChange(Sender: TObject); + procedure SetAlignment(const Value: TAlignment); + procedure ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); message CM_PARENTSTYLEMANAGERCHANGED; + procedure SetParentStyleManager(const Value: Boolean); + protected + procedure Paint; override; + procedure TextChanged; override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure RequestAlign; override; + // 25.09.2007 - SESS + procedure SetAlign(Value: TAlign); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + // NB! Color is published but not used + property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify; + property Align default alNone; + property Anchors; + property AutoSnap default False; + property Caption; + property ColorFrom: TColor read FColorFrom write SetColorFrom default TColor($FFDBBC); + property ColorTo: TColor read FColorTo write SetColorTo default TColor($F2C0A4); + property Constraints; + property Cursor default crSizeNS; + property Enabled; + property Font; + property FrameColor: TColor read FFrameColor write SetFrameColor default TColor($6F2F0C); + property Height default 19; + property ResizeStyle default rsUpdate; + property StyleManager: TJvNavPaneStyleManager read FStyleManager write SetStyleManager; + // (p3) must be published after StyleManager + property ParentStyleManager: Boolean read FParentStyleManager write SetParentStyleManager default True; + property Width default 125; + end; + + TJvOutlookSplitter = class(TJvExSplitter) + private + FColorTo: TColor; + FColorFrom: TColor; + FStyleManager: TJvNavPaneStyleManager; + FStyleLink: TJvNavStyleLink; + FParentStyleManager: Boolean; + FDragZone: Integer; + FOldCursor: TCursor; + procedure SetColorFrom(const Value: TColor); + procedure SetColorTo(const Value: TColor); + procedure SetStyleManager(const Value: TJvNavPaneStyleManager); + procedure DoStyleChange(Sender: TObject); + procedure ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); message CM_PARENTSTYLEMANAGERCHANGED; + procedure SetParentStyleManager(const Value: Boolean); + procedure SetCursor(const Value: TCursor); + function GetDragZoneRect: TRect; + function MouseInDragZone(X, Y: Integer): Boolean; + protected + procedure Paint; override; + procedure EnabledChanged; override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure WMLButtonDown(var Msg: TLMLButtonDown); message LM_LBUTTONDOWN; + procedure WMMouseMove(var Msg: TLMMouseMove); message LM_MOUSEMOVE; + procedure RequestAlign; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + // NB! Color is published but not used + property Align default alBottom; + property AutoSnap default False; + property Cursor write SetCursor default crSizeNS; + // DragZone is the number of pixels in the center of the control that constitutes the draggable area. + // For example, with a left/right aligned splitter and a DragZone of 100, 50 pixels above and 50 pixels below + // the vertical midpoint can be clicked to start the sizing. Any clicks outside this area will not start a sizing operation + // If DragZone <= 0, the entire control is a drag zone + property DragZone: Integer read FDragZone write FDragZone default 0; + property ResizeStyle default rsUpdate; + property ColorFrom: TColor read FColorFrom write SetColorFrom default TColor($B78676); + property ColorTo: TColor read FColorTo write SetColorTo default TColor($A03D09); + property Height default 7; + property Enabled; + property StyleManager: TJvNavPaneStyleManager read FStyleManager write SetStyleManager; + // (p3) must be published after StyleManager + property ParentStyleManager: Boolean read FParentStyleManager write SetParentStyleManager default True; + property OnClick; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnDblClick; + property OnMouseUp; + property OnMouseMove; + end; + + TJvNavPanelColors = class(TPersistent) + private + FButtonColorTo: TColor; + FButtonColorFrom: TColor; + FFrameColor: TColor; + FButtonHotColorFrom: TColor; + FButtonHotColorTo: TColor; + FButtonSelectedColorFrom: TColor; + FButtonSelectedColorTo: TColor; + FOnChange: TNotifyEvent; + FSplitterColorFrom: TColor; + FSplitterColorTo: TColor; + FDividerColorTo: TColor; + FDividerColorFrom: TColor; + FHeaderColorFrom: TColor; + FHeaderColorTo: TColor; + FButtonSeparatorColor: TColor; + FToolPanelColorFrom: TColor; + FToolPanelColorTo: TColor; + FToolPanelHeaderColorTo: TColor; + FToolPanelHeaderColorFrom: TColor; + procedure SetButtonColorFrom(const Value: TColor); + procedure SetButtonColorTo(const Value: TColor); + procedure SetFrameColor(const Value: TColor); + procedure SetButtonHotColorFrom(const Value: TColor); + procedure SetButtonHotColorTo(const Value: TColor); + procedure SetButtonSelectedColorFrom(const Value: TColor); + procedure SetButtonSelectedColorTo(const Value: TColor); + procedure SetSplitterColorFrom(const Value: TColor); + procedure SetSplitterColorTo(const Value: TColor); + procedure SetDividerColorFrom(const Value: TColor); + procedure SetDividerColorTo(const Value: TColor); + procedure SetHeaderColorFrom(const Value: TColor); + procedure SetHeaderColorTo(const Value: TColor); + procedure SetButtonSeparatorColor(const Value: TColor); + procedure SetToolPanelColorFrom(const Value: TColor); + procedure SetToolPanelColorTo(const Value: TColor); + procedure SetToolPanelHeaderColorFrom(const Value: TColor); + procedure SetToolPanelHeaderColorTo(const Value: TColor); + protected + procedure Change; + public + constructor Create; + procedure Assign(Source: TPersistent); override; + published + property ButtonColorFrom: TColor read FButtonColorFrom write SetButtonColorFrom default TColor($F7E2CD); + property ButtonColorTo: TColor read FButtonColorTo write SetButtonColorTo default TColor($F3A080); + property ButtonHotColorFrom: TColor read FButtonHotColorFrom write SetButtonHotColorFrom default TColor($DBFBFF); + property ButtonHotColorTo: TColor read FButtonHotColorTo write SetButtonHotColorTo default TColor($5FC8FB); + property ButtonSelectedColorFrom: TColor read FButtonSelectedColorFrom write SetButtonSelectedColorFrom default TColor($BBE2EA); + property ButtonSelectedColorTo: TColor read FButtonSelectedColorTo write SetButtonSelectedColorTo default TColor($389FDD); + property ButtonSeparatorColor: TColor read FButtonSeparatorColor write SetButtonSeparatorColor default clGray; + property SplitterColorFrom: TColor read FSplitterColorFrom write SetSplitterColorFrom default TColor($B78676); + property SplitterColorTo: TColor read FSplitterColorTo write SetSplitterColorTo default TColor($A03D09); + property DividerColorFrom: TColor read FDividerColorFrom write SetDividerColorFrom default TColor($FFDBBC); + property DividerColorTo: TColor read FDividerColorTo write SetDividerColorTo default TColor($F2C0A4); + property HeaderColorFrom: TColor read FHeaderColorFrom write SetHeaderColorFrom default TColor($D0835C); + property HeaderColorTo: TColor read FHeaderColorTo write SetHeaderColorTo default TColor($903B09); + property FrameColor: TColor read FFrameColor write SetFrameColor default TColor($6F2F0C); + property ToolPanelColorFrom: TColor read FToolPanelColorFrom write SetToolPanelColorFrom default clWindow; + property ToolPanelColorTo: TColor read FToolPanelColorTo write SetToolPanelColorTo default clWindow; + property ToolPanelHeaderColorFrom: TColor read FToolPanelHeaderColorFrom write SetToolPanelHeaderColorFrom default TColor($F7E2CD); + property ToolPanelHeaderColorTo: TColor read FToolPanelHeaderColorTo write SetToolPanelHeaderColorTo default TColor($F3A080); + property OnChange: TNotifyEvent read FOnChange write FOnChange; + end; + + TJvNavPanelFonts = class(TPersistent) + private + FHeaderFont: TFont; + FNavPanelFont: TFont; + FDividerFont: TFont; + FOnChange: TNotifyEvent; + FNavPanelHotTrackFont: TFont; + FNavPanelHotTrackFontOptions: TJvTrackFontOptions; + procedure SetDividerFont(const Value: TFont); + procedure SetHeaderFont(const Value: TFont); + procedure SetNavPanelFont(const Value: TFont); + procedure SetNavPanelHotTrackFont(const Value: TFont); + procedure SetNavPanelHotTrackFontOptions(const Value: TJvTrackFontOptions); + protected + procedure Change; + procedure DoFontChange(Sender: TObject); + public + procedure Assign(Source: TPersistent); override; + constructor Create; + destructor Destroy; override; + published + property NavPanelFont: TFont read FNavPanelFont write SetNavPanelFont; + property NavPanelHotTrackFont: TFont read FNavPanelHotTrackFont write SetNavPanelHotTrackFont; + property NavPanelHotTrackFontOptions: TJvTrackFontOptions read FNavPanelHotTrackFontOptions write SetNavPanelHotTrackFontOptions default DefaultTrackFontOptions; + property DividerFont: TFont read FDividerFont write SetDividerFont; + property HeaderFont: TFont read FHeaderFont write SetHeaderFont; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + end; + + TJvIconPanel = class(TJvCustomControl) + private + FDropButton: TJvNavIconButton; + FColors: TJvNavPanelColors; + FStyleManager: TJvNavPaneStyleManager; + FStyleLink: TJvNavStyleLink; + FOnDropDownMenu: TContextPopupEvent; + FParentStyleManager: Boolean; + procedure SetDropDownMenu(const Value: TPopupMenu); + function GetDropDownMenu: TPopupMenu; + procedure SetColors(const Value: TJvNavPanelColors); + procedure SetStyleManager(const Value: TJvNavPaneStyleManager); + procedure DoStyleChange(Sender: TObject); + procedure ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); message CM_PARENTSTYLEMANAGERCHANGED; + procedure ParentStyleManagerChange(var Msg: TLMessage); message CM_PARENTSTYLEMANAGERCHANGE; + procedure CMControlChange(var Msg: TLMessage); message CM_CONTROLCHANGE; + procedure WMEraseBkgnd(var Msg: TLMEraseBkgnd); message LM_ERASEBKGND; + procedure SetParentStyleManager(const Value: Boolean); + protected + procedure DoDropDownMenu(Sender: TObject; MousePos: TPoint; var Handled: Boolean); + procedure DoColorsChange(Sender: TObject); + procedure Paint; override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + property Colors: TJvNavPanelColors read FColors write SetColors; + property StyleManager: TJvNavPaneStyleManager read FStyleManager write SetStyleManager; + // (p3) must be published after StyleManager + property ParentStyleManager: Boolean read FParentStyleManager write SetParentStyleManager default True; + property DropDownMenu: TPopupMenu read GetDropDownMenu write SetDropDownMenu; + property OnDropDownMenu: TContextPopupEvent read FOnDropDownMenu write FOnDropDownMenu; + end; + + TJvNavIconButtonType = (nibDropDown, nibImage, nibDropArrow, nibClose); + + TJvNavIconButton = class(TJvCustomGraphicButton) + private + FChangeLink: TChangeLink; + FImages: TCustomImageList; + FImageIndex: TImageIndex; + FButtonType: TJvNavIconButtonType; + FColors: TJvNavPanelColors; + FStyleManager: TJvNavPaneStyleManager; + FStyleLink: TJvNavStyleLink; + FParentStyleManager: Boolean; + procedure SetImages(const Value: TCustomImageList); + procedure SetImageIndex(const Value: TImageIndex); + procedure DoImagesChange(Sender: TObject); + procedure SetButtonType(const Value: TJvNavIconButtonType); + procedure SetColors(const Value: TJvNavPanelColors); + procedure DoColorsChange(Sender: TObject); + procedure SetStyleManager(const Value: TJvNavPaneStyleManager); + procedure DoStyleChange(Sender: TObject); + procedure ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); message CM_PARENTSTYLEMANAGERCHANGED; + procedure SetParentStyleManager(const Value: Boolean); + function IsColorsStored: Boolean; + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure Paint; override; + property OnDropDownMenu; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property Action; + property Align; + property AllowAllUp; + property Anchors; + // property Caption; + property Constraints; + property Down; + property DragCursor; + property DragKind; + property OnEndDock; + property OnStartDock; + property DragMode; + property DropDownMenu; + property GroupIndex; + property Enabled; + property Font; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowHint; + property Visible; + property ButtonType: TJvNavIconButtonType read FButtonType write SetButtonType; + property Colors: TJvNavPanelColors read FColors write SetColors stored IsColorsStored; + property Images: TCustomImageList read FImages write SetImages; + property ImageIndex: TImageIndex read FImageIndex write SetImageIndex; + property StyleManager: TJvNavPaneStyleManager read FStyleManager write SetStyleManager; + // (p3) must be published after StyleManager + property ParentStyleManager: Boolean read FParentStyleManager write SetParentStyleManager default True; + property Width default 22; + property Height default 22; + property OnClick; + property OnContextPopup; + property OnDragDrop; + property OnDragOver; + property OnEndDrag; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnStartDrag; + end; + + TJvNavPanelToolButton = class(TJvCustomGraphicButton) + private + FChangeLink: TChangeLink; + FImages: TCustomImageList; + FImageIndex: TImageIndex; + FButtonType: TJvNavIconButtonType; + FDrawPartialMenuFrame: Boolean; + FTransparentDown: Boolean; + procedure DoImagesChange(Sender: TObject); + procedure SetButtonType(const Value: TJvNavIconButtonType); + procedure SetImageIndex(const Value: TImageIndex); + procedure SetImages(const Value: TCustomImageList); + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure Paint; override; + procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + property TransparentDown: Boolean read FTransparentDown write FTransparentDown default False; + property DrawPartialMenuFrame: Boolean read FDrawPartialMenuFrame write FDrawPartialMenuFrame default False; + property Images: TCustomImageList read FImages write SetImages; + property ImageIndex: TImageIndex read FImageIndex write SetImageIndex; + property ButtonType: TJvNavIconButtonType read FButtonType write SetButtonType; + property Caption; + end; + + TJvNavPanelButton = class(TJvCustomGraphicButton) + private + FImageIndex: TImageIndex; + FImages: TCustomImageList; + FColors: TJvNavPanelColors; + FStyleManager: TJvNavPaneStyleManager; + FStyleLink: TJvNavStyleLink; + FAlignment: TAlignment; + FWordWrap: Boolean; + FParentStyleManager: Boolean; + procedure SetImageIndex(const Value: TImageIndex); + procedure SetImages(const Value: TCustomImageList); + procedure SetColors(const Value: TJvNavPanelColors); + procedure DoColorsChange(Sender: TObject); + procedure SetStyleManager(const Value: TJvNavPaneStyleManager); + procedure DoStyleChange(Sender: TObject); + procedure SetAlignment(const Value: TAlignment); + procedure SetWordWrap(const Value: Boolean); + procedure CMDialogChar(var Msg: TCMDialogChar); message CM_DIALOGCHAR; + procedure ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); message CM_PARENTSTYLEMANAGERCHANGED; + procedure SetParentStyleManager(const Value: Boolean); + function IsColorsStored: Boolean; + protected + procedure TextChanged; override; + procedure FontChanged; override; + procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify; + property WordWrap: Boolean read FWordWrap write SetWordWrap default False; + procedure PaintButton(ACanvas: TCanvas); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property Action; + property Align; + property AllowAllUp; + property Anchors; + property Caption; + property Constraints; + property Down; + property DropDownMenu; + property DragCursor; + property DragKind; + property OnEndDock; + property OnStartDock; + property DragMode; + property Enabled; + property Font; + property GroupIndex; + property HotTrack default True; + property HotTrackFont; + property HotTrackFontOptions; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowHint; + property Visible; + property Width default 125; + property Height default 28; + property Colors: TJvNavPanelColors read FColors write SetColors stored IsColorsStored; + property StyleManager: TJvNavPaneStyleManager read FStyleManager write SetStyleManager; + // (p3) must be published after StyleManager + property ParentStyleManager: Boolean read FParentStyleManager write SetParentStyleManager default True; + property ImageIndex: TImageIndex read FImageIndex write SetImageIndex; + property Images: TCustomImageList read FImages write SetImages; + property OnClick; + property OnContextPopup; + property OnDragDrop; + property OnDragOver; + property OnEndDrag; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnStartDrag; + end; + + TJvNavPaneBackgroundImage = class(TPersistent) + private + FCenter: Boolean; + FTile: Boolean; + FTransparent: Boolean; + FProportional: Boolean; + FStretch: Boolean; + FDrawing: Boolean; + FPicture: TPicture; + FOnChange: TNotifyEvent; + procedure SetCenter(const Value: Boolean); + procedure SetPicture(const Value: TPicture); + procedure SetProportional(const Value: Boolean); + procedure SetStretch(const Value: Boolean); + procedure SetTile(const Value: Boolean); + procedure SetTransparent(const Value: Boolean); + procedure PictureChanged(Sender: TObject); + protected + procedure DrawImage(Canvas: TCanvas; ARect: TRect); virtual; + procedure Change; virtual; + function CalcRect(ADestRect: TRect): TRect; + public + constructor Create; + destructor Destroy; override; + function HasImage: Boolean; + published + property Picture: TPicture read FPicture write SetPicture; + property Stretch: Boolean read FStretch write SetStretch; + property Proportional: Boolean read FProportional write SetProportional; + property Center: Boolean read FCenter write SetCenter; + property Tile: Boolean read FTile write SetTile; + property Transparent: Boolean read FTransparent write SetTransparent; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + end; + + TJvNavPanelPage = class(TJvCustomPage) + private + FNavPanel: TJvNavPanelButton; + FIconButton: TJvNavIconButton; + FOnClick: TNotifyEvent; + FIconPanel: TJvIconPanel; + FStyleManager: TJvNavPaneStyleManager; + FStyleLink: TJvNavStyleLink; + FHeader: TJvNavPanelHeader; + FImageIndex: TImageIndex; + FParentStyleManager: Boolean; + FBackground: TJvNavPaneBackgroundImage; + procedure SetCaption(const Value: TCaption); + procedure SetIconic(const Value: Boolean); + procedure SetImageIndex(const Value: TImageIndex); + function GetCaption: TCaption; + function GetIconic: Boolean; + function GetImageIndex: TImageIndex; + procedure DoButtonClick(Sender: TObject); + function GetHint: string; + procedure SetHint(const Value: string); + procedure SetIconPanel(const Value: TJvIconPanel); + function GetColors: TJvNavPanelColors; + procedure SetColors(const Value: TJvNavPanelColors); + procedure SetStyleManager(const Value: TJvNavPaneStyleManager); + procedure DoStyleChange(Sender: TObject); + procedure SetAutoHeader(const Value: Boolean); + function GetAutoHeader: Boolean; + function GetAlignment: TAlignment; + function GetWordWrap: Boolean; + procedure SetAlignment(const Value: TAlignment); + procedure SetWordWrap(const Value: Boolean); + procedure ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); message CM_PARENTSTYLEMANAGERCHANGED; + procedure ParentStyleManagerChange(var Msg: TLMessage); message CM_PARENTSTYLEMANAGERCHANGE; + procedure CMControlChange(var Msg: TLMessage); message CM_CONTROLCHANGE; + procedure SetParentStyleManager(const Value: Boolean); + procedure SetAction(const Value: TBasicAction); // override; + procedure SetBackground(const Value: TJvNavPaneBackgroundImage); + procedure DoBackgroundChange(Sender: TObject); + protected + procedure UpdatePageList; + function GetAction: TBasicAction; override; + procedure SetParent(AParent: TWinControl); override; + procedure SetPageIndex(Value: Integer); override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + property NavPanel: TJvNavPanelButton read FNavPanel; + property IconButton: TJvNavIconButton read FIconButton; + property IconPanel: TJvIconPanel read FIconPanel write SetIconPanel; + property Colors: TJvNavPanelColors read GetColors write SetColors; + property StyleManager: TJvNavPaneStyleManager read FStyleManager write SetStyleManager; + // (p3) must be published after StyleManager + property ParentStyleManager: Boolean read FParentStyleManager write SetParentStyleManager default True; + property Header: TJvNavPanelHeader read FHeader; + property Alignment: TAlignment read GetAlignment write SetAlignment; + property WordWrap: Boolean read GetWordWrap write SetWordWrap; + procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override; + procedure Paint; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + property AutoHeader: Boolean read GetAutoHeader write SetAutoHeader; + published + property Action: TBasicAction read GetAction write SetAction; + property Background: TJvNavPaneBackgroundImage read FBackground write SetBackground; + property Color default clWindow; + property ParentColor default False; + property Caption: TCaption read GetCaption write SetCaption; + property DragCursor; + property DragKind; + property OnStartDock; + property OnDockDrop; + property OnDockOver; + property OnUnDock; + property OnEndDock; + property DragMode; + property Iconic: Boolean read GetIconic write SetIconic default False; + property ImageIndex: TImageIndex read GetImageIndex write SetImageIndex default -1; + property Hint: string read GetHint write SetHint; + property OnClick: TNotifyEvent read FOnClick write FOnClick; + property OnContextPopup; + 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 OnMouseWheel; + property OnMouseWheelDown; + property OnMouseWheelUp; + property OnResize; + property OnShow; + property OnStartDrag; + end; + + TJvCustomNavPaneToolPanel = class; + + TJvNavPaneToolButton = class(TCollectionItem) + private + FRealButton: TJvNavPanelToolButton; + procedure SetImageIndex(const Value: TImageIndex); + procedure SetEnabled(const Value: Boolean); + procedure SetAction(const Value: TBasicAction); + procedure SetHint(const Value: string); + function GetAction: TBasicAction; + function GetEnabled: Boolean; + function GetHint: string; + function GetImageIndex: TImageIndex; + public + procedure Assign(Source: TPersistent); override; + constructor Create(ACollection: Classes.TCollection); override; + destructor Destroy; override; + property Button: TJvNavPanelToolButton read FRealButton; + published + property Action: TBasicAction read GetAction write SetAction; + property Hint: string read GetHint write SetHint; + property ImageIndex: TImageIndex read GetImageIndex write SetImageIndex default -1; + property Enabled: Boolean read GetEnabled write SetEnabled default True; + end; + + TJvNavPaneToolButtons = class(TOwnedCollection) + private + FPanel: TJvCustomNavPaneToolPanel; + function GetItem(Index: Integer): TJvNavPaneToolButton; + procedure SetItem(Index: Integer; const Value: TJvNavPaneToolButton); + protected + procedure Update(Item: TCollectionItem); override; + public + constructor Create(AOwner: TJvCustomNavPaneToolPanel); + function Add: TJvNavPaneToolButton; + property Items[Index: Integer]: TJvNavPaneToolButton read GetItem write SetItem; default; + end; + + TJvNavPaneToolButtonClick = procedure(Sender: TObject; Index: Integer) of object; + TJvToolPanelHitTestInfo = (phtNowhere, phtAbove, phtBelow, phtToLeft, phtToRight, phtGrabber, phtHeader, phtClient); + TJvToolPanelHitTestInfos = set of TJvToolPanelHitTestInfo; + + //SESS + TWMNCPaint = TLMessage; + + TJvCustomNavPaneToolPanel = class(TJvCustomControl) + private + FStyleLink: TJvNavStyleLink; + FChangeLink: TChangeLink; + FStyleManager: TJvNavPaneStyleManager; + FButtonWidth: Integer; + FHeaderHeight: Integer; + FEdgeRounding: Integer; + FButtonHeight: Integer; + FImages: TCustomImageList; + FButtons: TJvNavPaneToolButtons; + FOnButtonClick: TJvNavPaneToolButtonClick; + FDropDown: TJvNavPanelToolButton; + FCloseButton: TJvNavPanelToolButton; + FOnClose: TNotifyEvent; + FShowGrabber: Boolean; + FOnDropDownMenu: TContextPopupEvent; + FParentStyleManager: Boolean; + FBackground: TJvNavPaneBackgroundImage; + FColors: TJvNavPanelColors; + FHeaderVisible: Boolean; + procedure DoStyleChange(Sender: TObject); + procedure DoImagesChange(Sender: TObject); + procedure ButtonsChanged; + procedure SetStyleManager(const Value: TJvNavPaneStyleManager); + procedure SetButtonHeight(const Value: Integer); + procedure SetButtonWidth(const Value: Integer); + procedure SetEdgeRounding(const Value: Integer); + procedure SetHeaderHeight(const Value: Integer); + procedure SetImages(const Value: TCustomImageList); + procedure SetButtons(const Value: TJvNavPaneToolButtons); + procedure InternalButtonClick(Sender: TObject); + function GetCloseButton: Boolean; + function GetDropDownMenu: TPopupMenu; + procedure SetCloseButton(const Value: Boolean); + procedure SetDropDownMenu(const Value: TPopupMenu); + procedure DoCloseClick(Sender: TObject); + procedure SetShowGrabber(const Value: Boolean); + procedure ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); message CM_PARENTSTYLEMANAGERCHANGED; + procedure ParentStyleManagerChange(var Msg: TLMessage); message CM_PARENTSTYLEMANAGERCHANGE; + procedure SetParentStyleManager(const Value: Boolean); + function GetDrawPartialMenuFrame: Boolean; + procedure SetDrawPartialMenuFrame(const Value: Boolean); + procedure SetBackground(const Value: TJvNavPaneBackgroundImage); + procedure SetColors(const Value: TJvNavPanelColors); + procedure SetHeaderVisible(const Value: Boolean); + function IsColorsStored: Boolean; + procedure CMControlChange(var Msg: TLMessage); message CM_CONTROLCHANGE; + procedure WMEraseBkgnd(var Msg: TLMEraseBkgnd); message LM_ERASEBKGND; + procedure WMNCPaint(var Msg: TWMNCPaint); message LM_NCPAINT; + procedure AlignButtons; + protected + procedure Paint; override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure TextChanged; override; + procedure FontChanged; override; + procedure DoDropDownMenu(Sender: TObject; MousePos: TPoint; var Handled: Boolean); + property EdgeRounding: Integer read FEdgeRounding write SetEdgeRounding default 9; + procedure AdjustClientRect(var Rect: TRect); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function GetHitTestInfoAt(X, Y: Integer): TJvToolPanelHitTestInfos; + procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer; AHeight: Integer); override; + protected + property Background: TJvNavPaneBackgroundImage read FBackground write SetBackground; + property DrawPartialMenuFrame: Boolean read GetDrawPartialMenuFrame write SetDrawPartialMenuFrame default False; + property Buttons: TJvNavPaneToolButtons read FButtons write SetButtons; + property ButtonWidth: Integer read FButtonWidth write SetButtonWidth default 25; + property ButtonHeight: Integer read FButtonHeight write SetButtonHeight default 22; + property CloseButton: Boolean read GetCloseButton write SetCloseButton default True; + property Colors: TJvNavPanelColors read FColors write SetColors stored IsColorsStored; + property DropDownMenu: TPopupMenu read GetDropDownMenu write SetDropDownMenu; + property HeaderHeight: Integer read FHeaderHeight write SetHeaderHeight default 29; + property HeaderVisible: Boolean read FHeaderVisible write SetHeaderVisible default True; + property Images: TCustomImageList read FImages write SetImages; +// property ParentColor default False; + property ShowGrabber: Boolean read FShowGrabber write SetShowGrabber default True; + property StyleManager: TJvNavPaneStyleManager read FStyleManager write SetStyleManager; + property ParentStyleManager: Boolean read FParentStyleManager write SetParentStyleManager default True; + property OnButtonClick: TJvNavPaneToolButtonClick read FOnButtonClick write FOnButtonClick; + property OnClose: TNotifyEvent read FOnClose write FOnClose; + property OnDropDownMenu: TContextPopupEvent read FOnDropDownMenu write FOnDropDownMenu; + end; + + TJvNavPaneToolPanel = class(TJvCustomNavPaneToolPanel) + published + property Align; + property Anchors; + property Caption; + property Constraints; + property BorderWidth; + property DragCursor; + property DragKind; + property DragMode; + property Background; + property DrawPartialMenuFrame; + property Buttons; + property ButtonWidth; + property ButtonHeight; + property CloseButton; + property Colors; + property DropDownMenu; + property HeaderHeight; + property HeaderVisible; + property Images; + property ShowGrabber; + property StyleManager; + // (p3) must be published after StyleManager + property ParentStyleManager; + property OnButtonClick; + property OnClose; + property OnDropDownMenu; + property Enabled; + property Font; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowHint; + property Visible; + property Width default 185; + property Height default 41; + property OnEndDock; + property OnStartDock; + property OnUnDock; + property OnClick; + property OnContextPopup; + property OnDragDrop; + property OnDragOver; + property OnEndDrag; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnStartDrag; + end; + + TJvCustomNavigationPane = class(TJvCustomPageList) + private + FIconPanel: TJvIconPanel; + FSplitter: TJvOutlookSplitter; + FLargeImages: TCustomImageList; + FSmallImages: TCustomImageList; + FColors: TJvNavPanelColors; + FNavPanelFont: TFont; + FResizable: Boolean; + FButtonWidth: Integer; + FButtonHeight: Integer; + FStyleManager: TJvNavPaneStyleManager; + FStyleLink: TJvNavStyleLink; + FNavPanelHotTrackFont: TFont; + FNavPanelHotTrackFontOptions: TJvTrackFontOptions; + FAutoHeaders: Boolean; + FWordWrap: Boolean; + FAlignment: TAlignment; + FOnDropDownMenu: TContextPopupEvent; + FParentStyleManager: Boolean; + FBackground: TJvNavPaneBackgroundImage; + function GetDropDownMenu: TPopupMenu; + function GetSmallImages: TCustomImageList; + procedure SetDropDownMenu(const Value: TPopupMenu); + procedure SetLargeImages(const Value: TCustomImageList); + procedure SetSmallImages(const Value: TCustomImageList); + function GetMaximizedCount: Integer; + procedure SetMaximizedCount(Value: Integer); + procedure HidePanel(Index: Integer); + procedure ShowPanel(Index: Integer); + procedure SetColors(const Value: TJvNavPanelColors); + procedure SetResizable(const Value: Boolean); + function GetNavPage(Index: Integer): TJvNavPanelPage; + procedure DoSplitterCanResize(Sender: TObject; var NewSize: Integer; var Accept: Boolean); + procedure DoColorsChange(Sender: TObject); + procedure SetNavPanelFont(const Value: TFont); + procedure SetNavPanelHotTrackFont(const Value: TFont); + procedure SetNavPanelHotTrackFontOptions(const Value: TJvTrackFontOptions); + procedure DoNavPanelFontChange(Sender: TObject); + procedure SetButtonHeight(const Value: Integer); + procedure SetButtonWidth(const Value: Integer); + procedure SetSplitterHeight(const Value: Integer); + function GetSplitterHeight: Integer; + procedure SetStyleManager(const Value: TJvNavPaneStyleManager); + procedure DoStyleChange(Sender: TObject); + procedure SetAutoHeaders(const Value: Boolean); + procedure SetAlignment(const Value: TAlignment); + procedure SetWordWrap(const Value: Boolean); + procedure ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); message CM_PARENTSTYLEMANAGERCHANGED; + procedure ParentStyleManagerChange(var Msg: TLMessage); message CM_PARENTSTYLEMANAGERCHANGE; + procedure CMControlChange(var Msg: TLMessage); message CM_CONTROLCHANGE; + procedure WMNCPaint(var Msg: TWMNCPaint); message LM_NCPAINT; + procedure WMEraseBkgnd(var Msg: TLMEraseBkgnd); message LM_ERASEBKGND; + procedure SetParentStyleManager(const Value: Boolean); + procedure SetBackground(const Value: TJvNavPaneBackgroundImage); + function GetSplitterClick: TNotifyEvent; + function GetSplitterDblClick: TNotifyEvent; + function GetSplitterMouseDown: TMouseEvent; + function GetSplitterMouseEnter: TNotifyEvent; + function GetSplitterMouseLeave: TNotifyEvent; + function GetSplitterMouseMove: TMouseMoveEvent; + function GetSplitterMouseUp: TMouseEvent; + procedure SetSplitterClick(const Value: TNotifyEvent); + procedure SetSplitterDblClick(const Value: TNotifyEvent); + procedure SetSplitterMouseDown(const Value: TMouseEvent); + procedure SetSplitterMouseEnter(const Value: TNotifyEvent); + procedure SetSplitterMouseLeave(const Value: TNotifyEvent); + procedure SetSplitterMouseMove(const Value: TMouseMoveEvent); + procedure SetSplitterMouseUp(const Value: TMouseEvent); + function GetSplitterCanResize: TCanResizeEvent; + function GetSplitterMoved: TNotifyEvent; + function GetSplitterPaint: TNotifyEvent; + procedure SetSplitterCanResize(const Value: TCanResizeEvent); + procedure SetSplitterMoved(const Value: TNotifyEvent); + procedure SetSplitterPaint(const Value: TNotifyEvent); + protected + function IsColorsStored: Boolean; + function IsNavPanelFontStored: Boolean; + function IsNavPanelFontHotTrackStored: Boolean; + function IsNavPanelHotTrackFontOptionsStored: Boolean; + procedure UpdatePages; virtual; + procedure SetActivePage(Page: TJvCustomPage); override; + procedure InsertPage(APage: TJvCustomPage); override; + procedure RemovePage(APage: TJvCustomPage); override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure Loaded; override; + procedure DoDropDownMenu(Sender: TObject; MousePos: TPoint; var Handled: Boolean); + function InternalGetPageClass: TJvCustomPageClass; override; + property NavPages[Index: Integer]: TJvNavPanelPage read GetNavPage; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function HidePage(Page: TJvCustomPage): TJvCustomPage; override; + function ShowPage(Page: TJvCustomPage; PageIndex: Integer = -1): TJvCustomPage; override; + procedure UpdatePositions; + protected + property BorderWidth default 1; + property AutoHeaders: Boolean read FAutoHeaders write SetAutoHeaders default False; + property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify; + property Background: TJvNavPaneBackgroundImage read FBackground write SetBackground; + property ButtonHeight: Integer read FButtonHeight write SetButtonHeight default 28; + property ButtonWidth: Integer read FButtonWidth write SetButtonWidth default 22; + property NavPanelFont: TFont read FNavPanelFont write SetNavPanelFont; + property NavPanelHotTrackFont: TFont read FNavPanelHotTrackFont write SetNavPanelHotTrackFont; + property NavPanelHotTrackFontOptions: TJvTrackFontOptions read FNavPanelHotTrackFontOptions write SetNavPanelHotTrackFontOptions; + property Color default clWindow; + property Colors: TJvNavPanelColors read FColors write SetColors; + property StyleManager: TJvNavPaneStyleManager read FStyleManager write SetStyleManager; + // (p3) must be published after StyleManager + property ParentStyleManager: Boolean read FParentStyleManager write SetParentStyleManager default True; + property DropDownMenu: TPopupMenu read GetDropDownMenu write SetDropDownMenu; + property LargeImages: TCustomImageList read FLargeImages write SetLargeImages; + property MaximizedCount: Integer read GetMaximizedCount write SetMaximizedCount; + property ParentColor default False; + property Resizable: Boolean read FResizable write SetResizable default True; + property SmallImages: TCustomImageList read GetSmallImages write SetSmallImages; + property SplitterHeight: Integer read GetSplitterHeight write SetSplitterHeight default 7; + property WordWrap: Boolean read FWordWrap write SetWordWrap default False; + property Splitter: TJvOutlookSplitter read FSplitter; + property IconPanel: TJvIconPanel read FIconPanel; + property OnDropDownMenu: TContextPopupEvent read FOnDropDownMenu write FOnDropDownMenu; + property OnSplitterCanResize: TCanResizeEvent read GetSplitterCanResize write SetSplitterCanResize; + property OnSplitterMoved: TNotifyEvent read GetSplitterMoved write SetSplitterMoved; + property OnSplitterPaint: TNotifyEvent read GetSplitterPaint write SetSplitterPaint; + property OnSplitterClick: TNotifyEvent read GetSplitterClick write SetSplitterClick; + property OnSplitterMouseEnter: TNotifyEvent read GetSplitterMouseEnter write SetSplitterMouseEnter; + property OnSplitterMouseLeave: TNotifyEvent read GetSplitterMouseLeave write SetSplitterMouseLeave; + property OnSplitterDblClick: TNotifyEvent read GetSplitterDblClick write SetSplitterDblClick; + property OnSplitterMouseDown: TMouseEvent read GetSplitterMouseDown write SetSplitterMouseDown; + property OnSplitterMouseMove: TMouseMoveEvent read GetSplitterMouseMove write SetSplitterMouseMove; + property OnSplitterMouseUp: TMouseEvent read GetSplitterMouseUp write SetSplitterMouseUp; + end; + + TJvNavigationPane = class(TJvCustomNavigationPane) + public + property NavPages; + property Splitter; + property IconPanel; + published + property ActivePage; + // property Alignment; + property Align; + property Anchors; + property AutoHeaders; + property BorderWidth; + property DragCursor; + property DragKind; + property OnStartDock; + property OnDockDrop; + property OnDockOver; + property OnUnDock; + property OnEndDock; + property Background; + property ButtonHeight; + property ButtonWidth; + property Caption; + property Color; + property Colors stored IsColorsStored; + property StyleManager; + // (p3) must be published after StyleManager + property ParentStyleManager; + property Constraints; + property DragMode; + property DropDownMenu; + property Enabled; + property Font; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowHint; + property SplitterHeight; + property Visible; + property LargeImages; + property MaximizedCount; + property NavPanelFont stored IsNavPanelFontStored; + property NavPanelHotTrackFont stored IsNavPanelFontHotTrackStored; + property NavPanelHotTrackFontOptions stored IsNavPanelHotTrackFontOptionsStored; + property Resizable; + property SmallImages; + // property WordWrap; + property OnChange; + property OnChanging; + property OnDropDownMenu; + property OnClick; + property OnContextPopup; + property OnDragDrop; + property OnDragOver; + property OnEndDrag; + property OnStartDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnMouseWheel; + property OnMouseWheelDown; + property OnMouseWheelUp; + property OnResize; + property OnSplitterCanResize; + property OnSplitterMoved; + property OnSplitterPaint; + property OnSplitterClick; + property OnSplitterMouseEnter; + property OnSplitterMouseLeave; + property OnSplitterDblClick; + property OnSplitterMouseDown; + property OnSplitterMouseMove; + property OnSplitterMouseUp; + end; + + TJvNavStyleLink = class(TObject) + private + FSender: TObject; + FOnChange: TNotifyEvent; + public + destructor Destroy; override; + procedure Change; dynamic; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + property Sender: TObject read FSender write FSender; + end; + + TJvNavPanelTheme = (nptStandard, nptXPBlue, nptXPSilver, nptXPOlive, nptCustom); + + // TJvNavPaneStyleManager = class(TJvComponent) + TJvNavPaneStyleManager = class(TComponent) + private + FColors: TJvNavPanelColors; + FTheme: TJvNavPanelTheme; + FClients: TList; + FFonts: TJvNavPanelFonts; + FOnThemeChange: TNotifyEvent; + procedure SetColors(const Value: TJvNavPanelColors); + procedure SetTheme(const Value: TJvNavPanelTheme); + procedure DoThemeChange(Sender: TObject); + procedure SetFonts(const Value: TJvNavPanelFonts); + function IsColorsStored: Boolean; + function IsFontsStored: Boolean; + protected + procedure Change; virtual; + procedure AssignTo(Dest: TPersistent); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Assign(Source: TPersistent); override; + procedure RegisterChanges(Value: TJvNavStyleLink); + procedure UnregisterChanges(Value: TJvNavStyleLink); + published + property Colors: TJvNavPanelColors read FColors write SetColors stored IsColorsStored; + property Fonts: TJvNavPanelFonts read FFonts write SetFonts stored IsFontsStored; + property Theme: TJvNavPanelTheme read FTheme write SetTheme nodefault; + property OnThemeChange: TNotifyEvent read FOnThemeChange write FOnThemeChange; + end; + +implementation + +uses + ActnList, Forms, JvJVCLUtils, JvJCLUtils; + +const + cNavPanelButtonGroupIndex = 113; + cToolButtonHeight = 18; + cToolButtonOffset = 14; + cToolButtonWidth = 18; + +procedure InternalStyleManagerChanged(AControl: TWinControl; AStyleManager: TJvNavPaneStyleManager); +var + Msg: TMsgStyleManagerChange; +begin + Msg.Msg := CM_PARENTSTYLEMANAGERCHANGED; + Msg.Sender := AControl; + Msg.StyleManager := AStyleManager; + Msg.Result := 0; + AControl.Broadcast(Msg); +end; + +//=== { TJvIconPanel } ======================================================= + +constructor TJvIconPanel.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + ControlStyle := ControlStyle - [csAcceptsControls]; + FStyleLink := TJvNavStyleLink.Create; + FStyleLink.OnChange := @DoStyleChange; + ControlStyle := ControlStyle + [csOpaque, csAcceptsControls]; + Height := 28; + FDropButton := TJvNavIconButton.Create(Self); + FDropButton.Visible := False; + FDropButton.ButtonType := nibDropDown; + FDropButton.GroupIndex := 0; + FDropButton.Width := 22; + FDropButton.Left := Width + 10; + FDropButton.Align := alRight; + FDropButton.Parent := Self; + FDropButton.OnDropDownMenu := @DoDropDownMenu; + FColors := TJvNavPanelColors.Create; + FColors.OnChange := @DoColorsChange; + FParentStyleManager := True; +end; + +destructor TJvIconPanel.Destroy; +begin + FStyleLink.Free; + FColors.Free; + // Don't free FDropButton: it is freed automatically + inherited Destroy; +end; + +procedure TJvIconPanel.DoColorsChange(Sender: TObject); +begin + Invalidate; +end; + +procedure TJvIconPanel.DoStyleChange(Sender: TObject); +begin + Colors := (Sender as TJvNavPaneStyleManager).Colors; + Font := (Sender as TJvNavPaneStyleManager).Fonts.NavPanelFont; +end; + +function TJvIconPanel.GetDropDownMenu: TPopupMenu; +begin + Result := FDropButton.DropDownMenu +end; + +procedure TJvIconPanel.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if Operation = opRemove then + begin + if AComponent = StyleManager then + StyleManager := nil; + end; +end; + +procedure TJvIconPanel.Paint; +begin + GradientFillRect(Canvas, ClientRect, Colors.ButtonColorFrom, Colors.ButtonColorTo, fdTopToBottom, 32); + Canvas.Pen.Color := Colors.FrameColor; + if Align = alBottom then + begin + Canvas.MoveTo(0, 0); + Canvas.LineTo(Width + 1, 0); + end + else + begin + Canvas.MoveTo(0, ClientHeight - 1); + Canvas.LineTo(Width + 1, ClientHeight - 1); + end; +end; + +procedure TJvIconPanel.SetColors(const Value: TJvNavPanelColors); +begin + FColors.Assign(Value); + FDropButton.Colors := Value; +end; + +procedure TJvIconPanel.SetStyleManager(const Value: TJvNavPaneStyleManager); +//var +// I: Integer; +begin + if FStyleManager <> Value then + begin + ParentStyleManager := False; + if FStyleManager <> nil then + FStyleManager.UnregisterChanges(FStyleLink); + FStyleManager := Value; + if FStyleManager <> nil then + begin + FStyleManager.RegisterChanges(FStyleLink); + FStyleManager.FreeNotification(Self); + Colors := FStyleManager.Colors; + end; + end; + // FDropButton.StyleManager := Value; + InternalStyleManagerChanged(Self, Value); + // TODO: should this be removed? +// for I := 0 to ControlCount - 1 do +// if Controls[I] is TJvNavIconButton then +// TJvNavIconButton(Controls[I]).StyleManager := Value; +end; + +procedure TJvIconPanel.SetDropDownMenu(const Value: TPopupMenu); +begin + FDropButton.DropDownMenu := Value; + FDropButton.Visible := Value <> nil; +end; + +procedure TJvIconPanel.DoDropDownMenu(Sender: TObject; MousePos: TPoint; + var Handled: Boolean); +begin + if Assigned(FOnDropDownMenu) then + FOnDropDownMenu(Self, MousePos, Handled); +end; + +procedure TJvIconPanel.ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); +begin + if (Msg.Sender <> Self) and ParentStyleManager then + begin + StyleManager := Msg.StyleManager; + ParentStyleManager := True; + InternalStyleManagerChanged(Self, Msg.StyleManager); + end; +end; + +procedure TJvIconPanel.SetParentStyleManager(const Value: Boolean); +begin + if FParentStyleManager <> Value then + begin + FParentStyleManager := Value; + if FParentStyleManager and (Parent <> nil) then + Parent.Perform(CM_PARENTSTYLEMANAGERCHANGE, 0, 0); + end; +end; + + +procedure TJvIconPanel.CMControlChange(var Msg: TLMessage); +begin + InternalStyleManagerChanged(Self, StyleManager); +end; + +procedure TJvIconPanel.WMEraseBkgnd(var Msg: TLMEraseBkgnd); +begin + Msg.Result := 1; +end; + +procedure TJvIconPanel.ParentStyleManagerChange(var Msg: TLMessage); +begin + InternalStyleManagerChanged(Self, StyleManager); +end; + +//=== { TJvCustomNavigationPane } ============================================ + +var + GlobalNavPanelPageRegistered: Boolean = False; + +constructor TJvCustomNavigationPane.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + if not GlobalNavPanelPageRegistered then + begin + GlobalNavPanelPageRegistered := True; + RegisterClasses([TJvNavPanelPage]); + end; + + FBackground := TJvNavPaneBackgroundImage.Create; + FBackground.OnChange := @DoColorsChange; + ControlStyle := ControlStyle - [csAcceptsControls]; + FStyleLink := TJvNavStyleLink.Create; + FStyleLink.OnChange := @DoStyleChange; + FButtonHeight := 28; + FButtonWidth := 22; + BorderWidth := 1; + ParentColor := False; + Color := clWindow; + ControlStyle := ControlStyle + [csOpaque]; + FResizable := True; + FColors := TJvNavPanelColors.Create; + FColors.OnChange := @DoColorsChange; + FIconPanel := TJvIconPanel.Create(Self); + FIconPanel.Parent := Self; + FIconPanel.Align := alBottom; + FIconPanel.OnDropDownMenu := @DoDropDownMenu; + + FNavPanelFont := TFont.Create; + FNavPanelHotTrackFont := TFont.Create; + //TODO: + //FNavPanelFont.Assign(Screen.IconFont); + FNavPanelFont.Style := [fsBold]; + FNavPanelFont.OnChange := @DoNavPanelFontChange; + FNavPanelHotTrackFont.Assign(FNavPanelFont); + FNavPanelHotTrackFont.OnChange := @DoNavPanelFontChange; + FNavPanelHotTrackFontOptions := DefaultTrackFontOptions; + FSplitter := TJvOutlookSplitter.Create(Self); + with FSplitter do + begin + ResizeStyle := rsNone; + MinSize := 1; + OnCanResize := @DoSplitterCanResize; + Parent := Self; + end; + FParentStyleManager := True; + FIconPanel.SetSubComponent(True); + FSplitter.SetSubComponent(True); +end; + +destructor TJvCustomNavigationPane.Destroy; +begin + FStyleLink.Free; + FColors.Free; + FNavPanelFont.Free; + FNavPanelHotTrackFont.Free; + FBackground.Free; + inherited Destroy; +end; + +procedure TJvCustomNavigationPane.DoSplitterCanResize(Sender: TObject; + var NewSize: Integer; var Accept: Boolean); +var + ACount: Integer; +begin + ACount := MaximizedCount; + if NewSize < ButtonHeight div 2 then + MaximizedCount := ACount - 1 + else + if NewSize > ButtonHeight + ButtonHeight div 2 then + MaximizedCount := ACount + 1; + NewSize := 0; + Accept := False; +end; + +function TJvCustomNavigationPane.GetDropDownMenu: TPopupMenu; +begin + if FIconPanel <> nil then + Result := FIconPanel.DropDownMenu + else + Result := nil; +end; + +function TJvCustomNavigationPane.GetSmallImages: TCustomImageList; +begin + Result := FSmallImages; +end; + +function TJvCustomNavigationPane.GetMaximizedCount: Integer; +var + I: Integer; +begin + Result := 0; + for I := 0 to PageCount - 1 do + if not NavPages[I].Iconic then + Inc(Result); +end; + +function TJvCustomNavigationPane.HidePage(Page: TJvCustomPage): TJvCustomPage; +begin + Result := inherited HidePage(Page); + if Result <> nil then + UpdatePositions; +end; + +function TJvCustomNavigationPane.ShowPage(Page: TJvCustomPage; PageIndex: Integer): TJvCustomPage; +begin + Result := inherited ShowPage(Page, PageIndex); + if Result <> nil then + UpdatePositions; +end; + +procedure TJvCustomNavigationPane.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if Operation = opRemove then + begin + if AComponent = LargeImages then + LargeImages := nil; + if AComponent = SmallImages then + SmallImages := nil; + if AComponent = StyleManager then + StyleManager := nil; + end; +end; + +procedure TJvCustomNavigationPane.SetDropDownMenu(const Value: TPopupMenu); +begin + if FIconPanel <> nil then + FIconPanel.DropDownMenu := Value; +end; + +procedure TJvCustomNavigationPane.SetLargeImages(const Value: TCustomImageList); +begin + if FLargeImages <> Value then + begin + FLargeImages := Value; + UpdatePages; + end; +end; + +procedure TJvCustomNavigationPane.SetSmallImages(const Value: TCustomImageList); +begin + if FSmallImages <> Value then + begin + FSmallImages := Value; + UpdatePages; + end; +end; + +procedure TJvCustomNavigationPane.HidePanel(Index: Integer); +begin + if (Index >= 0) and (Index < PageCount) then // don't hide the first panel + NavPages[Index].Iconic := True; +end; + +procedure TJvCustomNavigationPane.ShowPanel(Index: Integer); +begin + if (Index >= 0) and (Index < PageCount) then + NavPages[Index].Iconic := False; +end; + +procedure TJvCustomNavigationPane.SetMaximizedCount(Value: Integer); +var + I, ACount: Integer; +begin + ACount := MaximizedCount; + if Value < 0 then + Value := 0; + if Value > PageCount then + Value := PageCount; + if Value = MaximizedCount then + Exit; + while ACount > Value do + begin + HidePanel(ACount - 1); + Dec(ACount); + end; + if Value > ACount then + for I := Value downto ACount do + ShowPanel(I - 1); + UpdatePositions; +end; + +procedure TJvCustomNavigationPane.UpdatePositions; +var + bw, bh, I, X, Y: Integer; +begin + if (csDestroying in ComponentState) or (FIconPanel = nil) then + Exit; + DisableAlign; + FIconPanel.DisableAlign; + try + // 25.09.2007 - SESS: Original code doesn't work in lazarus. + (* + Y := 0; + X := 0; + FSplitter.Top := Y; + FIconPanel.FDropButton.Left := Width; + FIconPanel.Top := Height - FIconPanel.Height; + Inc(Y, FSplitter.Height); + for I := 0 to PageCount - 1 do + begin + if (NavPages[I].NavPanel = nil) or (NavPages[I].IconButton = nil) then + Exit; + NavPages[I].IconButton.Left := X; + Inc(X, NavPages[I].IconButton.Width); + NavPages[I].NavPanel.Top := Y; + Inc(Y, NavPages[I].NavPanel.Height); + NavPages[I].Invalidate; + end; + *) + + // 25.09.2007: Rewrited by SESS. + // Buttons heights & widths + bw := 0; + bh := 0; + for I := 0 to PageCount - 1 do + if NavPages[I].Iconic then + Inc(bw, NavPages[I].IconButton.Width) + else + Inc(bh, NavPages[I].NavPanel.Height); + + // First positions + X := Self.Width - bw - FIconPanel.FDropButton.Width; + Y := Self.Height - FSplitter.Height - bh - FIconPanel.Height; + + // Splitter + FSplitter.Top := Y; + Inc(Y, FSplitter.Height); + + // Pages + for I := 0 to PageCount - 1 do + begin + if (NavPages[I].NavPanel = nil) or (NavPages[I].IconButton = nil) then + Exit; + if NavPages[I].Iconic then + begin + NavPages[I].IconButton.Left := X; + Inc(X, NavPages[I].IconButton.Width); + end + else + begin + NavPages[I].NavPanel.Top := Y; + Inc(Y, NavPages[I].NavPanel.Height); + end; + NavPages[I].Invalidate; + end; + + // Icon panel + FIconPanel.FDropButton.Left := X; + FIconPanel.Top := Y; + finally + EnableAlign; + FIconPanel.EnableAlign; + end; + Invalidate; +end; + +procedure TJvCustomNavigationPane.SetColors(const Value: TJvNavPanelColors); +begin + FColors.Assign(Value); +end; + +procedure TJvCustomNavigationPane.DoColorsChange(Sender: TObject); +begin + if FIconPanel <> nil then + TJvIconPanel(FIconPanel).Colors := Colors; + UpdatePages; + FSplitter.ColorFrom := Colors.SplitterColorFrom; + FSplitter.ColorTo := Colors.SplitterColorTo; + Invalidate; +end; + +procedure TJvCustomNavigationPane.Loaded; +begin + inherited Loaded; + UpdatePositions; +end; + +procedure TJvCustomNavigationPane.SetResizable(const Value: Boolean); +begin + if FResizable <> Value then + begin + FResizable := Value; + FSplitter.Enabled := FResizable; + end; +end; + +function TJvCustomNavigationPane.InternalGetPageClass: TJvCustomPageClass; +begin + Result := TJvNavPanelPage; +end; + +function TJvCustomNavigationPane.GetNavPage(Index: Integer): TJvNavPanelPage; +begin + Result := TJvNavPanelPage(Pages[Index]); +end; + +procedure TJvCustomNavigationPane.InsertPage(APage: TJvCustomPage); +begin + inherited InsertPage(APage); + if APage <> nil then + begin + TJvNavPanelPage(APage).Top := FIconPanel.Top; + if (ActivePage = nil) and not (csLoading in ComponentState) then + ActivePage := APage; + end; + UpdatePositions; +end; + +procedure TJvCustomNavigationPane.SetActivePage(Page: TJvCustomPage); +begin + inherited SetActivePage(Page); + if ActivePage <> nil then + begin + TJvNavPanelPage(ActivePage).NavPanel.Down := True; + TJvNavPanelPage(ActivePage).IconButton.Down := True; + TJvNavPanelPage(ActivePage).NavPanel.Invalidate; + TJvNavPanelPage(ActivePage).IconButton.Invalidate; + ActivePage.Invalidate; + end; +end; + +procedure TJvCustomNavigationPane.SetBackground(const Value: TJvNavPaneBackgroundImage); +begin + FBackground.Assign(Value); +end; + +procedure TJvCustomNavigationPane.SetNavPanelFont(const Value: TFont); +begin + FNavPanelFont.Assign(Value); +end; + +procedure TJvCustomNavigationPane.SetNavPanelHotTrackFont(const Value: TFont); +begin + FNavPanelHotTrackFont.Assign(Value); +end; + +procedure TJvCustomNavigationPane.SetNavPanelHotTrackFontOptions(const Value: TJvTrackFontOptions); +begin + if FNavPanelHotTrackFontOptions <> Value then + begin + FNavPanelHotTrackFontOptions := Value; + UpdatePages; + end; +end; + +function TJvCustomNavigationPane.IsNavPanelFontStored: Boolean; +var + F: TFont; +begin + //TODO: + (* + F := Screen.IconFont; + with FNavPanelFont do + Result := ((StyleManager = nil) or (StyleManager.Theme = nptCustom)) and ((Name <> F.Name) or (Size <> F.Size) or (Style <> [fsBold]) or + (Color <> F.Color) or (Pitch <> F.Pitch) or (Charset <> F.Charset)); + *) + Result := true; +end; + +function TJvCustomNavigationPane.IsNavPanelFontHotTrackStored: Boolean; +begin + Result := IsNavPanelHotTrackFontOptionsStored or IsNavPanelFontStored; +end; + +function TJvCustomNavigationPane.IsNavPanelHotTrackFontOptionsStored: Boolean; +begin + Result := not (hoFollowFont in NavPanelHotTrackFontOptions); +end; + +procedure TJvCustomNavigationPane.DoNavPanelFontChange(Sender: TObject); +begin + UpdatePages; +end; + +procedure TJvCustomNavigationPane.RemovePage(APage: TJvCustomPage); +begin + inherited RemovePage(APage); + Invalidate; +end; + +procedure TJvCustomNavigationPane.SetButtonHeight(const Value: Integer); +begin + if FButtonHeight <> Value then + begin + FButtonHeight := Value; + UpdatePages; + FIconPanel.Height := FButtonHeight; + end; +end; + +procedure TJvCustomNavigationPane.SetButtonWidth(const Value: Integer); +begin + if FButtonWidth <> Value then + begin + FButtonWidth := Value; + UpdatePages; + FIconPanel.FDropButton.Width := FButtonWidth; + end; +end; + +procedure TJvCustomNavigationPane.SetSplitterHeight(const Value: Integer); +begin + if FSplitter.Height <> Value then + FSplitter.Height := Value; +end; + +function TJvCustomNavigationPane.GetSplitterHeight: Integer; +begin + Result := FSplitter.Height; +end; + +procedure TJvCustomNavigationPane.SetStyleManager(const Value: TJvNavPaneStyleManager); +begin + if FStyleManager <> Value then + begin + ParentStyleManager := False; + if FStyleManager <> nil then + FStyleManager.UnregisterChanges(FStyleLink); + FStyleManager := Value; + if FStyleManager <> nil then + begin + FStyleManager.RegisterChanges(FStyleLink); + FStyleManager.FreeNotification(Self); + Colors := FStyleManager.Colors; + NavPanelFont := FStyleManager.Fonts.FNavPanelFont; + NavPanelHotTrackFont := FStyleManager.Fonts.FNavPanelHotTrackFont; + NavPanelHotTrackFontOptions := FStyleManager.Fonts.FNavPanelHotTrackFontOptions; + end; + // FSplitter.StyleManager := Value; + InternalStyleManagerChanged(Self, Value); + end; +end; + +procedure TJvCustomNavigationPane.DoStyleChange(Sender: TObject); +begin + Colors := (Sender as TJvNavPaneStyleManager).Colors; + NavPanelFont := (Sender as TJvNavPaneStyleManager).Fonts.NavPanelFont; + NavPanelHotTrackFont := (Sender as TJvNavPaneStyleManager).Fonts.NavPanelHotTrackFont; + NavPanelHotTrackFontOptions := (Sender as TJvNavPaneStyleManager).Fonts.NavPanelHotTrackFontOptions; +end; + +procedure TJvCustomNavigationPane.SetAutoHeaders(const Value: Boolean); +begin + if FAutoHeaders <> Value then + begin + FAutoHeaders := Value; + UpdatePages; + end; +end; + +procedure TJvCustomNavigationPane.SetAlignment(const Value: TAlignment); +begin + if FAlignment <> Value then + begin + FAlignment := Value; + UpdatePages; + end; +end; + +procedure TJvCustomNavigationPane.SetWordWrap(const Value: Boolean); +begin + if FWordWrap <> Value then + begin + FWordWrap := Value; + UpdatePages; + end; +end; + +procedure TJvCustomNavigationPane.UpdatePages; +var + I: Integer; +begin + for I := 0 to PageCount - 1 do + begin + NavPages[I].AutoHeader := AutoHeaders; + NavPages[I].NavPanel.Height := ButtonHeight; + NavPages[I].IconButton.Width := ButtonWidth; + NavPages[I].NavPanel.Colors := Colors; + NavPages[I].IconButton.Colors := Colors; + NavPages[I].NavPanel.HotTrackFontOptions := NavPanelHotTrackFontOptions; + NavPages[I].NavPanel.Font := FNavPanelFont; + NavPages[I].NavPanel.HotTrackFont := FNavPanelHotTrackFont; + + NavPages[I].WordWrap := WordWrap; + NavPages[I].Alignment := Alignment; + NavPages[I].NavPanel.Images := LargeImages; + if AutoHeaders then + NavPages[I].Header.Images := LargeImages; + NavPages[I].IconButton.Images := SmallImages; + // NavPages[I].StyleManager := StyleManager; + end; +end; + +procedure TJvCustomNavigationPane.DoDropDownMenu(Sender: TObject; + MousePos: TPoint; var Handled: Boolean); +begin + if Assigned(FOnDropDownMenu) then + FOnDropDownMenu(Self, MousePos, Handled); +end; + +procedure TJvCustomNavigationPane.ParentStyleManagerChanged( + var Msg: TMsgStyleManagerChange); +begin + if (Msg.Sender <> Self) and ParentStyleManager then + begin + StyleManager := Msg.StyleManager; + ParentStyleManager := True; + InternalStyleManagerChanged(Self, Msg.StyleManager); + end; +end; + +procedure TJvCustomNavigationPane.SetParentStyleManager(const Value: Boolean); +begin + if FParentStyleManager <> Value then + begin + FParentStyleManager := Value; + if FParentStyleManager and (Parent <> nil) then + Parent.Perform(CM_PARENTSTYLEMANAGERCHANGE, 0, 0); + end; +end; + + +procedure TJvCustomNavigationPane.CMControlChange(var Msg: TLMessage); +begin + InternalStyleManagerChanged(Self, StyleManager); +end; + +procedure TJvCustomNavigationPane.WMNCPaint(var Msg: TWMNCPaint); +var + AColor: TColor; +begin + AColor := Color; + try + Color := Colors.FrameColor; + inherited; + finally + Color := AColor; + end; +end; + +procedure TJvCustomNavigationPane.WMEraseBkgnd(var Msg: TLMEraseBkgnd); +begin + if ActivePage = nil then + begin + Canvas.Brush.Color := Color; + Canvas.FillRect(ClientRect); + FBackground.DrawImage(Canvas, ClientRect); + end; + Msg.Result := 1; +end; + +procedure TJvCustomNavigationPane.ParentStyleManagerChange(var Msg: TLMessage); +begin + InternalStyleManagerChanged(Self, StyleManager); +end; + +function TJvCustomNavigationPane.IsColorsStored: Boolean; +begin + Result := (StyleManager = nil) or (StyleManager.Theme = nptCustom); +end; + +function TJvCustomNavigationPane.GetSplitterClick: TNotifyEvent; +begin + if FSplitter <> nil then + Result := FSplitter.OnClick + else + Result := nil; +end; + +function TJvCustomNavigationPane.GetSplitterDblClick: TNotifyEvent; +begin + if FSplitter <> nil then + Result := FSplitter.OnDblClick + else + Result := nil; +end; + +function TJvCustomNavigationPane.GetSplitterMouseDown: TMouseEvent; +begin + if FSplitter <> nil then + Result := FSplitter.OnMouseDown + else + Result := nil; +end; + +function TJvCustomNavigationPane.GetSplitterMouseEnter: TNotifyEvent; +begin + if FSplitter <> nil then + Result := FSplitter.OnMouseEnter + else + Result := nil; +end; + +function TJvCustomNavigationPane.GetSplitterMouseLeave: TNotifyEvent; +begin + if FSplitter <> nil then + Result := FSplitter.OnMouseLeave + else + Result := nil; +end; + +function TJvCustomNavigationPane.GetSplitterMouseMove: TMouseMoveEvent; +begin + if FSplitter <> nil then + Result := FSplitter.OnMouseMove + else + Result := nil; +end; + +function TJvCustomNavigationPane.GetSplitterMouseUp: TMouseEvent; +begin + if FSplitter <> nil then + Result := FSplitter.OnMouseUp + else + Result := nil; +end; + +function TJvCustomNavigationPane.GetSplitterCanResize: TCanResizeEvent; +begin + if FSplitter <> nil then + Result := FSplitter.OnCanResize + else + Result := nil; +end; + +function TJvCustomNavigationPane.GetSplitterMoved: TNotifyEvent; +begin + if FSplitter <> nil then + Result := FSplitter.OnMoved + else + Result := nil; +end; + +function TJvCustomNavigationPane.GetSplitterPaint: TNotifyEvent; +begin + if FSplitter <> nil then + Result := FSplitter.OnPaint + else + Result := nil; +end; + +procedure TJvCustomNavigationPane.SetSplitterCanResize(const Value: TCanResizeEvent); +begin + if FSplitter <> nil then + FSplitter.OnCanResize := Value; +end; + +procedure TJvCustomNavigationPane.SetSplitterMoved(const Value: TNotifyEvent); +begin + if FSplitter <> nil then + FSplitter.OnMoved := Value; +end; + +procedure TJvCustomNavigationPane.SetSplitterPaint(const Value: TNotifyEvent); +begin + if FSplitter <> nil then + FSplitter.OnPaint := Value; +end; + +procedure TJvCustomNavigationPane.SetSplitterClick(const Value: TNotifyEvent); +begin + if FSplitter <> nil then + FSplitter.OnClick := Value; +end; + +procedure TJvCustomNavigationPane.SetSplitterDblClick( + const Value: TNotifyEvent); +begin + if FSplitter <> nil then + FSplitter.OnDblClick := Value; +end; + +procedure TJvCustomNavigationPane.SetSplitterMouseDown( + const Value: TMouseEvent); +begin + if FSplitter <> nil then + FSplitter.OnMouseDown := Value; +end; + +procedure TJvCustomNavigationPane.SetSplitterMouseEnter( + const Value: TNotifyEvent); +begin + if FSplitter <> nil then + FSplitter.OnMouseEnter := Value; +end; + +procedure TJvCustomNavigationPane.SetSplitterMouseLeave( + const Value: TNotifyEvent); +begin + if FSplitter <> nil then + FSplitter.OnMouseLeave := Value; +end; + +procedure TJvCustomNavigationPane.SetSplitterMouseMove( + const Value: TMouseMoveEvent); +begin + if FSplitter <> nil then + FSplitter.OnMouseMove := Value; +end; + +procedure TJvCustomNavigationPane.SetSplitterMouseUp( + const Value: TMouseEvent); +begin + if FSplitter <> nil then + FSplitter.OnMouseUp := Value; +end; + +//=== { TJvNavIconButton } =================================================== + +constructor TJvNavIconButton.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FStyleLink := TJvNavStyleLink.Create; + FStyleLink.OnChange := @DoStyleChange; + FColors := TJvNavPanelColors.Create; + FColors.OnChange := @DoColorsChange; + FChangeLink := TChangeLink.Create; + FChangeLink.OnChange := @DoImagesChange; + Width := 22; + Height := 22; + //TODO: + //Font := Screen.IconFont; + Font.Style := [fsBold]; + FParentStyleManager := True; +end; + +destructor TJvNavIconButton.Destroy; +begin + FStyleLink.Free; + FChangeLink.Free; + FColors.Free; + inherited Destroy; +end; + +procedure TJvNavIconButton.DoColorsChange(Sender: TObject); +begin + Invalidate; +end; + +procedure TJvNavIconButton.DoImagesChange(Sender: TObject); +begin + Invalidate; +end; + +procedure TJvNavIconButton.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if Operation = opRemove then + if AComponent = Images then + Images := nil + else + if AComponent = StyleManager then + StyleManager := nil; +end; + +procedure TJvNavIconButton.Paint; +var + Rect: TRect; + P: TPoint; + I: Integer; + + h, w: integer; +begin + with Canvas do + begin + Rect := ClientRect; + Brush.Style := bsClear; + InflateRect(Rect, 0, -1); + if bsMouseInside in MouseStates then + begin + if bsMouseDown in MouseStates then + GradientFillRect(Canvas, Rect, Self.Colors.ButtonSelectedColorFrom, + Self.Colors.ButtonSelectedColorTo, fdTopToBottom, 32) + else + GradientFillRect(Canvas, Rect, Self.Colors.ButtonHotColorFrom, + Self.Colors.ButtonHotColorTo, fdTopToBottom, 32) + end + else + if Down then + GradientFillRect(Canvas, Rect, Self.Colors.ButtonSelectedColorFrom, + Self.Colors.ButtonSelectedColorTo, fdTopToBottom, 32); + case ButtonType of + nibDropDown: + begin // area should be 7x12 + InflateRect(Rect, -((Rect.Right - Rect.Left) - 7) div 2, -((Rect.Bottom - Rect.Top) - 12) div 2); + if bsMouseDown in MouseStates then + OffsetRect(Rect, 1, 1); + Canvas.Pen.Color := clBlack; + P.X := Rect.Left; + P.Y := Rect.Top; + // chevron, upper + for I := 0 to 2 do + begin + Canvas.MoveTo(P.X, P.Y); + Canvas.LineTo(P.X + 2, P.Y); + Canvas.MoveTo(P.X + 4, P.Y); + Canvas.LineTo(P.X + 6, P.Y); + Inc(P.X); + Inc(P.Y); + end; + // chevron, lower + Dec(P.X); + Dec(P.Y); + for I := 0 to 2 do + begin + Canvas.MoveTo(P.X, P.Y); + Canvas.LineTo(P.X + 2, P.Y); + Canvas.MoveTo(P.X + 4, P.Y); + Canvas.LineTo(P.X + 6, P.Y); + Dec(P.X); + Inc(P.Y); + end; + // drop arrow + Inc(P.X, 1); + Inc(P.Y, 3); + for I := 0 to 3 do + begin + Canvas.MoveTo(P.X + I, P.Y + I); + Canvas.LineTo(P.X + 7 - I, P.Y + I); + end; + end; + nibImage: + begin + if (Images <> nil) and (ImageIndex >= 0) and (ImageIndex < Images.Count) then + // draw image only + Images.Draw(Canvas, + (Self.Width - Images.Width) div 2 + Ord(bsMouseDown in MouseStates), + (Self.Height - Images.Height) div 2 + Ord(bsMouseDown in MouseStates), + ImageIndex, Enabled); + end; + nibDropArrow: + begin + // area should be 9 x 5, centered + P.X := Rect.Left + (RectWidth(Rect) - 9) div 2 + Ord(bsMouseDown in MouseStates); + P.Y := Rect.Top + (RectHeight(Rect) - 5) div 2 + Ord(bsMouseDown in MouseStates); + Canvas.Pen.Color := clBlack; + for I := 0 to 4 do + begin + Canvas.MoveTo(P.X + I, P.Y + I); + Canvas.LineTo(P.X + 9 - I, P.Y + I); + end; + end; + nibClose: + begin + // area should be 8 x 8, centered + P.X := (RectWidth(ClientRect) - 8) div 2 + Ord(bsMouseDown in MouseStates); + P.Y := (RectHeight(ClientRect) - 8) div 2 + Ord(bsMouseDown in MouseStates); + Canvas.Pen.Color := clBlack; + for I := 0 to 7 do + begin + Canvas.MoveTo(P.X + I, P.Y + I); + Canvas.LineTo(P.X + I + 2, P.Y + I); + end; + Inc(P.X, 7); + for I := 0 to 7 do + begin + Canvas.MoveTo(P.X - I, P.Y + I); + Canvas.LineTo(P.X - I + 2, P.Y + I); + end; + end; + end; + if csDesigning in ComponentState then + begin + Canvas.Pen.Color := clBlack; + Canvas.Pen.Style := psDot; + Canvas.Brush.Style := bsClear; + Canvas.Rectangle(ClientRect); + end; + end; +end; + +procedure TJvNavIconButton.SetColors(const Value: TJvNavPanelColors); +begin + FColors.Assign(Value); +end; + +procedure TJvNavIconButton.SetImageIndex(const Value: TImageIndex); +begin + if FImageIndex <> Value then + begin + FImageIndex := Value; + Invalidate; + end; +end; + +procedure TJvNavIconButton.SetImages(const Value: TCustomImageList); +begin + if FImages <> Value then + begin + if FImages <> nil then + FImages.UnregisterChanges(FChangeLink); + FImages := Value; + if FImages <> nil then + begin + FImages.FreeNotification(Self); + FImages.RegisterChanges(FChangeLink); + end; + Invalidate; + end; +end; + +procedure TJvNavIconButton.SetButtonType(const Value: TJvNavIconButtonType); +begin + if FButtonType <> Value then + begin + FButtonType := Value; + Invalidate; + end; +end; + +procedure TJvNavIconButton.SetStyleManager(const Value: TJvNavPaneStyleManager); +begin + if FStyleManager <> Value then + begin + ParentStyleManager := False; + if FStyleManager <> nil then + FStyleManager.UnregisterChanges(FStyleLink); + FStyleManager := Value; + if FStyleManager <> nil then + begin + FStyleManager.RegisterChanges(FStyleLink); + FStyleManager.FreeNotification(Self); + Colors := FStyleManager.Colors; + end; + end; +end; + +procedure TJvNavIconButton.DoStyleChange(Sender: TObject); +begin + Colors := (Sender as TJvNavPaneStyleManager).Colors; + Font := (Sender as TJvNavPaneStyleManager).Fonts.DividerFont; +end; + +procedure TJvNavIconButton.ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); +begin + if (Msg.Sender <> Self) and ParentStyleManager then + begin + StyleManager := Msg.StyleManager; + ParentStyleManager := True; + end; +end; + +procedure TJvNavIconButton.SetParentStyleManager(const Value: Boolean); +begin + if FParentStyleManager <> Value then + begin + FParentStyleManager := Value; + if FParentStyleManager and (Parent <> nil) then + Parent.Perform(CM_PARENTSTYLEMANAGERCHANGE, 0, 0); + end; +end; + +function TJvNavIconButton.IsColorsStored: Boolean; +begin + Result := (StyleManager = nil) or (StyleManager.Theme = nptCustom); +end; + +//=== { TJvNavPanelButton } ================================================== + +constructor TJvNavPanelButton.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FAlignment := taLeftJustify; + + FStyleLink := TJvNavStyleLink.Create; + FStyleLink.OnChange := @DoStyleChange; + ControlStyle := ControlStyle + [csOpaque, csDisplayDragImage]; + Flat := True; + HotTrack := True; + Height := 28; + FColors := TJvNavPanelColors.Create; + FColors.OnChange := @DoColorsChange; + //TODO: + //Font := Screen.IconFont; + Font.Style := [fsBold]; + HotTrackFont := Font; + HotTrackFont.Style := [fsBold]; + Width := 125; + Height := 28; + FParentStyleManager := True; +end; + +destructor TJvNavPanelButton.Destroy; +begin + FStyleLink.Free; + FColors.Free; + inherited Destroy; +end; + +procedure TJvNavPanelButton.ActionChange(Sender: TObject; + CheckDefaults: Boolean); +begin + if Sender is TCustomAction then + with TCustomAction(Sender) do + begin + if not CheckDefaults or (Self.Caption = '') or (Self.Caption = Self.Name) then + Self.Caption := Caption; + if not CheckDefaults or Self.Enabled then + Self.Enabled := Enabled; + if not CheckDefaults or (Self.Hint = '') then + Self.Hint := Hint; + if not CheckDefaults or (Self.ImageIndex = -1) then + Self.ImageIndex := ImageIndex; + if not CheckDefaults or Self.Visible then + Self.Visible := Visible; + if not CheckDefaults or not Assigned(Self.OnClick) then + Self.OnClick := OnExecute; + end; +end; + +procedure TJvNavPanelButton.DoColorsChange(Sender: TObject); +begin + Invalidate; +end; + +procedure TJvNavPanelButton.DoStyleChange(Sender: TObject); +begin + Colors := (Sender as TJvNavPaneStyleManager).Colors; + Font := (Sender as TJvNavPaneStyleManager).Fonts.NavPanelFont; + HotTrackFont := (Sender as TJvNavPaneStyleManager).Fonts.NavPanelHotTrackFont; + HotTrackFontOptions := (Sender as TJvNavPaneStyleManager).Fonts.NavPanelHotTrackFontOptions; +end; + +procedure TJvNavPanelButton.FontChanged; +begin + inherited FontChanged; + Invalidate; +end; + +procedure TJvNavPanelButton.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if Operation = opRemove then + begin + if AComponent = StyleManager then + StyleManager := nil; + end; +end; + +procedure TJvNavPanelButton.PaintButton(ACanvas:TCanvas); +//const +// cAlignment: array [TAlignment] of Cardinal = (DT_LEFT, DT_RIGHT, DT_CENTER); +// cWordWrap: array [Boolean] of Cardinal = (DT_SINGLELINE, DT_WORDBREAK); +var + R: TRect; + X, Y: Integer; + + function IsValidImage: Boolean; + begin + Result := Assigned(Images) and (ImageIndex >= 0); + end; + +begin + R := ClientRect; + if HotTrack and (bsMouseInside in MouseStates) then + begin + if bsMouseDown in MouseStates then + GradientFillRect(ACanvas, R, Colors.ButtonSelectedColorTo, Colors.ButtonSelectedColorFrom, fdTopToBottom, 32) + else + GradientFillRect(ACanvas, R, Colors.ButtonHotColorFrom, Colors.ButtonHotColorTo, fdTopToBottom, 32); + end + else + if Down then + GradientFillRect(ACanvas, R, Colors.ButtonSelectedColorFrom, Colors.ButtonSelectedColorTo, fdTopToBottom, 32) + else + if bsMouseDown in MouseStates then + GradientFillRect(ACanvas, R, Colors.ButtonSelectedColorTo, Colors.ButtonSelectedColorFrom, fdTopToBottom, 32) + else + GradientFillRect(ACanvas, ClientRect, Colors.ButtonColorFrom, Colors.ButtonColorTo, fdTopToBottom, 32); + InflateRect(R, -4, -4); + if IsValidImage then + begin + Y := (Height - Images.Height) div 2; + X := 4; + Images.Draw(ACanvas, X, Y, ImageIndex); + Inc(R.Left, Images.Width + 4); + end; + if Caption <> '' then + begin + if HotTrack and (bsMouseInside in MouseStates) and not (bsMouseDown in MouseStates) then + ACanvas.Font := HotTrackFont + else + ACanvas.Font := Font; + SetBkMode(ACanvas.Handle, TRANSPARENT); + DrawText(ACanvas, Caption, Length(Caption), R, DT_SINGLELINE or DT_VCENTER); + end; + if Colors.ButtonSeparatorColor <> clNone then + begin + ACanvas.Pen.Color := Colors.ButtonSeparatorColor; + if Align = alBottom then + begin + ACanvas.MoveTo(0, 0); + ACanvas.LineTo(Width + 1, 0); + end + else + begin + ACanvas.MoveTo(0, ClientHeight - 1); + ACanvas.LineTo(Width + 1, ClientHeight - 1); + end; + end; +end; + +procedure TJvNavPanelButton.SetColors(const Value: TJvNavPanelColors); +begin + FColors.Assign(Value); +end; + +procedure TJvNavPanelButton.SetStyleManager(const Value: TJvNavPaneStyleManager); +begin + if FStyleManager <> Value then + begin + ParentStyleManager := False; + if FStyleManager <> nil then + FStyleManager.UnregisterChanges(FStyleLink); + FStyleManager := Value; + if FStyleManager <> nil then + begin + FStyleManager.RegisterChanges(FStyleLink); + FStyleManager.FreeNotification(Self); + Colors := FStyleManager.Colors; + end; + end; +end; + +procedure TJvNavPanelButton.SetImageIndex(const Value: TImageIndex); +begin + if FImageIndex <> Value then + begin + FImageIndex := Value; + Invalidate; + end; +end; + +procedure TJvNavPanelButton.SetImages(const Value: TCustomImageList); +begin + if FImages <> Value then + begin + FImages := Value; + Invalidate; + end; +end; + +procedure TJvNavPanelButton.TextChanged; +begin + inherited TextChanged; + Invalidate; +end; + +procedure TJvNavPanelButton.SetAlignment(const Value: TAlignment); +begin + if FAlignment <> Value then + begin + FAlignment := Value; + Invalidate; + end; +end; + +procedure TJvNavPanelButton.SetWordWrap(const Value: Boolean); +begin + if FWordWrap <> Value then + begin + FWordWrap := Value; + Invalidate; + end; +end; + + +procedure TJvNavPanelButton.CMDialogChar(var Msg: TCMDialogChar); +begin + if IsAccel(Msg.CharCode, Caption) then + begin + Msg.Result := 1; + Click; + end + else + inherited; +end; + +procedure TJvNavPanelButton.ParentStyleManagerChanged( + var Msg: TMsgStyleManagerChange); +begin + if (Msg.Sender <> Self) and ParentStyleManager then + begin + StyleManager := Msg.StyleManager; + ParentStyleManager := True; + end; +end; + +procedure TJvNavPanelButton.SetParentStyleManager(const Value: Boolean); +begin + if FParentStyleManager <> Value then + begin + FParentStyleManager := Value; + if FParentStyleManager and (Parent <> nil) then + Parent.Perform(CM_PARENTSTYLEMANAGERCHANGE, 0, 0); + end; +end; + +function TJvNavPanelButton.IsColorsStored: Boolean; +begin + Result := (StyleManager = nil) or (StyleManager.Theme = nptCustom); +end; + +//=== { TJvNavPanelColors } ================================================== + +constructor TJvNavPanelColors.Create; +begin + inherited Create; + // use XPBlue as standard + FButtonColorFrom := TColor($F7E2CD); + FButtonColorTo := TColor($F3A080); + FButtonSelectedColorFrom := TColor($BBE2EA); + FButtonSelectedColorTo := TColor($389FDD); + FFrameColor := TColor($6F2F0C); + FButtonHotColorFrom := TColor($DBFBFF); + FButtonHotColorTo := TColor($5FC8FB); + FDividerColorFrom := TColor($FFDBBC); + FDividerColorTo := TColor($F2C0A4); + FHeaderColorFrom := TColor($D0835C); + FHeaderColorTo := TColor($903B09); + FSplitterColorFrom := TColor($B78676); + FSplitterColorTo := TColor($A03D09); + FButtonSeparatorColor := clGray; + FToolPanelColorFrom := clWindow; + FToolPanelColorTo := clWindow; + FToolPanelHeaderColorFrom := TColor($F7E2CD); + FToolPanelHeaderColorTo := TColor($F3A080); +end; + +procedure TJvNavPanelColors.Assign(Source: TPersistent); +begin + if (Source is TJvNavPanelColors) then + begin + if (Source <> Self) then + begin + FButtonColorFrom := TJvNavPanelColors(Source).ButtonColorFrom; + FButtonColorTo := TJvNavPanelColors(Source).ButtonColorTo; + FButtonHotColorFrom := TJvNavPanelColors(Source).ButtonHotColorFrom; + FButtonHotColorTo := TJvNavPanelColors(Source).ButtonHotColorTo; + FButtonSelectedColorFrom := TJvNavPanelColors(Source).ButtonSelectedColorFrom; + FButtonSelectedColorTo := TJvNavPanelColors(Source).ButtonSelectedColorTo; + FFrameColor := TJvNavPanelColors(Source).FrameColor; + FHeaderColorFrom := TJvNavPanelColors(Source).HeaderColorFrom; + FHeaderColorTo := TJvNavPanelColors(Source).HeaderColorTo; + FDividerColorFrom := TJvNavPanelColors(Source).DividerColorFrom; + FDividerColorTo := TJvNavPanelColors(Source).DividerColorTo; + FSplitterColorFrom := TJvNavPanelColors(Source).SplitterColorFrom; + FSplitterColorTo := TJvNavPanelColors(Source).SplitterColorTo; + FButtonSeparatorColor := TJvNavPanelColors(Source).ButtonSeparatorColor; + FToolPanelColorFrom := TJvNavPanelColors(Source).ToolPanelColorFrom; + FToolPanelColorTo := TJvNavPanelColors(Source).ToolPanelColorTo; + FToolPanelHeaderColorFrom := TJvNavPanelColors(Source).ToolPanelHeaderColorFrom; + FToolPanelHeaderColorTo := TJvNavPanelColors(Source).ToolPanelHeaderColorTo; + Change; + end; + end + else + inherited Assign(Source); +end; + +procedure TJvNavPanelColors.Change; +begin + if Assigned(FOnChange) then + FOnChange(Self); +end; + +procedure TJvNavPanelColors.SetButtonColorFrom(const Value: TColor); +begin + if FButtonColorFrom <> Value then + begin + FButtonColorFrom := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetButtonColorTo(const Value: TColor); +begin + if FButtonColorTo <> Value then + begin + FButtonColorTo := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetDividerColorFrom(const Value: TColor); +begin + if FDividerColorFrom <> Value then + begin + FDividerColorFrom := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetDividerColorTo(const Value: TColor); +begin + if FDividerColorTo <> Value then + begin + FDividerColorTo := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetFrameColor(const Value: TColor); +begin + if FFrameColor <> Value then + begin + FFrameColor := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetHeaderColorFrom(const Value: TColor); +begin + if FHeaderColorFrom <> Value then + begin + FHeaderColorFrom := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetHeaderColorTo(const Value: TColor); +begin + if FHeaderColorTo <> Value then + begin + FHeaderColorTo := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetButtonHotColorFrom(const Value: TColor); +begin + if FButtonHotColorFrom <> Value then + begin + FButtonHotColorFrom := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetButtonHotColorTo(const Value: TColor); +begin + if FButtonHotColorTo <> Value then + begin + FButtonHotColorTo := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetButtonSelectedColorFrom(const Value: TColor); +begin + if FButtonSelectedColorFrom <> Value then + begin + FButtonSelectedColorFrom := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetButtonSelectedColorTo(const Value: TColor); +begin + if FButtonSelectedColorTo <> Value then + begin + FButtonSelectedColorTo := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetSplitterColorFrom(const Value: TColor); +begin + if FSplitterColorFrom <> Value then + begin + FSplitterColorFrom := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetSplitterColorTo(const Value: TColor); +begin + if FSplitterColorTo <> Value then + begin + FSplitterColorTo := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetButtonSeparatorColor(const Value: TColor); +begin + if FButtonSeparatorColor <> Value then + begin + FButtonSeparatorColor := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetToolPanelColorFrom(const Value: TColor); +begin + if FToolPanelColorFrom <> Value then + begin + FToolPanelColorFrom := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetToolPanelColorTo(const Value: TColor); +begin + if FToolPanelColorTo <> Value then + begin + FToolPanelColorTo := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetToolPanelHeaderColorFrom( + const Value: TColor); +begin + if FToolPanelHeaderColorFrom <> Value then + begin + FToolPanelHeaderColorFrom := Value; + Change; + end; +end; + +procedure TJvNavPanelColors.SetToolPanelHeaderColorTo(const Value: TColor); +begin + if FToolPanelHeaderColorTo <> Value then + begin + FToolPanelHeaderColorTo := Value; + Change; + end; +end; + +//=== { TJvNavPanelFonts } =================================================== + +constructor TJvNavPanelFonts.Create; +begin + inherited Create; + FDividerFont := TFont.Create; + FNavPanelFont := TFont.Create; + FNavPanelHotTrackFont := TFont.Create; + FHeaderFont := TFont.Create; + FHeaderFont.Name := 'Arial'; + FHeaderFont.Size := 12; + FHeaderFont.Style := [fsBold]; + FHeaderFont.Color := clWhite; + FHeaderFont.OnChange := @DoFontChange; + + //TODO: + //FDividerFont.Assign(Screen.IconFont); + //FNavPanelFont.Assign(Screen.IconFont); + + FNavPanelFont.Style := [fsBold]; + FNavPanelHotTrackFont.Assign(FNavPanelFont); + FNavPanelHotTrackFontOptions := DefaultTrackFontOptions; + + FDividerFont.OnChange := @DoFontChange; + FNavPanelFont.OnChange := @DoFontChange; + FNavPanelHotTrackFont.OnChange := @DoFontChange; +end; + +destructor TJvNavPanelFonts.Destroy; +begin + FDividerFont.Free; + FHeaderFont.Free; + FNavPanelFont.Free; + FNavPanelHotTrackFont.Free; + inherited Destroy; +end; + +procedure TJvNavPanelFonts.Assign(Source: TPersistent); +begin + if Source is TJvNavPanelFonts then + begin + if Source <> Self then + begin + NavPanelFont := TJvNavPanelFonts(Source).NavPanelFont; + DividerFont := TJvNavPanelFonts(Source).DividerFont; + HeaderFont := TJvNavPanelFonts(Source).HeaderFont; + end; + end + else + inherited Assign(Source); +end; + +procedure TJvNavPanelFonts.Change; +begin + if Assigned(FOnChange) then + FOnChange(Self); +end; + +procedure TJvNavPanelFonts.DoFontChange(Sender: TObject); +begin + Change; +end; + +procedure TJvNavPanelFonts.SetDividerFont(const Value: TFont); +begin + FDividerFont.Assign(Value); +end; + +procedure TJvNavPanelFonts.SetHeaderFont(const Value: TFont); +begin + FHeaderFont.Assign(Value); +end; + +procedure TJvNavPanelFonts.SetNavPanelFont(const Value: TFont); +begin + FNavPanelFont.Assign(Value); +end; + +procedure TJvNavPanelFonts.SetNavPanelHotTrackFont(const Value: TFont); +begin + FNavPanelHotTrackFont.Assign(Value); +end; + +procedure TJvNavPanelFonts.SetNavPanelHotTrackFontOptions(const Value: TJvTrackFontOptions); +begin + if FNavPanelHotTrackFontOptions <> Value then + begin + FNavPanelHotTrackFontOptions := Value; + Change; + end; +end; + +//=== { TJvNavPanelPage } ==================================================== + +constructor TJvNavPanelPage.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FBackground := TJvNavPaneBackgroundImage.Create; + FBackground.OnChange := @DoBackgroundChange; + ParentColor := False; + Color := clWindow; + ControlStyle := ControlStyle + [csDisplayDragImage]; + FStyleLink := TJvNavStyleLink.Create; + FStyleLink.OnChange := @DoStyleChange; + FNavPanel := TJvNavPanelButton.Create(Self); + FNavPanel.Visible := True; + FNavPanel.Align := alBottom; + FNavPanel.GroupIndex := cNavPanelButtonGroupIndex; // use a silly number that no one else is probable to use + FNavPanel.AllowAllUp := False; + FIconButton := TJvNavIconButton.Create(Self); + FIconButton.ButtonType := nibImage; + FIconButton.Visible := False; + FIconButton.Align := alRight; + FIconButton.Width := 0; + FIconButton.GroupIndex := cNavPanelButtonGroupIndex; + FIconButton.AllowAllUp := False; + FNavPanel.OnClick := @DoButtonClick; + FIconButton.OnClick := @DoButtonClick; + ImageIndex := -1; + FParentStyleManager := True; +end; + +destructor TJvNavPanelPage.Destroy; +begin + FStyleLink.Free; + FBackground.Free; + inherited Destroy; +end; + +type + TJvCustomGraphicButtonAccess = class(TJvCustomGraphicButton) + public + property Down; + end; + +procedure TJvNavPanelPage.DoButtonClick(Sender: TObject); +begin + { We cannot test for NavPanel.Down if the Sender is a icon button } + if (Sender is TJvCustomGraphicButton) and TJvCustomGraphicButtonAccess(Sender).Down then + begin + if Parent <> nil then + TJvCustomNavigationPane(Parent).ActivePage := Self; // this sets "Down" as well + if Assigned(FOnClick) then + FOnClick(Self); + end; +end; + +procedure TJvNavPanelPage.DoStyleChange(Sender: TObject); +begin + Colors := (Sender as TJvNavPaneStyleManager).Colors; + NavPanel.Font := (Sender as TJvNavPaneStyleManager).Fonts.NavPanelFont; + NavPanel.HotTrackFont := (Sender as TJvNavPaneStyleManager).Fonts.NavPanelHotTrackFont; + NavPanel.HotTrackFontOptions := (Sender as TJvNavPaneStyleManager).Fonts.NavPanelHotTrackFontOptions; +end; + +function TJvNavPanelPage.GetCaption: TCaption; +begin + if NavPanel = nil then + Result := '' + else + Result := NavPanel.Caption; +end; + +function TJvNavPanelPage.GetColors: TJvNavPanelColors; +begin + Result := NavPanel.Colors; +end; + +function TJvNavPanelPage.GetHint: string; +begin + if NavPanel = nil then + Result := '' + else + Result := NavPanel.Hint; +end; + +function TJvNavPanelPage.GetIconic: Boolean; +begin + if NavPanel = nil then + Result := False + else + Result := not NavPanel.Visible; +end; + +function TJvNavPanelPage.GetImageIndex: TImageIndex; +begin + if NavPanel = nil then + Result := FImageIndex + else + Result := NavPanel.ImageIndex; +end; + +procedure TJvNavPanelPage.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if Operation = opRemove then + begin + if AComponent = IconPanel then + IconPanel := nil + else + if AComponent = StyleManager then + StyleManager := nil; + end; +end; + +procedure TJvNavPanelPage.SetCaption(const Value: TCaption); +begin + if NavPanel <> nil then + NavPanel.Caption := Value; + // TODO: StripHotkey + (* + if AutoHeader then + Header.Caption := StripHotkey(Value); + *) +end; + +procedure TJvNavPanelPage.SetColors(const Value: TJvNavPanelColors); +begin + NavPanel.Colors := Value; + IconButton.Colors := Value; + if AutoHeader then + begin + Header.ColorFrom := Value.HeaderColorFrom; + Header.ColorTo := Value.HeaderColorTo; + end; +end; + +procedure TJvNavPanelPage.SetStyleManager(const Value: TJvNavPaneStyleManager); +begin + if FStyleManager <> Value then + begin + ParentStyleManager := False; + if FStyleManager <> nil then + FStyleManager.UnregisterChanges(FStyleLink); + FStyleManager := Value; + if FStyleManager <> nil then + begin + FStyleManager.RegisterChanges(FStyleLink); + FStyleManager.FreeNotification(Self); + Colors := FStyleManager.Colors; + end; + end; + // FNavPanel.StyleManager := Value; + // FIconButton.StyleManager := Value; + // if AutoHeader then + // Header.StyleManager := Value; +end; + +procedure TJvNavPanelPage.SetHint(const Value: string); +begin + NavPanel.Hint := Value; + IconButton.Hint := Value; +end; + +procedure TJvNavPanelPage.SetIconic(const Value: Boolean); +begin + NavPanel.Visible := not Value; + IconButton.Visible := Value; + NavPanel.Height := TJvCustomNavigationPane(Parent).ButtonHeight * Ord(NavPanel.Visible); + IconButton.Width := TJvCustomNavigationPane(Parent).ButtonWidth * Ord(IconButton.Visible); + UpdatePageList; +end; + +procedure TJvNavPanelPage.SetIconPanel(const Value: TJvIconPanel); +begin + if (FIconPanel <> Value) and not (csDestroying in ComponentState) then + begin + FIconPanel := Value; + if IconButton <> nil then + begin + if FIconPanel <> nil then + begin + IconButton.Parent := FIconPanel; + FIconPanel.FreeNotification(Self); + end + else + IconButton.Parent := nil; + end; + end; +end; + +procedure TJvNavPanelPage.SetImageIndex(const Value: TImageIndex); +begin + FImageIndex := Value; + NavPanel.ImageIndex := Value; + IconButton.ImageIndex := Value; + if AutoHeader then + Header.ImageIndex := Value; +end; + +procedure TJvNavPanelPage.SetPageIndex(Value: Integer); +begin + inherited SetPageIndex(Value); + UpdatePageList; +end; + +procedure TJvNavPanelPage.SetParent( AParent: TWinControl); +begin + inherited SetParent(AParent); + if (FNavPanel = nil) or (FIconButton = nil) or (csDestroying in ComponentState) then + Exit; + NavPanel.Parent := AParent; + if AParent is TJvCustomNavigationPane then + begin + IconPanel := TJvCustomNavigationPane(AParent).FIconPanel; + // StyleManager := TJvCustomNavigationPane(AParent).StyleManager; + + NavPanel.Colors := TJvCustomNavigationPane(AParent).Colors; + NavPanel.StyleManager := StyleManager; + NavPanel.Height := TJvCustomNavigationPane(AParent).ButtonHeight; + NavPanel.Images := TJvCustomNavigationPane(AParent).LargeImages; + NavPanel.Font := TJvCustomNavigationPane(AParent).NavPanelFont; + NavPanel.HotTrackFont := TJvCustomNavigationPane(AParent).NavPanelHotTrackFont; + NavPanel.HotTrackFontOptions := TJvCustomNavigationPane(AParent).NavPanelHotTrackFontOptions; + + IconButton.Images := TJvCustomNavigationPane(AParent).SmallImages; + IconButton.Width := TJvCustomNavigationPane(AParent).ButtonWidth; + AutoHeader := TJvCustomNavigationPane(AParent).AutoHeaders; + end + else + IconButton.Parent := nil; +end; + +procedure TJvNavPanelPage.UpdatePageList; +begin + if PageList <> nil then + TJvCustomNavigationPane(PageList).UpdatePositions; +end; + +procedure TJvNavPanelPage.SetAutoHeader(const Value: Boolean); +begin + if AutoHeader <> Value then + begin + FreeAndNil(FHeader); + if Value then + begin + FHeader := TJvNavPanelHeader.Create(nil); + FHeader.ColorFrom := Colors.HeaderColorFrom; + FHeader.ColorTo := Colors.HeaderColorTo; + FHeader.Images := NavPanel.Images; + FHeader.ImageIndex := ImageIndex; + //TODO: StripHotkey + //FHeader.Caption := StripHotkey(Caption); + FHeader.Caption := Caption; + // make sure header is top-most + FHeader.Top := -10; + FHeader.Parent := Self; + FHeader.Align := alTop; + FHeader.Alignment := Alignment; + FHeader.WordWrap := WordWrap; + end; + end; +end; + +function TJvNavPanelPage.GetAutoHeader: Boolean; +begin + Result := FHeader <> nil; +end; + +function TJvNavPanelPage.GetAlignment: TAlignment; +begin + if NavPanel <> nil then + Result := NavPanel.Alignment + else + Result := taLeftJustify; +end; + +function TJvNavPanelPage.GetWordWrap: Boolean; +begin + if NavPanel <> nil then + Result := NavPanel.WordWrap + else + Result := False; +end; + +procedure TJvNavPanelPage.SetAlignment(const Value: TAlignment); +begin + if NavPanel <> nil then + NavPanel.Alignment := Value; + if AutoHeader then + Header.Alignment := Value; +end; + +procedure TJvNavPanelPage.SetWordWrap(const Value: Boolean); +begin + if NavPanel <> nil then + NavPanel.WordWrap := Value; + if AutoHeader then + Header.WordWrap := Value; +end; + +procedure TJvNavPanelPage.ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); +begin + if (Msg.Sender <> Self) and ParentStyleManager then + begin + StyleManager := Msg.StyleManager; + ParentStyleManager := True; + InternalStyleManagerChanged(Self, Msg.StyleManager); + end; +end; + +procedure TJvNavPanelPage.SetParentStyleManager(const Value: Boolean); +begin + if FParentStyleManager <> Value then + begin + FParentStyleManager := Value; + if FParentStyleManager and (Parent <> nil) then + Parent.Perform(CM_PARENTSTYLEMANAGERCHANGE, 0, 0); + end; +end; + +procedure TJvNavPanelPage.CMControlChange(var Msg: TLMessage); +begin + InternalStyleManagerChanged(Self, StyleManager); +end; + +procedure TJvNavPanelPage.ParentStyleManagerChange(var Msg: TLMessage); +begin + InternalStyleManagerChanged(Self, StyleManager); +end; + +procedure TJvNavPanelPage.SetBackground(const Value: TJvNavPaneBackgroundImage); +begin + FBackground.Assign(Value); +end; + +procedure TJvNavPanelPage.DoBackgroundChange(Sender: TObject); +begin + Invalidate; +end; + +procedure TJvNavPanelPage.Paint; +begin + inherited Paint; + if FBackground.HasImage then + FBackground.DrawImage(Canvas, ClientRect) + else + if (Parent is TJvCustomNavigationPane) and TJvCustomNavigationPane(Parent).Background.HasImage then + TJvCustomNavigationPane(Parent).Background.DrawImage(Canvas, ClientRect); +end; + +function TJvNavPanelPage.GetAction: TBasicAction; +begin + Result := inherited GetAction; +end; + +procedure TJvNavPanelPage.SetAction(const Value: TBasicAction); +begin + inherited Action := Value; + FNavPanel.Action := Value; + FIconButton.Action := Value; +end; + +procedure TJvNavPanelPage.ActionChange(Sender: TObject; + CheckDefaults: Boolean); +begin + if Sender is TCustomAction then + with TCustomAction(Sender) do + begin + if not CheckDefaults or (Self.Caption = '') or (Self.Caption = Self.Name) then + Self.Caption := Caption; + if not CheckDefaults or Self.Enabled then + Self.Enabled := Enabled; // NB! This disables resizing if the top-most button is disabled (due to TSplitter.FindControl) + if not CheckDefaults or (Self.Hint = '') then + Self.Hint := Hint; + if not CheckDefaults or (Self.ImageIndex = -1) then + Self.ImageIndex := ImageIndex; + if not CheckDefaults or Self.Visible then + Self.Visible := Visible; + if not CheckDefaults or not Assigned(Self.OnClick) then + Self.OnClick := OnExecute; + end; +end; + +//=== { TJvOutlookSplitter } ================================================= + +constructor TJvOutlookSplitter.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + ControlStyle := ControlStyle + [csOpaque]; + FStyleLink := TJvNavStyleLink.Create; + FStyleLink.OnChange := @DoStyleChange; + FColorFrom := TColor($B78676); + FColorTo := TColor($A03D09); + Align := alBottom; + AutoSnap := False; + ResizeStyle := rsUpdate; + Height := 7; + Cursor := crSizeNS; + FParentStyleManager := True; +end; + +destructor TJvOutlookSplitter.Destroy; +begin + FStyleLink.Free; + FStyleLink := nil; + inherited Destroy; +end; + +procedure TJvOutlookSplitter.EnabledChanged; +begin + inherited EnabledChanged; + Invalidate; +end; + +procedure TJvOutlookSplitter.DoStyleChange(Sender: TObject); +begin + with (Sender as TJvNavPaneStyleManager).Colors do + begin + FColorFrom := SplitterColorFrom; + FColorTo := SplitterColorTo; + Invalidate; + end; +end; + +procedure TJvOutlookSplitter.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if Operation = opRemove then + if AComponent = StyleManager then + StyleManager := nil; +end; + +procedure TJvOutlookSplitter.Paint; +var + I: Integer; + R: TRect; +begin + R := ClientRect; + if Align in [alTop, alBottom] then + begin + GradientFillRect(Canvas, R, ColorFrom, ColorTo, fdTopToBottom, R.Bottom - R.Top); + Inc(R.Left, (R.Right - R.Left) div 2 - 20); + Inc(R.Top, (R.Bottom - R.Top) div 2 - 1); + R.Right := R.Left + 2; + R.Bottom := R.Top + 2; + if Enabled then + for I := 0 to 9 do // draw the dots + begin + Canvas.Brush.Color := cl3DDkShadow; + Canvas.FillRect(R); + OffsetRect(R, 1, 1); + Canvas.Brush.Color := clWhite; + Canvas.FillRect(R); + Canvas.Brush.Color := ColorFrom; // (p3) this is probably not the right color, but it's close enough for me... + Canvas.FillRect(Rect(R.Left, R.Top, R.Left + 1, R.Top + 1)); + OffsetRect(R, 3, -1); + end; + end + else + begin + GradientFillRect(Canvas, R, ColorFrom, ColorTo, fdLeftToRight, R.Right - R.Left); + Inc(R.Top, (R.Bottom - R.Top) div 2 - 20); + Inc(R.Left, (R.Right - R.Left) div 2 - 1); + R.Right := R.Left + 2; + R.Bottom := R.Top + 2; + if Enabled then + for I := 0 to 9 do // draw the dots + begin + Canvas.Brush.Color := cl3DDkShadow; + Canvas.FillRect(R); + OffsetRect(R, 1, 1); + Canvas.Brush.Color := clWhite; + Canvas.FillRect(R); + Canvas.Brush.Color := ColorFrom; + Canvas.FillRect(Rect(R.Left, R.Top, R.Left + 1, R.Top + 1)); + OffsetRect(R, -1, 3); + end; + end; +end; + +procedure TJvOutlookSplitter.SetColorFrom(const Value: TColor); +begin + if FColorFrom <> Value then + begin + FColorFrom := Value; + Invalidate; + end; +end; + +procedure TJvOutlookSplitter.SetStyleManager(const Value: TJvNavPaneStyleManager); +begin + if FStyleManager <> Value then + begin + ParentStyleManager := False; + if FStyleManager <> nil then + FStyleManager.UnregisterChanges(FStyleLink); + FStyleManager := Value; + if FStyleManager <> nil then + begin + FStyleManager.RegisterChanges(FStyleLink); + FStyleManager.FreeNotification(Self); + ColorFrom := FStyleManager.Colors.SplitterColorFrom; + ColorTo := FStyleManager.Colors.SplitterColorTo; + end; + end; +end; + +procedure TJvOutlookSplitter.SetColorTo(const Value: TColor); +begin + if FColorTo <> Value then + begin + FColorTo := Value; + Invalidate; + end; +end; + +procedure TJvOutlookSplitter.ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); +begin + if (Msg.Sender <> Self) and ParentStyleManager then + begin + StyleManager := Msg.StyleManager; + ParentStyleManager := True; + end; +end; + +procedure TJvOutlookSplitter.SetParentStyleManager(const Value: Boolean); +begin + if FParentStyleManager <> Value then + begin + FParentStyleManager := Value; + if FParentStyleManager and (Parent <> nil) then + Parent.Perform(CM_PARENTSTYLEMANAGERCHANGE, 0, 0); + end; +end; + +function TJvOutlookSplitter.GetDragZoneRect: TRect; +begin + Result := ClientRect; + if DragZone <> 0 then + begin + if Align in [alLeft, alRight] then + begin + if DragZone < RectHeight(Result) then + begin + Result.Top := (RectHeight(Result) - DragZone) div 2; + Result.Bottom := Result.Top + DragZone; + end; + end + else + if Align in [alTop, alBottom] then + begin + if DragZone < RectWidth(Result) then + begin + Result.Left := (RectWidth(Result) - DragZone) div 2; + Result.Right := Result.Left + DragZone; + end; + end; + end; +end; + +function TJvOutlookSplitter.MouseInDragZone(X, Y: Integer): Boolean; +begin + Result := (DragZone <= 0) or PtInRect(GetDragZoneRect, Point(X, Y)); +end; + +procedure TJvOutlookSplitter.WMLButtonDown(var Msg: TLMLButtonDown); +begin + if MouseInDragZone(Msg.XPos, Msg.YPos) then + inherited; +end; + +procedure TJvOutlookSplitter.WMMouseMove(var Msg: TLMMouseMove); +begin + inherited; + if MouseInDragZone(Msg.XPos, Msg.YPos) then + begin + if Cursor <> FOldCursor then + inherited Cursor := FOldCursor; + end + else + begin + if Cursor <> crDefault then + begin + FOldCursor := Cursor; + inherited Cursor := crDefault; + end; + end; +end; + +procedure TJvOutlookSplitter.SetCursor(const Value: TCursor); +begin + inherited Cursor := Value; + FOldCursor := Value; +end; + +procedure TJvOutlookSplitter.RequestAlign; +begin + if (Cursor = crSizeWE) or (Cursor = crSizeNS) then + begin + if Align in [alLeft, alRight] then + Cursor := crSizeWE + else + Cursor := crSizeNS; + end; +end; + +//=== { TJvNavPanelHeader } ================================================== + +constructor TJvNavPanelHeader.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FChangeLink := TChangeLink.Create; + FChangeLink.OnChange := @DoImagesChange; + FStyleLink := TJvNavStyleLink.Create; + FStyleLink.OnChange := @DoStyleChange; + ControlStyle := ControlStyle + [csOpaque, csAcceptsControls]; + FColorFrom := TColor($D0835C); + FColorTo := TColor($903B09); + Font.Name := 'Arial'; + Font.Size := 12; + Font.Style := [fsBold]; + Font.Color := clWhite; + Height := 27; + Width := 225; + FParentStyleManager := True; +end; + +destructor TJvNavPanelHeader.Destroy; +begin + FChangeLink.Free; + FStyleLink.Free; + inherited Destroy; +end; + +procedure TJvNavPanelHeader.DoImagesChange(Sender: TObject); +begin + Invalidate; +end; + +procedure TJvNavPanelHeader.DoStyleChange(Sender: TObject); +begin + Font := (Sender as TJvNavPaneStyleManager).Fonts.HeaderFont; + with (Sender as TJvNavPaneStyleManager).Colors do + begin + FColorFrom := HeaderColorFrom; + FColorTo := HeaderColorTo; + Invalidate; + end; +end; + +procedure TJvNavPanelHeader.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if Operation = opRemove then + if AComponent = Images then + Images := nil + else + if AComponent = StyleManager then + StyleManager := nil; +end; + +procedure TJvNavPanelHeader.Paint; +const + cAlignment: array[TAlignment] of Cardinal = (DT_LEFT, DT_RIGHT, DT_CENTER); + cWordWrap: array[Boolean] of Cardinal = (DT_SINGLELINE, DT_WORDBREAK); +var + R, TempRect: TRect; + X, Y, H: Integer; + + function IsValidImage: Boolean; + begin + Result := (Images <> nil) and (ImageIndex >= 0) and (ImageIndex < Images.Count); + end; + +begin + R := ClientRect; + GradientFillRect(Canvas, R, ColorFrom, ColorTo, fdTopToBottom, 32); + H := Canvas.TextHeight(Caption); + if Caption <> '' then + begin + Canvas.Font := Font; + InflateRect(R, -4, 0); + SetBkMode(Canvas.Handle, TRANSPARENT); + TempRect := R; + DrawText(Canvas, Caption, Length(Caption), TempRect, + DT_CALCRECT or cAlignment[Alignment] or cWordWrap[WordWrap] or DT_VCENTER or DT_NOPREFIX or DT_END_ELLIPSIS); + if WordWrap then + OffsetRect(R, 0, (Height - H) div 2); + if IsValidImage and (Alignment = taCenter) then + OffsetRect(R, 0, -Images.Height div 2); + DrawText(Canvas, Caption, Length(Caption), R, + cAlignment[Alignment] or cWordWrap[WordWrap] or DT_VCENTER or DT_NOPREFIX or DT_END_ELLIPSIS); + end; + if IsValidImage then + begin + Y := (Height - Images.Height) div 2; + case Alignment of + taLeftJustify: + X := R.Right - Images.Width; + taRightJustify: + X := R.Left + 4; + else // taCenter + begin + if Caption <> '' then + begin + if WordWrap then + Y := R.Top + H + 4 + else + Y := (Height + Canvas.TextHeight('Wq')) div 2 + 4; + end; + X := (Width - Images.Width) div 2; + end; + end; + if Y > Height - Images.Height - 4 then + Y := Height - Images.Height - 4; + Images.Draw(Canvas, X, Y, ImageIndex, True); + end; +end; + +procedure TJvNavPanelHeader.SetColorFrom(const Value: TColor); +begin + if FColorFrom <> Value then + begin + FColorFrom := Value; + Invalidate; + end; +end; + +procedure TJvNavPanelHeader.SetStyleManager(const Value: TJvNavPaneStyleManager); +begin + if FStyleManager <> Value then + begin + ParentStyleManager := False; + if FStyleManager <> nil then + FStyleManager.UnregisterChanges(FStyleLink); + FStyleManager := Value; + if FStyleManager <> nil then + begin + FStyleManager.RegisterChanges(FStyleLink); + FStyleManager.FreeNotification(Self); + FColorFrom := FStyleManager.Colors.HeaderColorFrom; + FColorTo := FStyleManager.Colors.HeaderColorTo; + Font := FStyleManager.Fonts.HeaderFont; + Invalidate; + end; + InternalStyleManagerChanged(Self, Value); + end; +end; + +procedure TJvNavPanelHeader.SetColorTo(const Value: TColor); +begin + if FColorTo <> Value then + begin + FColorTo := Value; + Invalidate; + end; +end; + +procedure TJvNavPanelHeader.SetImageIndex(const Value: TImageIndex); +begin + if FImageIndex <> Value then + begin + FImageIndex := Value; + Invalidate; + end; +end; + +procedure TJvNavPanelHeader.SetImages(const Value: TCustomImageList); +begin + if FImages <> Value then + begin + if FImages <> nil then + FImages.UnregisterChanges(FChangeLink); + FImages := Value; + if FImages <> nil then + begin + FImages.RegisterChanges(FChangeLink); + FImages.FreeNotification(Self); + end; + Invalidate; + end; +end; + +procedure TJvNavPanelHeader.TextChanged; +begin + inherited TextChanged; + Invalidate; +end; + +procedure TJvNavPanelHeader.WMEraseBkgnd(var Msg: TLMEraseBkgnd); +begin + Msg.Result := 1; +end; + +procedure TJvNavPanelHeader.SetAlignment(const Value: TAlignment); +begin + if FAlignment <> Value then + begin + FAlignment := Value; + Invalidate; + end; +end; + +procedure TJvNavPanelHeader.SetWordWrap(const Value: Boolean); +begin + if FWordWrap <> Value then + begin + FWordWrap := Value; + Invalidate; + end; +end; + +procedure TJvNavPanelHeader.ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); +begin + if (Msg.Sender <> Self) and ParentStyleManager then + begin + StyleManager := Msg.StyleManager; + ParentStyleManager := True; + InternalStyleManagerChanged(Self, Msg.StyleManager); + end; +end; + +procedure TJvNavPanelHeader.ParentStyleManagerChange(var Msg: TLMessage); +begin + InternalStyleManagerChanged(Self, StyleManager); +end; + +procedure TJvNavPanelHeader.SetParentStyleManager(const Value: Boolean); +begin + if FParentStyleManager <> Value then + begin + FParentStyleManager := Value; + if FParentStyleManager and (Parent <> nil) then + Parent.Perform(CM_PARENTSTYLEMANAGERCHANGE, 0, 0); + end; +end; + +procedure TJvNavPanelHeader.CMControlChange(var Msg: TLMessage); +begin + // a control was inserted or removed + InternalStyleManagerChanged(Self, StyleManager); +end; + +//=== { TJvNavPanelDivider } ================================================= + +constructor TJvNavPanelDivider.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FAlignment := taLeftJustify; + FStyleLink := TJvNavStyleLink.Create; + FStyleLink.OnChange := @DoStyleChange; + Align := alNone; + AutoSnap := False; + ResizeStyle := rsUpdate; + ControlStyle := ControlStyle + [csOpaque]; + FColorFrom := TColor($FFDBBC); + FColorTo := TColor($F2C0A4); + FFrameColor := TColor($6F2F0C); + Cursor := crSizeNS; + //TODO: + //Font := Screen.IconFont; + Height := 19; + Width := 125; + FParentStyleManager := True; +end; + +// 25.09.2007 - SESS +// When align is assigned height is lost +procedure TJvNavPanelDivider.SetAlign(Value: TAlign); +var + SaveHeight: integer; +begin + SaveHeight := Height; + inherited SetAlign(Value); + Height := SaveHeight; +end; + +destructor TJvNavPanelDivider.Destroy; +begin + FStyleLink.Free; + FStyleLink := nil; + inherited Destroy; +end; + +procedure TJvNavPanelDivider.TextChanged; +begin + inherited TextChanged; + Invalidate; +end; + +procedure TJvNavPanelDivider.DoStyleChange(Sender: TObject); +begin + Font := (Sender as TJvNavPaneStyleManager).Fonts.DividerFont; + with (Sender as TJvNavPaneStyleManager).Colors do + begin + FColorFrom := DividerColorFrom; + FColorTo := DividerColorTo; + Self.FFrameColor := FrameColor; + Invalidate; + end; +end; + +procedure TJvNavPanelDivider.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if Operation = opRemove then + begin + if AComponent = StyleManager then + StyleManager := nil; + end; +end; + +procedure TJvNavPanelDivider.Paint; +const + cAlignment: array[TAlignment] of Cardinal = (DT_LEFT, DT_RIGHT, DT_CENTER); +var + R: TRect; +begin + R := ClientRect; + GradientFillRect(Canvas, R, ColorFrom, ColorTo, fdTopToBottom, 32); + if Caption <> '' then + begin + Canvas.Font := Font; + case Alignment of + taLeftJustify: + Inc(R.Left, 7); + taRightJustify: + Dec(R.Right, 7); + end; + SetBkMode(Canvas.Handle, TRANSPARENT); + DrawText(Canvas, Caption, Length(Caption), R, + DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX or DT_EDITCONTROL or cAlignment[Alignment]); + end; + Canvas.Pen.Color := FrameColor; + Canvas.MoveTo(0, ClientHeight - 1); + Canvas.LineTo(Width, ClientHeight - 1); +end; + +procedure TJvNavPanelDivider.SetColorFrom(const Value: TColor); +begin + if FColorFrom <> Value then + begin + FColorFrom := Value; + Invalidate; + end; +end; + +procedure TJvNavPanelDivider.SetStyleManager(const Value: TJvNavPaneStyleManager); +begin + if FStyleManager <> Value then + begin + ParentStyleManager := False; + if FStyleManager <> nil then + FStyleManager.UnregisterChanges(FStyleLink); + FStyleManager := Value; + if FStyleManager <> nil then + begin + FStyleManager.RegisterChanges(FStyleLink); + FStyleManager.FreeNotification(Self); + ColorFrom := FStyleManager.Colors.DividerColorFrom; + ColorTo := FStyleManager.Colors.DividerColorTo; + Font := FStyleManager.Fonts.DividerFont; + end; + end; +end; + +procedure TJvNavPanelDivider.SetColorTo(const Value: TColor); +begin + if FColorTo <> Value then + begin + FColorTo := Value; + Invalidate; + end; +end; + +procedure TJvNavPanelDivider.SetFrameColor(const Value: TColor); +begin + if FFrameColor <> Value then + begin + FFrameColor := Value; + Invalidate; + end; +end; + +procedure TJvNavPanelDivider.SetAlignment(const Value: TAlignment); +begin + if FAlignment <> Value then + begin + FAlignment := Value; + Invalidate; + end; +end; + +procedure TJvNavPanelDivider.ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); +begin + if (Msg.Sender <> Self) and ParentStyleManager then + begin + StyleManager := Msg.StyleManager; + ParentStyleManager := True; + end; +end; + +procedure TJvNavPanelDivider.SetParentStyleManager(const Value: Boolean); +begin + if FParentStyleManager <> Value then + begin + FParentStyleManager := Value; + if FParentStyleManager and (Parent <> nil) then + Parent.Perform(CM_PARENTSTYLEMANAGERCHANGE, 0, 0); + end; +end; + +procedure TJvNavPanelDivider.RequestAlign; +begin + if (Cursor = crSizeWE) or (Cursor = crSizeNS) then + begin + if Align in [alLeft, alRight] then + Cursor := crSizeWE + else + Cursor := crSizeNS; + end; +end; + +//=== { TJvNavPaneStyleManager } ============================================= + +constructor TJvNavPaneStyleManager.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FClients := TList.Create; + FColors := TJvNavPanelColors.Create; + FFonts := TJvNavPanelFonts.Create; + FColors.OnChange := @DoThemeChange; + FFonts.OnChange := @DoThemeChange; + FTheme := nptCustom; // (p3) required to trigger the change method + Theme := nptStandard; +end; + +destructor TJvNavPaneStyleManager.Destroy; +begin + while FClients.Count > 0 do + UnregisterChanges(TJvNavStyleLink(FClients.Last)); + FClients.Free; + FClients := nil; + FColors.Free; + FFonts.Free; + inherited Destroy; +end; + +procedure TJvNavPaneStyleManager.Assign(Source: TPersistent); +var + SourceColors: TJvNavPanelColors; + SourceFonts: TJvNavPanelFonts; +begin + SourceFonts := nil; + if Source is TJvNavPaneStyleManager then + begin + Theme := TJvNavPaneStyleManager(Source).Theme; + if Theme = nptCustom then + begin + SourceColors := TJvNavPaneStyleManager(Source).Colors; + SourceFonts := TJvNavPaneStyleManager(Source).Fonts; + end + else + Exit; + end + else + if Source is TJvIconPanel then + SourceColors := TJvIconPanel(Source).Colors + else + if Source is TJvNavIconButton then + SourceColors := TJvNavIconButton(Source).Colors + else + if Source is TJvNavPanelButton then + SourceColors := TJvNavPanelButton(Source).Colors + else + if Source is TJvNavPanelPage then + SourceColors := TJvNavPanelPage(Source).Colors + else + if Source is TJvCustomNavigationPane then + SourceColors := TJvCustomNavigationPane(Source).Colors + else + begin + inherited Assign(Source); + Exit; + end; + FColors.Assign(SourceColors); + if SourceFonts <> nil then + FFonts.Assign(SourceFonts); +end; + +procedure TJvNavPaneStyleManager.AssignTo(Dest: TPersistent); +var + DestColors: TJvNavPanelColors; + DestFonts: TJvNavPanelFonts; +begin + DestFonts := nil; + if Dest is TJvNavPaneStyleManager then + begin + TJvNavPaneStyleManager(Dest).Theme := Theme; + if Theme = nptCustom then + begin + DestColors := TJvNavPaneStyleManager(Dest).Colors; + DestFonts := TJvNavPaneStyleManager(Dest).Fonts; + end + else + Exit; + end + else + if Dest is TJvIconPanel then + DestColors := TJvIconPanel(Dest).Colors + else + if Dest is TJvNavIconButton then + DestColors := TJvNavIconButton(Dest).Colors + else + if Dest is TJvNavPanelButton then + DestColors := TJvNavPanelButton(Dest).Colors + else + if Dest is TJvNavPanelPage then + DestColors := TJvNavPanelPage(Dest).Colors + else + if Dest is TJvCustomNavigationPane then + DestColors := TJvCustomNavigationPane(Dest).Colors + else + begin + inherited AssignTo(Dest); + Exit; + end; + DestColors.Assign(Colors); + if DestFonts <> nil then + DestFonts.Assign(Fonts); +end; + +procedure TJvNavPaneStyleManager.Change; +var + I: Integer; +begin + if FClients <> nil then + for I := 0 to FClients.Count - 1 do + TJvNavStyleLink(FClients[I]).Change; + if Assigned(FOnThemeChange) then + FOnThemeChange(Self); +end; + +procedure TJvNavPaneStyleManager.DoThemeChange(Sender: TObject); +begin + Theme := nptCustom; + Change; +end; + +procedure TJvNavPaneStyleManager.RegisterChanges(Value: TJvNavStyleLink); +begin + Value.Sender := Self; + if FClients <> nil then + FClients.Add(Value); +end; + +procedure TJvNavPaneStyleManager.SetColors(const Value: TJvNavPanelColors); +begin + FColors.Assign(Value); +end; + +procedure TJvNavPaneStyleManager.SetFonts(const Value: TJvNavPanelFonts); +begin + FFonts.Assign(Value); +end; + +procedure TJvNavPaneStyleManager.SetTheme(const Value: TJvNavPanelTheme); +begin + if FTheme <> Value then + begin + FColors.OnChange := nil; + FFonts.OnChange := nil; + try + case Value of + nptStandard: + begin + FColors.ButtonColorFrom := TColor($FFFFFF); + FColors.ButtonColorTo := TColor($BDBEBD); + FColors.ButtonSelectedColorFrom := TColor($DECFCE); + FColors.ButtonSelectedColorTo := TColor($DECFCE); + FColors.FrameColor := TColor($848484); + FColors.ButtonHotColorFrom := TColor($C68284); + FColors.ButtonHotColorTo := TColor($C68284); + FColors.DividerColorFrom := TColor($EFF3EF); + FColors.DividerColorTo := TColor($C6C3C6); + FColors.HeaderColorFrom := TColor($848284); + FColors.HeaderColorTo := TColor($848284); + FColors.SplitterColorFrom := TColor($C6C3C6); + FColors.SplitterColorTo := TColor($8C8E8C); + FColors.ButtonSeparatorColor := clGray; + FColors.ToolPanelColorFrom := clWindow; + FColors.ToolPanelColorTo := clWindow; + FColors.ToolPanelHeaderColorFrom := TColor($FFFFFF); + FColors.ToolPanelHeaderColorTo := TColor($BDBEBD); + FFonts.HeaderFont.Color := clWindow; + FFonts.NavPanelFont.Color := clWindowText; + FFonts.NavPanelHotTrackFont.Color := clWindow; + FFonts.DividerFont.Color := clWindowText; + end; + nptXPBlue: + begin + FColors.ButtonColorFrom := TColor($F7E2CD); + FColors.ButtonColorTo := TColor($F3A080); + FColors.ButtonSelectedColorFrom := TColor($BBE2EA); + FColors.ButtonSelectedColorTo := TColor($389FDD); + FColors.FrameColor := TColor($6F2F0C); + FColors.ButtonHotColorFrom := TColor($DBFBFF); + FColors.ButtonHotColorTo := TColor($5FC8FB); + FColors.DividerColorFrom := TColor($FFDBBC); + FColors.DividerColorTo := TColor($F2C0A4); + FColors.HeaderColorFrom := TColor($D0835C); + FColors.HeaderColorTo := TColor($903B09); + FColors.SplitterColorFrom := TColor($B78676); + FColors.SplitterColorTo := TColor($A03D09); + FColors.ButtonSeparatorColor := TColor($602D00); // SESS + + FColors.ToolPanelColorFrom := clWindow; + FColors.ToolPanelColorTo := clWindow; + FColors.ToolPanelHeaderColorFrom := TColor($F7E2CD); + FColors.ToolPanelHeaderColorTo := TColor($F3A080); + + FFonts.HeaderFont.Color := clWindow; + FFonts.NavPanelFont.Color := clWindowText; + FFonts.NavPanelHotTrackFont.Color := clWindowText; + FFonts.DividerFont.Color := clWindowText; + end; + nptXPSilver: + begin + FColors.ButtonColorFrom := TColor($F4E2E1); + FColors.ButtonColorTo := TColor($B09494); + FColors.ButtonSelectedColorFrom := TColor($BBE2EA); + FColors.ButtonSelectedColorTo := TColor($389FDD); + FColors.FrameColor := TColor($527D92); + FColors.ButtonHotColorFrom := TColor($DBFBFF); + FColors.ButtonHotColorTo := TColor($5FC8FB); + FColors.DividerColorFrom := TColor($F8F3F4); + FColors.DividerColorTo := TColor($EADADB); + FColors.HeaderColorFrom := TColor($BAA8BA); + FColors.HeaderColorTo := TColor($917275); + FColors.SplitterColorFrom := TColor($B8ABA9); + FColors.SplitterColorTo := TColor($81767E); + FColors.ButtonSeparatorColor := TColor($947C7C); + FColors.ToolPanelColorFrom := clWindow; + FColors.ToolPanelColorTo := clWindow; + FColors.ToolPanelHeaderColorFrom := TColor($F4E2E1); + FColors.ToolPanelHeaderColorTo := TColor($B09494); + + FFonts.HeaderFont.Color := clWindow; + FFonts.NavPanelFont.Color := clWindowText; + FFonts.NavPanelHotTrackFont.Color := clWindowText; + FFonts.DividerFont.Color := clWindowText; + end; + nptXPOlive: + begin + FColors.ButtonColorFrom := TColor($D6F3E3); + FColors.ButtonColorTo := TColor($93BFB2); + FColors.ButtonSelectedColorFrom := TColor($BBE2EA); + FColors.ButtonSelectedColorTo := TColor($389FDD); + FColors.FrameColor := TColor($5A7972); + FColors.ButtonHotColorFrom := TColor($DBFBFF); + FColors.ButtonHotColorTo := TColor($5FC8FB); + FColors.DividerColorFrom := TColor($D2F4EE); + FColors.DividerColorTo := TColor($B5DFD8); + FColors.HeaderColorFrom := TColor($94BFB4); + FColors.HeaderColorTo := TColor($427665); + FColors.SplitterColorFrom := TColor($758D81); + FColors.SplitterColorTo := TColor($3A584D); + FColors.ButtonSeparatorColor := TColor($588060); + FColors.ToolPanelColorFrom := clWindow; + FColors.ToolPanelColorTo := clWindow; + FColors.ToolPanelHeaderColorFrom := TColor($D6F3E3); + FColors.ToolPanelHeaderColorTo := TColor($93BFB2); + + FFonts.HeaderFont.Color := clWindow; + FFonts.NavPanelFont.Color := clWindowText; + FFonts.NavPanelHotTrackFont.Color := clWindowText; + FFonts.DividerFont.Color := clWindowText; + end; + nptCustom: + begin + // do nothing + end; + end; + FTheme := Value; + Change; + finally + FColors.OnChange := @DoThemeChange; + FFonts.OnChange := @DoThemeChange; + end; + end; +end; + +procedure TJvNavPaneStyleManager.UnregisterChanges(Value: TJvNavStyleLink); +var + I: Integer; +begin + if FClients <> nil then + for I := 0 to FClients.Count - 1 do + if FClients[I] = Pointer(Value) then + begin + Value.Sender := nil; + FClients.Delete(I); + Break; + end; +end; + +function TJvNavPaneStyleManager.IsColorsStored: Boolean; +begin + Result := Theme = nptCustom; +end; + +function TJvNavPaneStyleManager.IsFontsStored: Boolean; +begin + Result := Theme = nptCustom; +end; + +//=== { TJvNavStyleLink } ==================================================== + +destructor TJvNavStyleLink.Destroy; +begin + if Sender is TJvNavPaneStyleManager then + TJvNavPaneStyleManager(Sender).UnregisterChanges(Self); + inherited Destroy; +end; + +procedure TJvNavStyleLink.Change; +begin + if Assigned(FOnChange) then + FOnChange(Sender); +end; + +//=== { TJvCustomNavPaneToolPanel } ========================================== + +constructor TJvCustomNavPaneToolPanel.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FHeaderVisible := True; + ParentColor := False; + FColors := TJvNavPanelColors.Create; + FColors.OnChange := @DoImagesChange; + FBackground := TJvNavPaneBackgroundImage.Create; + FBackground.OnChange := @DoImagesChange; + ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents, + csOpaque, csDoubleClicks, csReplicatable]; + FButtons := TJvNavPaneToolButtons.Create(Self); + FStyleLink := TJvNavStyleLink.Create; + FStyleLink.OnChange := @DoStyleChange; + FChangeLink := TChangeLink.Create; + FChangeLink.OnChange := @DoImagesChange; + { + FColorFrom := TColor($F7E2CD); + FColorTo := TColor($F3A080); + FButtonColor := TColor($A03D09); + } + FButtonWidth := 25; + FButtonHeight := 22; + FHeaderHeight := 29; + FEdgeRounding := 9; + FShowGrabber := True; + //TODO: + //Font := Screen.IconFont; + Font.Style := [fsBold]; + + FCloseButton := TJvNavPanelToolButton.Create(Self); + FCloseButton.ButtonType := nibClose; + FCloseButton.Parent := Self; + FCloseButton.Visible := True; + FCloseButton.OnClick := @DoCloseClick; + + FDropDown := TJvNavPanelToolButton.Create(Self); + FDropDown.Visible := False; + FDropDown.ButtonType := nibDropArrow; + FDropDown.OnDropDownMenu := @DoDropDownMenu; + FDropDown.Parent := Self; + + Width := 185; + Height := 41; + FParentStyleManager := True; +end; + +destructor TJvCustomNavPaneToolPanel.Destroy; +begin + FStyleLink.Free; + FChangeLink.Free; + FButtons.Free; + FBackground.Free; + FColors.Free; + inherited Destroy; +end; + +procedure TJvCustomNavPaneToolPanel.ButtonsChanged; +var + I: Integer; + B: TJvNavPanelToolButton; +begin + if HeaderVisible then + for I := 0 to Buttons.Count - 1 do + begin + B := Buttons[I].Button; + B.Visible := False; + B.SetBounds(0, 0, ButtonWidth - 3, ButtonHeight - 2); + B.Images := Images; + if B.Action = nil then + B.OnClick := @InternalButtonClick; + B.Tag := I; + B.Parent := Self; + end; + Invalidate; +end; + +procedure TJvCustomNavPaneToolPanel.DoCloseClick(Sender: TObject); +begin + if Assigned(FOnClose) then + FOnClose(Self); +end; + +procedure TJvCustomNavPaneToolPanel.DoDropDownMenu(Sender: TObject; + MousePos: TPoint; var Handled: Boolean); +begin + if Assigned(FOnDropDownMenu) then + FOnDropDownMenu(Self, MousePos, Handled); +end; + +procedure TJvCustomNavPaneToolPanel.DoImagesChange(Sender: TObject); +begin + ButtonsChanged; +end; + +procedure TJvCustomNavPaneToolPanel.DoStyleChange(Sender: TObject); +begin + Font := (Sender as TJvNavPaneStyleManager).Fonts.NavPanelFont; + Colors := (Sender as TJvNavPaneStyleManager).Colors; +end; + +procedure TJvCustomNavPaneToolPanel.FontChanged; +begin + inherited FontChanged; + Invalidate; +end; + +function TJvCustomNavPaneToolPanel.GetCloseButton: Boolean; +begin + Result := FCloseButton.Visible; // and HeaderVisible; +end; + +function TJvCustomNavPaneToolPanel.GetDropDownMenu: TPopupMenu; +begin + if not (csDestroying in ComponentState) then + Result := FDropDown.DropDownMenu + else + Result := nil; +end; + +function TJvCustomNavPaneToolPanel.GetHitTestInfoAt(X, Y: Integer): TJvToolPanelHitTestInfos; + + function InRange(Value, Min, Max: Integer): Boolean; + begin + Result := (Value >= Min) and (Value <= Max); + end; + +begin + if not Visible then + begin + Result := [phtNowhere]; + Exit; + end; + Result := []; + if X < 0 then + Include(Result, phtToLeft); + if X > ClientWidth then + Include(Result, phtToRight); + if Y < 0 then + Include(Result, phtAbove); + if Y > ClientHeight then + Include(Result, phtBelow); + if InRange(Y, 0, HeaderHeight - EdgeRounding) then + if InRange(X, 0, ClientWidth) then + begin + Include(Result, phtHeader); + if (X <= 16) and ShowGrabber then + Include(Result, phtGrabber); + end; + if InRange(X, 0, ClientWidth) and InRange(Y, HeaderHeight, ClientHeight) then + Include(Result, phtClient); +end; + +procedure TJvCustomNavPaneToolPanel.InternalButtonClick(Sender: TObject); +begin + if Assigned(FOnButtonClick) then + FOnButtonClick(Self, TJvNavPanelToolButton(Sender).Tag); +end; + +procedure TJvCustomNavPaneToolPanel.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if Operation = opRemove then + begin + if AComponent = Images then + Images := nil + else + if AComponent = StyleManager then + StyleManager := nil + else + if AComponent = DropDownMenu then + DropDownMenu := nil; + end; +end; + +procedure TJvCustomNavPaneToolPanel.Paint; +var + R, R2: TRect; + I, X, Y: Integer; + B: TJvNavPanelToolButton; +begin + // first, fill the background + Canvas.Lock; + try + R := ClientRect; + if HeaderVisible then + Inc(R.Top, HeaderHeight); + GradientFillRect(Canvas, R, Colors.ToolPanelColorFrom, Colors.ToolPanelColorTo, fdTopToBottom, 255); + FBackground.DrawImage(Canvas, R); + R := ClientRect; + if HeaderVisible then + begin + R.Bottom := HeaderHeight - EdgeRounding; + R.Bottom := R.Top + HeaderHeight; + GradientFillRect(Canvas, R, Colors.ToolPanelHeaderColorFrom, Colors.ToolPanelHeaderColorTo, fdTopToBottom, 255); + // draw the drag dots + R2 := Rect(R.Left, R.Top + (HeaderHeight - cToolButtonHeight) div 2 + 2, R.Left + 2, R.Top + (HeaderHeight - cToolButtonHeight) div 2 + 4); + OffsetRect(R2, 6, 0); + if ShowGrabber then + begin + for I := 0 to 3 do + begin + Canvas.Brush.Color := clWhite; + OffsetRect(R2, 1, 1); + Canvas.FillRect(R2); + Canvas.Brush.Color := Colors.FrameColor; + OffsetRect(R2, -1, -1); + Canvas.FillRect(R2); + OffsetRect(R2, 0, 4); + end; + // draw the text + Inc(R.Left, 16); + end + else + Inc(R.Left, 12); + Canvas.Font := Self.Font; + if (DropDownMenu = nil) and not (csDesigning in ComponentState) then + begin + OffsetRect(R, 2, -1); // line up with where button caption should have been + SetBkMode(Canvas.Handle, TRANSPARENT); + if CloseButton then + R := Rect(R.Left, R.Top, FCloseButton.Left, R.Bottom); + DrawText(Canvas, Caption, Length(Caption), R, DT_SINGLELINE or DT_VCENTER or DT_LEFT or DT_END_ELLIPSIS); + end; + + // draw the client areas top rounding, set pixels directly to avoid messing up any background image + + // just a simple "arrow" in each corner in the same color as the gradient + // left corner + Y := HeaderHeight; + X := 0; + for I := 0 to 3 do + Canvas.Pixels[X, Y + I] := Colors.ToolPanelHeaderColorTo; + Inc(X); + for I := 0 to 2 do + Canvas.Pixels[X, Y + I] := Colors.ToolPanelHeaderColorTo; + Inc(X); + for I := 0 to 1 do + Canvas.Pixels[X, Y + I] := Colors.ToolPanelHeaderColorTo; + Inc(X); + Canvas.Pixels[X, Y] := Colors.ToolPanelHeaderColorTo; + // Inc(X); + // Canvas.Pixels[X, Y] := Colors.HeaderColorTo; + + // right corner + Y := HeaderHeight; + X := ClientWidth - 1; + for I := 0 to 4 do + Canvas.Pixels[X, Y + I] := Colors.ToolPanelHeaderColorTo; + Dec(X); + for I := 0 to 2 do + Canvas.Pixels[X, Y + I] := Colors.ToolPanelHeaderColorTo; + Dec(X); + for I := 0 to 1 do + Canvas.Pixels[X, Y + I] := Colors.ToolPanelHeaderColorTo; + Dec(X); + Canvas.Pixels[X, Y] := Colors.ToolPanelHeaderColorTo; + Dec(X); + Canvas.Pixels[X, Y] := Colors.HeaderColorTo; + + // draw the button area + R := ClientRect; + Inc(R.Top, HeaderHeight); + Inc(R.Right); + Canvas.Brush.Color := Colors.FrameColor; + Canvas.Pen.Style := psClear; + if Buttons.Count > 0 then + begin + R2 := Rect(R.Left, R.Top, R.Left + ButtonWidth * Buttons.Count - 1, R.Top + ButtonHeight); + Canvas.RoundRect(R2.Left, R2.Top, R2.Right, R2.Bottom, EdgeRounding, EdgeRounding); + // square two corners + Canvas.FillRect(Rect(R2.Right - EdgeRounding, R2.Top, R2.Right - 1, R2.Top + EdgeRounding)); + Canvas.FillRect(Rect(R2.Left, R2.Bottom - EdgeRounding, R2.Left + EdgeRounding, R2.Bottom - 1)); + Canvas.Pen.Style := psSolid; + Y := R2.Top; + // adjust the buttons and draw the dividers + for I := 0 to Buttons.Count - 1 do + begin + X := R2.Left + ButtonWidth * I; + B := Buttons[I].Button; + B.SetBounds(X + 3, Y + 2, ButtonWidth - 6, ButtonHeight - 4); + B.Visible := True; + if I > 0 then + begin + Canvas.Pen.Color := TColor($E7EBEF); + Canvas.MoveTo(X, R2.Top + 2); + Canvas.LineTo(X, R2.Bottom - 3); + end; + if I < Buttons.Count - 1 then + begin + Canvas.Pen.Color := TColor($CED3D6); + Canvas.MoveTo(X + ButtonWidth - 1, R2.Top + 1); + Canvas.LineTo(X + ButtonWidth - 1, R2.Bottom - 4); + end; + end; + end; + end; + finally + Canvas.Unlock; + end; +end; + +procedure TJvCustomNavPaneToolPanel.AlignButtons; +var + AOffset: Integer; +begin + if HeaderVisible and ShowGrabber then + AOffset := cToolButtonOffset + else + AOffset := 4; + if (Parent <> nil) and (HeaderHeight > cToolButtonHeight) then + begin + FCloseButton.SetBounds(ClientWidth - cToolButtonWidth - 2, (HeaderHeight - cToolButtonHeight) div 2, cToolButtonWidth, cToolButtonHeight); + if FCloseButton.Visible or (csDesigning in ComponentState) then + FDropDown.SetBounds(AOffset, (HeaderHeight - cToolButtonHeight) div 2, ClientWidth - cToolButtonWidth - AOffset - 2, cToolButtonHeight) + else + FDropDown.SetBounds(AOffset, (HeaderHeight - cToolButtonHeight) div 2, ClientWidth - AOffset - 4, cToolButtonHeight); + end + else + begin + FCloseButton.SetBounds(0, 0, 0, 0); + FDropDown.SetBounds(0, 0, 0, 0); + end; +end; + +procedure TJvCustomNavPaneToolPanel.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); +begin + inherited SetBounds(ALeft, ATop, AWidth, AHeight); + AlignButtons; +end; + +procedure TJvCustomNavPaneToolPanel.SetButtonHeight(const Value: Integer); +begin + if FButtonHeight <> Value then + begin + FButtonHeight := Value; + Invalidate; + end; +end; + +procedure TJvCustomNavPaneToolPanel.SetButtons(const Value: TJvNavPaneToolButtons); +begin + FButtons.Assign(Value); +end; + +procedure TJvCustomNavPaneToolPanel.SetButtonWidth(const Value: Integer); +begin + if FButtonWidth <> Value then + begin + FButtonWidth := Value; + Invalidate; + end; +end; + +procedure TJvCustomNavPaneToolPanel.SetCloseButton(const Value: Boolean); +begin + if FCloseButton.Visible <> Value then + begin + FCloseButton.Visible := Value; + SetBounds(Left, Top, Width, Height); + end; +end; + +procedure TJvCustomNavPaneToolPanel.SetDropDownMenu(const Value: TPopupMenu); +begin + if FDropDown.DropDownMenu <> Value then + begin + FDropDown.DropDownMenu := Value; + FDropDown.Visible := (Value <> nil); // and HeaderVisible; + SetBounds(Left, Top, Width, Height); + Invalidate; + end; +end; + +procedure TJvCustomNavPaneToolPanel.SetEdgeRounding(const Value: Integer); +begin + if FEdgeRounding <> Value then + begin + FEdgeRounding := Value; + Invalidate; + end; +end; + +procedure TJvCustomNavPaneToolPanel.SetHeaderHeight(const Value: Integer); +begin + if FHeaderHeight <> Value then + begin + FHeaderHeight := Value; + Invalidate; + end; +end; + +procedure TJvCustomNavPaneToolPanel.SetImages(const Value: TCustomImageList); +var + I: Integer; +begin + if FImages <> Value then + begin + if FImages <> nil then + FImages.UnregisterChanges(FChangeLink); + FImages := Value; + if FImages <> nil then + begin + FImages.RegisterChanges(FChangeLink); + FImages.FreeNotification(Self); + end; + for I := 0 to Buttons.Count - 1 do + Buttons[I].Button.Images := FImages; + Invalidate; + end; +end; + +procedure TJvCustomNavPaneToolPanel.SetShowGrabber(const Value: Boolean); +begin + if FShowGrabber <> Value then + begin + FShowGrabber := Value; + Invalidate; + end; +end; + +procedure TJvCustomNavPaneToolPanel.SetStyleManager(const Value: TJvNavPaneStyleManager); +begin + if FStyleManager <> Value then + begin + ParentStyleManager := False; + if FStyleManager <> nil then + FStyleManager.UnregisterChanges(FStyleLink); + FStyleManager := Value; + if FStyleManager <> nil then + begin + FStyleManager.RegisterChanges(FStyleLink); + FStyleManager.FreeNotification(Self); + Colors := FStyleManager.Colors; + Invalidate; + end; + InternalStyleManagerChanged(Self, StyleManager); + end; +end; + +procedure TJvCustomNavPaneToolPanel.ParentStyleManagerChanged(var Msg: TMsgStyleManagerChange); +begin + if (Msg.Sender <> Self) and ParentStyleManager then + begin + StyleManager := Msg.StyleManager; + ParentStyleManager := True; + InternalStyleManagerChanged(Self, Msg.StyleManager); + end; +end; + +procedure TJvCustomNavPaneToolPanel.TextChanged; +begin + inherited TextChanged; + FDropDown.Caption := Caption; + Invalidate; +end; + +procedure TJvCustomNavPaneToolPanel.SetParentStyleManager(const Value: Boolean); +begin + if FParentStyleManager <> Value then + begin + FParentStyleManager := Value; + if FParentStyleManager and (Parent <> nil) then + Parent.Perform(CM_PARENTSTYLEMANAGERCHANGE, 0, 0); + end; +end; + + +procedure TJvCustomNavPaneToolPanel.CMControlChange(var Msg: TLMessage); +begin + InternalStyleManagerChanged(Self, StyleManager); +end; + +procedure TJvCustomNavPaneToolPanel.WMEraseBkgnd(var Msg: TLMEraseBkgnd); +begin + Msg.Result := 1; +end; + +procedure TJvCustomNavPaneToolPanel.WMNCPaint(var Msg: TWMNCPaint); +var + AColor: TColor; +begin + AColor := Color; + Color := Colors.FrameColor; + inherited; + Color := AColor; +end; + +procedure TJvCustomNavPaneToolPanel.ParentStyleManagerChange(var Msg: TLMessage); +begin + InternalStyleManagerChanged(Self, StyleManager); +end; + +function TJvCustomNavPaneToolPanel.GetDrawPartialMenuFrame: Boolean; +begin + if FDropDown <> nil then + Result := FDropDown.DrawPartialMenuFrame + else + Result := False; +end; + +procedure TJvCustomNavPaneToolPanel.SetDrawPartialMenuFrame(const Value: Boolean); +begin + if FDropDown <> nil then + FDropDown.DrawPartialMenuFrame := Value; +end; + +procedure TJvCustomNavPaneToolPanel.SetBackground(const Value: TJvNavPaneBackgroundImage); +begin + FBackground.Assign(Value); +end; + +procedure TJvCustomNavPaneToolPanel.SetColors(const Value: TJvNavPanelColors); +begin + FColors.Assign(Value); +end; + +procedure TJvCustomNavPaneToolPanel.SetHeaderVisible(const Value: Boolean); +begin + if FHeaderVisible <> Value then + begin + FHeaderVisible := Value; + FCloseButton.Visible := CloseButton; + FDropDown.Visible := (FDropDown.DropDownMenu <> nil); // and Value; + ButtonsChanged; + end; +end; + +function TJvCustomNavPaneToolPanel.IsColorsStored: Boolean; +begin + Result := (StyleManager = nil) or (StyleManager.Theme = nptCustom); +end; + +//=== { TJvNavPaneToolButton } =============================================== + +procedure TJvNavPaneToolButton.Assign(Source: TPersistent); +begin + if Source is TJvNavPaneToolButton then + begin +// if Source <> Self then + begin + Action := TJvNavPaneToolButton(Source).Action; + Hint := TJvNavPaneToolButton(Source).Hint; + ImageIndex := TJvNavPaneToolButton(Source).ImageIndex; + Enabled := TJvNavPaneToolButton(Source).Enabled + end; + end + else + inherited Assign(Source); +end; + +constructor TJvNavPaneToolButton.Create(ACollection: Classes.TCollection); +begin + FRealButton := TJvNavPanelToolButton.Create(nil); + FRealButton.ButtonType := nibImage; + FRealButton.ImageIndex := -1; + inherited Create(ACollection); +end; + +destructor TJvNavPaneToolButton.Destroy; +begin + FRealButton.Free; + inherited Destroy; +end; + +function TJvNavPaneToolButton.GetAction: TBasicAction; +begin + Result := FRealButton.Action; +end; + +function TJvNavPaneToolButton.GetEnabled: Boolean; +begin + Result := FRealButton.Enabled; +end; + +function TJvNavPaneToolButton.GetHint: string; +begin + Result := FRealButton.Hint; +end; + +function TJvNavPaneToolButton.GetImageIndex: TImageIndex; +begin + Result := FRealButton.ImageIndex; +end; + +procedure TJvNavPaneToolButton.SetAction(const Value: TBasicAction); +begin + FRealButton.Action := Value; + FRealButton.ActionChange(Value, False); +end; + +procedure TJvNavPaneToolButton.SetEnabled(const Value: Boolean); +begin + FRealButton.Enabled := Value; +end; + +procedure TJvNavPaneToolButton.SetHint(const Value: string); +begin + FRealButton.Hint := Value; +end; + +procedure TJvNavPaneToolButton.SetImageIndex(const Value: TImageIndex); +begin + FRealButton.ImageIndex := Value; +end; + +//=== { TJvNavPaneToolButtons } ============================================== + +constructor TJvNavPaneToolButtons.Create(AOwner: TJvCustomNavPaneToolPanel); +begin + inherited Create(AOwner, TJvNavPaneToolButton); + FPanel := AOwner; +end; + +function TJvNavPaneToolButtons.Add: TJvNavPaneToolButton; +begin + Result := TJvNavPaneToolButton(inherited Add); +end; + +function TJvNavPaneToolButtons.GetItem(Index: Integer): TJvNavPaneToolButton; +begin + Result := TJvNavPaneToolButton(inherited Items[Index]); +end; + +procedure TJvNavPaneToolButtons.SetItem(Index: Integer; + const Value: TJvNavPaneToolButton); +begin + inherited Items[Index] := Value; +end; + +procedure TJvNavPaneToolButtons.Update(Item: TCollectionItem); +begin + inherited Update(Item); + if FPanel <> nil then + FPanel.ButtonsChanged; +end; + +//=== { TJvNavPanelToolButton } ============================================== + +constructor TJvNavPanelToolButton.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FChangeLink := TChangeLink.Create; + FChangeLink.OnChange := @DoImagesChange; + DrawPartialMenuFrame := False; + TransparentDown := False; + HotTrack := True; +end; + +destructor TJvNavPanelToolButton.Destroy; +begin + FChangeLink.Free; + inherited Destroy; +end; + +procedure TJvNavPanelToolButton.ActionChange(Sender: TObject; CheckDefaults: Boolean); +begin + if Sender is TCustomAction then + with TCustomAction(Sender) do + begin + if not CheckDefaults or Self.Enabled then + Self.Enabled := Enabled; + if not CheckDefaults or (Self.Hint = '') then + Self.Hint := Hint; + if not CheckDefaults or (Self.ImageIndex = -1) then + Self.ImageIndex := ImageIndex; + if not CheckDefaults or Self.Visible then + Self.Visible := Visible; + if not CheckDefaults or not Assigned(Self.OnClick) then + Self.OnClick := OnExecute; + end; +end; + +procedure TJvNavPanelToolButton.DoImagesChange(Sender: TObject); +begin + Invalidate; +end; + +procedure TJvNavPanelToolButton.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if (Operation = opRemove) and (AComponent = Images) then + Images := nil; +end; + +procedure TJvNavPanelToolButton.Paint; +label + DrawButton; +var + R: TRect; + I: Integer; +begin + // inherited Paint; + if MouseStates <> [] then + begin + Canvas.Pen.Color := TColor($6B2408); + if bsMouseInside in MouseStates then + Canvas.Brush.Color := TColor($D6BEB5); + if (bsMouseDown in MouseStates) or Down then + begin + if TransparentDown then + Canvas.Brush.Style := bsClear; // (p3) don't draw background - looks better IMO + if (ButtonType = nibDropArrow) and (DropDownMenu <> nil) then + begin + Canvas.Brush.Color := clWindow; + Canvas.Pen.Color := cl3DDkShadow; + if DrawPartialMenuFrame then + begin + Canvas.FillRect(ClientRect); // if Brush.Style = bsClear, this does nothing + Canvas.MoveTo(0, Height); + Canvas.LineTo(0, 0); + Canvas.LineTo(Width - 1, 0); + Canvas.LineTo(Width - 1, Height); + // (p3) yucky! first goto in JVCL?!!! + goto DrawButton; + end; + end + else + Canvas.Brush.Color := TColor($B59284); + end; + Canvas.Rectangle(ClientRect); + end; +DrawButton: + case ButtonType of + nibDropArrow: // dropdown arrow is 7x4, right-aligned + begin + R := ClientRect; + if Caption <> '' then + begin + InflateRect(R, -2, -2); + Canvas.Font := Font; + SetBkMode(Canvas.Handle, TRANSPARENT); + InflateRect(R, -2, 0); + Dec(R.Right, 3 + 7); + DrawText(Canvas, Caption, Length(Caption), R, DT_LEFT or DT_VCENTER or DT_NOPREFIX or DT_END_ELLIPSIS); + Inc(R.Right, 3 + 7); + InflateRect(R, 2, 0); + end; + R.Left := R.Right - 11; + Dec(R.Right, 4); + R.Top := (RectHeight(ClientRect) - 4) div 2; + Canvas.Pen.Color := clWindowText; + for I := 0 to 3 do + begin + Canvas.MoveTo(R.Left, R.Top); + Canvas.LineTo(R.Right, R.Top); + Dec(R.Right); + Inc(R.Left); + Inc(R.Top); + end; + end; + nibClose: + begin + // close button is 8x8, centered + if bsMouseDown in MouseStates then + Canvas.Pen.Color := clHighlightText + else + Canvas.Pen.Color := clWindowText; + R := ClientRect; + InflateRect(R, -(RectWidth(R) div 2 - 4), -(RectHeight(R) div 2 - 4)); + if Odd(Height) or Odd(Width) then + begin + Inc(R.Right); + Inc(R.Bottom); + end; + // (p3) this isn't exactly the same as MS's but good enough for me :) + for I := 0 to 7 do + begin + Canvas.MoveTo(R.Left + I, R.Top + I); + Canvas.LineTo(R.Left + I + 2, R.Top + I); + end; + for I := 0 to 7 do + begin + Canvas.MoveTo(R.Right - I, R.Top + I); + Canvas.LineTo(R.Right - I - 2, R.Top + I); + end; + end; + nibImage: + if Assigned(Images) then + Images.Draw(Canvas, + (Width - Images.Width) div 2, (Height - Images.Height) div 2, + ImageIndex, Enabled); + else + //TODO: + //raise EJVCLException.CreateRes(@RsEUnsupportedButtonType); + raise Exception.Create('RsEUnsupportedButtonType'); + end; +end; + +procedure TJvNavPanelToolButton.SetButtonType(const Value: TJvNavIconButtonType); +begin + if FButtonType <> Value then + begin + FButtonType := Value; + Invalidate; + end; +end; + +procedure TJvNavPanelToolButton.SetImageIndex(const Value: TImageIndex); +begin + if FImageIndex <> Value then + begin + FImageIndex := Value; + Invalidate; + end; +end; + +procedure TJvNavPanelToolButton.SetImages(const Value: TCustomImageList); +begin + if FImages <> Value then + begin + if FImages <> nil then + FImages.UnregisterChanges(FChangeLink); + FImages := Value; + if FImages <> nil then + begin + FImages.RegisterChanges(FChangeLink); + FImages.FreeNotification(Self); + end; + Invalidate; + end; +end; + +//=== { TJvNavPaneBackgroundImage } ========================================== + +constructor TJvNavPaneBackgroundImage.Create; +begin + inherited Create; + FPicture := TPicture.Create; + FPicture.OnChange := @PictureChanged; +end; + +destructor TJvNavPaneBackgroundImage.Destroy; +begin + FPicture.Free; + inherited Destroy; +end; + +function TJvNavPaneBackgroundImage.CalcRect(ADestRect: TRect): TRect; +var + W, H, CW, CH: Integer; + XYAspect: Double; +begin + W := Picture.Width; + H := Picture.Height; + CW := ADestRect.Right - ADestRect.Left; + CH := ADestRect.Bottom - ADestRect.Top; + if Stretch or (Proportional and ((W > CW) or (H > CH))) then + begin + if Proportional and (W > 0) and (H > 0) then + begin + XYAspect := W / H; + if W > H then + begin + W := CW; + H := Trunc(CW / XYAspect); + if H > CH then // woops, too big + begin + H := CH; + W := Trunc(CH * XYAspect); + end; + end + else + begin + H := CH; + W := Trunc(CH * XYAspect); + if W > CW then // woops, too big + begin + W := CW; + H := Trunc(CW / XYAspect); + end; + end; + end + else + begin + W := CW; + H := CH; + end; + end; + + with Result do + begin + Left := ADestRect.Left; + Top := ADestRect.Top; + Right := ADestRect.Left + W; + Bottom := ADestRect.Top + H; + end; + + if Center then + OffsetRect(Result, (CW - W) div 2, (CH - H) div 2); +end; + +procedure TJvNavPaneBackgroundImage.Change; +begin + FDrawing := True; + if Assigned(FOnChange) then + FOnChange(Self); + FDrawing := False; +end; + +procedure TJvNavPaneBackgroundImage.DrawImage(Canvas: TCanvas; ARect: TRect); + + procedure TileImage; + var + X, Y: Integer; + G: TGraphic; + begin + G := Picture.Graphic; + X := ARect.Left; + Y := ARect.Top; + while Y < ARect.Bottom do + begin + Canvas.Draw(X, Y, G); // this doesn't clip on the right or bottom sides of ARect :( + Inc(X, G.Width); + if X > ARect.Right then + begin + X := ARect.Left; + Inc(Y, G.Height); + end; + end; + end; + +begin + if (Picture.Graphic = nil) or (Picture.Width = 0) or (Picture.Height = 0) then + Exit; + if Tile then + TileImage + else + with Canvas do + StretchDraw(CalcRect(ARect), Picture.Graphic); +end; + +function TJvNavPaneBackgroundImage.HasImage: Boolean; +begin + with Picture do + Result := (Graphic <> nil) and (Width <> 0) and (Height <> 0); +end; + +procedure TJvNavPaneBackgroundImage.PictureChanged(Sender: TObject); +var + G: TGraphic; +begin + G := Picture.Graphic; + //TODO: + (* + if G <> nil then + if not ( (G is TMetaFile) or (G is TIcon)) then + G.Transparent := FTransparent; + *) + if not FDrawing then + Change; +end; + +procedure TJvNavPaneBackgroundImage.SetCenter(const Value: Boolean); +begin + if FCenter <> Value then + begin + FCenter := Value; + PictureChanged(Self); + end; +end; + +procedure TJvNavPaneBackgroundImage.SetPicture(const Value: TPicture); +begin + FPicture.Assign(Value); +end; + +procedure TJvNavPaneBackgroundImage.SetProportional(const Value: Boolean); +begin + if FProportional <> Value then + begin + FProportional := Value; + PictureChanged(Self); + end; +end; + +procedure TJvNavPaneBackgroundImage.SetStretch(const Value: Boolean); +begin + if FStretch <> Value then + begin + FStretch := Value; + PictureChanged(Self); + end; +end; + +procedure TJvNavPaneBackgroundImage.SetTile(const Value: Boolean); +begin + if FTile <> Value then + begin + FTile := Value; + PictureChanged(Self); + end; +end; + +procedure TJvNavPaneBackgroundImage.SetTransparent(const Value: Boolean); +begin + if FTransparent <> Value then + begin + FTransparent := Value; + PictureChanged(Self) + end; +end; + +procedure TJvCustomNavPaneToolPanel.AdjustClientRect(var Rect: TRect); +begin + if HeaderVisible then + begin + Rect.Top := Rect.Top + HeaderHeight + EdgeRounding; + if Buttons.Count > 0 then + Rect.Top := Rect.Top + ButtonHeight - EdgeRounding; + end; + InflateRect(Rect, -2, -2); + inherited AdjustClientRect(Rect); +end; + +{initialization + RegisterClasses([TJvNavPanelPage]);} // ahuser: moved to TJvCustomNavigationPane.Create + +end. + diff --git a/components/jvcllaz/run/JvPageList.pas b/components/jvcllaz/run/JvPageList.pas new file mode 100644 index 000000000..1e35228fb --- /dev/null +++ b/components/jvcllaz/run/JvPageList.pas @@ -0,0 +1,943 @@ +{----------------------------------------------------------------------------- +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: JvPageList.PAS, released on 2003-04-25. + +The Initial Developer of the Original Code is Peter Thörnqvist [peter3 at sourceforge dot net] . +Portions created by Peter Thörnqvist are Copyright (C) 2004 Peter Thörnqvist. +All Rights Reserved. + +Contributor(s): + +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: + +-----------------------------------------------------------------------------} +// $Id: JvPageList.pas 11400 2007-06-28 21:24:06Z ahuser $ + +// Initial port to Lazarus by Sergio Samayoa - september 2007. +// Conversion is done in incremental way: as types / classes / routines +// are needed they are converted. + +{$mode objfpc}{$H+} + +unit JvPageList; + +interface + +uses + Classes, Controls, Graphics, JvComponent, LCLIntf, LCLType, LMessages, + SysUtils; + +type + EPageListError = class(Exception); + +(******************** NOT CONVERTED + IPageList = interface + ['{6BB90183-CFB1-4431-9CFD-E9A032E0C94C}'] + function CanChange(AIndex: Integer): Boolean; + procedure SetActivePageIndex(AIndex: Integer); + function GetPageCount: Integer; + function GetPageCaption(AIndex: Integer): string; + procedure AddPage(const ACaption: string); + procedure DeletePage(Index: Integer); + procedure MovePage(CurIndex, NewIndex: Integer); + procedure PageCaptionChanged(Index: Integer; const NewCaption: string); + end; +******************** NOT CONVERTED *) + + TJvCustomPageList = class; + + TJvPagePaintEvent = procedure(Sender: TObject; ACanvas: TCanvas; ARect: TRect) of object; + TJvPageCanPaintEvent = procedure(Sender: TObject; ACanvas: TCanvas; ARect: TRect; var DefaultDraw: Boolean) of object; + + { TJvCustomPage is the base class for pages in a TJvPageList and implements the basic behaviour of such + a control. It has support for accepting components, propagating it's Enabled state, changing it's order in the + page list and custom painting } + + TJvCustomPage = class(TJvCustomControl) + private + FPageList: TJvCustomPageList; + FPageIndex: Integer; + FOnBeforePaint: TJvPageCanPaintEvent; + FOnPaint: TJvPagePaintEvent; + FOnAfterPaint: TJvPagePaintEvent; + FOnHide: TNotifyEvent; + FOnShow: TNotifyEvent; + FData: TObject; + protected + procedure CreateParams(var Params: TCreateParams); override; + function DoEraseBackground(ACanvas: TCanvas; Param: Integer): Boolean; override; + procedure SetPageIndex(Value: Integer);virtual; + function GetPageIndex: Integer;virtual; + procedure SetPageList(Value: TJvCustomPageList);virtual; + procedure TextChanged; override; + procedure ShowingChanged; override; + procedure Paint; override; + procedure ReadState(Reader: TReader); override; + function DoBeforePaint(ACanvas: TCanvas; ARect: TRect): Boolean; dynamic; + procedure DoAfterPaint(ACanvas: TCanvas; ARect: TRect); dynamic; + procedure DoPaint(ACanvas: TCanvas; ARect: TRect); virtual; + procedure DoShow; virtual; + procedure DoHide; virtual; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + property PageList: TJvCustomPageList read FPageList write SetPageList; + protected + property Left stored False; + property Top stored False; + property Width stored False; + property Height stored False; + property OnHide: TNotifyEvent read FOnHide write FOnHide; + property OnShow: TNotifyEvent read FOnShow write FOnShow; + property OnBeforePaint: TJvPageCanPaintEvent read FOnBeforePaint write FOnBeforePaint; + property OnPaint: TJvPagePaintEvent read FOnPaint write FOnPaint; + property OnAfterPaint: TJvPagePaintEvent read FOnAfterPaint write FOnAfterPaint; + public + property Data: TObject read FData write FData; + property PageIndex: Integer read GetPageIndex write SetPageIndex stored False; + end; + + TJvCustomPageClass = class of TJvCustomPage; + TJvPageChangingEvent = procedure(Sender: TObject; PageIndex: Integer; var AllowChange: Boolean) of object; + + { + TJvCustomPageList is a base class for components that implements the IPageList interface. + It works like TPageControl but does not have any tabs + } + TJvShowDesignCaption = (sdcNone, sdcTopLeft, sdcTopCenter, sdcTopRight, sdcLeftCenter, sdcCenter, sdcRightCenter, sdcBottomLeft, sdcBottomCenter, sdcBottomRight, sdcRunTime); + + //TODO: 25.09.2007 - SESS - Find a better place... + TCMDesignHitTest = TLMMouse; + + // TJvCustomPageList = class(TJvCustomControl, IUnknown, IPageList) + TJvCustomPageList = class(TJvCustomControl) + private + FPages: TList; + FActivePage: TJvCustomPage; + FPropagateEnable: Boolean; + FOnChange: TNotifyEvent; + FOnChanging: TJvPageChangingEvent; + FShowDesignCaption: TJvShowDesignCaption; + FHiddenPages: TList; + procedure CMDesignHitTest(var Msg: TCMDesignHitTest); message CM_DESIGNHITTEST; + procedure UpdateEnabled; + procedure SetPropagateEnable(const Value: Boolean); + procedure SetShowDesignCaption(const Value: TJvShowDesignCaption); + function GetPage(Index: Integer): TJvCustomPage; + protected + procedure EnabledChanged; override; + { IPageList } + procedure AddPage(const ACaption: string); + procedure DeletePage(Index: Integer); + procedure MovePage(CurIndex, NewIndex: Integer); + function CanChange(AIndex: Integer): Boolean; virtual; + function GetActivePageIndex: Integer; virtual; + procedure SetActivePageIndex(AIndex: Integer); virtual; + function GetPageFromIndex(AIndex: Integer): TJvCustomPage; virtual; + function GetPageCount: Integer;virtual; + function GetPageCaption(AIndex: Integer): string; virtual; + procedure Paint; override; + procedure PageCaptionChanged(Index: Integer; const NewCaption: string); virtual; + procedure Change; dynamic; + procedure Loaded; override; + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + procedure ShowControl(AControl: TControl); override; + function InternalGetPageClass: TJvCustomPageClass; virtual; + procedure SetActivePage(Page: TJvCustomPage); virtual; + procedure InsertPage(APage: TJvCustomPage); virtual; + procedure RemovePage(APage: TJvCustomPage); virtual; + property PageList: TList read FPages; + property HiddenPageList: TList read FHiddenPages; + property PropagateEnable: Boolean read FPropagateEnable write SetPropagateEnable; + property ShowDesignCaption: TJvShowDesignCaption read FShowDesignCaption write SetShowDesignCaption default sdcCenter; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + property OnChanging: TJvPageChangingEvent read FOnChanging write FOnChanging; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function FindNextPage(CurPage: TJvCustomPage; GoForward: Boolean; IncludeDisabled: Boolean): TJvCustomPage; + procedure PrevPage; + procedure NextPage; + function HidePage(Page: TJvCustomPage): TJvCustomPage; virtual; + function ShowPage(Page: TJvCustomPage; PageIndex: Integer = -1): TJvCustomPage; virtual; + function GetPageClass: TJvCustomPageClass; + function GetVisiblePageCount: Integer; + property Height default 200; + property Width default 300; + property ActivePageIndex: Integer read GetActivePageIndex write SetActivePageIndex; + property ActivePage: TJvCustomPage read FActivePage write SetActivePage; + property Pages[Index: Integer]: TJvCustomPage read GetPage; default; + property PageCount: Integer read GetPageCount; + end; + +(******************** NOT CONVERTED + TJvStandardPage = class(TJvCustomPage) + published + property BorderWidth; + property Caption; + property Color; + property DragMode; + property Enabled; + property Font; + property Constraints; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowHint; + property PageIndex; + property OnContextPopup; + property OnDragDrop; + property OnDragOver; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnHide; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnResize; + property OnShow; + property OnStartDrag; + property OnBeforePaint; + property OnPaint; + property OnAfterPaint; + property OnMouseEnter; + property OnMouseLeave; + property OnParentColorChange; + {$IFDEF JVCLThemesEnabled} + property ParentBackground default False; + {$ENDIF JVCLThemesEnabled} + end; + + TJvPageList = class(TJvCustomPageList) + protected + function InternalGetPageClass: TJvCustomPageClass; override; + public + property PageCount; + published + property ActivePage; + property PropagateEnable; + property ShowDesignCaption; + property Action; + property Align; + property Anchors; + property BiDiMode; + property BorderWidth; + property DragCursor; + property DragKind; + property OnStartDock; + property OnUnDock; + property OnEndDock; + property OnCanResize; + property OnDockDrop; + property OnDockOver; + property OnGetSiteInfo; + property Constraints; + property DragMode; + property Enabled; + property PopupMenu; + property ShowHint; + property Visible; + property OnMouseEnter; + property OnMouseLeave; + property OnParentColorChange; + property OnChange; + property OnChanging; + property OnConstrainedResize; + property OnContextPopup; + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnMouseWheel; + property OnMouseWheelDown; + property OnMouseWheelUp; + property OnResize; + property OnStartDrag; + {$IFDEF JVCLThemesEnabled} + property ParentBackground default False; + {$ENDIF JVCLThemesEnabled} + end; +******************** NOT CONVERTED *) + +implementation + +uses + Forms; + +function GetUniqueName(AOwner: TComponent; const AClassName: string): string; +var + i: Integer; +begin + i := 0; + if AOwner = nil then + begin + repeat + Inc(i); + Result := AClassName + IntToStr(i); + until FindGlobalComponent(Result) = nil; + end + else + repeat + Inc(i); + Result := AClassName + IntToStr(i); + until AOwner.FindComponent(Result) = nil; +end; + +//=== { TJvCustomPage } ====================================================== + +constructor TJvCustomPage.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FPageIndex := -1; + Align := alClient; + ControlStyle := ControlStyle + [csOpaque, csAcceptsControls, csNoDesignVisible]; +// IncludeThemeStyle(Self, [csParentBackground]); + Visible := False; + DoubleBuffered := True; +end; + +procedure TJvCustomPage.CreateParams(var Params: TCreateParams); +begin + inherited CreateParams(Params); + with Params.WindowClass do + Style := Style and not (CS_HREDRAW or CS_VREDRAW); +end; + +destructor TJvCustomPage.Destroy; +begin + PageList := nil; + inherited Destroy; +end; + +procedure TJvCustomPage.DoAfterPaint(ACanvas: TCanvas; ARect: TRect); +begin + if Assigned(FOnAfterPaint) then + FOnAfterPaint(Self, ACanvas, ARect); +end; + +function TJvCustomPage.DoBeforePaint(ACanvas: TCanvas; ARect: TRect): Boolean; +begin + Result := True; + if Assigned(FOnBeforePaint) then + FOnBeforePaint(Self, ACanvas, ARect, Result); +end; + +function GetDesignCaptionFlags(Value: TJvShowDesignCaption): Cardinal; +begin + case Value of + sdcTopLeft: + Result := DT_TOP or DT_LEFT; + sdcTopCenter: + Result := DT_TOP or DT_CENTER; + sdcTopRight: + Result := DT_TOP or DT_RIGHT; + sdcLeftCenter: + Result := DT_VCENTER or DT_LEFT; + sdcCenter: + Result := DT_VCENTER or DT_CENTER; + sdcRightCenter: + Result := DT_VCENTER or DT_RIGHT; + sdcBottomLeft: + Result := DT_BOTTOM or DT_LEFT; + sdcBottomCenter: + Result := DT_BOTTOM or DT_CENTER; + sdcBottomRight: + Result := DT_BOTTOM or DT_RIGHT; + else + Result := 0; + end; +end; + +procedure TJvCustomPage.DoPaint(ACanvas: TCanvas; ARect: TRect); +var + S: string; +begin + with ACanvas do + begin + Font := Self.Font; + Brush.Style := bsSolid; + Brush.Color := Self.Color; + //SESS + //DrawThemedBackground(Self, Canvas, ARect); + DoEraseBackground(Canvas, 0); + if (csDesigning in ComponentState) then + begin + Pen.Style := psDot; + Pen.Color := clBlack; + Brush.Style := bsClear; + Rectangle(ARect); + Brush.Style := bsSolid; + Brush.Color := Color; + if (PageList <> nil) and (PageList.ShowDesignCaption <> sdcNone) then + begin + S := Caption; + if S = '' then + S := Name; + // make some space around the edges + InflateRect(ARect, -4, -4); + if not Enabled then + begin + SetBkMode(Handle, TRANSPARENT); + Canvas.Font.Color := clHighlightText; + //TODO: Use JCLUtils one? + DrawText(Handle, PChar(S), Length(S), ARect, GetDesignCaptionFlags(PageList.ShowDesignCaption) or DT_SINGLELINE); + OffsetRect(ARect, -1, -1); + Canvas.Font.Color := clGrayText; + end; + DrawText(Handle, PChar(S), Length(S), ARect, GetDesignCaptionFlags(PageList.ShowDesignCaption) or DT_SINGLELINE); + InflateRect(ARect, 4, 4); + end; + end; + end; + if Assigned(FOnPaint) then + FOnPaint(Self, ACanvas, ARect); +end; + +function TJvCustomPage.GetPageIndex: Integer; +begin + if Assigned(FPageList) then + Result := FPageList.PageList.IndexOf(Self) + else + Result := FPageIndex; +end; + +procedure TJvCustomPage.Paint; +var + R: TRect; +begin + R := ClientRect; + if DoBeforePaint(Canvas, R) then + DoPaint(Canvas, R); + DoAfterPaint(Canvas, R); +end; + +procedure TJvCustomPage.ReadState(Reader: TReader); +begin + if Reader.Parent is TJvCustomPageList then + PageList := TJvCustomPageList(Reader.Parent); + inherited ReadState(Reader); +end; + +procedure TJvCustomPage.SetPageList(Value: TJvCustomPageList); +begin + if FPageList <> Value then + begin + if Assigned(FPageList) then + FPageList.RemovePage(Self); + FPageList := Value; + Parent := FPageList; + if FPageList <> nil then + FPageList.InsertPage(Self); + end; +end; + +procedure TJvCustomPage.SetPageIndex(Value: Integer); +var + OldIndex: Integer; +begin + if (Value <> PageIndex) then + begin + OldIndex := PageIndex; + if Assigned(FPageList) and (Value >= 0) and (Value < FPageList.PageCount) then + FPageList.PageList.Move(OldIndex, Value); + FPageIndex := Value; + end; +end; + +function TJvCustomPage.DoEraseBackground(ACanvas: TCanvas; Param: Integer): Boolean; +begin + ACanvas.Brush.Color := Self.Color; + ACanvas.Brush.Style := bsSolid; + ACanvas.FillRect(Rect(0, 0, Width, Height)); + Result := True; +end; + +procedure TJvCustomPage.TextChanged; +begin + inherited TextChanged; + if csDesigning in ComponentState then + Invalidate; +end; + +procedure TJvCustomPage.DoHide; +begin + if Assigned(FOnHide) then + FOnHide(Self); +end; + +procedure TJvCustomPage.DoShow; +begin + if Assigned(FOnShow) then + FOnShow(Self); +end; + +procedure TJvCustomPage.ShowingChanged; +begin + inherited ShowingChanged; + if Showing then + try + DoShow + except + Application.HandleException(Self); + end + else + if not Showing then + try + DoHide; + except + Application.HandleException(Self); + end; +end; + +//=== { TJvCustomPageList } ================================================== + +constructor TJvCustomPageList.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + ControlStyle := ControlStyle + [csAcceptsControls]; +// IncludeThemeStyle(Self, [csParentBackground]); + FPages := TList.Create; + FHiddenPages := TList.Create; + Height := 200; + Width := 300; + FShowDesignCaption := sdcCenter; + ActivePageIndex := -1; +end; + +destructor TJvCustomPageList.Destroy; +var + I: Integer; +begin + for I := FPages.Count - 1 downto 0 do + TJvCustomPage(FPages[I]).FPageList := nil; + FPages.Free; + FHiddenPages.Free; + inherited Destroy; +end; + +function TJvCustomPageList.CanChange(AIndex: Integer): Boolean; +begin + Result := (AIndex >= 0) and (AIndex < GetPageCount); + if Result and Assigned(FOnChanging) then + FOnChanging(Self, AIndex, Result); +end; + +procedure TJvCustomPageList.Change; +begin + if Assigned(FOnChange) then + FOnChange(Self); +end; + +procedure TJvCustomPageList.CMDesignHitTest(var Msg: TCMDesignHitTest); +var + Pt: TPoint; +begin + inherited; + Pt := SmallPointToPoint(Msg.Pos); + if Assigned(ActivePage) and PtInRect(ActivePage.BoundsRect, Pt) then + Msg.Result := 1; +end; + +procedure TJvCustomPageList.GetChildren(Proc: TGetChildProc; + Root: TComponent); +var + I: Integer; + Control: TControl; +begin + for I := 0 to FPages.Count - 1 do + Proc(TComponent(FPages[I])); + for I := 0 to ControlCount - 1 do + begin + Control := Controls[I]; + if not (Control is TJvCustomPage) and (Control.Owner = Root) then + Proc(Control); + end; +end; + +function TJvCustomPageList.GetPageCaption(AIndex: Integer): string; +begin + if (AIndex >= 0) and (AIndex < GetPageCount) then + Result := TJvCustomPage(FPages[AIndex]).Caption + else + Result := ''; +end; + +function TJvCustomPageList.InternalGetPageClass: TJvCustomPageClass; +begin + Result := TJvCustomPage; +end; + +function TJvCustomPageList.GetPageCount: Integer; +begin + if FPages = nil then + Result := 0 + else + Result := FPages.Count; +end; + +procedure TJvCustomPageList.InsertPage(APage: TJvCustomPage); +begin + if (APage <> nil) and (FPages.IndexOf(APage) = -1) then + FPages.Add(APage); +end; + +procedure TJvCustomPageList.Loaded; +begin + inherited Loaded; + if (GetPageCount > 0) and (ActivePage = nil) then + ActivePage := Pages[0]; +end; + +procedure TJvCustomPageList.Paint; +begin + if (csDesigning in ComponentState) and (GetPageCount = 0) then + with Canvas do + begin + Pen.Color := clBlack; + Pen.Style := psDot; + Brush.Style := bsClear; + Rectangle(ClientRect); + end; +end; + +procedure TJvCustomPageList.RemovePage(APage: TJvCustomPage); +var + I: Integer; + WNextPage: TJvCustomPage; +begin + WNextPage := FindNextPage(APage, True, not (csDesigning in ComponentState)); + if WNextPage = APage then + WNextPage := nil; + APage.Visible := False; + APage.FPageList := nil; + FPages.Remove(APage); + SetActivePage(WNextPage); + // (ahuser) In some cases SetActivePage does not change FActivePage + // so we force FActivePage not to be "APage" + if (FActivePage = APage) or (FActivePage = nil) then + begin + FActivePage := nil; + for I := 0 to PageCount - 1 do + if Pages[I] <> APage then + begin + FActivePage := Pages[I]; + Break; + end; + end; +end; + +function TJvCustomPageList.GetPageFromIndex(AIndex: Integer): TJvCustomPage; +begin + if (AIndex >= 0) and (AIndex < GetPageCount) then + Result := TJvCustomPage(Pages[AIndex]) + else + Result := nil; +end; + +function TJvCustomPageList.GetVisiblePageCount: Integer; +var + i: Integer; +begin + Result := 0; + for i := 0 to PageCount - 1 do + if Pages[i].Visible then + Inc(Result); +end; + +procedure TJvCustomPageList.SetActivePageIndex(AIndex: Integer); +begin + if (AIndex > -1) and (AIndex < PageCount) then + ActivePage := Pages[AIndex] + else + ActivePage := nil; +end; + +procedure TJvCustomPageList.ShowControl(AControl: TControl); +begin + if AControl is TJvCustomPage then + ActivePage := TJvCustomPage(AControl); + inherited ShowControl(AControl); +end; + +function TJvCustomPageList.GetPageClass: TJvCustomPageClass; +begin + Result := InternalGetPageClass; +end; + +function TJvCustomPageList.HidePage(Page: TJvCustomPage): TJvCustomPage; +var + I: Integer; +begin + if (Page <> nil) and (Page.PageList = Self) then + begin + if ActivePage = Page then + NextPage; + if ActivePage = Page then + ActivePage := nil; + I := Page.PageIndex; + Page.PageList := nil; + Page.PageIndex := I; + Result := Page; + FHiddenPages.Add(Result); + end + else + Result := nil; +end; + +function TJvCustomPageList.ShowPage(Page: TJvCustomPage; PageIndex: Integer): TJvCustomPage; +var + I: Integer; +begin + if (Page <> nil) and (Page.PageList = nil) then + begin + I := Page.PageIndex; + Page.PageList := Self; + Page.Parent := Self; + if PageIndex > -1 then + Page.PageIndex := PageIndex + else + if I > -1 then + Page.PageIndex := I; + Result := Page; + FHiddenPages.Remove(Result); + end + else + Result := nil; +end; + +procedure TJvCustomPageList.SetActivePage(Page: TJvCustomPage); +var + ParentForm: TCustomForm; + //TODO: why? + //{$IFDEF COMPILER9_UP} + I: Integer; + //{$ENDIF COMPILER9_UP} +begin + // Mantis 3227: Checking if the page can be changed has to be done at the + // beginning or the page would change but not the index... + if not (csLoading in ComponentState) and not CanChange(FPages.IndexOf(Page)) then + Exit; + + if GetPageCount = 0 then + FActivePage := nil; + if (Page = nil) or (Page.PageList <> Self) then + Exit + else + begin + ParentForm := GetParentForm(Self); + if (ParentForm <> nil) and (FActivePage <> nil) and + FActivePage.ContainsControl(ParentForm.ActiveControl) then + begin + ParentForm.ActiveControl := FActivePage; + if ParentForm.ActiveControl <> FActivePage then + begin + ActivePage := GetPageFromIndex(FActivePage.PageIndex); + Exit; + end; + end; + + //TODO: why? + //{$IFDEF COMPILER9_UP} + for I := 0 to GetPageCount - 1 do + if Pages[i] <> Page then + Pages[i].Hide; + //{$ELSE} + //Page.BringToFront; + //{$ENDIF COMPILER9_UP} + Page.Visible := True; + if (ParentForm <> nil) and (FActivePage <> nil) and (ParentForm.ActiveControl = FActivePage) then + begin + if Page.CanFocus then + ParentForm.ActiveControl := Page + else + ParentForm.ActiveControl := Self; + end; + Page.Refresh; + + if (FActivePage <> nil) and (FActivePage <> Page) then + FActivePage.Visible := False; + if (FActivePage <> Page) then + begin + FActivePage := Page; + if not (csLoading in ComponentState) then + Change; + end; + if (ParentForm <> nil) and (FActivePage <> nil) and + (ParentForm.ActiveControl = FActivePage) then + begin + FActivePage.SelectFirst; + end; + end; +end; + +function TJvCustomPageList.GetActivePageIndex: Integer; +begin + if ActivePage <> nil then + Result := ActivePage.PageIndex + else + Result := -1; +end; + +procedure TJvCustomPageList.NextPage; +begin + if (ActivePageIndex < PageCount - 1) and (PageCount > 1) then + ActivePageIndex := ActivePageIndex + 1 + else + if PageCount > 0 then + ActivePageIndex := 0 + else + ActivePageIndex := -1; +end; + +procedure TJvCustomPageList.PrevPage; +begin + if ActivePageIndex > 0 then + ActivePageIndex := ActivePageIndex - 1 + else + ActivePageIndex := PageCount - 1; +end; + +procedure TJvCustomPageList.SetPropagateEnable(const Value: Boolean); +begin + if FPropagateEnable <> Value then + begin + FPropagateEnable := Value; + UpdateEnabled; + end; +end; + +procedure TJvCustomPageList.EnabledChanged; +begin + inherited EnabledChanged; + UpdateEnabled; +end; + +function TJvCustomPageList.FindNextPage(CurPage: TJvCustomPage; + GoForward, IncludeDisabled: Boolean): TJvCustomPage; +var + I, StartIndex: Integer; +begin + if PageCount <> 0 then + begin + StartIndex := FPages.IndexOf(CurPage); + if StartIndex < 0 then + if GoForward then + StartIndex := FPages.Count - 1 + else + StartIndex := 0; + I := StartIndex; + repeat + if GoForward then + begin + Inc(I); + if I >= FPages.Count - 1 then + I := 0; + end + else + begin + if I <= 0 then + I := FPages.Count - 1; + Dec(I); + end; + Result := Pages[I]; + if IncludeDisabled or Result.Enabled then + Exit; + until I = StartIndex; + end; + Result := nil; +end; + +procedure TJvCustomPageList.SetShowDesignCaption(const Value: TJvShowDesignCaption); +begin + if FShowDesignCaption <> Value then + begin + FShowDesignCaption := Value; + //TODO: + (* + if HandleAllocated and (csDesigning in ComponentState) then + RedrawWindow(Handle, nil, 0, RDW_UPDATENOW or RDW_INVALIDATE or RDW_ALLCHILDREN); + *) + end; +end; + +procedure TJvCustomPageList.UpdateEnabled; + + procedure InternalSetEnabled(AControl: TWinControl); + var + I: Integer; + begin + for I := 0 to AControl.ControlCount - 1 do + begin + AControl.Controls[I].Enabled := Self.Enabled; + if AControl.Controls[I] is TWinControl then + InternalSetEnabled(TWinControl(AControl.Controls[I])); + end; + end; + +begin + if PropagateEnable then + InternalSetEnabled(Self); +end; + +function TJvCustomPageList.GetPage(Index: Integer): TJvCustomPage; +begin + if (Index >= 0) and (Index < FPages.Count) then + Result := TJvCustomPage(FPages[Index]) + else + Result := nil; +end; +procedure TJvCustomPageList.DeletePage(Index: Integer); +begin + if (Index >= 0) and (Index < PageCount) then + Pages[Index].Free; +end; + +procedure TJvCustomPageList.AddPage(const ACaption: string); +var + Page: TJvCustomPage; +begin + Page := GetPageClass.Create(Owner); + Page.Caption := ACaption; + Page.Name := GetUniqueName(Owner, Copy(Page.ClassName, 2, MaxInt)); + Page.PageList := Self; +end; + +procedure TJvCustomPageList.MovePage(CurIndex, NewIndex: Integer); +begin + FPages.Move(CurIndex, NewIndex); +end; + +procedure TJvCustomPageList.PageCaptionChanged(Index: Integer; + const NewCaption: string); +begin + if (Index >= 0) and (Index < PageCount) then + Pages[Index].Caption := NewCaption; +end; + +(************** +//===TJvPageList ============================================================= + +function TJvPageList.InternalGetPageClass: TJvCustomPageClass; +begin + Result := TJvStandardPage; +end; +*******************) + +end. diff --git a/components/jvcllaz/run/JvTypes.pas b/components/jvcllaz/run/JvTypes.pas new file mode 100644 index 000000000..a665f0ec3 --- /dev/null +++ b/components/jvcllaz/run/JvTypes.pas @@ -0,0 +1,739 @@ +{----------------------------------------------------------------------------- +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: JvTypes.PAS, released on 2001-02-28. + +The Initial Developer of the Original Code is Sébastien Buysse [sbuysse att buypin dott com] +Portions created by Sébastien Buysse are Copyright (C) 2001 Sébastien Buysse. +All Rights Reserved. + +Contributor(s): Michael Beck [mbeck att bigfoot dott com]. + Peter Thornqvist + Oliver Giesen + Gustavo Bianconi + dejoy + +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: +-----------------------------------------------------------------------------} +// $Id: JvTypes.pas 11400 2007-06-28 21:24:06Z ahuser $ + +// Initial port to Lazarus by Sergio Samayoa - september 2007. +// Conversion is done in incremental way: as types / classes / routines +// are needed they are converted. + +{$mode objfpc}{$H+} + +unit JvTypes; + +interface + +uses + Classes, Controls, Forms, Graphics, LMessages, SysUtils; + +const + MaxPixelCount = 32767; + +(******************** +type + TJvBytes = Pointer; + IntPtr = Pointer; +********************) + +type + PCaptionChar = PChar; + + // used in JvSpeedButton, JvArrowButton, JvButton CM_JVBUTTONPRESSED + // asn: can also be used with CM_BUTTONPRESSED + TCMButtonPressed = packed record + Msg: Cardinal; + Index: Integer; { clx has Index and Control switched } + Control: TControl; + Result: Longint; + end; + +(******************** + THintString = string; + THintStringList = TStringList; + + { JvExVCL classes } + TInputKey = (ikAll, ikArrows, ikChars, ikButton, ikTabs, ikEdit, ikNative{, ikNav, ikEsc}); + TInputKeys = set of TInputKey; + + {$IFDEF CLR} + [StructLayout(LayoutKind.Sequential)] + {$ENDIF CLR} + TJvRGBTriple = packed record + rgbBlue: Byte; + rgbGreen: Byte; + rgbRed: Byte; + end; + +const + NullHandle = 0; + // (rom) deleted fbs constants. They are already in JvConsts.pas. + + +type + TTimerProc = procedure(hwnd: THandle; Msg: Cardinal; idEvent: Cardinal; dwTime: Cardinal); + +type + {$IFDEF COMPILER5} + EOSError = class(EWin32Error); + IInterface = IUnknown; + {$M+} + IInvokable = interface(IInterface) + end; + {$M-} + {$ENDIF COMPILER5} + {$IFDEF CLR} + IUnknown = IInterface; + {$ENDIF CLR} + + // Base class for persistent properties that can show events. + // By default, Delphi and BCB don't show the events of a class + // derived from TPersistent unless it also derives from + // TComponent. However, up until version 5, you couldn't have + // a Component as a Sub Component of another one, thus preventing + // from having events for a sub property. + // The design time editor associated with TJvPersistent will display + // the events, thus mimicking a Sub Component. + {$IFDEF COMPILER6_UP} + TJvPersistent = class(TComponent) + public + constructor Create(AOwner: TComponent); override; + end; + {$ELSE} + TJvPersistent = class(TPersistent); + {$ENDIF COMPILER6_UP} + + // Added by dejoy (2005-04-20) + // A lot of TJVxxx control persistent properties used TPersistent, + // So and a TJvPersistentProperty to do this job. make to support batch-update mode + // and property change notify. + TJvPropertyChangeEvent = procedure(Sender: TObject; const PropName: string) of object; + + TJvPersistentProperty = class(TPersistent)//?? TJvPersistent + private + FUpdateCount: Integer; + FOnChanging: TNotifyEvent; + FOnChange: TNotifyEvent; + FOnChangingProperty: TJvPropertyChangeEvent; + FOnChangeProperty: TJvPropertyChangeEvent; + protected + procedure Changed; virtual; + procedure Changing; virtual; + procedure ChangedProperty(const PropName: string); virtual; + procedure ChangingProperty(const PropName: string); virtual; + procedure SetUpdateState(Updating: Boolean); virtual; + property UpdateCount: Integer read FUpdateCount; + public + procedure BeginUpdate; virtual; + procedure EndUpdate; virtual; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + property OnChanging: TNotifyEvent read FOnChanging write FOnChanging; + property OnChangeProperty: TJvPropertyChangeEvent read FOnChangeProperty write FOnChangeProperty; + property OnChangingProperty: TJvPropertyChangeEvent read FOnChangingProperty write FOnChangingProperty; + end; + + TJvRegKey = (hkClassesRoot, hkCurrentUser, hkLocalMachine, hkUsers, + hkPerformanceData, hkCurrentConfig, hkDynData); + TJvRegKeys = set of TJvRegKey; + + // base JVCL Exception class to derive from + EJVCLException = class(Exception); + + TJvLinkClickEvent = procedure(Sender: TObject; Link: string) of object; + // TOnRegistryChangeKey = procedure(Sender: TObject; RootKey: HKEY; Path: string) of object; + // TAngle = 0..360; + TJvOutputMode = (omFile, omStream); + // TLabelDirection = (sdLeftToRight, sdRightToLeft); // JvScrollingLabel + + TJvDoneFileEvent = procedure(Sender: TObject; FileName: string; FileSize: Integer; Url: string) of object; + TJvDoneStreamEvent = procedure(Sender: TObject; Stream: TStream; StreamSize: Integer; Url: string) of object; + TJvHTTPProgressEvent = procedure(Sender: TObject; UserData, Position: Integer; TotalSize: Integer; Url: string; var Continue: Boolean) of object; + TJvFTPProgressEvent = procedure(Sender: TObject; Position: Integer; Url: string) of object; + + // from JvComponent.pas + TJvClipboardCommand = (caCopy, caCut, caPaste, caClear, caUndo); + TJvClipboardCommands = set of TJvClipboardCommand; +********************) + + // used in JvButton + TCMForceSize = record + Msg: Cardinal; + NewSize: TSmallPoint; + Sender: TControl; + Result: Longint; + end; + +(******************** + PJvRGBArray = ^TJvRGBArray; + TJvRGBArray = array [0..MaxPixelCount] of TJvRGBTriple; + PRGBQuadArray = ^TRGBQuadArray; + TRGBQuadArray = array [0..MaxPixelCount] of TRGBQuad; + PRGBPalette = ^TRGBPalette; + TRGBPalette = array [Byte] of TRGBQuad; + + { (rom) unused + TJvPoint = class(TPersistent) + protected + FX: Integer; + FY: Integer; + published + property X: Integer read FX write FX; + property Y: Integer read FY write FY; + end; + } + + TJvErrorEvent = procedure(Sender: TObject; ErrorMsg: string) of object; + TJvWaveLocation = (frFile, frResource, frRAM); + + TJvPopupPosition = (ppNone, ppForm, ppApplication); + // TJvDirMask = (dmFileNameChange, dmDirnameChange, dmAttributesChange, dmSizeChange, dmLastWriteChange, dmSecurityChange); //JvDirectorySpy + // TJvDirMasks = set of TJvDirMask; + // EJvDirectoryError = class(EJVCLException); // JvDirectorySpy + // TListEvent = procedure(Sender: TObject; Title: string; Handle: THandle) of object; // JvWindowsTitle + + TJvProgressEvent = procedure(Sender: TObject; Current, Total: Integer) of object; + TJvNextPageEvent = procedure(Sender: TObject; PageNumber: Integer) of object; + TJvBitmapStyle = (bsNormal, bsCentered, bsStretched); + + // TOnOpened = procedure(Sender: TObject; Value: string) of object; // archive + // TOnOpenCanceled = procedure(Sender: TObject) of object; // archive + + {$IFDEF COMPILER5} + + { TStream seek origins } +// TSeekOrigin = (soFromBeginning, soFromCurrent, soFromEnd); +// (outchy) +// TStream.Seek can not be used with TSeekOrigin +// soFromBeginning, soFromCurrent and soFromEnd are defined in Classes.pas + + TWMNCPaint = packed record + Msg: Cardinal; + RGN: HRGN; + Unused: Longint; + Result: Longint; + end; + +// (outchy) defined in Windows.pas +// PInteger = ^Integer; +// PDouble = ^Double; + PBoolean = ^Boolean; + PWordBool = ^WordBool; + PCardinal = ^Cardinal; +// PByte = ^Byte; + + TVarType = Word; + + {$ENDIF COMPILER5} + + TJvGradientStyle = (grFilled, grEllipse, grHorizontal, grVertical, grPyramid, grMount); + // TOnDelete = procedure(Sender: TObject; Path: string) of object; + TJvParentEvent = procedure(Sender: TObject; ParentWindow: THandle) of object; + // TOnImage = procedure(Sender: TObject; Image: TBitmap) of object; // JvClipboardViewer + // TOnText = procedure(Sender: TObject; Text: string) of object; + // TJvRestart = (rsLogoff, rsShutdown, rsReboot, rsRestart, rsRebootSystem, rsExitAndExecApp); + // TJvRunOption = (roNoBrowse, roNoDefault, roCalcDirectory, roNoLabel, roNoSeparateMem); // JvRunDlg + // TJvRunOptions = set of TJvRunOption; // JvRunDlg + // TJvFileKind = (ftFile, ftPrinter); // JvObjectPropertiesDlg + + // TSHFormatDrive = function(Handle: THandle; Drive, ID, Options: Word): LongInt; stdcall; // JvFormatDrive + // TFormatOption = (shQuickFormat, shFull, shSystemFilesOnly); // JvFormatDrive + // TButtonStyle = (bsAbortRetryIgnore, bsOk, bsOkCancel, bsRetryCancel, bsYesNo, bsYesNoCancel); // JvMessageBox + // TButtonDisplay = (bdIconExclamation, bdIconWarning, bdIconInformation, bdIconAsterisk, bdIconQuestion, bdIconStop, bdIconError, bdIconHand); // JvMessageBox + + // TDefault = (dbButton1, dbButton2, dbButton3, dbButton4); // JvMessageBox + // TModality = (bmApplModal, bmSystemModal, bmTaskModal); // JvMessageBox + // TButtonOption = (boDefaultDesktopOnly, boHelp, boRight, boRtlReading, boSetForeground, boTopMost); // JvMessageBox + // TButtonOptions = set of TButtonOption; // JvMessageBox + // TButtonResult = (brAbort, brCancel, brIgnore, brNo, brOk, brRetry, brYes); // JvMessageBox + // TMsgStyle = (msBeep, msIconAsterisk, msIconExclamation, msIconHand, msIconQuestion, msOk); // JvMessageBeep + TJvDiskRes = (dsSuccess, dsCancel, dsSkipfile, dsError); + TJvDiskStyle = (idfCheckFirst, idfNoBeep, idfNoBrowse, idfNoCompressed, idfNoDetails, + idfNoForeground, idfNoSkip, idfOemDisk, idfWarnIfSkip); + TJvDiskStyles = set of TJvDiskStyle; + TJvDeleteStyle = (idNoBeep, idNoForeground); + TJvDeleteStyles = set of TJvDeleteStyle; + // TOnOk = procedure(Sender: TObject; Password: string; var Accept: Boolean) of object; // JvPasswordForm + + // TCoordChanged = procedure(Sender: TObject; Coord: string) of object; + TJvNotifyParamsEvent = procedure(Sender: TObject; Params: Pointer) of object; + + TJvFileInfoRec = record + Attributes: DWORD; + DisplayName: string; + ExeType: Integer; + Icon: HICON; + Location: string; + TypeName: string; + SysIconIndex: Integer; + end; + + TJvAnimation = (anLeftRight, anRightLeft, anRightAndLeft, anLeftVumeter, anRightVumeter); + TJvAnimations = set of TJvAnimation; + // TOnFound = procedure(Sender: TObject; Path: string) of object; // JvSearchFile + // TOnChangedDir = procedure(Sender: TObject; Directory: string) of object; // JvSearchFile + // TOnAlarm = procedure(Sender: TObject; Keyword: string) of object; // JvAlarm + { TAlarm = record + Keyword: string; + DateTime: TDateTime; + end; + } // JvAlarm + + // Bianconi - Moved from JvAlarms.pas + TJvTriggerKind = + (tkOneShot, tkEachSecond, tkEachMinute, tkEachHour, tkEachDay, tkEachMonth, tkEachYear); + // End of Bianconi + + TJvFourCC = array [0..3] of Char; + PJvAniTag = ^TJvAniTag; + TJvAniTag = packed record + ckID: TJvFourCC; + ckSize: Longint; + end; + + TJvAniHeader = packed record + dwSizeof: Longint; + dwFrames: Longint; + dwSteps: Longint; + dwCX: Longint; + dwCY: Longint; + dwBitCount: Longint; + dwPlanes: Longint; + dwJIFRate: Longint; + dwFlags: Longint; + end; + + TJvChangeColorEvent = procedure(Sender: TObject; Foreground, Background: TColor) of object; + + TJvLayout = (lTop, lCenter, lBottom); + TJvBevelStyle = (bsShape, bsLowered, bsRaised); + + {for OnLoseFocus the AFocusControl argument will point at the control that + receives focus while for OnGetFocus it is the control that lost the focus} + TJvFocusChangeEvent = procedure(const ASender: TObject; + const AFocusControl: TWinControl) of object; + + // JvJCLUtils + TTickCount = Cardinal; + + {**** string handling routines} + TSetOfChar = TSysCharSet; + TCharSet = TSysCharSet; + + TDateOrder = (doMDY, doDMY, doYMD); + TDayOfWeekName = (Sun, Mon, Tue, Wed, Thu, Fri, Sat); + TDaysOfWeek = set of TDayOfWeekName; + +const + DefaultDateOrder = doDMY; + + CenturyOffset: Byte = 60; + NullDate: TDateTime = 0; {-693594} + +type + // JvDriveCtrls / JvLookOut + TJvImageSize = (isSmall, isLarge); + TJvImageAlign = (iaLeft, iaCentered); + + TJvDriveType = (dtUnknown, dtRemovable, dtFixed, dtRemote, dtCDROM, dtRamDisk); + TJvDriveTypes = set of TJvDriveType; +********************) + +type + // Defines how a property (like a HotTrackFont) follows changes in the component's normal Font + TJvTrackFontOption = ( + hoFollowFont, // makes HotTrackFont follow changes to the normal Font + hoPreserveCharSet, // don't change HotTrackFont.Charset + hoPreserveColor, // don't change HotTrackFont.Color + hoPreserveHeight, // don't change HotTrackFont.Height (affects Size as well) + hoPreserveName, // don't change HotTrackFont.Name + hoPreservePitch, // don't change HotTrackFont.Pitch + hoPreserveStyle); // don't change HotTrackFont.Style + TJvTrackFontOptions = set of TJvTrackFontOption; + +const + DefaultTrackFontOptions = [hoFollowFont, hoPreserveColor, hoPreserveStyle]; + +(******************** +type + // from JvListView.pas + TJvSortMethod = (smAutomatic, smAlphabetic, smNonCaseSensitive, smNumeric, smDate, smTime, smDateTime, smCurrency); + TJvListViewColumnSortEvent = procedure(Sender: TObject; Column: Integer; var AMethod: TJvSortMethod) of object; + + // from JvOfficeColorPanel.pas + TJvAddInControlSiteInfo = record + AddInControl: TControl; + BoundsRect: TRect; + SiteInfoData: TObject; + end; + + TJvClickColorType = + (cctColors, cctNoneColor, cctDefaultColor, cctCustomColor, cctAddInControl, cctNone); + TJvHoldCustomColorEvent = procedure(Sender: TObject; AColor: TColor) of object; + TJvColorQuadLayOut = (cqlNone, cqlLeft, cqlRight, cqlClient); + TJvGetAddInControlSiteInfoEvent = procedure(Sender: TControl; var ASiteInfo: TJvAddInControlSiteInfo) of object; + + // from JvColorProvider.pas + TColorType = (ctStandard, ctSystem, ctCustom); + + TDefColorItem = record + Value: TColor; + Constant: string; + Description: string; + end; + +const + ColCount = 20; + StandardColCount = 40; + SysColCount = 30; + {$IFDEF COMPILER5} + clSystemColor = TColor($80000000); + clHotLight = TColor(clSystemColor or COLOR_HOTLIGHT); + clGradientActiveCaption = TColor(clSystemColor or COLOR_GRADIENTACTIVECAPTION); + clGradientInactiveCaption = TColor(clSystemColor or COLOR_GRADIENTINACTIVECAPTION); + clMenuHighlight = TColor(clSystemColor or COLOR_MENUHILIGHT); + clMenuBar = TColor(clSystemColor or COLOR_MENUBAR); + {$ENDIF COMPILER5} + {$IFDEF COMPILER6} + {$IF not declared(clHotLight)} + {$MESSAGE ERROR 'You do not have installed Delphi 6 Update 2. Please install this before installing the JVCL. http://www.borland.com/downloads/registered/del6_reg_updates_prompt.html'} + {$IFEND} + {$ENDIF COMPILER6} + + ColorValues: array [0 .. ColCount - 1] of TDefColorItem = ( + (Value: clBlack; Constant: 'clBlack'; Description: RsClBlack), + (Value: clMaroon; Constant: 'clMaroon'; Description: RsClMaroon), + (Value: clGreen; Constant: 'clGreen'; Description: RsClGreen), + (Value: clOlive; Constant: 'clOlive'; Description: RsClOlive), + (Value: clNavy; Constant: 'clNavy'; Description: RsClNavy), + (Value: clPurple; Constant: 'clPurple'; Description: RsClPurple), + (Value: clTeal; Constant: 'clTeal'; Description: RsClTeal), + (Value: clGray; Constant: 'clGray'; Description: RsClGray), + (Value: clSilver; Constant: 'clSilver'; Description: RsClSilver), + (Value: clRed; Constant: 'clRed'; Description: RsClRed), + (Value: clLime; Constant: 'clLime'; Description: RsClLime), + (Value: clYellow; Constant: 'clYellow'; Description: RsClYellow), + (Value: clBlue; Constant: 'clBlue'; Description: RsClBlue), + (Value: clFuchsia; Constant: 'clFuchsia'; Description: RsClFuchsia), + (Value: clAqua; Constant: 'clAqua'; Description: RsClAqua), + (Value: clWhite; Constant: 'clWhite'; Description: RsClWhite), + (Value: clMoneyGreen; Constant: 'clMoneyGreen'; Description: RsClMoneyGreen), + (Value: clSkyBlue; Constant: 'clSkyBlue'; Description: RsClSkyBlue), + (Value: clCream; Constant: 'clCream'; Description: RsClCream), + (Value: clMedGray; Constant: 'clMedGray'; Description: RsClMedGray) + ); + + //added by dejoy (2005-04-20) + StandardColorValues: array [0 .. StandardColCount - 1] of TDefColorItem = ( + (Value: $00000000; Constant: 'clBlack'; Description: RsClBlack), + (Value: $00003399; Constant: 'clBrown'; Description: RsClBrown), + (Value: $00003333; Constant: 'clOliveGreen'; Description: RsClOliveGreen), + (Value: $00003300; Constant: 'clDarkGreen'; Description: RsClDarkGreen), + (Value: $00663300; Constant: 'clDarkTeal'; Description: RsClDarkTeal), + (Value: $00800000; Constant: 'clDarkBlue'; Description: RsClDarkBlue), + (Value: $00993333; Constant: 'clIndigo'; Description: RsClIndigo), + (Value: $00333333; Constant: 'clGray80'; Description: RsClGray80), + + (Value: $00000080; Constant: 'clDarkRed'; Description: RsClDarkRed), + (Value: $000066FF; Constant: 'clOrange'; Description: RsClOrange), + (Value: $00008080; Constant: 'clDarkYellow'; Description: RsClDarkYellow), + (Value: $00008000; Constant: 'clGreen'; Description: RsClGreen), + (Value: $00808000; Constant: 'clTeal'; Description: RsClTeal), + (Value: $00FF0000; Constant: 'clBlue'; Description: RsClBlue), + (Value: $00996666; Constant: 'clBlueGray'; Description: RsClBlueGray), + (Value: $00808080; Constant: 'clGray50'; Description: RsClGray50), + + (Value: $000000FF; Constant: 'clRed'; Description: RsClRed), + (Value: $000099FF; Constant: 'clLightOrange'; Description: RsClLightOrange), + (Value: $0000CC99; Constant: 'clLime'; Description: RsClLime), + (Value: $00669933; Constant: 'clSeaGreen'; Description: RsClSeaGreen), + (Value: $00999933; Constant: 'clAqua'; Description: RsClAqua), + (Value: $00FF6633; Constant: 'clLightBlue'; Description: RsClLightBlue), + (Value: $00800080; Constant: 'clViolet'; Description: RsClViolet), + (Value: $00999999; Constant: 'clGray40'; Description: RsClGray40), + + (Value: $00FF00FF; Constant: 'clPink'; Description: RsClPink), + (Value: $0000CCFF; Constant: 'clGold'; Description: RsClGold), + (Value: $0000FFFF; Constant: 'clYellow'; Description: RsClYellow), + (Value: $0000FF00; Constant: 'clBrightGreen'; Description: RsClBrightGreen), + (Value: $00FFFF00; Constant: 'clTurquoise'; Description: RsClTurquoise), + (Value: $00F0CAA6; Constant: 'clSkyBlue'; Description: RsClSkyBlue), + (Value: $00663399; Constant: 'clPlum'; Description: RsClPlum), + (Value: $00C0C0C0; Constant: 'clGray25'; Description: RsClGray25), + + (Value: $00CC99FF; Constant: 'clRose'; Description: RsClRose), + (Value: $0099CCFF; Constant: 'clTan'; Description: RsClTan), + (Value: $0099FFFF; Constant: 'clLightYellow'; Description: RsClLightYellow), + (Value: $00CCFFCC; Constant: 'clLightGreen'; Description: RsClLightGreen), + (Value: $00FFFFCC; Constant: 'clLightTurquoise'; Description: RsClLightTurquoise), + (Value: $00FFCC99; Constant: 'clPaleBlue'; Description: RsClPaleBlue), + (Value: $00FF99CC; Constant: 'clLavender'; Description: RsClLavender), + (Value: $00FFFFFF; Constant: 'clWhite'; Description: RsClWhite) + ); + + SysColorValues: array [0 .. SysColCount - 1] of TDefColorItem = ( + (Value: clScrollBar; Constant: 'clScrollBar'; Description: RsClScrollBar), + (Value: clBackground; Constant: 'clBackground'; Description: RsClBackground), + (Value: clActiveCaption; Constant: 'clActiveCaption'; Description: RsClActiveCaption), + (Value: clInactiveCaption; Constant: 'clInactiveCaption'; Description: RsClInactiveCaption), + (Value: clMenu; Constant: 'clMenu'; Description: RsClMenu), + (Value: clWindow; Constant: 'clWindow'; Description: RsClWindow), + (Value: clWindowFrame; Constant: 'clWindowFrame'; Description: RsClWindowFrame), + (Value: clMenuText; Constant: 'clMenuText'; Description: RsClMenuText), + (Value: clWindowText; Constant: 'clWindowText'; Description: RsClWindowText), + (Value: clCaptionText; Constant: 'clCaptionText'; Description: RsClCaptionText), + (Value: clActiveBorder; Constant: 'clActiveBorder'; Description: RsClActiveBorder), + (Value: clInactiveBorder; Constant: 'clInactiveBorder'; Description: RsClInactiveBorder), + (Value: clAppWorkSpace; Constant: 'clAppWorkSpace'; Description: RsClAppWorkSpace), + (Value: clHighlight; Constant: 'clHighlight'; Description: RsClHighlight), + (Value: clHighlightText; Constant: 'clHighlightText'; Description: RsClHighlightText), + (Value: clBtnFace; Constant: 'clBtnFace'; Description: RsClBtnFace), + (Value: clBtnShadow; Constant: 'clBtnShadow'; Description: RsClBtnShadow), + (Value: clGrayText; Constant: 'clGrayText'; Description: RsClGrayText), + (Value: clBtnText; Constant: 'clBtnText'; Description: RsClBtnText), + (Value: clInactiveCaptionText; Constant: 'clInactiveCaptionText'; Description: RsClInactiveCaptionText), + (Value: clBtnHighlight; Constant: 'clBtnHighlight'; Description: RsClBtnHighlight), + (Value: cl3DDkShadow; Constant: 'cl3DDkShadow'; Description: RsCl3DDkShadow), + (Value: cl3DLight; Constant: 'cl3DLight'; Description: RsCl3DLight), + (Value: clInfoText; Constant: 'clInfoText'; Description: RsClInfoText), + (Value: clInfoBk; Constant: 'clInfoBk'; Description: RsClInfoBk), + + (Value: clGradientActiveCaption; Constant: 'clGradientActiveCaption'; Description: RsGradientActiveCaption), + (Value: clGradientInactiveCaption; Constant: 'clGradientInactiveCaption';Description: RsGradientInactiveCaption), + (Value: clHotLight; Constant: 'clHotLight'; Description: RsHotLight), + (Value: clMenuBar; Constant: 'clMenuBar'; Description: RsMenuBar), + (Value: clMenuHighlight; Constant: 'clMenuHighlight'; Description: RsMenuHighlight) + ); + + +type + TJvSizeRect = packed record + Top: Integer; + Left: Integer; + Width: Integer; + Height: Integer; + end; + +{$IFNDEF CLR} + TJvMessage = packed record + Msg: Integer; + case Integer of + 0: + ( + WParam: Integer; + LParam: Integer; + Result: Integer; + ); + 1: + ( + WParamLo: Word; + WParamHi: Word; + LParamLo: Word; + LParamHi: Word; + ResultLo: Word; + ResultHi: Word; + ); + 2: + ( // WM_NOPARAMS + Unused: array[0..3] of Word; + Handled: LongBool; // "Result" + ); + 3: + ( // WM_SCROLL + Pos: Integer; // WParam + ScrollCode: Integer; // LParam + ); + 4: + ( // WM_TIMER + TimerID: Integer; // WParam + TimerProc: TTimerProc;// LParam + ); + 5: + ( // WM_MOUSEACTIVATE + TopLevel: HWND; // WParam + HitTestCode: Word; // LParamLo + MouseMsg: Word; // LParamHi + ); + 6: + ( // WM_MOUSE(WHEEL) | WM_MOVE + case Integer of + 0: + ( // WM_MOUSE + Keys: Integer; // WParam + // LParam: Pos | (XPos, YPos) + case Integer of + 0: + ( + Position: TSmallPoint; + ); + 1: + ( + XPos: Smallint; + YPos: Smallint; + ) + ); + 1: + ( // WM_MOUSEWHEEL + WheelDelta: Integer; // WParam + ); + ); + 7: + ( // WM_ACTIVATE + Active: Word; { WA_INACTIVE, WA_ACTIVE, WA_CLICKACTIVE } // WParamLo + Minimized: WordBool; // WParamHi + ActiveWindow: HWND; // LParam + ); + + 8: + ( // WM_COMMAND + ItemID: Word; // WParamLo + NotifyCode: Word; // WParamHi + Ctl: HWND; // LParam + ); + 9: + ( // WM_GETICON + BigIcon: LongBool; + ); + 10: + ( // CM_(FOCUS|CONTROL)CHANGED | CM_HINTSHOW + Reserved: Integer; // WParam + case Integer of + 0: + ( // CM_(CONTROL)CHANGED + Child: TControl; // LParam + ); + 1: + ( // CM_FOCUSCHANGED | CM_FORCESIZE } + Sender: TControl; // LParam + ); + 2: + ( //CM_HINTSHOW + HintInfo: PHintInfo; + ) + ); + 11: + ( // CM_CONTROLLISTCHANGE | CM_(CONTROL)CHANGED (| CM_BUTTONPRESSED for clx) + Control: TControl; // WParam + case Integer of + 0: + ( // CM_(CONTROL)CHANGED + Inserting: LongBool; // LParam + ); + 1: // CM_BUTTONPRESSED (clx) + ( + Index: Integer; + ) + ); + 12: + ( // CM_HINTSHOWPAUSE + WasActive: LongBool; + Pause: PInteger; + ); + 13: + ( // WM_KEY + CharCode: Word; + NotUsed: Word; + KeyData: Integer; + ); + 14: + ( // WM_GETTEXT + TextMax: Integer; + Text: PChar + ); + 15: + ( // WM_ERASEBKGND | WM_PAINT + DC: HDC; + ); + 16: + ( // WM_KILLFOCUS + FocusedWnd: HWND; + ); + 17: + ( + NewSize: TSmallPoint; //CM_FORCESIZE wParam + ); + 18: + ( { alternative naming for VCL CM_BUTTONPRESSED } + GroupIndex: Integer; + Button: TControl; + ); + end; +{$ENDIF !CLR} +***************) + +implementation + +(*************** +{$IFDEF COMPILER6_UP} +constructor TJvPersistent.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + + SetSubComponent(True); + Name := 'SubComponent'; +end; +{$ENDIF COMPILER6_UP} + +{ TJvPersistentProperty } + +procedure TJvPersistentProperty.BeginUpdate; +begin + if FUpdateCount = 0 then + SetUpdateState(True); + Inc(FUpdateCount); +end; + +procedure TJvPersistentProperty.Changed; +begin + if (FUpdateCount = 0) and Assigned(FOnChange) then + FOnChange(Self); +end; + +procedure TJvPersistentProperty.ChangedProperty(const PropName: string); +begin + if Assigned(FOnChangeProperty) then + FOnChangeProperty(Self, PropName); +end; + +procedure TJvPersistentProperty.Changing; +begin + if (FUpdateCount = 0) and Assigned(FOnChanging) then + FOnChanging(Self); +end; + +procedure TJvPersistentProperty.ChangingProperty(const PropName: string); +begin + if Assigned(FOnChangingProperty) then + FOnChangingProperty(Self, PropName); +end; + +procedure TJvPersistentProperty.EndUpdate; +begin + Dec(FUpdateCount); + if FUpdateCount = 0 then + SetUpdateState(False); +end; + +procedure TJvPersistentProperty.SetUpdateState(Updating: Boolean); +begin + if Updating then + Changing + else + Changed; +end; +***************) + +end. + diff --git a/components/jvcllaz/run/JvXPBar.pas b/components/jvcllaz/run/JvXPBar.pas new file mode 100644 index 000000000..5f176e804 --- /dev/null +++ b/components/jvcllaz/run/JvXPBar.pas @@ -0,0 +1,2336 @@ +{----------------------------------------------------------------------------- +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: JvXPBar.PAS, released on 2004-01-01. + +The Initial Developer of the Original Code is Marc Hoffman. +Portions created by Marc Hoffman are Copyright (C) 2002 APRIORI business solutions AG. +Portions created by APRIORI business solutions AG are Copyright (C) 2002 APRIORI business solutions AG +All Rights Reserved. + +Contributor(s): dejoy + //dejoy 2004-4-20 + --add GroupIndex,AutoCheck,Checked property in TJvXPBarItem. + --add GetItemClass in TJvXPBarItems. + --add GetBarItemsClass in TJvXPCustomWinXPBar. + +Contributor(s): dierk schmid + //dierk 2004-4-23 + --add property RoundedItemFrame in TJvXPCustomWinXPBar (Integer>0 is the edge radius) + --add property ItemFrameColor in TJvXPBarColors + //dejoy 2004-4-25 + -- splitt ItemFrameColor to CheckedFrameColor , FocusedFrameColor in TJvXPBarColors. + +Contributors(s): matej golob + //matej 2004-5-3 + --add property BorderColor in TJvXPBarColors. + --add property HeaderRounded + --add property TopSpace + +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: +-----------------------------------------------------------------------------} +// $Id: JvXPBar.pas 11400 2007-06-28 21:24:06Z ahuser $ + +// Ported to Lazarus (no too hard after all) by Sergio Samayoa - september 2007. +// Still dont tested on linux. + +{$mode objfpc}{$H+} + +unit JvXPBar; + +interface + +uses + ActnList, Classes, Controls, Graphics, ExtCtrls, Forms, ImgList, + LCLIntf, LCLProc, LCLType, LMessages, LResources, SysUtils, + JvXPCore, JvXPCoreUtils; + +type + TJvXPBarRollDirection = (rdExpand, rdCollapse); + + TJvXPBarRollMode = (rmFixed, rmShrink); // rmFixed is default + + TJvXPBarHitTest = + ( + htNone, // mouse is inside non-supported rect + htHeader, // mouse is inside header + htRollButton // mouse is inside rollbutton + ); + + TJvXPBarRollDelay = 1..200; + TJvXPBarRollStep = 1..50; + +const + WM_XPBARAFTERCOLLAPSE = WM_USER + 303; // Ord('J') + Ord('V') + Ord('C') + Ord('L') + WM_XPBARAFTEREXPAND = WM_XPBARAFTERCOLLAPSE + 1; + + { color constants. + } + +// dxColor_CheckedColorXP := TColor($00c9b4e2); +// dxColor_CheckedColorXP := TColor($00d9c1bb); +// dxColor_CheckedColorXP := TColor($00e8ccae); + + dxColor_FocusedColorXP = TColor($00D8ACB0); + dxColor_CheckedColorXP = TColor($00D9C1BB); + dxColor_BodyColorXP = TColor($00F7DFD6); + clHotLight = TColor(COLOR_HOTLIGHT or $80000000); + + dxColor_FocusedFrameColorXP = clHotLight; + dxColor_CheckedFrameColorXP = clHighlight; + +type + TJvXPBarItem = class; + TJvXPBarItems = class; + TJvXPCustomWinXPBar = class; + + TJvXPBarOnCanChangeEvent = procedure(Sender: TObject; Item: TJvXPBarItem; + var AllowChange: Boolean) of object; + + TJvXPBarOnCollapsedChangeEvent = procedure(Sender: TObject; + Collapsing: Boolean) of object; + + TJvXPBarOnDrawItemEvent = procedure(Sender: TObject; ACanvas: TCanvas; + Rect: TRect; State: TJvXPDrawState; Item: TJvXPBarItem; Bitmap: TBitmap) of object; + TJvXPBarOwnerDrawEvent = procedure(Sender: TObject; ACanvas: TCanvas; var ARect: TRect) of object; + + TJvXPBarOnItemClickEvent = procedure(Sender: TObject; Item: TJvXPBarItem) of object; + + TJvXPBarItemActionLink = class(TActionLink) + private + FClient: TJvXPBarItem; + protected + procedure AssignClient(AClient: TObject); override; + function IsCaptionLinked: Boolean; override; + function IsCheckedLinked: Boolean; override; + function IsEnabledLinked: Boolean; override; + function IsHintLinked: Boolean; override; + function IsImageIndexLinked: Boolean; override; + function IsVisibleLinked: Boolean; override; + function IsOnExecuteLinked: Boolean; override; + procedure SetCaption(const Value: string); override; + procedure SetHint(const Value: string); override; + function DoShowHint(var HintStr: string): Boolean; virtual; + function IsAutoCheckLinked: Boolean; virtual; + procedure SetAutoCheck(Value: Boolean); override; + procedure SetChecked(Value: Boolean); override; + procedure SetEnabled(Value: Boolean); override; + procedure SetImageIndex(Value: Integer); override; + procedure SetVisible(Value: Boolean); override; + procedure SetOnExecute(Value: TNotifyEvent); override; + property Client: TJvXPBarItem read FClient write FClient; + end; + + TJvXPBarItemActionLinkClass = class of TJvXPBarItemActionLink; + + TJvXPBarItemClass = class of TJvXPBarItem; + + TJvXPBarItem = class(TCollectionItem) + private + FActionLink: TJvXPBarItemActionLink; + FCollection: TJvXPBarItems; + FCaption: TCaption; + FData: Pointer; + FDataObject: TObject; + FEnabled: Boolean; + FHint: string; + FImageIndex: TImageIndex; + FImageList: TCustomImageList; + FName: string; + FWinXPBar: TJvXPCustomWinXPBar; + FTag: Integer; + FVisible: Boolean; + FOnClick: TNotifyEvent; + FOnDblClick: TNotifyEvent; + FGroupIndex: Integer; + FChecked: Boolean; + FAutoCheck: Boolean; + function IsAutoCheckStored: Boolean; + function IsCaptionStored: Boolean; + function IsEnabledStored: Boolean; + function IsHintStored: Boolean; + function IsImageIndexStored: Boolean; + function IsVisibleStored: Boolean; + function IsOnClickStored: Boolean; + function IsCheckedStored: Boolean; + function GetImages: TCustomImageList; + procedure DoActionChange(Sender: TObject); + procedure SetAction(Value: TBasicAction); + procedure SetCaption(Value: TCaption); + procedure SetEnabled(Value: Boolean); + procedure SetImageIndex(Value: TImageIndex); + procedure SetImageList(Value: TCustomImageList); + procedure SetName(const Value: string); + procedure SetVisible(Value: Boolean); + procedure SetGroupIndex(const Value: Integer); + procedure SetChecked(const Value: Boolean); + procedure TurnSiblingsOff; + protected + function GetActionLinkClass: TJvXPBarItemActionLinkClass; dynamic; + function GetAction: TBasicAction; virtual; + function GetDisplayName: string; override; + procedure Notification(AComponent: TComponent); virtual; + procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); dynamic; + + procedure DrawItem(AWinXPBar: TJvXPCustomWinXPBar; ACanvas: TCanvas; + Rect: TRect; State: TJvXPDrawState; ShowItemFrame: Boolean; Bitmap: TBitmap); virtual; + property ActionLink: TJvXPBarItemActionLink read FActionLink write FActionLink; + public + constructor Create(ACollection: TCollection); override; + destructor Destroy; override; + procedure Assign(Source: TPersistent); override; + property Data: Pointer read FData write FData; + property DataObject: TObject read FDataObject write FDataObject; + property Images: TCustomImageList read GetImages; + property WinXPBar: TJvXPCustomWinXPBar read FWinXPBar; + published + property Action: TBasicAction read GetAction write SetAction; + property AutoCheck: Boolean read FAutoCheck write FAutoCheck + stored IsAutoCheckStored default False; + property Caption: TCaption read FCaption write SetCaption stored IsCaptionStored; + property Checked: Boolean read FChecked write SetChecked stored IsCheckedStored default False; + property Enabled: Boolean read FEnabled write SetEnabled stored IsEnabledStored default True; + property GroupIndex: Integer read FGroupIndex write SetGroupIndex default 0; + property Hint: string read FHint write FHint stored IsHintStored; + property ImageIndex: TImageIndex read FImageIndex write SetImageIndex stored IsImageIndexStored default -1; + property ImageList: TCustomImageList read FImageList write SetImageList; + property Name: string read FName write SetName; + property Tag: Integer read FTag write FTag default 0; + property Visible: Boolean read FVisible write SetVisible stored IsVisibleStored default True; + property OnClick: TNotifyEvent read FOnClick write FOnClick stored IsOnClickStored; + property OnDblClick: TNotifyEvent read FOnDblClick write FOnDblClick; + end; + + TJvXPBarItemsClass = class of TJvXPBarItems; + + TJvXPBarItems = class(TCollection) + private + FWinXPBar: TJvXPCustomWinXPBar; + function GetItem(Index: Integer): TJvXPBarItem; + procedure SetItem(Index: Integer; Value: TJvXPBarItem); + protected + procedure Update(Item: TCollectionItem); override; + function GetOwner: TPersistent; override; + class function GetItemClass: TJvXPBarItemClass; virtual; + public + constructor Create(WinXPBar: TJvXPCustomWinXPBar); + function Add: TJvXPBarItem; overload; + function Add(Action: TBasicAction): TJvXPBarItem; overload; + function Add(DataObject: TObject): TJvXPBarItem; overload; + function Insert(Index: Integer): TJvXPBarItem; overload; + function Insert(Index: Integer; Action: TBasicAction): TJvXPBarItem; overload; + function Insert(Index: Integer; DataObject: TObject): TJvXPBarItem; overload; + function Find(const AName: string): TJvXPBarItem; overload; + function Find(const Action: TBasicAction): TJvXPBarItem; overload; + function Find(const DataObject: TObject): TJvXPBarItem; overload; + property Items[Index: Integer]: TJvXPBarItem read GetItem write SetItem; default; + end; + + TJvXPBarVisibleItems = class(TPersistent) + private + FItems: TList; + FWinXPBar: TJvXPCustomWinXPBar; + function Exists(Item: TJvXPBarItem): Boolean; + function GetItem(Index: Integer): TJvXPBarItem; + procedure Add(Item: TJvXPBarItem); + procedure Delete(Item: TJvXPBarItem); + public + constructor Create(WinXPBar: TJvXPCustomWinXPBar); + destructor Destroy; override; + function Count: Integer; + property Items[Index: Integer]: TJvXPBarItem read GetItem; default; + end; + + TJvXPFadeThread = class(TThread) + private + FWinXPBar: TJvXPCustomWinXPBar; + FRollDirection: TJvXPBarRollDirection; + FWinXPBarNewOffSet: Integer; + protected + procedure DoWinXPBarSetRollOffset; + procedure DoWinXPBarInternalRedraw; + public + constructor Create(WinXPBar: TJvXPCustomWinXPBar; RollDirection: TJvXPBarRollDirection); + procedure Execute; override; + end; + + TJvXPBarColors = class(TPersistent) + private + FCheckedFrameColor: TColor; + FFocusedFrameColor: TColor; + FCheckedColor: TColor; + FFocusedColor: TColor; + FBodyColor: TColor; + FBodyBorderColor: TColor; + FGradientTo: TColor; + FGradientFrom: TColor; + FSeparatorColor: TColor; + FBorderColor: TColor; + FOnChange: TNotifyEvent; + procedure SetBorderColor(const Value: TColor); + procedure SetBodyColor(const Value: TColor); + procedure SetGradientFrom(const Value: TColor); + procedure SetGradientTo(const Value: TColor); + procedure SetSeparatorColor(const Value: TColor); + procedure SetCheckedColor(const Value: TColor); + procedure SetFocusedColor(const Value: TColor); + procedure SetCheckedFrameColor(const Value: TColor); + procedure SetFocusedFrameColor(const Value: TColor); + procedure SetBodyBorderColor(const Value: TColor); + public + constructor Create; + procedure Assign(Source: TPersistent); override; + procedure Change; + published + property BorderColor: TColor read FBorderColor write SetBorderColor default clWhite; + property CheckedColor: TColor read FCheckedColor write SetCheckedColor default dxColor_CheckedColorXP; + property FocusedColor: TColor read FFocusedColor write SetFocusedColor default dxColor_FocusedColorXP; + property CheckedFrameColor: TColor read FCheckedFrameColor write SetCheckedFrameColor + default dxColor_CheckedFrameColorXP; + property FocusedFrameColor: TColor read FFocusedFrameColor write SetFocusedFrameColor + default dxColor_FocusedFrameColorXP; + property BodyColor: TColor read FBodyColor write SetBodyColor default dxColor_BodyColorXP; + property BodyBorderColor: TColor read FBodyBorderColor write SetBodyBorderColor default dxColor_BodyColorXP; + property GradientFrom: TColor read FGradientFrom write SetGradientFrom default clWhite; + property GradientTo: TColor read FGradientTo write SetGradientTo default TColor($00F7D7C6); + property SeparatorColor: TColor read FSeparatorColor write SetSeparatorColor default TColor($00F7D7C6); + property OnChange: TNotifyEvent read FOnChange write FOnChange; + end; + + TJvXPBarOptions = class(TPersistent) + end; + + TJvXPCustomWinXPBar = class(TJvXPCustomControl) + private + FCollapsed: Boolean; + FFadeThread: TJvXPFadeThread; + FFont: TFont; + FFontChanging: Boolean; + FGradientWidth: Integer; + FHeaderFont: TFont; + FHeaderRounded: Boolean; + FHitTest: TJvXPBarHitTest; + FHotTrack: Boolean; + FHoverIndex: Integer; + FIcon: TIcon; + FImageList: TCustomImageList; + FItemHeight: Integer; + FItems: TJvXPBarItems; + FRollDelay: TJvXPBarRollDelay; + FRolling: Boolean; + FRollMode: TJvXPBarRollMode; + FRollOffset: Integer; + FRollStep: TJvXPBarRollStep; + FShowLinkCursor: Boolean; + FShowRollButton: Boolean; + FHotTrackColor: TColor; + FVisibleItems: TJvXPBarVisibleItems; + FAfterCollapsedChange: TJvXPBarOnCollapsedChangeEvent; + FBeforeCollapsedChange: TJvXPBarOnCollapsedChangeEvent; + FOnCollapsedChange: TJvXPBarOnCollapsedChangeEvent; + FOnCanChange: TJvXPBarOnCanChangeEvent; + FOnDrawItem: TJvXPBarOnDrawItemEvent; + FOnItemClick: TJvXPBarOnItemClickEvent; + FColors: TJvXPBarColors; + FRollImages: TCustomImageList; + FImageChangeLink: TChangeLink; + FRollChangeLink: TChangeLink; + FGrouped: Boolean; + FHeaderHeight: Integer; + FStoredHint: string; + FShowItemFrame: Boolean; + FRoundedItemFrame: Integer; // DS + FTopSpace: Integer; + FOwnerDraw: Boolean; + FOnDrawBackground: TJvXPBarOwnerDrawEvent; + FOnDrawHeader: TJvXPBarOwnerDrawEvent; + procedure FontChange(Sender: TObject); + procedure SetCollapsed(Value: Boolean); + procedure SetFont(Value: TFont); + procedure SetHeaderFont(Value: TFont); + procedure SetHotTrack(Value: Boolean); + procedure SetHotTrackColor(Value: TColor); + procedure SetIcon(Value: TIcon); + procedure SetImageList(Value: TCustomImageList); + procedure SetItemHeight(Value: Integer); + procedure SetItems(Value: TJvXPBarItems); + procedure SetRollOffset(const Value: Integer); + procedure SetShowRollButton(Value: Boolean); + procedure ResizeToMaxHeight; + procedure SetColors(const Value: TJvXPBarColors); + procedure SetRollImages(const Value: TCustomImageList); + procedure SetGrouped(const Value: Boolean); + procedure GroupMessage; + procedure SetHeaderHeight(const Value: Integer); + function GetRollHeight: Integer; + function GetRollWidth: Integer; + procedure SetHeaderRounded(const Value: Boolean); + procedure SetTopSpace(const Value: Integer); + procedure SetOwnerDraw(const Value: Boolean); + protected + procedure CMDialogChar(var Msg: TCMDialogChar); message CM_DIALOGCHAR; + class function GetBarItemsClass: TJvXPBarItemsClass; virtual; + function GetHitTestRect(const HitTest: TJvXPBarHitTest): TRect; + function GetItemRect(Index: Integer): TRect; virtual; + procedure ItemVisibilityChanged(Item: TJvXPBarItem); dynamic; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure HookMouseDown; override; + procedure HookMouseEnter; override; + procedure HookMouseLeave; override; + procedure HookMouseMove(X: Integer = 0; Y: Integer = 0); override; + procedure HookParentFontChanged; override; + procedure HookResized; override; + procedure SortVisibleItems(const Redraw: Boolean); + procedure DoColorsChange(Sender: TObject); + procedure DoDrawItem(const Index: Integer; State: TJvXPDrawState); virtual; + procedure Paint; override; + procedure EndUpdate; override; + procedure WMAfterXPBarCollapse(var Msg: TLMessage); message WM_XPBARAFTERCOLLAPSE; + procedure WMAfterXPBarExpand(var Msg: TLMessage); message WM_XPBARAFTEREXPAND; + property Collapsed: Boolean read FCollapsed write SetCollapsed default False; + property Colors: TJvXPBarColors read FColors write SetColors; + property RollImages: TCustomImageList read FRollImages write SetRollImages; + property Font: TFont read FFont write SetFont; + property Grouped: Boolean read FGrouped write SetGrouped default False; + property HeaderFont: TFont read FHeaderFont write SetHeaderFont stored; + property HeaderHeight: Integer read FHeaderHeight write SetHeaderHeight default 28; + property HeaderRounded: Boolean read FHeaderRounded write SetHeaderRounded default True; + property OwnerDraw: Boolean read FOwnerDraw write SetOwnerDraw; + property HotTrack: Boolean read FHotTrack write SetHotTrack default True; + property HotTrackColor: TColor read FHotTrackColor write SetHotTrackColor default $00FF7C35; + property Icon: TIcon read FIcon write SetIcon; + property ImageList: TCustomImageList read FImageList write SetImageList; + property ItemHeight: Integer read FItemHeight write SetItemHeight default 20; + property Items: TJvXPBarItems read FItems write SetItems; + property RollDelay: TJvXPBarRollDelay read FRollDelay write FRollDelay default 25; + property Rolling: Boolean read FRolling default False; + property RollMode: TJvXPBarRollMode read FRollMode write FRollMode default rmShrink; + property RollOffset: Integer read FRollOffset write SetRollOffset; + property RollStep: TJvXPBarRollStep read FRollStep write FRollStep default 3; + property ShowLinkCursor: Boolean read FShowLinkCursor write FShowLinkCursor default True; + property ShowRollButton: Boolean read FShowRollButton write SetShowRollButton default True; + property ShowItemFrame: Boolean read FShowItemFrame write FShowItemFrame; + property RoundedItemFrame: Integer read FRoundedItemFrame write FRoundedItemFrame default 1; //DS + property TopSpace: Integer read FTopSpace write SetTopSpace default 5; + property AfterCollapsedChange: TJvXPBarOnCollapsedChangeEvent read FAfterCollapsedChange + write FAfterCollapsedChange; + property BeforeCollapsedChange: TJvXPBarOnCollapsedChangeEvent read FBeforeCollapsedChange + write FBeforeCollapsedChange; + property OnCollapsedChange: TJvXPBarOnCollapsedChangeEvent read FOnCollapsedChange write FOnCollapsedChange; + property OnCanChange: TJvXPBarOnCanChangeEvent read FOnCanChange write FOnCanChange; + property OnDrawItem: TJvXPBarOnDrawItemEvent read FOnDrawItem write FOnDrawItem; + property OnDrawBackground: TJvXPBarOwnerDrawEvent read FOnDrawBackground write FOnDrawBackground; + property OnDrawHeader: TJvXPBarOwnerDrawEvent read FOnDrawHeader write FOnDrawHeader; + property OnItemClick: TJvXPBarOnItemClickEvent read FOnItemClick write FOnItemClick; + procedure AdjustClientRect(var Rect: TRect); override; + // show hints for individual items in the list + function HintShow(var HintInfo: THintInfo): Boolean; dynamic; + procedure CMHintShow(var Msg: TCMHintShow); message CM_HINTSHOW; + procedure DblClick; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function GetHitTestAt(X, Y: Integer): TJvXPBarHitTest; + function GetItemAt(X, Y: Integer): Integer; + procedure Click; override; + property Height default 46; + property VisibleItems: TJvXPBarVisibleItems read FVisibleItems; + property Width default 153; + procedure InitiateAction; override; + end; + + TJvXPBar = class(TJvXPCustomWinXPBar) + published + property Caption; + property Collapsed; + property Colors; + property Items; + property RollImages; + property Font; + property Grouped; + property HeaderFont; + property HeaderHeight; + property HeaderRounded; + property HotTrack; + property HotTrackColor; + property OwnerDraw; + property Icon; + property ImageList; + property ItemHeight; + property RollDelay; + property RollMode; + property RollStep; + property ShowLinkCursor; + property ShowRollButton; + property ShowItemFrame; + property RoundedItemFrame; + property TopSpace; + + property AfterCollapsedChange; + property BeforeCollapsedChange; + property OnCollapsedChange; + property OnCanChange; + property OnDrawItem; + property OnDrawBackground; + property OnDrawHeader; + property OnItemClick; + + //property BevelInner; + //property BevelOuter; + //property BevelWidth; + //property BiDiMode; + //property Ctl3D; + //property DockSite; + //property ParentBiDiMode; + //property ParentCtl3D; + //property TabOrder; + //property TabStop; + //property UseDockManager default True; + property Align; + property Anchors; + //property AutoSize; + property Constraints; + property DragCursor; + property DragKind; + //21.09.07 - SESS + //property OnCanResize; + property DragMode; + //property Enabled; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowHint; + property Visible; + //property OnDockDrop; + //property OnDockOver; + //property OnEndDock; + //property OnGetSiteInfo; + //property OnStartDock; + //property OnUnDock; + property OnClick; + property OnDblClick; + property OnConstrainedResize; + property OnContextPopup; + 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; + end; + +procedure RoundedFrame(Canvas: TCanvas; ARect: TRect; AColor: TColor; R: Integer); + +implementation + +uses + Menus; + +resourcestring + RsUntitled = 'untitled'; + RsUntitledFmt = '(%s %d)'; + RsHintShortcutFmt = '%s (%s)'; + +const + FC_HEADER_MARGIN = 6; + FC_ITEM_MARGIN = 8; + +function SortByIndex(Item1, Item2: Pointer): Integer; +var + Idx1, Idx2: Integer; +begin + Idx1 := TCollectionItem(Item1).Index; + Idx2 := TCollectionItem(Item2).Index; + if Idx1 < Idx2 then + Result := -1 + else + if Idx1 = Idx2 then + Result := 0 + else + Result := 1; +end; + +//=== { TJvXPBarItemActionLink } ============================================= + +procedure TJvXPBarItemActionLink.AssignClient(AClient: TObject); +begin + Client := AClient as TJvXPBarItem; +end; + + +function TJvXPBarItemActionLink.IsAutoCheckLinked: Boolean; +begin + Result := (Client.AutoCheck = (Action as TCustomAction).AutoCheck); +end; + +function TJvXPBarItemActionLink.IsCaptionLinked: Boolean; +begin + Result := inherited IsCaptionLinked and + (Client.Caption = (Action as TCustomAction).Caption); +end; + +function TJvXPBarItemActionLink.IsCheckedLinked: Boolean; +begin + Result := inherited IsCheckedLinked and + (Client.Checked = (Action as TCustomAction).Checked); +end; + +function TJvXPBarItemActionLink.IsEnabledLinked: Boolean; +begin + Result := inherited IsEnabledLinked and + (Client.Enabled = (Action as TCustomAction).Enabled); +end; + +function TJvXPBarItemActionLink.IsHintLinked: Boolean; +begin + Result := inherited IsHintLinked and + (Client.Hint = (Action as TCustomAction).Hint); +end; + +function TJvXPBarItemActionLink.IsImageIndexLinked: Boolean; +begin + Result := inherited IsImageIndexLinked and + (Client.ImageIndex = (Action as TCustomAction).ImageIndex); +end; + +function TJvXPBarItemActionLink.IsVisibleLinked: Boolean; +begin + Result := inherited IsVisibleLinked and + (Client.Visible = (Action as TCustomAction).Visible); +end; + +function TJvXPBarItemActionLink.IsOnExecuteLinked: Boolean; +begin + Result := inherited IsOnExecuteLinked and + JvXPMethodsEqual(TMethod(Client.OnClick), TMethod(Action.OnExecute)); +end; + +procedure TJvXPBarItemActionLink.SetAutoCheck(Value: Boolean); +begin + if IsAutoCheckLinked then + Client.AutoCheck := Value; +end; + +procedure TJvXPBarItemActionLink.SetCaption(const Value: string); +begin + if IsCaptionLinked then + Client.Caption := Value; +end; + +procedure TJvXPBarItemActionLink.SetEnabled(Value: Boolean); +begin + if IsEnabledLinked then + Client.Enabled := Value; +end; + +procedure TJvXPBarItemActionLink.SetChecked(Value: Boolean); +begin + if IsCheckedLinked then + Client.Checked := Value; +end; + + +procedure TJvXPBarItemActionLink.SetHint(const Value: string); +begin + if IsHintLinked then + Client.Hint := Value; +end; + +procedure TJvXPBarItemActionLink.SetImageIndex(Value: Integer); +begin + if IsImageIndexLinked then + Client.ImageIndex := Value; +end; + +procedure TJvXPBarItemActionLink.SetVisible(Value: Boolean); +begin + if IsVisibleLinked then + Client.Visible := Value; +end; + +procedure TJvXPBarItemActionLink.SetOnExecute(Value: TNotifyEvent); +begin + if IsOnExecuteLinked then + Client.OnClick := Value; +end; + +//===TJvXPBarItem ============================================================ + +constructor TJvXPBarItem.Create(ACollection: TCollection); +begin + inherited Create(ACollection); + FCollection := TJvXPBarItems(ACollection); + FCaption := ''; + FData := nil; + FDataObject := nil; + FEnabled := True; + FImageIndex := -1; + FImageList := nil; + FHint := ''; + FName := ''; + FWinXPBar := FCollection.FWinXPBar; + FTag := 0; + FVisible := True; + FAutoCheck := False; + FChecked := False; + FGroupIndex := 0; + FWinXPBar.ItemVisibilityChanged(Self); + FWinXPBar.ResizeToMaxHeight; +end; + +destructor TJvXPBarItem.Destroy; +begin + FVisible := False; // required to remove from visible list! + FWinXPBar.ItemVisibilityChanged(Self); + FActionLink.Free; + FActionLink := nil; + + inherited Destroy; + FWinXPBar.ResizeToMaxHeight; +end; + +procedure TJvXPBarItem.Notification(AComponent: TComponent); +begin + if AComponent = Action then + Action := nil; + if AComponent = FImageList then + FImageList := nil; +end; + +function TJvXPBarItem.GetDisplayName: string; +var + _DisplayName, ItemName: string; +begin + _DisplayName := FCaption; + if _DisplayName = '' then + _DisplayName := RsUntitled; + ItemName := FName; + if ItemName <> '' then + DisplayName := DisplayName + ' [' + ItemName + ']'; + if not FVisible then + _DisplayName := _DisplayName + '*'; + Result := _DisplayName; +end; + +function TJvXPBarItem.GetImages: TCustomImageList; +begin + Result := nil; + if Assigned(FImageList) then + Result := FImageList + else + if Assigned(Action) and Assigned(TAction(Action).ActionList.Images) then + Result := TAction(Action).ActionList.Images + else + if Assigned(FWinXPBar.FImageList) then + Result := FWinXPBar.FImageList; +end; + +procedure TJvXPBarItem.ActionChange(Sender: TObject; CheckDefaults: Boolean); +begin + if Sender is TCustomAction then + with TCustomAction(Sender) do + begin + if not (csLoading in ComponentState) then + Update; + if not CheckDefaults or not Self.AutoCheck then + Self.AutoCheck := AutoCheck; + if not CheckDefaults or (Self.Caption = '') or (Self.Caption = Self.Name) then + Self.Caption := Caption; + if not CheckDefaults or not Self.Checked then + Self.Checked := Checked; + if not CheckDefaults or Self.Enabled then + Self.Enabled := Enabled; + if not CheckDefaults or (Self.Hint = '') then + Self.Hint := Hint; + if not CheckDefaults or (Self.ImageIndex = -1) then + Self.ImageIndex := ImageIndex; + if not CheckDefaults or Self.Visible then + Self.Visible := Visible; + if not CheckDefaults or not Assigned(Self.OnClick) then + Self.OnClick := OnExecute; + end; +end; + +procedure TJvXPBarItem.DrawItem(AWinXPBar: TJvXPCustomWinXPBar; ACanvas: TCanvas; + Rect: TRect; State: TJvXPDrawState; ShowItemFrame: Boolean; Bitmap: TBitmap); +var + ItemCaption: TCaption; + HasImages: Boolean; + LBar: TJvXPCustomWinXPBar; +begin + LBar := (AWinXPBar as TJvXPCustomWinXPBar); + HasImages := Self.Images <> nil; + with ACanvas do + begin + Font.Assign(LBar.Font); + Brush.Color := LBar.Colors.BodyColor; + if not ShowItemFrame then + FillRect(Rect); + if not Self.Enabled then + Font.Color := clGray + else + begin + if dsFocused in State then + begin + if LBar.HotTrack then + begin + if LBar.FHotTrackColor <> clNone then + Font.Color := LBar.FHotTrackColor; + Font.Style := Font.Style + [fsUnderline]; + end; + if ShowItemFrame then + begin + Brush.Color := LBar.Colors.FocusedColor; + if LBar.RoundedItemFrame > 0 then + RoundedFrame(ACanvas, Rect, LBar.Colors.FocusedFrameColor, LBar.RoundedItemFrame) + else + begin + FillRect(Rect); + JvXPFrame3D(ACanvas, Rect, LBar.Colors.FocusedFrameColor, LBar.Colors.FocusedFrameColor); + end; + end; + end + else + if dsClicked in State then + begin + if ShowItemFrame then + begin + Brush.Color := LBar.Colors.CheckedColor; + if LBar.RoundedItemFrame > 0 then + RoundedFrame(ACanvas, Rect, LBar.Colors.CheckedFrameColor, LBar.RoundedItemFrame) + else + begin + FillRect(Rect); + JvXPFrame3D(ACanvas, Rect, LBar.Colors.CheckedFrameColor, LBar.Colors.CheckedFrameColor); + end; + end; + end + else + FillRect(Rect); + end; + if HasImages then + begin + if (Self.ImageIndex <> -1) then + Self.Images.Draw(ACanvas, Rect.Left + 1, + Rect.Top + (LBar.FItemHeight - Bitmap.Height) div 2, Self.ImageIndex); + //Original: + //Draw(Rect.Left + 1, Rect.Top + (LBar.FItemHeight - Bitmap.Height) div 2, Bitmap); + Inc(Rect.Left, Self.Images.Width + 4); + end + else + Inc(Rect.Left, 4); + ItemCaption := Self.Caption; + if (ItemCaption = '') and ((csDesigning in LBar.ComponentState) or (LBar.ControlCount = 0)) then + ItemCaption := Format(RsUntitledFmt, [RsUntitled, Index]); + DrawText(ACanvas.Handle, PAnsiChar(ItemCaption), Length(ItemCaption), Rect, + DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS); + end; +end; + +function TJvXPBarItem.GetActionLinkClass: TJvXPBarItemActionLinkClass; +begin + Result := TJvXPBarItemActionLink; +end; + +procedure TJvXPBarItem.Assign(Source: TPersistent); +begin + if Source is TJvXPBarItem then + with TJvXPBarItem(Source) do + begin + Self.Action := Action; + Self.Caption := Caption; + Self.Data := Data; + Self.DataObject := DataObject; + Self.Enabled := Enabled; + Self.Hint := Hint; + Self.ImageList := ImageList; + Self.ImageIndex := ImageIndex; + Self.Name := Name; + Self.Tag := Tag; + Self.Visible := Visible; + Self.OnClick := OnClick; + Self.AutoCheck := AutoCheck; + Self.Checked := Checked; + Self.GroupIndex := GroupIndex; + Self.OnDblClick := OnDblClick; + end + else + inherited Assign(Source); +end; + +function TJvXPBarItem.IsAutoCheckStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsAutoCheckLinked; +end; + +function TJvXPBarItem.IsCaptionStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsCaptionLinked; +end; + +function TJvXPBarItem.IsEnabledStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsEnabledLinked; +end; + +function TJvXPBarItem.IsHintStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsHintLinked; +end; + +function TJvXPBarItem.IsImageIndexStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsImageIndexLinked; +end; + +function TJvXPBarItem.IsVisibleStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsVisibleLinked; +end; + +function TJvXPBarItem.IsOnClickStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsOnExecuteLinked; +end; + +function TJvXPBarItem.IsCheckedStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsCheckedLinked; +end; + +procedure TJvXPBarItem.DoActionChange(Sender: TObject); +begin + if Sender = Action then + ActionChange(Sender, False); +end; + +function TJvXPBarItem.GetAction: TBasicAction; +begin + if FActionLink <> nil then + Result := FActionLink.Action + else + Result := nil; +end; + +procedure TJvXPBarItem.SetAction(Value: TBasicAction); +begin + if Value = nil then + begin + FActionLink.Free; + FActionLink := nil; + FWinXPBar.InternalRedraw; // redraw image + end + else + begin + if FActionLink = nil then + FActionLink := GetActionLinkClass.Create(Self); + FActionLink.Action := Value; + FActionLink.OnChange := @DoActionChange; + ActionChange(Value, csLoading in Value.ComponentState); + Value.FreeNotification(FWinXPBar); // deligates notification to WinXPBar! + end; +end; + +procedure TJvXPBarItem.SetCaption(Value: TCaption); +begin + if Value <> FCaption then + begin + FCaption := Value; + FWinXPBar.InternalRedraw; + end; +end; + +procedure TJvXPBarItem.SetEnabled(Value: Boolean); +begin + if Value <> FEnabled then + begin + FEnabled := Value; + FWinXPBar.InternalRedraw; + end; +end; + +procedure TJvXPBarItem.SetImageIndex(Value: TImageIndex); +begin + if Value <> FImageIndex then + begin + FImageIndex := Value; + FWinXPBar.InternalRedraw; + end; +end; + +procedure TJvXPBarItem.SetImageList(Value: TCustomImageList); +begin + if Value <> FImageList then + begin + FImageList := Value; + FWinXPBar.InternalRedraw; + end; +end; + +procedure TJvXPBarItem.SetName(const Value: string); +begin + if (Value <> FName) and (FCollection.Find(Value) = nil) then + FName := Value; +end; + +procedure TJvXPBarItem.SetVisible(Value: Boolean); +begin + if Value <> FVisible then + begin + FVisible := Value; + FWinXPBar.ItemVisibilityChanged(Self); + FWinXPBar.ResizeToMaxHeight; + end; +end; + +procedure TJvXPBarItem.SetGroupIndex(const Value: Integer); +begin + if FGroupIndex <> Value then + begin + FGroupIndex := Value; + if Checked then + TurnSiblingsOff; + end; +end; + +procedure TJvXPBarItem.SetChecked(const Value: Boolean); +begin + if FChecked <> Value then + begin + FChecked := Value; +// Change(False); + if Value then + TurnSiblingsOff; + end; +end; + +procedure TJvXPBarItem.TurnSiblingsOff; +var + I: Integer; + Item: TJvXPBarItem; +begin + if (GroupIndex <> 0) and Assigned(FWinXPBar) then + begin + for I := 0 to FWinXPBar.Items.Count - 1 do + begin + Item := FWinXPBar.Items[I]; + if (Item <> Self) and (Item.GroupIndex = GroupIndex) then + Item.Checked := False; + end; + end; +end; + +//=== { TJvXPBarItems } ====================================================== + +constructor TJvXPBarItems.Create(WinXPBar: TJvXPCustomWinXPBar); +begin + inherited Create(GetItemClass); + FWinXPBar := WinXPBar; +end; + +function TJvXPBarItems.Add: TJvXPBarItem; +begin + Result := TJvXPBarItem(inherited Add); +end; + +function TJvXPBarItems.Add(Action: TBasicAction): TJvXPBarItem; +begin + Result := Add; + Result.Action := Action; +end; + +function TJvXPBarItems.Add(DataObject: TObject): TJvXPBarItem; +begin + Result := Add; + Result.DataObject := DataObject; +end; + +function TJvXPBarItems.Insert(Index: Integer): TJvXPBarItem; +begin + Result := TJvXPBarItem(inherited Insert(Index)); +end; + +function TJvXPBarItems.Insert(Index: Integer; Action: TBasicAction): TJvXPBarItem; +begin + Result := Insert(Index); + Result.Action := Action; +end; + +function TJvXPBarItems.Insert(Index: Integer; DataObject: TObject): TJvXPBarItem; +begin + Result := Insert(Index); + Result.DataObject := DataObject; +end; + +function TJvXPBarItems.GetOwner: TPersistent; +begin + Result := FWinXPBar; +end; + +class function TJvXPBarItems.GetItemClass: TJvXPBarItemClass; +begin + Result := TJvXPBarItem; +end; + +function TJvXPBarItems.GetItem(Index: Integer): TJvXPBarItem; +begin + Result := TJvXPBarItem(inherited GetItem(Index)); +end; + +procedure TJvXPBarItems.SetItem(Index: Integer; Value: TJvXPBarItem); +begin + inherited SetItem(Index, Value); +end; + +procedure TJvXPBarItems.Update(Item: TCollectionItem); +begin + FWinXPBar.SortVisibleItems(True); +end; + +function TJvXPBarItems.Find(const AName: string): TJvXPBarItem; +var + I: Integer; +begin + Result := nil; + for I := 0 to Count - 1 do + if Items[I].Name = AName then + begin + Result := Items[I]; + Break; + end; +end; + +function TJvXPBarItems.Find(const Action: TBasicAction): TJvXPBarItem; +var + I: Integer; +begin + Result := nil; + for I := 0 to Count - 1 do + if Items[I].Action = Action then + begin + Result := Items[I]; + Break; + end; +end; + +function TJvXPBarItems.Find(const DataObject: TObject): TJvXPBarItem; +var + I: Integer; +begin + Result := nil; + for I := 0 to Count - 1 do + if Items[I].DataObject = DataObject then + begin + Result := Items[I]; + Break; + end; +end; + +//=== { TJvXPBarVisibleItems } =============================================== + +constructor TJvXPBarVisibleItems.Create(WinXPBar: TJvXPCustomWinXPBar); +begin + inherited Create; + FItems := TList.Create; + FWinXPBar := WinXPBar; +end; + +destructor TJvXPBarVisibleItems.Destroy; +begin + FItems.Free; + inherited Destroy; +end; + +function TJvXPBarVisibleItems.GetItem(Index: Integer): TJvXPBarItem; +begin + Result := nil; + if Index < FItems.Count then + Result := TJvXPBarItem(FItems[Index]); +end; + +function TJvXPBarVisibleItems.Count: Integer; +begin + Result := FItems.Count; +end; + +function TJvXPBarVisibleItems.Exists(Item: TJvXPBarItem): Boolean; +var + I: Integer; +begin + Result := False; + for I := 0 to Count - 1 do + if Items[I] = Item then + begin + Result := True; + Break; + end; +end; + +procedure TJvXPBarVisibleItems.Add(Item: TJvXPBarItem); +begin + if not Exists(Item) then + begin + FItems.Add(Item); + FWinXPBar.SortVisibleItems(False); + end; +end; + +procedure TJvXPBarVisibleItems.Delete(Item: TJvXPBarItem); +begin + if Exists(Item) then + FItems.Delete(FItems.IndexOf(Item)); +end; + +//=== { TJvXPFadeThread } ==================================================== + +constructor TJvXPFadeThread.Create(WinXPBar: TJvXPCustomWinXPBar; + RollDirection: TJvXPBarRollDirection); +begin + inherited Create(True); + FWinXPBar := WinXPBar; + FRollDirection := RollDirection; + FreeOnTerminate := True; + Suspended := False; +end; + +procedure TJvXPFadeThread.DoWinXPBarInternalRedraw; +begin + FWinXPBar.InternalRedraw; +end; + +procedure TJvXPFadeThread.DoWinXPBarSetRollOffset; +begin + FWinXPBar.RollOffset := FWinXPBarNewOffSet; +end; + +procedure TJvXPFadeThread.Execute; +var + NewOffset: Integer; +begin + while not Terminated do + try + FWinXPBar.FRolling := True; + + { calculate new roll offset } + if FRollDirection = rdCollapse then + NewOffset := FWinXPBar.RollOffset - FWinXPBar.FRollStep + else + NewOffset := FWinXPBar.RollOffset + FWinXPBar.FRollStep; + + { validate offset ranges } + if NewOffset < 0 then + NewOffset := 0; + if NewOffset > FWinXPBar.FItemHeight then + NewOffset := FWinXPBar.FItemHeight; + + FWinXPBarNewOffSet := NewOffset; + + Synchronize(@DoWinXPBarSetRollOffset); + + { terminate on 'out-of-range' } + if ((FRollDirection = rdCollapse) and (NewOffset = 0)) or + ((FRollDirection = rdExpand) and (NewOffset = FWinXPBar.FItemHeight)) then + Terminate; + + { idle process } + Sleep(FWinXPBar.FRollDelay); + finally + FWinXPBar.FRolling := False; + end; + + { redraw button state } + FWinXPBar.FCollapsed := FRollDirection = rdCollapse; + if FWinXPBar.FShowRollButton then + Synchronize(@DoWinXPBarInternalRedraw); + + { update inspector } + if csDesigning in FWinXPBar.ComponentState then + TCustomForm(FWinXPBar.Owner).Designer.Modified + else + PostMessage(FWinXPBar.Handle, WM_XPBARAFTERCOLLAPSE, + Ord(FRollDirection = rdCollapse), 0); +end; + +//=== { TJvXPBarColors } ===================================================== + +constructor TJvXPBarColors.Create; +begin + inherited Create; + // (rom) needs local color constants + FBodyColor := dxColor_BodyColorXP; + FBodyBorderColor := dxColor_BodyColorXP; + FBorderColor := clWhite; + FGradientFrom := clWhite; + FGradientTo := TColor($00F7D7C6); + FSeparatorColor := TColor($00F7D7C6); + FCheckedColor := dxColor_CheckedColorXP; + FFocusedColor := dxColor_FocusedColorXP; + FCheckedFrameColor := dxColor_CheckedFrameColorXP; + FFocusedFrameColor := dxColor_FocusedFrameColorXP; +end; + +procedure TJvXPBarColors.Assign(Source: TPersistent); +begin + if Source is TJvXPBarColors then + with TJvXPBarColors(Source) do + begin + Self.CheckedColor := CheckedColor; + Self.FocusedColor := FocusedColor; + Self.CheckedFrameColor := CheckedFrameColor; + Self.FocusedFrameColor := FocusedFrameColor; + Self.BodyColor := BodyColor; + Self.GradientTo := GradientTo; + Self.GradientFrom := GradientFrom; + Self.SeparatorColor := SeparatorColor; + end + else + inherited Assign(Source); +end; + +procedure TJvXPBarColors.Change; +begin + if Assigned(FOnChange) then + FOnChange(Self); +end; + +procedure TJvXPBarColors.SetBodyColor(const Value: TColor); +begin + if FBodyColor <> Value then + begin + FBodyColor := Value; + Change; + end; +end; + +procedure TJvXPBarColors.SetGradientFrom(const Value: TColor); +begin + if FGradientFrom <> Value then + begin + FGradientFrom := Value; + Change; + end; +end; + +procedure TJvXPBarColors.SetGradientTo(const Value: TColor); +begin + if FGradientTo <> Value then + begin + FGradientTo := Value; + Change; + end; +end; + +procedure TJvXPBarColors.SetSeparatorColor(const Value: TColor); +begin + if FSeparatorColor <> Value then + begin + FSeparatorColor := Value; + Change; + end; +end; + +procedure TJvXPBarColors.SetCheckedColor(const Value: TColor); +begin + if FCheckedColor <> Value then + begin + FCheckedColor := Value; + Change; + end; +end; + +procedure TJvXPBarColors.SetBorderColor(const Value: TColor); +begin + if FBorderColor <> Value then + begin + FBorderColor := Value; + Change; + end; +end; + +procedure TJvXPBarColors.SetFocusedColor(const Value: TColor); +begin + if FFocusedColor <> Value then + begin + FFocusedColor := Value; + Change; + end; +end; + +procedure TJvXPBarColors.SetCheckedFrameColor(const Value: TColor); +begin + if FCheckedFrameColor <> Value then + begin + FCheckedFrameColor := Value; + Change; + end; +end; + +procedure TJvXPBarColors.SetFocusedFrameColor(const Value: TColor); +begin + if FFocusedFrameColor <> Value then + begin + FFocusedFrameColor := Value; + Change; + end; +end; + +procedure TJvXPBarColors.SetBodyBorderColor(const Value: TColor); +begin + if FBodyBorderColor <> Value then + begin + FBodyBorderColor := Value; + Change; + end; +end; + +//=== { TJvXPCustomWinXPBar } ================================================ + +constructor TJvXPCustomWinXPBar.Create(AOwner: TComponent); +const + MouseEvents: TJvXPControlStyle = [csRedrawMouseEnter, csRedrawMouseLeave]; +begin + inherited Create(AOwner); + FStoredHint := '|'; // no one in their right mind uses a pipe as the only character in a hint... + ControlStyle := ControlStyle {- [csDoubleClicks]} + [csAcceptsControls, csActionClient]; + ExControlStyle := [csRedrawCaptionChanged]; + ExControlStyle := ExControlStyle + MouseEvents; + Height := 46; + HotTrack := True; // initialize mouse events + Width := 153; + FColors := TJvXPBarColors.Create; + FColors.OnChange := @DoColorsChange; + FCollapsed := False; + FFadeThread := nil; + FImageChangeLink := TChangeLink.Create; + FImageChangeLink.OnChange := @DoColorsChange; + FRollChangeLink := TChangeLink.Create; + FRollChangeLink.OnChange := @DoColorsChange; + FTopSpace := 5; + + FFont := TFont.Create; + FFont.Color := $00840000; + FFont.Size := 8; + FFont.OnChange := @FontChange; + FHeaderHeight := 28; + FHeaderRounded := True; + FGradientWidth := 0; + FHeaderFont := TFont.Create; + FHeaderFont.Color := $00840000; + FHeaderFont.Size := 8; + FHeaderFont.Style := [fsBold]; + FHeaderFont.OnChange := @FontChange; + + FHitTest := htNone; + + FHotTrackColor := $00FF7C35; + FHoverIndex := -1; + FIcon := TIcon.Create; + FItemHeight := 20; + FItems := GetBarItemsClass.Create(Self); + FRollDelay := 25; + FRolling := False; + FRollMode := rmShrink; + FRollOffset := FItemHeight; + FRollStep := 3; + FShowLinkCursor := True; + FShowRollButton := True; + FVisibleItems := TJvXPBarVisibleItems.Create(Self); +end; + +destructor TJvXPCustomWinXPBar.Destroy; +begin + FFont.Free; + FHeaderFont.Free; + FIcon.Free; + FItems.Free; + FVisibleItems.Free; + FColors.Free; + FImageChangeLink.Free; + FRollChangeLink.Free; + inherited Destroy; +end; + +procedure TJvXPCustomWinXPBar.Notification(AComponent: TComponent; + Operation: TOperation); +var + I: Integer; +begin + if not (csDestroying in ComponentState) and (Operation = opRemove) then + begin + if AComponent = FImageList then + ImageList := nil; + if AComponent = FRollImages then + RollImages := nil; + for I := 0 to FItems.Count - 1 do + FItems[I].Notification(AComponent); + end; + inherited Notification(AComponent, Operation); +end; + +procedure TJvXPCustomWinXPBar.FontChange(Sender: TObject); +begin + if (not FFontChanging) and not (csLoading in ComponentState) then + ParentFont := False; + InternalRedraw; +end; + +procedure TJvXPCustomWinXPBar.ResizeToMaxHeight; +var + NewHeight: Integer; +begin + { TODO: Check this!!! } + if IsLocked then + Exit; + NewHeight := FC_HEADER_MARGIN + HeaderHeight + FVisibleItems.Count * FRollOffset + FC_ITEM_MARGIN + 1; + { full collapsing } + if ((FRolling and not FCollapsed) or (not FRolling and FCollapsed) or + (FVisibleItems.Count = 0)) then + Dec(NewHeight, FC_ITEM_MARGIN); +// if Height <> NewHeight then + Height := NewHeight - 5 + FTopSpace; +end; + +function TJvXPCustomWinXPBar.GetHitTestAt(X, Y: Integer): TJvXPBarHitTest; +begin + Result := htNone; + if PtInRect(GetHitTestRect(htHeader), Point(X, Y)) then + Result := htHeader; + if PtInRect(GetHitTestRect(htRollButton), Point(X, Y)) then + Result := htRollButton; +end; + +function TJvXPCustomWinXPBar.GetItemRect(Index: Integer): TRect; +begin + Result.Left := 3; + Result.Right := Width - 3; + if FRollMode = rmShrink then + Result.Top := FC_HEADER_MARGIN + HeaderHeight + FC_ITEM_MARGIN div 2 + + Index * FRollOffset - 4 + FTopSpace + else + Result.Top := FC_HEADER_MARGIN + HeaderHeight + FC_ITEM_MARGIN div 2 + + Index * FItemHeight - 4 + FTopSpace; + Result.Bottom := Result.Top + FItemHeight; +end; + +function TJvXPCustomWinXPBar.GetRollHeight: Integer; +begin + if Assigned(FRollImages) then + Result := FRollImages.Height + else + Result := 18; +end; + +function TJvXPCustomWinXPBar.GetRollWidth: Integer; +begin + if Assigned(FRollImages) then + Result := FRollImages.Width + else + Result := 18; +end; + +function TJvXPCustomWinXPBar.GetHitTestRect(const HitTest: TJvXPBarHitTest): TRect; + +begin + case HitTest of + htHeader: + Result := Bounds(0, FTopSpace, Width, FHeaderHeight); + htRollButton: + Result := Bounds(Width - 24, FTopSpace + (FHeaderHeight - GetRollHeight) div 2, GetRollWidth, GetRollHeight); + end; +end; + +procedure TJvXPCustomWinXPBar.SortVisibleItems(const Redraw: Boolean); +begin + if (csLoading in ComponentState) or (csDestroying in ComponentState) then + Exit; + FVisibleItems.FItems.Sort(@SortByIndex); + if Redraw then + InternalRedraw; +end; + +procedure TJvXPCustomWinXPBar.ItemVisibilityChanged(Item: TJvXPBarItem); +begin + // update visible-item list + if Item.Visible then + FVisibleItems.Add(Item) + else + FVisibleItems.Delete(Item); +end; + +procedure TJvXPCustomWinXPBar.HookMouseDown; +var + Rect: TRect; +begin + inherited HookMouseDown; // update drawstate + if FHitTest = htRollButton then + begin + Rect := GetHitTestRect(htRollButton); + Invalidate; + end; +end; + +procedure TJvXPCustomWinXPBar.HookMouseEnter; +begin + inherited HookMouseEnter; + if FHoverIndex <> -1 then + DoDrawItem(FHoverIndex, [dsFocused]); +end; + +procedure TJvXPCustomWinXPBar.HookMouseLeave; +begin + inherited HookMouseLeave; + if (FHoverIndex <> -1) and (FVisibleItems[FHoverIndex] <> nil) and + (not FVisibleItems[FHoverIndex].Checked) then + DoDrawItem(FHoverIndex, []); +end; + + +function TJvXPCustomWinXPBar.GetItemAt(X, Y: Integer): Integer; +var + Header: Integer; +begin + Header := FC_HEADER_MARGIN div 2 + HeaderHeight + FC_ITEM_MARGIN div 2 + FTopSpace; + if (Y < Header) or (Y > Height - FC_ITEM_MARGIN div 2) then + Result := -1 + else + Result := (Y - Header) div ItemHeight; +end; + +procedure TJvXPCustomWinXPBar.HookMouseMove(X, Y: Integer); +const + cPipe = '|'; +var + Rect: TRect; + OldHitTest: TJvXPBarHitTest; + NewIndex: Integer; +begin + OldHitTest := FHitTest; + FHitTest := GetHitTestAt(X, Y); + if FHitTest <> OldHitTest then + begin + Rect := Bounds(0, FTopSpace, Width, FHeaderHeight); // header + Invalidate; + if FShowLinkCursor then + if FHitTest <> htNone then + Cursor := crHandPoint + else + Cursor := crDefault; + end; + + NewIndex := GetItemAt(X, Y); + + if (NewIndex >= 0) and (NewIndex < VisibleItems.Count) then + begin + if FStoredHint = cPipe then + FStoredHint := Hint; + if Action is TCustomAction then + inherited Hint := TCustomAction(Action).Hint + else + inherited Hint := VisibleItems[NewIndex].Hint; + end + else + begin + NewIndex := -1; + if FStoredHint <> cPipe then + inherited Hint := FStoredHint; + FStoredHint := cPipe; + end; + + if NewIndex <> FHoverIndex then + begin + if (FHoverIndex <> -1) and (FVisibleItems[FHoverIndex] <> nil) then + if FVisibleItems[FHoverIndex].Checked then + DoDrawItem(FHoverIndex, [dsClicked]) + else + DoDrawItem(FHoverIndex, []); + FHoverIndex := NewIndex; + if (FHoverIndex <> -1) and (FVisibleItems[FHoverIndex] <> nil) and + (FVisibleItems[FHoverIndex].Enabled) then + begin + DoDrawItem(FHoverIndex, [dsFocused]); + if FShowLinkCursor then + Cursor := crHandPoint; + end + else + if FShowLinkCursor then + Cursor := crDefault; + end; + + inherited HookMouseMove(X, Y); +end; + +procedure TJvXPCustomWinXPBar.HookParentFontChanged; +begin + if ParentFont then + begin + FFontChanging := True; + try + FFont.Color := $00E75100; + FFont.Name := inherited Font.Name; + FFont.Size := 8; + FFont.Style := inherited Font.Style; + FHeaderFont.Color := $00E75100; + FHeaderFont.Name := Font.Name; + FHeaderFont.Size := 8; + FHeaderFont.Style := [fsBold]; + finally + FFontChanging := False; + end; + inherited HookParentFontChanged; + end; +end; + +procedure TJvXPCustomWinXPBar.HookResized; +begin + // perform actions only on 'width'-change + if FGradientWidth <> Width then + FGradientWidth := Width; + + // resize to maximum height + ResizeToMaxHeight; + inherited HookResized; +end; + +procedure TJvXPCustomWinXPBar.SetCollapsed(Value: Boolean); +begin + if Value <> FCollapsed then + begin + // Using fading while loading is useless. + // Using the fading thread at design time is NOT safe. See Mantis 3547. + if ComponentState * [csLoading, csDesigning] = [] then + begin + if Assigned(FBeforeCollapsedChange) then + FBeforeCollapsedChange(Self, Value); + if Value then + FFadeThread := TJvXPFadeThread.Create(Self, rdCollapse) + else + FFadeThread := TJvXPFadeThread.Create(Self, rdExpand); + if Assigned(FOnCollapsedChange) then + FOnCollapsedChange(Self, Value); + end + else + begin + FCollapsed := Value; + FRolling := True; + if Value then + RollOffset := 0 + else + RollOffset := FItemHeight; + FRolling := False; + if Grouped and not Value then + GroupMessage; + end; + end; +end; + +procedure TJvXPCustomWinXPBar.SetFont(Value: TFont); +begin + FFont.Assign(Value); + InternalRedraw; +end; + +procedure TJvXPCustomWinXPBar.SetHeaderFont(Value: TFont); +begin + FHeaderFont.Assign(Value); + InternalRedraw; +end; + +procedure TJvXPCustomWinXPBar.SetHotTrack(Value: Boolean); +const + MouseEvents: TJvXPControlStyle = [csRedrawMouseEnter, csRedrawMouseLeave]; +begin + if Value <> FHotTrack then + begin + FHotTrack := Value; +// if FHotTrack then +// ExControlStyle := ExControlStyle + MouseEvents +// else +// ExControlStyle := ExControlStyle - MouseEvents; + if not (csLoading in ComponentState) then + InternalRedraw; + end; +end; + +procedure TJvXPCustomWinXPBar.SetHotTrackColor(Value: TColor); +begin + if Value <> FHotTrackColor then + begin + FHotTrackColor := Value; + InternalRedraw; + end; +end; + +procedure TJvXPCustomWinXPBar.SetIcon(Value: TIcon); +begin + if Value <> FIcon then + begin + FIcon.Assign(Value); + InternalRedraw; + end; +end; + +procedure TJvXPCustomWinXPBar.SetImageList(Value: TCustomImageList); +begin + if Value <> FImageList then + begin + if FImageList <> nil then + FImageList.UnRegisterChanges(FImageChangeLink); + FImageList := Value; + if FImageList <> nil then + begin + FImageList.FreeNotification(Self); + FImageList.RegisterChanges(FImageChangeLink); + end; + InternalRedraw; + end; +end; + +procedure TJvXPCustomWinXPBar.SetItemHeight(Value: Integer); +begin + if Value <> FItemHeight then + begin + FItemHeight := Value; + if not FCollapsed then + RollOffset := FItemHeight; + end; +end; + +procedure TJvXPCustomWinXPBar.SetItems(Value: TJvXPBarItems); +begin + FItems.Assign(Value); +end; + +procedure TJvXPCustomWinXPBar.SetRollOffset(const Value: Integer); +begin + if Value <> FRollOffset then + begin + FRollOffset := Value; + ResizeToMaxHeight; + end; +end; + +procedure TJvXPCustomWinXPBar.SetShowRollButton(Value: Boolean); +begin + if Value <> FShowRollButton then + begin + FShowRollButton := Value; + InternalRedraw; + end; +end; + +procedure TJvXPCustomWinXPBar.EndUpdate; +begin + inherited EndUpdate; + ResizeToMaxHeight; +end; + +procedure TJvXPCustomWinXPBar.Click; +var + AllowChange, CallInherited: Boolean; + LItem: TJvXPBarItem; +begin + CallInherited := True; + if FShowRollButton and (FHitTest <> htNone) then + Collapsed := not Collapsed; + if (FHoverIndex <> -1) and (FVisibleItems[FHoverIndex] <> nil) and + FVisibleItems[FHoverIndex].Enabled then + begin + AllowChange := True; + if Assigned(FOnCanChange) then + FOnCanChange(Self, FVisibleItems[FHoverIndex], AllowChange); + if not AllowChange then + Exit; + + //dejoy add + LItem := FVisibleItems[FHoverIndex]; + with LItem do + begin + if (not Assigned(ActionLink) and AutoCheck) or + (Assigned(ActionLink) and not ActionLink.IsAutoCheckLinked and AutoCheck) then + LItem.Checked := not LItem.Checked; + end; + if FVisibleItems[FHoverIndex].Checked then + DrawState := DrawState + [dsClicked] + else + DrawState := DrawState - [dsClicked]; + + if Assigned(FOnItemClick) then + begin + FOnItemClick(Self, FVisibleItems[FHoverIndex]); + CallInherited := False; + end; + if Assigned(FVisibleItems[FHoverIndex].FOnClick) then + begin + { set linked 'action' as Sender } + if Assigned(FVisibleItems[FHoverIndex].Action) and + (@FVisibleItems[FHoverIndex].FOnClick <> @FVisibleItems[FHoverIndex].Action.OnExecute) then + FVisibleItems[FHoverIndex].FOnClick(FVisibleItems[FHoverIndex]) + else + if not (csDesigning in ComponentState) and Assigned(FVisibleItems[FHoverIndex].ActionLink) then + FVisibleItems[FHoverIndex].ActionLink.Execute(Self) + else + if Assigned(FVisibleItems[FHoverIndex].FOnClick) then + FVisibleItems[FHoverIndex].FOnClick(FVisibleItems[FHoverIndex]); + + CallInherited := False; + end; + Collapsed := False; + InternalRedraw; //dejoy + end; + if CallInherited then + inherited Click; +end; + +procedure TJvXPCustomWinXPBar.DoDrawItem(const Index: Integer; State: TJvXPDrawState); +var + Bitmap: TBitmap; + ItemRect: TRect; + HasImages: Boolean; +begin + Bitmap := TBitmap.Create; + with Canvas do + try + Bitmap.Assign(nil); + ItemRect := GetItemRect(Index); + HasImages := FVisibleItems[Index].Images <> nil; + if HasImages then + begin + FVisibleItems[Index].Images.GetBitmap(FVisibleItems[Index].ImageIndex, Bitmap); + end; + Bitmap.Transparent := True; + if OwnerDraw then + begin + if Assigned(FOnDrawItem) then + FOnDrawItem(Self, Canvas, ItemRect, State, FVisibleItems[Index], Bitmap); + end + else + FVisibleItems[Index].DrawItem(Self, Canvas, ItemRect, State, ShowItemFrame, Bitmap); + finally + Bitmap.Free; + end; +end; + +procedure TJvXPCustomWinXPBar.Paint; +var + ARect: TRect; + Bitmap: TBitmap; + Index, I: Integer; + OwnColor: TColor; + + // (rom) Do as prefix for a local function is not ideal + procedure DoDrawBackground(ACanvas: TCanvas; var R: TRect); + begin + ACanvas.Brush.Color := FColors.BodyColor; // $00F7DFD6; + Inc(R.Top, FTopSpace + FHeaderHeight); + if OwnerDraw then + begin + if Assigned(FOnDrawBackground) then + FOnDrawBackground(Self, ACanvas, R); + end + else + begin + if not FCollapsed and (FColors.FBodyColor <> FColors.FBodyBorderColor) then + begin + ACanvas.Pen.Color := FColors.FBodyBorderColor; + ACanvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom - 1); + end + else + ACanvas.FillRect(R); + end; + end; + + procedure DoDrawHeader(ACanvas: TCanvas; var R: TRect); + begin + Dec(R.Top, FHeaderHeight); + R.Bottom := R.Top + FHeaderHeight; + if OwnerDraw then + begin + ACanvas.Brush.Color := FColors.FBorderColor; + if Assigned(FOnDrawHeader) then + FOnDrawHeader(Self, ACanvas, R); + end + else + begin + ACanvas.GradientFill(Rect(0, R.Top, Width, R.Top + FHeaderHeight), + FColors.GradientFrom, FColors.GradientTo, gdHorizontal); + + { draw frame... } + ACanvas.Brush.Color := FColors.FBorderColor; + ACanvas.FrameRect(R); + + if FHeaderRounded then + begin + OwnColor := TJvXPWinControl(Parent).Color; + ACanvas.Pixels[0, R.Top] := OwnColor; + ACanvas.Pixels[0, R.Top + 1] := OwnColor; + ACanvas.Pixels[1, R.Top] := OwnColor; + ACanvas.Pixels[1, R.Top + 1] := FColors.FBorderColor; + ACanvas.Pixels[Width - 1, R.Top] := OwnColor; + ACanvas.Pixels[Width - 2, R.Top] := OwnColor; + ACanvas.Pixels[Width - 1, R.Top + 1] := OwnColor; + ACanvas.Pixels[Width - 2, R.Top + 1] := FColors.FBorderColor; + end; + + // Paint rollover button: (expanded/collapsed state button images) + if FShowRollButton and (Width >= 115) then + begin + Bitmap := TBitmap.Create; + try + if Assigned(FRollImages) then + begin + // format: + // 0 - normal collapsed + // 1 - normal expanded + // 2 - hot collapsed + // 3 - hot expanded + // 4 - down collapsed + // 5 - down expanded + Index := 0; // normal + if FHitTest = htRollButton then + begin + if dsHighlight in DrawState then + Index := 2; // hot + if (dsClicked in DrawState) and (dsHighlight in DrawState) then + Index := 4; // down + end; + if not FCollapsed then + Inc(Index); + if Index >= FRollImages.Count then + Index := Ord(not FCollapsed); + FRollImages.GetBitmap(Index, Bitmap); + end + else + begin + Index := 0; + if FHitTest = htRollButton then + begin + if dsHighlight in DrawState then + Index := 1; // hot + if (dsClicked in DrawState) and (dsHighlight in DrawState) then + Index := 2; // down + end; + Bitmap.Assign(nil); // fixes GDI resource leak + if FCollapsed then + //Bitmap.LoadFromResourceName(HInstance, 'JvXPCustomWinXPBarEXPAND' + IntToStr(Index)) + Bitmap.LoadFromLazarusResource('JvXPCustomWinXPBarEXPAND' + IntToStr(Index)) + else + //Bitmap.LoadFromResourceName(HInstance, 'JvXPCustomWinXPBarCOLLAPSE' + IntToStr(Index)); + Bitmap.LoadFromLazarusResource('JvXPCustomWinXPBarCOLLAPSE' + IntToStr(Index)); + end; + // Transparency fix not needed Here! -WPostma + Bitmap.Transparent := True; + ACanvas.Draw(R.Right - 24, R.Top + (HeaderHeight - GetRollHeight) div 2, Bitmap); + finally + Bitmap.Free; + end; + Dec(R.Right, 25); + end; + Inc(R.Left, 22); + ACanvas.Pen.Color := FColors.SeparatorColor; + JvXPDrawLine(ACanvas, 1, ARect.Top + FHeaderHeight, Width - 1, ARect.Top + FHeaderHeight); + if not FIcon.Empty then + begin + ACanvas.Draw(2, 0, FIcon); + Inc(R.Left, 16); + end; + Dec(ARect.Right, 25); + end; + + { draw seperator line } + ACanvas.Pen.Color := FColors.SeparatorColor; + JvXPDrawLine(ACanvas, 1, ARect.Top + FHeaderHeight, Width - 1, ARect.Top + FHeaderHeight); + + { draw icon } +// Inc(ARect.Left, 22); + if not FIcon.Empty then + begin + ACanvas.Draw(2, 1, FIcon); + Inc(ARect.Left, 6); + end + else + Dec(ARect.Left, 16); + SetBkMode(ACanvas.Handle, TRANSPARENT); + ACanvas.Font.Assign(FHeaderFont); + if FHotTrack and (dsHighlight in DrawState) and (FHitTest <> htNone) and (FHotTrackColor <> clNone) then + ACanvas.Font.Color := FHotTrackColor; + ARect.Bottom := ARect.Top + FHeaderHeight; + Dec(ARect.Right, 3); + DrawText(ACanvas.Handle, PChar(Caption), Length(Caption), ARect, + DT_SINGLELINE or DT_LEFT or DT_VCENTER or DT_END_ELLIPSIS or DT_NOPREFIX); + end; +begin + { get client rect } + ARect := GetClientRect; + DoDrawBackground(Canvas, ARect); + { draw header } + DoDrawHeader(Canvas, ARect); + { draw visible items } + Canvas.Brush.Color := FColors.BodyColor; + if not FCollapsed or FRolling then + for I := 0 to FVisibleItems.Count - 1 do + if FVisibleItems[I].Checked then + DoDrawItem(I, [dsClicked]) + else + DoDrawItem(I, []); +end; + +procedure TJvXPCustomWinXPBar.WMAfterXPBarCollapse(var Msg: TLMessage); +begin + if Assigned(FAfterCollapsedChange) then + FAfterCollapsedChange(Self, Msg.WParam <> 0); + if Grouped and not FCollapsed then + GroupMessage; +end; + +procedure TJvXPCustomWinXPBar.DoColorsChange(Sender: TObject); +begin + Invalidate; +end; + +procedure TJvXPCustomWinXPBar.SetColors(const Value: TJvXPBarColors); +begin + FColors.Assign(Value); +end; + +procedure TJvXPCustomWinXPBar.SetRollImages(const Value: TCustomImageList); +begin + if FRollImages <> Value then + begin + if FRollImages <> nil then + FRollImages.UnRegisterChanges(FRollChangeLink); + FRollImages := Value; + if FRollImages <> nil then + begin + FRollImages.FreeNotification(Self); + FRollImages.RegisterChanges(FRollChangeLink); + end; + InternalRedraw; + end; +end; + +procedure TJvXPCustomWinXPBar.GroupMessage; +var + Msg: TLMessage; +begin + if Parent <> nil then + begin + Msg.Msg := WM_XPBARAFTEREXPAND; + Msg.WParam := WPARAM(Self); + Msg.Result := 0; + Parent.Broadcast(Msg); + end; +end; + +procedure TJvXPCustomWinXPBar.WMAfterXPBarExpand(var Msg: TLMessage); +begin + if Grouped and (TObject(Msg.WParam) <> Self) then + Collapsed := True; +end; + +procedure TJvXPCustomWinXPBar.SetGrouped(const Value: Boolean); +begin + if FGrouped <> Value then + begin + FGrouped := Value; + if FGrouped and not Collapsed then + Collapsed := True; + end; +end; + +procedure TJvXPCustomWinXPBar.AdjustClientRect(var Rect: TRect); +begin + inherited AdjustClientRect(Rect); + if ControlCount > 0 then + begin + Inc(Rect.Top, FHeaderHeight + 4); + InflateRect(Rect, -4, -4); + end; +end; + +procedure TJvXPCustomWinXPBar.SetHeaderHeight(const Value: Integer); +begin + if FHeaderHeight <> Value then + begin + FHeaderHeight := Value; + ResizeToMaxHeight; +// InternalRedraw; + end; +end; + +function TJvXPCustomWinXPBar.HintShow(var HintInfo: THintInfo): Boolean; +begin + // draw the item hint (if available) + if (FHoverIndex > -1) and (FVisibleItems[FHoverIndex] <> nil) then + begin + HintInfo.CursorRect := GetItemRect(FHoverIndex); + with VisibleItems[FHoverIndex] do + begin + if Action is TCustomAction then + HintInfo.HintStr := TCustomAction(Action).Hint + else + HintInfo.HintStr := VisibleItems[FHoverIndex].Hint; + end; + end + else + if (VisibleItems.Count > 0) and not Collapsed then + HintInfo.CursorRect := GetHitTestRect(htHeader); + + if HintInfo.HintStr = '' then + HintInfo.HintStr := Hint; + Result := False; // use default hint window +end; + +procedure TJvXPCustomWinXPBar.CMHintShow(var Msg: TCMHintShow); +begin + Msg.Result := Ord(HintShow(Msg.HintInfo^)); +end; + +function TJvXPBarItemActionLink.DoShowHint(var HintStr: string): Boolean; +begin + Result := True; + if Action is TCustomAction then + begin + Result := TCustomAction(Action).DoHint(HintStr); + if Result and Application.HintShortCuts and (TCustomAction(Action).ShortCut <> scNone) then + if HintStr <> '' then + HintStr := Format(RsHintShortcutFmt, [HintStr, ShortCutToText(TCustomAction(Action).ShortCut)]); + end; +end; + +procedure TJvXPCustomWinXPBar.InitiateAction; +var + I: Integer; +begin + inherited InitiateAction; + // go through each item and update + // Note: Do not call ActionChange as it would trigger Mantis 3244 and it is + // basically wrong as the point of InitiateAction is to call Update (see in + // the inherited code). + for I := 0 to Items.Count - 1 do + if Assigned(Items[I].ActionLink) then + Items[I].ActionLink.Update; +end; + + +procedure TJvXPCustomWinXPBar.CMDialogChar(var Msg: TCMDialogChar); +var + I: Integer; +begin + if CanFocus then + begin + if IsAccel(Msg.CharCode, Caption) then + begin + Collapsed := not Collapsed; + Msg.Result := 1; + end + else + if not Collapsed then + for I := 0 to VisibleItems.Count - 1 do + if IsAccel(Msg.CharCode, VisibleItems[I].Caption) and VisibleItems[I].Enabled then + begin + Msg.Result := 1; + FHitTest := htNone; + FHoverIndex := I; + Click; + Exit; + end; + end; + // 21.07.2007 - SESS: Parece no estar en la clase base + // inherited; +end; + +class function TJvXPCustomWinXPBar.GetBarItemsClass: TJvXPBarItemsClass; +begin + Result := TJvXPBarItems; +end; + +procedure TJvXPCustomWinXPBar.DblClick; +var + LItem: TJvXPBarItem; +begin + if (FHoverIndex <> -1) and (FVisibleItems[FHoverIndex] <> nil) and + FVisibleItems[FHoverIndex].Enabled then + begin + LItem := FVisibleItems[FHoverIndex]; + if Assigned(LItem.FOnDblClick) then + LItem.FOnDblClick(LItem); + end; + inherited DblClick; +end; + +procedure RoundedFrame(Canvas: TCanvas; ARect: TRect; AColor: TColor; R: Integer); +begin + // Draw Frame with round edges + with Canvas, ARect do + begin + Pen.Color := AColor; + Dec(Right); + Dec(Bottom); + Polygon( + [Point(Left + R, Top), + Point(Right - R, Top), + Point(Right, Top + R), + Point(Right, Bottom - R), + Point(Right - R, Bottom), + Point(Left + R, Bottom), + Point(Left, Bottom - R), + Point(Left, Top + R), + Point(Left + R, Top)]); + Inc(Right); + Inc(Bottom); + end; +end; + +procedure TJvXPCustomWinXPBar.SetHeaderRounded(const Value: Boolean); +begin + if FHeaderRounded <> Value then + begin + FHeaderRounded := Value; + InternalRedraw; + end; +end; + +procedure TJvXPCustomWinXPBar.SetTopSpace(const Value: Integer); +begin + if Value <> FTopSpace then + begin + FTopSpace := Value; + if FTopSpace < 0 then + FTopSpace := 0; + ResizeToMaxHeight; + InternalRedraw; + end; +end; + +procedure TJvXPCustomWinXPBar.SetOwnerDraw(const Value: Boolean); +begin + if FOwnerDraw <> Value then + begin + FOwnerDraw := Value; + Invalidate; + end; +end; + +initialization + {$I JvXPBar.lrs} + +end. + diff --git a/components/jvcllaz/run/JvXPCore.pas b/components/jvcllaz/run/JvXPCore.pas new file mode 100644 index 000000000..f6ab4c0f1 --- /dev/null +++ b/components/jvcllaz/run/JvXPCore.pas @@ -0,0 +1,913 @@ +{----------------------------------------------------------------------------- +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: JvXPCore.PAS, released on 2004-01-01. + +The Initial Developer of the Original Code is Marc Hoffman. +Portions created by Marc Hoffman are Copyright (C) 2002 APRIORI business solutions AG. +Portions created by APRIORI business solutions AG are Copyright (C) 2002 APRIORI business solutions AG +All Rights Reserved. + +Contributor(s): + +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: +-----------------------------------------------------------------------------} +// $Id: JvXPCore.pas 11400 2007-06-28 21:24:06Z ahuser $ + +// Ported to Lazarus (no too hard after all) by Sergio Samayoa - september 2007. +// Still dont tested on linux. + +unit JvXPCore; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, Controls, Forms, Graphics, LCLIntf, LCLType, LMessages; + +(* 23.09.2007 - SESS - unused +const + { color constants. + + these constants are used as default colors for descendant controls + and may be replaced with other (common) values. + + syntax: JvXPColor_[Control]_[Enabled: Enb, Dis]_[Type]_[Theme: WXP, OXP] } + + { button colors - WindowsXP } + dxColor_Btn_Enb_Border_WXP = TColor($00733800); // border line + dxColor_Btn_Dis_Border_WXP = TColor($00BDC7CE); // border line (disabled) + dxColor_Btn_Enb_Edges_WXP = TColor($00AD9E7B); // border edges + dxColor_Btn_Dis_Edges_WXP = TColor($00BDC7CE); // border edges (disabled) + dxColor_Btn_Enb_BgFrom_WXP = TColor($00FFFFFF); // background from + dxColor_Btn_Enb_BgTo_WXP = TColor($00E7EBEF); // background to + dxColor_Btn_Enb_CkFrom_WXP = TColor($00C6CFD6); // clicked from + dxColor_Btn_Enb_CkTo_WXP = TColor($00EBF3F7); // clicked to + dxColor_Btn_Enb_FcFrom_WXP = TColor($00FFE7CE); // focused from + dxColor_Btn_Enb_FcTo_WXP = TColor($00EF846D); // focused to + dxColor_Btn_Enb_HlFrom_WXP = TColor($00CEF3FF); // highlight from + dxColor_Btn_Enb_HlTo_WXP = TColor($000096E7); // highlight to + + { checkbox colors - WindowsXP } + dxColor_Chk_Enb_Border_WXP = TColor($00845118); // border line + dxColor_Chk_Enb_NmSymb_WXP = TColor($0021A621); // symbol normal + dxColor_Chk_Enb_GraSymb_WXP = TColor($0071C671); // symbol grayed + + { misc colors - WindowsXP } + dxColor_Msc_Dis_Caption_WXP = TColor($0094A6A5); // caption color (disabled) + + dxColor_DotNetFrame = TColor($00F7FBFF); // $00E7EBEF; + dxColor_BorderLineOXP = TColor($00663300); + dxColor_BgOXP = TColor($00D6BEB5); + dxColor_BgCkOXP = TColor($00CC9999); + +type + TJvXPCustomStyleControl = class; + + TJvXPBoundLines = set of + ( + blLeft, // left line + blTop, // top line + blRight, // right line + blBottom // bottom line + ); +23.09.2007 - SESS - unused *) + +type + TJvXPControlStyle = set of + ( + csRedrawCaptionChanged, // (default) + csRedrawBorderChanged, // + csRedrawEnabledChanged, // (default) + csRedrawFocusedChanged, // (default) + csRedrawMouseDown, // (default) + csRedrawMouseEnter, // (default) + csRedrawMouseLeave, // (default) + csRedrawMouseMove, // + csRedrawMouseUp, // (default) + csRedrawParentColorChanged, // (default) + csRedrawParentFontChanged, // + csRedrawPosChanged, // + csRedrawResized // + ); + +type + TJvXPDrawState = set of + ( + dsDefault, // default + dsHighlight, // highlighted + dsClicked, // clicked + dsFocused // focused + ); + +(* 23.09.2007 - SESS - unused + TJvXPGlyphLayout = + ( + glBottom, // bottom glyph + glCenter, // centered glyph + glTop // top glyph + ); + + TJvXPTheme = + ( + WindowsXP, // WindowsXP theme + OfficeXP // OfficeXP theme + ); + + { baseclass for non-focusable component descendants. } + TJvXPCustomComponent = class(TComponent) + private + FVersion: string; + procedure SetVersion(const Value: string); + public + constructor Create(AOwner: TComponent); override; + published + property Version: string read FVersion write SetVersion stored False; + end; +23.09.2007 - SESS - unused *) + +type + TJvXPWinControl = class(TWinControl) + published + property Color; + end; + + { baseclass for focusable control descendants. } + + TJvXPCustomControl = class(TCustomControl) + private + FClicking: Boolean; + FDrawState: TJvXPDrawState; + FIsLocked: Boolean; + FIsSibling: Boolean; + FModalResult: TModalResult; + FOnMouseLeave: TNotifyEvent; + FOnMouseEnter: TNotifyEvent; + FVersion: string; + procedure SetVersion(const Value: string); + procedure CMFocusChanged(var Msg: TLMessage); message CM_FOCUSCHANGED; + procedure CMDialogChar(var Msg: TCMDialogChar); message CM_DIALOGCHAR; + procedure CMBorderChanged(var Msg: TLMessage); message CM_BORDERCHANGED; + procedure CMEnabledChanged(var Msg: TLMessage); message CM_ENABLEDCHANGED; + procedure CMMouseEnter(var Msg: TLMessage); message CM_MOUSEENTER; + procedure CMMouseLeave(var Msg: TLMessage); message CM_MOUSELEAVE; + procedure CMParentColorChanged(var Msg: TLMessage); message CM_PARENTCOLORCHANGED; + + //21.09.07 - SESS + //procedure CMParentFontChanged(var Msg: TLMessage); message CM_PARENTFONTCHANGED; + + procedure CMTextChanged(var Msg: TLMessage); message CM_TEXTCHANGED; + procedure WMMouseMove(var Msg: TLMMouse); message LM_MOUSEMOVE; + procedure WMSize(var Msg: TLMSize); message LM_SIZE; + procedure WMWindowPosChanged(var Msg: TLMWindowPosChanged); message LM_WINDOWPOSCHANGED; + protected + ExControlStyle: TJvXPControlStyle; + procedure InternalRedraw; dynamic; + procedure HookBorderChanged; dynamic; + procedure HookEnabledChanged; dynamic; + procedure HookFocusedChanged; dynamic; + procedure HookMouseDown; dynamic; + procedure HookMouseEnter; dynamic; + procedure HookMouseLeave; dynamic; + procedure HookMouseMove(X: Integer = 0; Y: Integer = 0); dynamic; + procedure HookMouseUp; dynamic; + procedure HookParentColorChanged; dynamic; + procedure HookParentFontChanged; dynamic; + procedure HookPosChanged; dynamic; + procedure HookResized; dynamic; + procedure HookTextChanged; dynamic; + procedure BeginUpdate; dynamic; + procedure EndUpdate; dynamic; + procedure LockedInvalidate; dynamic; + procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure Click; override; + property ModalResult: TModalResult read FModalResult write FModalResult default 0; + property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter; + property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave; + public + constructor Create(AOwner: TComponent); override; + property Canvas; + property DrawState: TJvXPDrawState read FDrawState write FDrawState; + property IsLocked: Boolean read FIsLocked write FIsLocked; + property IsSibling: Boolean read FIsSibling write FIsSibling; + published + property Version: string read FVersion write SetVersion stored False; + end; + +(* 23.09.2007 - SESS - unused + TJvXPUnlimitedControl = class(TJvXPCustomControl) + published + //property BevelInner; + //property BevelOuter; + //property BevelWidth; + //property BiDiMode; + //property Ctl3D; + //property DockSite; + //property ParentBiDiMode; + //property ParentCtl3D; + //property TabOrder; + //property TabStop; + //property UseDockManager default True; + property Align; + property Anchors; + //property AutoSize; + property Constraints; + property DragCursor; + property DragKind; + + //21.09.07 - SESS resolver + //property OnCanResize; + + property DragMode; + //property Enabled; + property Font; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowHint; + property Visible; + //property OnDockDrop; + //property OnDockOver; + //property OnEndDock; + //property OnGetSiteInfo; + //property OnStartDock; + //property OnUnDock; + property OnClick; + property OnConstrainedResize; + property OnContextPopup; + 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; + end; + + TJvXPStyle = class(TPersistent) + private + FTheme: TJvXPTheme; + FUseStyleManager: Boolean; + protected + Parent: TJvXPCustomStyleControl; + procedure SetTheme(Value: TJvXPTheme); virtual; + procedure SetUseStyleManager(Value: Boolean); virtual; + public + constructor Create(AOwner: TComponent); + function GetTheme: TJvXPTheme; + published + property Theme: TJvXPTheme read FTheme write SetTheme default WindowsXP; + property UseStyleManager: Boolean read FUseStyleManager write SetUseStyleManager default True; + end; + + TJvXPStyleManager = class(TJvXPCustomComponent) + private + FControls: TList; + FTheme: TJvXPTheme; + FOnThemeChanged: TNotifyEvent; + procedure InvalidateControls; + protected + procedure SetTheme(Value: TJvXPTheme); virtual; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure RegisterControls(const AControls: array of TJvXPCustomControl); + procedure UnregisterControls(const AControls: array of TJvXPCustomControl); + published + property Theme: TJvXPTheme read FTheme write SetTheme default WindowsXP; + property OnThemeChanged: TNotifyEvent read FOnThemeChanged write FOnThemeChanged; + end; + + TJvXPCustomStyleControl = class(TJvXPCustomControl) + private + FStyle: TJvXPStyle; + FStyleManager: TJvXPStyleManager; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + protected + procedure SetStyleManager(Value: TJvXPStyleManager); virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + property Style: TJvXPStyle read FStyle write FStyle; + property StyleManager: TJvXPStyleManager read FStyleManager write SetStyleManager; + end; +23.09.2007 - SESS - unused *) + + TJvXPGradientColors = 2..255; + + TJvXPGradientStyle = (gsLeft, gsTop, gsRight, gsBottom); + +(* 23.09.2007 - SESS - unused + TJvXPGradient = class(TPersistent) + private + FColors: TJvXPGradientColors; + FDithered: Boolean; + FEnabled: Boolean; + FEndColor: TColor; + FStartColor: TColor; + FGradientStyle: TJvXPGradientStyle; + protected + Parent: TJvXPCustomControl; + procedure SetDithered(Value: Boolean); virtual; + procedure SetColors(Value: TJvXPGradientColors); virtual; + procedure SetEnabled(Value: Boolean); virtual; + procedure SetEndColor(Value: TColor); virtual; + procedure SetGradientStyle(Value: TJvXPGradientStyle); virtual; + procedure SetStartColor(Value: TColor); virtual; + public + Bitmap: TBitmap; + constructor Create(AOwner: TControl); + destructor Destroy; override; + procedure RecreateBands; virtual; + published + property Dithered: Boolean read FDithered write SetDithered default True; + property Colors: TJvXPGradientColors read FColors write SetColors default 16; + property Enabled: Boolean read FEnabled write SetEnabled default False; + property EndColor: TColor read FEndColor write SetEndColor default clSilver; + property StartColor: TColor read FStartColor write SetStartColor default clGray; + property Style: TJvXPGradientStyle read FGradientStyle write SetGradientStyle default gsLeft; + end; +23.09.2007 - SESS - unused *) + +implementation + +(* 23.09.2007 - SESS - Original strings +uses + JvXPCoreUtils; + +resourcestring + RsCopyright = 'Design eXperience. (c) 2002 M. Hoffmann Version '; + RsCopyright2 = 'Design eXperience II - (c) 2002 M. Hoffmann Version '; + RsVersion = '2.0.1'; // always increase version number on new releases! +*) + +(* 23.09.2007 - SESS - unused +//=== { TJvXPCustomComponent } =============================================== + +constructor TJvXPCustomComponent.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FVersion := RsCopyright + RsVersion; +end; + +procedure TJvXPCustomComponent.SetVersion(const Value: string); +begin + // do not enable overwriting this constant. +end; +23.09.2007 - SESS - unused *) + +//=== { TJvXPCustomControl } ================================================= + +constructor TJvXPCustomControl.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + ControlStyle := ControlStyle + [csOpaque, csReplicatable]; + DoubleBuffered := True; + ExControlStyle := [csRedrawEnabledChanged, csRedrawFocusedChanged, + csRedrawMouseDown, csRedrawMouseEnter, csRedrawMouseLeave, csRedrawMouseUp, + csRedrawParentColorChanged, csRedrawCaptionChanged]; + FClicking := False; + FDrawState := [dsDefault]; + FIsLocked := False; + FIsSibling := False; + FModalResult := 0; + // 23.09.2007 - SESS + // FVersion := RsCopyright2 + RsVersion; + FVersion := 'JvXP (JVCL) for Lazarus 1.0'; +end; + +procedure TJvXPCustomControl.SetVersion(const Value: string); +begin + // disallow changing this property. +end; + +procedure TJvXPCustomControl.BeginUpdate; +begin + FIsLocked := True; +end; + +procedure TJvXPCustomControl.EndUpdate; +begin + FIsLocked := False; + InternalRedraw; +end; + +procedure TJvXPCustomControl.LockedInvalidate; +begin + if not IsLocked then + Invalidate; +end; + +procedure TJvXPCustomControl.InternalRedraw; +begin + if not FIsLocked then + Invalidate; +end; + + + +procedure TJvXPCustomControl.CMDialogChar(var Msg: TCMDialogChar); +begin + with Msg do + if IsAccel(CharCode, Caption) and CanFocus and + (Focused or ((GetKeyState(VK_MENU) and $8000) <> 0)) then + begin + Click; + Result := 1; + end + else + inherited; +end; + +procedure TJvXPCustomControl.CMBorderChanged(var Msg: TLMessage); +begin + // delegate message "BorderChanged" to hook. + inherited; + HookBorderChanged; +end; + +procedure TJvXPCustomControl.CMEnabledChanged(var Msg: TLMessage); +begin + // delegate message "EnabledChanged" to hook. + inherited; + HookEnabledChanged; +end; + + +procedure TJvXPCustomControl.CMFocusChanged(var Msg: TLMessage); +begin + // delegate message "FocusChanged" to hook. + inherited; + HookFocusedChanged; +end; + + +procedure TJvXPCustomControl.CMMouseEnter(var Msg: TLMessage); +begin + // delegate message "MouseEnter" to hook. + inherited; + HookMouseEnter; +end; + +procedure TJvXPCustomControl.CMMouseLeave(var Msg: TLMessage); +begin + // delegate message "MouseLeave" to hook. + inherited; + HookMouseLeave; +end; + +procedure TJvXPCustomControl.CMParentColorChanged(var Msg: TLMessage); +begin + // delegate message "ParentColorChanged" to hook. + inherited; + HookParentColorChanged; +end; + +//21.09.07 - SESS resolver +(* +procedure TJvXPCustomControl.CMParentFontChanged(var Msg: TLMessage); +begin + // delegate message "ParentFontChanged" to hook. + inherited; + HookParentFontChanged; +end; +*) +procedure TJvXPCustomControl.CMTextChanged(var Msg: TLMessage); +begin + // delegate message "TextChanged" to hook. + inherited; + HookTextChanged; +end; + +procedure TJvXPCustomControl.WMMouseMove(var Msg: TLMMouse); +begin + // delegate message "MouseMove" to hook. + inherited; + HookMouseMove(Msg.XPos, Msg.YPos); +end; + +procedure TJvXPCustomControl.WMSize(var Msg: TLMSize); +begin + // delegate message "Size" to hook. + inherited; + HookResized; +end; + +procedure TJvXPCustomControl.WMWindowPosChanged(var Msg: TLMWindowPosChanged); +begin + // delegate message "WindowPosChanged" to hook. + inherited; + HookPosChanged; +end; + +procedure TJvXPCustomControl.MouseDown(Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +begin + // delegate message "MouseDown" to hook. + inherited MouseDown(Button, Shift, X, Y); + if Button = mbLeft then + begin + FClicking := True; + HookMouseDown; + end; +end; + +procedure TJvXPCustomControl.MouseUp(Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +begin + // delegate message "MouseUp" to hook. + inherited MouseUp(Button, Shift, X, Y); + if FClicking then + begin + FClicking := False; + HookMouseUp; + end; +end; + +procedure TJvXPCustomControl.Click; +var + Form: TCustomForm; +begin + Form := GetParentForm(Self); + if Form <> nil then + Form.ModalResult := ModalResult; + inherited Click; +end; + +// +// hooks are used to interrupt default windows messages in an easier +// way - it's possible to override them in descendant classes. +// Beware of multiple redraw calls - if you know that the calling +// hooks always redraws the component, use the lock i.e. unlock methods +// (rom) or LockedInvalidate. + +procedure TJvXPCustomControl.HookBorderChanged; +begin + // this hook is called, if the border property was changed. + // in that case we normaly have to redraw the control. + if csRedrawBorderChanged in ExControlStyle then + InternalRedraw; +end; + +procedure TJvXPCustomControl.HookEnabledChanged; +begin + // this hook is called, if the enabled property was switched. + // in that case we normaly have to redraw the control. + if csRedrawEnabledChanged in ExControlStyle then + InternalRedraw; +end; + +procedure TJvXPCustomControl.HookFocusedChanged; +begin + // this hook is called, if the currently focused control was changed. + if Focused then + Include(FDrawState, dsFocused) + else + begin + Exclude(FDrawState, dsFocused); + Exclude(FDrawState, dsClicked); + end; + FIsSibling := GetParentForm(Self).ActiveControl is TJvXPCustomControl; + if csRedrawFocusedChanged in ExControlStyle then + InternalRedraw; +end; + +procedure TJvXPCustomControl.HookMouseEnter; +begin + // this hook is called, if the user moves (hover) the mouse over the control. + if not (csDesigning in ComponentState) then + begin + Include(FDrawState, dsHighlight); + if csRedrawMouseEnter in ExControlStyle then + InternalRedraw; + end; + if Assigned(FOnMouseEnter) then + FOnMouseEnter(Self); +end; + +procedure TJvXPCustomControl.HookMouseLeave; +begin + // this hook is called, if the user moves the mouse away (unhover) from + // the control. + if not (csDesigning in ComponentState) then + begin + Exclude(FDrawState, dsHighlight); + if csRedrawMouseLeave in ExControlStyle then + InternalRedraw; + end; + if Assigned(FOnMouseLeave) then + FOnMouseLeave(Self); +end; + +procedure TJvXPCustomControl.HookMouseMove(X: Integer = 0; Y: Integer = 0); +begin + // this hook is called if the user moves the mouse inside the control. + if not (csDesigning in ComponentState) then + if csRedrawMouseMove in ExControlStyle then + InternalRedraw; +end; + +procedure TJvXPCustomControl.HookMouseDown; +begin + // this hook is called, if the user presses the left mouse button over the + // controls. + if not Focused and CanFocus then + SetFocus; + Include(FDrawState, dsClicked); + if csRedrawMouseDown in ExControlStyle then + InternalRedraw; +end; + +procedure TJvXPCustomControl.HookMouseUp; +var + CurrentPos: TPoint; + NewControl: TWinControl; +begin + // this hook is called, if the user releases the left mouse button. + begin + Exclude(FDrawState, dsClicked); + if csRedrawMouseUp in ExControlStyle then + InternalRedraw; + + // does the cursor is over another supported control? + GetCursorPos(CurrentPos); + //21.09.2007 - SESS resolver + //NewControl := FindVCLWindow(CurrentPos); + NewControl := nil; + if (NewControl <> nil) and (NewControl <> Self) and + (NewControl.InheritsFrom(TJvXPCustomControl)) then + TJvXPCustomControl(NewControl).HookMouseEnter; + end; +end; + +procedure TJvXPCustomControl.HookParentColorChanged; +begin + // this hook is called if, the parent color was changed. + if csRedrawParentColorChanged in ExControlStyle then + InternalRedraw; +end; + +procedure TJvXPCustomControl.HookParentFontChanged; +begin + // this hook is called if, the parent font was changed. + if csRedrawParentFontChanged in ExControlStyle then + InternalRedraw; +end; + +procedure TJvXPCustomControl.HookPosChanged; +begin + // this hook is called, if the window position was changed. + if csRedrawPosChanged in ExControlStyle then + InternalRedraw; +end; + +procedure TJvXPCustomControl.HookResized; +begin + // this hook is called, if the control was resized. + if csRedrawResized in ExControlStyle then + InternalRedraw; +end; + +procedure TJvXPCustomControl.HookTextChanged; +begin + // this hook is called, if the caption was changed. + if csRedrawCaptionChanged in ExControlStyle then + InternalRedraw; +end; + +(* 23.09.2007 - SESS - unused +//=== { TJvXPStyle } ========================================================= + +constructor TJvXPStyle.Create(AOwner: TComponent); +begin + inherited Create; + Parent := TJvXPCustomStyleControl(AOwner); + FTheme := WindowsXP; + FUseStyleManager := True; +end; + +procedure TJvXPStyle.SetTheme(Value: TJvXPTheme); +begin + if Value <> FTheme then + begin + FTheme := Value; + Parent.InternalRedraw; + end; +end; + +function TJvXPStyle.GetTheme: TJvXPTheme; +begin + Result := FTheme; + if FUseStyleManager and Assigned(Parent.StyleManager) then + Result := Parent.StyleManager.Theme; +end; + +procedure TJvXPStyle.SetUseStyleManager(Value: Boolean); +begin + if Value <> FUseStyleManager then + begin + FUseStyleManager := Value; + Parent.InternalRedraw; + end; +end; + +//=== { TJvXPStyleManager } ================================================== + +constructor TJvXPStyleManager.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FControls := TList.Create; + FTheme := WindowsXP; +end; + +destructor TJvXPStyleManager.Destroy; +begin + InvalidateControls; + FControls.Free; + inherited Destroy; +end; + +procedure TJvXPStyleManager.InvalidateControls; +var + I: Integer; +begin + for I := 0 to FControls.Count - 1 do + with TJvXPCustomControl(FControls[I]) do + InternalRedraw; +end; + +procedure TJvXPStyleManager.SetTheme(Value: TJvXPTheme); +begin + if Value <> FTheme then + begin + FTheme := Value; + if Assigned(FOnThemeChanged) then + FOnThemeChanged(Self); + InvalidateControls; + end; +end; + +procedure TJvXPStyleManager.RegisterControls(const AControls: array of TJvXPCustomControl); +var + I: Integer; +begin + for I := Low(AControls) to High(AControls) do + if FControls.IndexOf(AControls[I]) = -1 then + FControls.Add(AControls[I]); +end; + +procedure TJvXPStyleManager.UnregisterControls(const AControls: array of TJvXPCustomControl); +var + I: Integer; +begin + for I := Low(AControls) to High(AControls) do + if FControls.IndexOf(AControls[I]) <> -1 then + FControls.Delete(FControls.IndexOf(AControls[I])); +end; + +//=== { TJvXPCustomStyleControl } ============================================ + +constructor TJvXPCustomStyleControl.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FStyle := TJvXPStyle.Create(Self); + FStyleManager := nil; +end; + +destructor TJvXPCustomStyleControl.Destroy; +begin + if FStyleManager <> nil then + FStyleManager.UnregisterControls([Self]); + FStyle.Free; + inherited Destroy; +end; + +procedure TJvXPCustomStyleControl.Notification(AComponent: TComponent; + Operation: TOperation); +begin + if (AComponent is TJvXPStyleManager) and (Operation = opRemove) then + FStyleManager := nil; + inherited Notification(AComponent, Operation); +end; + +procedure TJvXPCustomStyleControl.SetStyleManager(Value: TJvXPStyleManager); +begin + if Value <> FStyleManager then + begin + if Value <> nil then + Value.RegisterControls([Self]) + else + FStyleManager.UnregisterControls([Self]); + FStyleManager := Value; + InternalRedraw; + end; +end; + +//=== { TJvXPGradient } ====================================================== + +constructor TJvXPGradient.Create(AOwner: TControl); +begin + inherited Create; + Parent := TJvXPCustomControl(AOwner); + Bitmap := TBitmap.Create; + FColors := 16; + FDithered := True; + FEnabled := False; + FEndColor := clSilver; + FGradientStyle := gsLeft; + FStartColor := clGray; +end; + +destructor TJvXPGradient.Destroy; +begin + Bitmap.Free; + inherited Destroy; +end; + +procedure TJvXPGradient.RecreateBands; +begin + if Assigned(Bitmap) then + JvXPCreateGradientRect(Parent.Width, Parent.Height, FStartColor, FEndColor, + FColors, FGradientStyle, FDithered, Bitmap); +end; + +procedure TJvXPGradient.SetDithered(Value: Boolean); +begin + if FDithered <> Value then + begin + FDithered := Value; + RecreateBands; + Parent.InternalRedraw; + end; +end; + +procedure TJvXPGradient.SetColors(Value: TJvXPGradientColors); +begin + if FColors <> Value then + begin + FColors := Value; + RecreateBands; + Parent.InternalRedraw; + end; +end; + +procedure TJvXPGradient.SetEnabled(Value: Boolean); +begin + if FEnabled <> Value then + begin + FEnabled := Value; + Parent.InternalRedraw; + end; +end; + +procedure TJvXPGradient.SetEndColor(Value: TColor); +begin + if FEndColor <> Value then + begin + FEndColor := Value; + RecreateBands; + Parent.InternalRedraw; + end; +end; + +procedure TJvXPGradient.SetGradientStyle(Value: TJvXPGradientStyle); +begin + if FGradientStyle <> Value then + begin + FGradientStyle := Value; + RecreateBands; + Parent.InternalRedraw; + end; +end; + +procedure TJvXPGradient.SetStartColor(Value: TColor); +begin + if FStartColor <> Value then + begin + FStartColor := Value; + RecreateBands; + Parent.InternalRedraw; + end; +end; +*) +end. + diff --git a/components/jvcllaz/run/JvXPCoreUtils.pas b/components/jvcllaz/run/JvXPCoreUtils.pas new file mode 100644 index 000000000..dadb05783 --- /dev/null +++ b/components/jvcllaz/run/JvXPCoreUtils.pas @@ -0,0 +1,419 @@ +{----------------------------------------------------------------------------- +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: JvXPCoreUtils.PAS, released on 2004-01-01. + +The Initial Developer of the Original Code is Marc Hoffman. +Portions created by Marc Hoffman are Copyright (C) 2002 APRIORI business solutions AG. +Portions created by APRIORI business solutions AG are Copyright (C) 2002 APRIORI business solutions AG +All Rights Reserved. + +Contributor(s): + +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: +-----------------------------------------------------------------------------} +// $Id: JvXPCoreUtils.pas 11400 2007-06-28 21:24:06Z ahuser $ + +// Ported to Lazarus (no too hard after all) by Sergio Samayoa - september 2007. +// Still dont tested on linux. + +unit JvXPCoreUtils; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, Controls, Graphics, LCLIntf, LCLType, SysUtils, + TypInfo, JvXPCore; + +function JvXPMethodsEqual(const Method1, Method2: TMethod): Boolean; +procedure JvXPDrawLine(const ACanvas: TCanvas; const X1, Y1, X2, Y2: Integer); + +(* 23.09.2007 - SESS - unused +procedure JvXPCreateGradientRect(const AWidth, AHeight: Integer; const StartColor, + EndColor: TColor; const AColors: TJvXPGradientColors; const Style: TJvXPGradientStyle; + const Dithered: Boolean; var Bitmap: TBitmap); +procedure JvXPAdjustBoundRect(const BorderWidth: Byte; + const ShowBoundLines: Boolean; const BoundLines: TJvXPBoundLines; var Rect: TRect); +procedure JvXPDrawBoundLines(const ACanvas: TCanvas; const BoundLines: TJvXPBoundLines; + const AColor: TColor; const Rect: TRect); + +// +// attic! +// + +procedure JvXPConvertToGray2(Bitmap: TBitmap); +procedure JvXPRenderText(const AParent: TControl; const ACanvas: TCanvas; + ACaption: TCaption; const AFont: TFont; const AEnabled, AShowAccelChar: Boolean; + var ARect: TRect; AFlags: Integer); +23.09.2007 - SESS - unused *) +procedure JvXPFrame3D(const ACanvas: TCanvas; const ARect: TRect; + const TopColor, BottomColor: TColor; const Swapped: Boolean = False); +(* 23.09.2007 - SESS - unused +procedure JvXPColorizeBitmap(Bitmap: TBitmap; const AColor: TColor); +procedure JvXPSetDrawFlags(const AAlignment: TAlignment; const AWordWrap: Boolean; + var Flags: Integer); +procedure JvXPPlaceText(const AParent: TControl; const ACanvas: TCanvas; + const AText: TCaption; const AFont: TFont; const AEnabled, AShowAccelChar: Boolean; + const AAlignment: TAlignment; const AWordWrap: Boolean; var Rect: TRect); +23.09.2007 - SESS - unused *) + +implementation + +function JvXPMethodsEqual(const Method1, Method2: TMethod): Boolean; +begin + Result := (Method1.Code = Method2.Code) and (Method1.Data = Method2.Data); +end; + +(* 23.09.2007 - SESS - unused +procedure JvXPCreateGradientRect(const AWidth, AHeight: Integer; const StartColor, + EndColor: TColor; const AColors: TJvXPGradientColors; const Style: TJvXPGradientStyle; + const Dithered: Boolean; var Bitmap: TBitmap); +{ // Short version... +var + gd: TGradientDirection; +begin + if (AHeight <= 0) or (AWidth <= 0) then + Exit; + Bitmap.Height := AHeight; + Bitmap.Width := AWidth; + Bitmap.PixelFormat := pf24bit; + if Style in [gsLeft, gsRight] then + gd := gdHorizontal + else + gd := gdVertical; + Bitmap.Canvas.GradientFill(Rect(0, 0, AWidth, AHeight), StartColor, EndColor, gd); +end; +} +const + PixelCountMax = 32768; + DitherDepth = 16; +type + TGradientBand = array [0..255] of TColor; + TRGBMap = packed record + case Boolean of + True: + (RGBVal: DWord); + False: + (R, G, B, D: Byte); + end; + PRGBTripleArray = ^TRGBTripleArray; + TRGBTripleArray = array [0..PixelCountMax-1] of TRGBTriple; +var + iLoop, xLoop, yLoop, XX, YY: Integer; + iBndS, iBndE: Integer; + GBand: TGradientBand; + Row: PRGBTripleArray; + + procedure CalculateGradientBand; + var + rR, rG, rB: Real; + lCol, hCol: TRGBMap; + iStp: Integer; + begin + if Style in [gsLeft, gsTop] then + begin + lCol.RGBVal := ColorToRGB(StartColor); + hCol.RGBVal := ColorToRGB(EndColor); + end + else + begin + lCol.RGBVal := ColorToRGB(EndColor); + hCol.RGBVal := ColorToRGB(StartColor); + end; + rR := (hCol.R - lCol.R) / (AColors - 1); + rG := (hCol.G - lCol.G) / (AColors - 1); + rB := (hCol.B - lCol.B) / (AColors - 1); + for iStp := 0 to (AColors - 1) do + GBand[iStp] := RGB( + lCol.R + Round(rR * iStp), + lCol.G + Round(rG * iStp), + lCol.B + Round(rB * iStp)); + end; + +begin + // Exit if Height or Width are not positive. If not, the calls would lead to + // GDI errors about "Invalid parameter" and/or "Out Of Resources". + if (AHeight <= 0) or (AWidth <= 0) then + Exit; + + Bitmap.Height := AHeight; + Bitmap.Width := AWidth; + Bitmap.PixelFormat := pf24bit; + + CalculateGradientBand; + + with Bitmap.Canvas do + begin + Brush.Color := StartColor; + FillRect(Bounds(0, 0, AWidth, AHeight)); + if Style in [gsLeft, gsRight] then + begin + for iLoop := 0 to AColors - 1 do + begin + iBndS := MulDiv(iLoop, AWidth, AColors); + iBndE := MulDiv(iLoop + 1, AWidth, AColors); + Brush.Color := GBand[iLoop]; + PatBlt(Handle, iBndS, 0, iBndE, AHeigth, PATCOPY); + if (iLoop > 0) and Dithered then + for yLoop := 0 to DitherDepth - 1 do + if yLoop < AHeight then + begin + Row := Bitmap.ScanLine[yLoop]; + for xLoop := 0 to AWidth div (AColors - 1) do + begin + XX := iBndS + Random(xLoop); + if (XX < AWidth) and (XX > -1) then + with Row[XX] do + begin + rgbtRed := GetRValue(GBand[iLoop - 1]); + rgbtGreen := GetGValue(GBand[iLoop - 1]); + rgbtBlue := GetBValue(GBand[iLoop - 1]); + end; + end; + end; + end; + for yLoop := 1 to AHeight div DitherDepth do + CopyRect(Bounds(0, yLoop * DitherDepth, AWidth, DitherDepth), + Bitmap.Canvas, Bounds(0, 0, AWidth, DitherDepth)); + end + else + begin + for iLoop := 0 to AColors - 1 do + begin + iBndS := MulDiv(iLoop, AHeight, AColors); + iBndE := MulDiv(iLoop + 1, AHeight, AColors); + Brush.Color := GBand[iLoop]; + PatBlt(Handle, 0, iBndS, AWidth, iBndE, PATCOPY); + if (iLoop > 0) and Dithered then + for yLoop := 0 to AHeight div (AColors - 1) do + begin + YY := iBndS + Random(yLoop); + if (YY < AHeight) and (YY > -1) then + begin + Row := Bitmap.ScanLine[YY]; + for xLoop := 0 to DitherDepth - 1 do + if xLoop < AWidth then + with Row[xLoop] do + begin + rgbtRed := GetRValue(GBand[iLoop - 1]); + rgbtGreen := GetGValue(GBand[iLoop - 1]); + rgbtBlue := GetBValue(GBand[iLoop - 1]); + end; + end; + end; + end; + for xLoop := 0 to AWidth div DitherDepth do + CopyRect(Bounds(xLoop * DitherDepth, 0, DitherDepth, AHeight), + Bitmap.Canvas, Bounds(0, 0, DitherDepth, AHeight)); + end; + end; +end; +*) + +procedure JvXPDrawLine(const ACanvas: TCanvas; const X1, Y1, X2, Y2: Integer); +begin + with ACanvas do + begin + MoveTo(X1, Y1); + LineTo(X2, Y2); + end; +end; + +(* 23.09.2007 - SESS - unused +procedure JvXPAdjustBoundRect(const BorderWidth: Byte; + const ShowBoundLines: Boolean; const BoundLines: TJvXPBoundLines; + var Rect: TRect); +begin + InflateRect(Rect, -BorderWidth, -BorderWidth); + if not ShowBoundLines then + Exit; + if blLeft in BoundLines then + Inc(Rect.Left); + if blRight in BoundLines then + Dec(Rect.Right); + if blTop in BoundLines then + Inc(Rect.Top); + if blBottom in BoundLines then + Dec(Rect.Bottom); +end; + +procedure JvXPDrawBoundLines(const ACanvas: TCanvas; const BoundLines: TJvXPBoundLines; + const AColor: TColor; const Rect: TRect); +begin + with ACanvas do + begin + Pen.Color := AColor; + Pen.Style := psSolid; + if blLeft in BoundLines then + JvXPDrawLine(ACanvas, Rect.Left, Rect.Top, Rect.Left, Rect.Bottom - 1); + if blTop in BoundLines then + JvXPDrawLine(ACanvas, Rect.Left, Rect.Top, Rect.Right, Rect.Top); + if blRight in BoundLines then + JvXPDrawLine(ACanvas, Rect.Right - 1, Rect.Top, Rect.Right - 1, Rect.Bottom - 1); + if blBottom in BoundLines then + JvXPDrawLine(ACanvas, Rect.Top, Rect.Bottom - 1, Rect.Right, Rect.Bottom - 1); + end; +end; + +// +// attic +// + +procedure JvXPConvertToGray2(Bitmap: TBitmap); +var + x, y, c: Integer; + PxlColor: TColor; +begin + for x := 0 to Bitmap.Width - 1 do + for y := 0 to Bitmap.Height - 1 do + begin + PxlColor := ColorToRGB(Bitmap.Canvas.Pixels[x, y]); + c := (PxlColor shr 16 + ((PxlColor shr 8) and $00FF) + PxlColor and $0000FF) div 3 + 100; + if c > 255 then + c := 255; + Bitmap.Canvas.Pixels[x, y] := RGB(c, c, c); + end; +end; + +procedure JvXPRenderText(const AParent: TControl; const ACanvas: TCanvas; + ACaption: TCaption; const AFont: TFont; const AEnabled, AShowAccelChar: Boolean; + var ARect: TRect; AFlags: Integer); + + procedure DoDrawText; + begin + // (rom) Kludge! This will probably not work for CLX + DrawText(ACanvas.Handle, PChar(ACaption), -1, ARect, AFlags); + end; + +begin + if (AFlags and DT_CALCRECT <> 0) and ((ACaption = '') or AShowAccelChar and + (ACaption[1] = '&') and (ACaption[2] = #0)) then + ACaption := ACaption + ' '; + if not AShowAccelChar then + AFlags := AFlags or DT_NOPREFIX; + AFlags := AParent.DrawTextBiDiModeFlags(AFlags); + with ACanvas do + begin + Font.Assign(AFont); + if not AEnabled then + Font.Color := dxColor_Msc_Dis_Caption_WXP; + if not AEnabled then + begin + OffsetRect(ARect, 1, 1); + Font.Color := clBtnHighlight; + DoDrawText; + OffsetRect(ARect, -1, -1); + Font.Color := clBtnShadow; + DoDrawText; + end + else + DoDrawText; + end; +end; +23.09.2007 - SESS - unused *) + +procedure JvXPFrame3D(const ACanvas: TCanvas; const ARect: TRect; + const TopColor, BottomColor: TColor; const Swapped: Boolean = False); +var + ATopColor, ABottomColor: TColor; +begin + ATopColor := TopColor; + ABottomColor := BottomColor; + if Swapped then + begin + ATopColor := BottomColor; + ABottomColor := TopColor; + end; + with ACanvas do + begin + Pen.Color := ATopColor; + // 21.09.07 - SESS + Polyline([ + Classes.Point(ARect.Left, ARect.Bottom - 1), + Classes.Point(ARect.Left, ARect.Top), + Classes.Point(ARect.Right - 1, ARect.Top)]); + Pen.Color := ABottomColor; + Polyline([ + Classes.Point(ARect.Right - 1, ARect.Top + 1), + Classes.Point(ARect.Right - 1 , ARect.Bottom - 1), + Classes.Point(ARect.Left, ARect.Bottom - 1)]); + end; +end; + +(* 23.09.2007 - SESS - unused +procedure JvXPColorizeBitmap(Bitmap: TBitmap; const AColor: TColor); +var + ColorMap: TBitmap; + Rect: TRect; +begin + Rect := Bounds(0, 0, Bitmap.Width, Bitmap.Height); + ColorMap := TBitmap.Create; + try + ColorMap.Assign(Bitmap); + Bitmap.FreeImage; + with ColorMap.Canvas do + begin + Brush.Color := AColor; + BrushCopy( Rect, Bitmap, Rect, clBlack); + end; + Bitmap.Assign(ColorMap); + finally + ColorMap.Free; + end; +end; + +procedure JvXPSetDrawFlags(const AAlignment: TAlignment; const AWordWrap: Boolean; + var Flags: Integer); +begin + Flags := DT_END_ELLIPSIS; + case AAlignment of + taLeftJustify: + Flags := Flags or DT_LEFT; + taCenter: + Flags := Flags or DT_CENTER; + taRightJustify: + Flags := Flags or DT_RIGHT; + end; + if not AWordWrap then + Flags := Flags or DT_SINGLELINE + else + Flags := Flags or DT_WORDBREAK; +end; + +procedure JvXPPlaceText(const AParent: TControl; const ACanvas: TCanvas; const AText: TCaption; + const AFont: TFont; const AEnabled, AShowAccelChar: Boolean; const AAlignment: TAlignment; + const AWordWrap: Boolean; var Rect: TRect); +var + Flags, DX, OH, OW: Integer; +begin + OH := Rect.Bottom - Rect.Top; + OW := Rect.Right - Rect.Left; + JvXPSetDrawFlags(AAlignment, AWordWrap, Flags); + JvXPRenderText(AParent, ACanvas, AText, AFont, AEnabled, AShowAccelChar, Rect, + Flags or DT_CALCRECT); + if AAlignment = taRightJustify then + DX := OW - (Rect.Right + Rect.Left) + else + if AAlignment = taCenter then + DX := (OW - Rect.Right) div 2 + else + DX := 0; + OffsetRect(Rect, DX, (OH - Rect.Bottom) div 2); + JvXPRenderText(AParent, ACanvas, AText, AFont, AEnabled, AShowAccelChar, Rect, Flags); +end; +23.09.2007 - SESS - unused *) + +end. +