diff --git a/README.md b/README.md index 693154d..992110f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,11 @@ + + + +![Delphi](https://img.shields.io/badge/Delphi-XE3-red.svg) +![Windows](https://img.shields.io/badge/Windiws-Vista--10-blue.svg) +![License](https://img.shields.io/badge/license-MIT-brightgreen.svg) + + What is Linkbar ? =============================== Linkbar is a free source code desktop toolbar. Running in the MS Windows Vista+ environment, its use is governed by diff --git a/components/ColorPicker/ColorPicker.pas b/components/ColorPicker/ColorPicker.pas index 9809442..374371b 100644 --- a/components/ColorPicker/ColorPicker.pas +++ b/components/ColorPicker/ColorPicker.pas @@ -91,6 +91,7 @@ TfrmColorPicker = class(TForm) LastHue: Integer; TextEnter: Boolean; AlpBarHeight: Integer; + procedure L10n; public procedure PaintVar; procedure PaintColorHue; @@ -104,7 +105,7 @@ implementation {$R *.dfm} uses - ColorUtils, GdiPlusHelpers, GdiPlus; + ColorUtils, GdiPlusHelpers, GdiPlus, Linkbar.L10n; function TfrmColorPicker.GetColor: Cardinal; begin @@ -244,6 +245,13 @@ procedure TfrmColorPicker.editColor1KeyUp(Sender: TObject; var Key: Word; TextEnter := False; end; +procedure TfrmColorPicker.L10n; +begin + L10nControl(Self, 'Color.Caption'); + L10nControl(btnOk, 'Color.OK'); + L10nControl(btnCancel, 'Color.Cancel'); +end; + procedure TfrmColorPicker.FormCreate(Sender: TObject); const Colors: array[0..15] of TColor = (clBlack, clWhite, clGray, clSilver, @@ -252,6 +260,8 @@ procedure TfrmColorPicker.FormCreate(Sender: TObject); var i: Integer; begin + L10n; + AlpBarHeight := imgAlpha.Height - 1; HBoxBmp := TBitmap.Create; diff --git a/components/DelLoc/LcUnitXe.pas b/components/DelLoc/LcUnitXe.pas deleted file mode 100644 index e42770e..0000000 --- a/components/DelLoc/LcUnitXe.pas +++ /dev/null @@ -1,875 +0,0 @@ -{* DelLocXe. LcUnitXe.pas. Serge Gavrilov ( C ) 2005-2012 *************************************** *} - -unit LcUnitXE; - -{ - DelLocXE (Delphi localization compiler for Xe) for Delphi XE. Interface unit. - - All right reserved. Serge Gavrilov (C) 2005-2012. - - e-mail: s.gav@mail.ru - icq: 777807 - http://delloc.narod.ru/en.html - - - To localize your delphi program You have to make next simple things: - 1. Create with DelLoc the localization file that will - include translations of the resourcestrings and translations of the form's - and component's string properties. - 2. Include unit LcUnitXe.pas in your project or make it available in search - pathes. - 3. In project source: after loading application call function LoadLcf() where - pass as parameters localization file name and locale identificator (LCID) - that will be used to translate. You may place the call of LoadLcf() in - project source file after "begin" keyword or in the initialization section - of the any project unit. - 4. After creating form which interface and components need to be translatad - call function TranslateComponent() and pass as parameter the created form. - You may place call at the body of the overrided constructor after - "inherited" keyword or in the OnCreate event handler. If you inherites - all project forms from one base form class you may provide call of the - TranslateComponent() only for the base form class. - - Unit LcUnitXe.pas includes declaration of the two functions: LoadLcf() and - TranslateComponent(), and declare one type: TLcCallBack. - - Function LoadLcf() loads localization file and activates translation for - the passed locale identificator. - - function LoadLcf( - const sFileName : nstr; - iLCID : LCID; - pCallBack : TLcCallBack; - pUd : pointer - ) : integer; - - Parameters: - sFileName - localization file name; - iLCID - locale identificator to activate. Use Delphi's class TLanguages - to inspect all available locale identificators and its string - descriptions. - pCallBack - pointer to callback function of type TLcCallBack. If this - parameter is not null then the callback function will be called - for each locale identificator supported by the localization - file. - pUd - used difened pointer. Will be passed as parameter to the callback - function pCallBack. - - Result: - 1 - localization file was loaded and translation for requeted locale - was activated; - 0 - localization file was loaded but translation for requeted locale is - not present in the localization file. Translation will not be make. - <0 - localization file error loading. Translation will not be make. - - Function TranslateComponent() translate the interface and form's - components string propertied. - - function TranslateComponent( - oComponent : TComponent - ) : boolean; - - Parameters: - oComponent - Form which interface and components will be localized. - Result: - true - localization success; - false - localization error. - - The type TLcCallBack is a prototype of the callback function which pointer is - passed into LoadLcf() as parameter. The callback function will be called - for each locale identificator supported by the localization file. - - type - TLcCallBack = function( - iLCID : integer; - pUd : pointer - ) : integer; stdcall; - - Parameters: - iLCID - locale identificator supported in localization file; - pUd - user defined pointer passed into LoadLcf() as parameter. - Result: - 0 - stop calling callback for the next locale ids; - <>0 - continue the callback calls for the next locale ids. - - To switch the langauges at runtime You may use next code: - - var - i : integer; - begin - for i := 0 to Screen.FormCount - 1 - do TranslateComponent( Screen.Forms[ i ] ); - end; - - - THIS UNIT IS DISTRIBUTED "AS IS". NO WARRANTY OF ANY KIND IS EXPRESSED - OR IMPLIED. YOU USE AT YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE - FOR DATA LOSS, DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS - WHILE USING OR MISUSING THIS SOFTWARE. - -} - -interface - -uses - SysUtils, Windows, Classes, StrUtils, TypInfo; - -type - - str = AnsiString; - nstr = string; - nchr = Char; - chr = AnsiChar; - wstr = WideString; - pchr = PAnsiChar; - wchr = WideChar; - pwchr = PWideChar; - pnchr = PChar; - - TLcCallBack = function( iLCID : integer; pUd : pointer ) : integer; stdcall; - TLcOnGetRes = function( - const sResStr : wstr; - var iLCID : integer; - var iCPage : integer; - pUd : pointer ) : integer; stdcall; - - TPLcLoadOpts = ^TLcLoadOpts; - TLcLoadOpts = record - iSize : integer; - iLCID : LCID; - pCallBack : TLcCallBack; - pOnGetResStr : TLcOnGetRes; - pUd : pointer; - end; - -function LoadLcf( - const sFileName : nstr; - iLCID : LCID; - pCallBack : TLcCallBack; - pUd : pointer - ) : integer; - -function LoadLcfEx( - const sFileName : nstr; - pOpts : TPLcLoadOpts - ) : integer; - -function TranslateComponent( oComponent : TComponent ) : boolean; -function TranslateComponentEx( - oComponent : TComponent; - iLCID : LCID ) : boolean; - - - -implementation - -{* ************************************************************************** *} - -const - LC_OPT_PROJINFO = 1; - LC_SIGNATURE = 'LCHEADER'; - LC_HEADE3_RESID = 'LCHEADE3'; - -type - -{* ************************************************************************** *} - - TLcHeaderRec = packed record - aSign : packed array[ 0..Length( LC_SIGNATURE ) - 1 ] of chr; - iOpts : integer; - iLCIDCount : integer; - end; - TPLcHeaderRec = ^TLcHeaderRec; - -{* ************************************************************************** *} - - TLcHeaderResRec = packed record - rHeader : TLcHeaderRec; - aLCID : packed array[ 0..0 ] of LCID; - end; - TPLcHeaderResRec = ^TLcHeaderResRec; - -{* ************************************************************************** *} - - TLcCPages = packed array[ 0..0 ] of UINT; - TPLcCPages = ^TLcCPages; - -{* ************************************************************************** *} - - TLcResItemStr = packed record - iOffset : integer; - iLength : integer; - end; - TLcResItemRec = packed array[ 0..0 ] of TLcResItemStr; - TPLcResItemRec = ^TLcResItemRec; - -{* ************************************************************************** *} - -type - - TProc = class - private - aOriginal : packed array[ 0..4 ] of byte; - pOldProc, pNewProc : pointer; - pPosition : PByteArray; - public - constructor Create( pOldProc, pNewProc : pointer ); - destructor Destroy; override; - end; - -{* ************************************************************************** *} - - TLcf = class - private - iLangIndex : integer; - iPropLangIndex : integer; - iLibHandle : THANDLE; - iLCID : LCID; - iCPage : UINT; - aProc : array[ 0..0 ] of TProc; - pUd : pointer; - pOnGetResStr : TLcOnGetRes; - pHeader : TPLcHeaderResRec; - isOldFormat : boolean; - public - constructor Create; - destructor Destroy; override; - function LoadLib( szFileName : PChar; iLCID : LCID; - pCallBack : TLcCallBack; pOnGetResStr : TLcOnGetRes; - pUd : pointer ) : integer; - function LoadLibEx( szFileName : PChar; pOpts : TPLcLoadOpts ) : integer; - function GetResString( pResStrRec : PResStringRec ) : nstr; - function TranslateComponent( - oComponent : TComponent; - iLCID : LCID ) : boolean; - procedure RegProcs( pN1, pO1 : pointer ); - function GetLangIndex( iLCID : LCID; - pLangIndex : pinteger; - pPropLangIndex : pinteger; - var iCPage : UINT ) : boolean; - end; - -{* ************************************************************************** *} - -var - - _oLcf : TLcf = nil; - -{* ************************************************************************** *} - -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -constructor TProc.Create; -var - iOffset : integer; - iMemProtect : cardinal; - i : integer; -begin - Self.pOldProc := pOldProc; - Self.pNewProc := pNewProc; - - pPosition := pOldProc; - iOffset := integer( pNewProc ) - integer( pointer( pPosition ) ) - 5; - - for i := 0 to 4 do aOriginal[ i ] := pPosition^[ i ]; - - if not VirtualProtect( pointer( pPosition ), 5, PAGE_EXECUTE_READWRITE, @iMemProtect ) - then RaiseLastOsError; - - pPosition^[ 0 ] := $E9; - pPosition^[ 1 ] := byte( iOffset ); - pPosition^[ 2 ] := byte( iOffset shr 8 ); - pPosition^[ 3 ] := byte( iOffset shr 16 ); - pPosition^[ 4 ] := byte( iOffset shr 24 ); - -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -destructor TProc.Destroy; -var - i : integer; -begin - for i := 0 to 4 do pPosition^[ i ] := aOriginal[ i ]; - inherited; -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} - -{* ************************************************************************** *} - -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -constructor TLcf.Create; -begin - _oLcf := Self; -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -destructor TLcf.Destroy; -var - i : integer; -begin - _oLcf := nil; - for i := Low( aProc ) to High( aProc ) do aProc[ i ].Free; - if iLibHandle <> 0 then FreeLibrary( iLibHandle ); - inherited; -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function LCIDToCodePage( iLCID : LCID ) : UINT; -var - iResultCode : integer; - p : array[ 0..6 ] of nchr; -begin - GetLocaleInfo( iLCID, LOCALE_IDEFAULTANSICODEPAGE, p, Length( p ) ); - Val( p, result, iResultCode ); - if iResultCode <> 0 then result := CP_ACP; -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function TLcf.GetLangIndex; -var - i : integer; - pPages : TPLcCPages; -begin - - result := false; - if pHeader = nil then exit; - - if iLCID = Self.iLCID - then begin - if pLangIndex <> nil then pLangIndex^ := Self.iLangIndex; - if pPropLangIndex <> nil then pPropLangIndex^ := Self.iPropLangIndex; - iCPage := Self.iCPage; - result := true; - exit; - end; - - for i := 0 to pHeader^.rHeader.iLCIDCount - 1 - do if pHeader^.aLCID[ i ] = iLCID - then begin - result := true; - if pLangIndex <> nil - then begin - pLangIndex^ := i; - if ( pHeader^.rHeader.iOpts and LC_OPT_PROJINFO ) <> 0 - then Inc( pLangIndex^ ); - end; - if pPropLangIndex <> nil then pPropLangIndex^ := i; - if not isOldFormat - then begin - pPages := pointer( integer( pHeader ) + - sizeof( TLcHeaderRec ) + - pHeader^.rHeader.iLCIDCount * sizeof( LCID ) ); - iCPage := pPages^[ i ]; - end - else iCPage := LCIDToCodePage( iLCID ); - exit; - end; -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function TLcf.LoadLib; -var - iRes : HRSRC; - iGlobal : HGLOBAL; - i : integer; - s : str; -begin - result := -1; - iLibHandle := LoadLibraryEx( szFileName, 0, - LOAD_LIBRARY_AS_DATAFILE or DONT_RESOLVE_DLL_REFERENCES ); - if iLibHandle = 0 then exit; - Self.pUd := pUd; - Self.pOnGetResStr := pOnGetResStr; - isOldFormat := true; - iRes := FindResource( iLibHandle, LC_HEADE3_RESID, RT_RCDATA ); - if iRes = 0 then exit; - - iGlobal := LoadResource( iLibHandle, iRes ); - if iGlobal = 0 then exit; - if SizeOfResource( iLibHandle, iRes ) < sizeof( TLcHeaderRec ) then exit; - pHeader := pointer( iGlobal ); - s := LC_SIGNATURE; - if not CompareMem( @pHeader^.rHeader.aSign[ 0 ], @s[ 1 ], Length( s ) ) - then begin - pHeader := nil; - exit; - end; - result := 0; - if Assigned( pCallBack ) - then for i := 0 to pHeader^.rHeader.iLCIDCount - 1 - do if pCallBack( pHeader^.aLCID[ i ], pUd ) = 0 then break; - if not GetLangIndex( iLCID, @iLangIndex, @iPropLangIndex, iCPage ) then exit; - Self.iLCID := iLCID; - result := 1; -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function TLcf.LoadLibEx; -begin - result := -1; - if ( pOpts = nil ) or ( pOpts^.iSize <> sizeof( pOpts^ ) ) then exit; - result := LoadLib( szFileName, pOpts^.iLCID, pOpts^.pCallBack, pOpts^.pOnGetResStr, pOpts^.pUd ); -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function TLcf.GetResString; -var - iDefLen : integer; - wBuffer : array [ 0..1023 ] of wchr; - iPrefix : integer; - iLCID : integer; - iCPage : UINT; - iLangIndex : integer; - iChangedCPage : integer; - - iRes : HRSRC; - iGlobal : HGLOBAL; - pResItem : TPLcResItemRec; - wString : wstr; - - procedure GetDefault; - begin - if iDefLen > 0 then exit; - iDefLen := LoadStringW( - FindResourceHInstance( pResStrRec.Module^ ), - pResStrRec.Identifier, - wBuffer, - SizeOf( wBuffer ) div SizeOf( wBuffer[ 0 ] ) ); - end; - -begin - iDefLen := 0; - iPrefix := 0; - - iLCID := Self.iLCID; - iChangedCPage := 0; - - if Assigned( pOnGetResStr ) - then begin - GetDefault; - if iDefLen > 0 - then iPrefix := pOnGetResStr( PWideChar( @wBuffer ), iLCID, iChangedCPage, pUd ); - end; - - if not GetLangIndex( iLCID, @iLangIndex, nil, iCPage ) - then iLCID := 0 - else if iChangedCPage <> 0 then iCPage := iChangedCPage; - - if iLCID <> 0 - then begin - iRes := FindResource( iLibHandle, - MAKEINTRESOURCE( IntToStr( pResStrRec^.Identifier ) ), RT_RCDATA ); - if iRes <> 0 - then begin - iGlobal := LoadResource( iLibHandle, iRes ); - if iGlobal <> 0 - then begin - pResItem := pointer( iGlobal ); - if pResItem^[ iLangIndex ].iLength >= 0 - then begin - SetLength( wString, - pResItem^[ iLangIndex ].iLength shr 1 ); - Move( - PByteArray( pResItem )^ - [ pResItem^[ iLangIndex ].iOffset ], - pointer( wString )^, - pResItem^[ iLangIndex ].iLength ); - result := wString; - exit; - end; - end; - end; - end; - - GetDefault; - if iDefLen > 0 - then begin - result := pwchr( @wBuffer ); - if iPrefix > 0 then Delete( result, 1, iPrefix ); - end - else result := ''; -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -procedure TLcf.RegProcs; -begin - if Assigned( pO1 ) and Assigned( pN1 ) - then aProc[ 0 ] := TProc.Create( pO1, pN1 ); -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} - -{* ************************************************************************** *} - -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function NewLoadResString( ResStringRec : PResStringRec ) : nstr; -const - MAX_ID = 64 * 1024; -begin - if ResStringRec = nil then exit; - if ResStringRec.Identifier >= MAX_ID - then result := pnchr( ResStringRec.Identifier ) - else result := _oLcf.GetResString( ResStringRec ); -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function LoadLcf; -begin - _oLcf.Free; - _oLcf := TLcf.Create; - result := _oLcf.LoadLib( PChar( sFileName ), iLCID, pCallBack, nil, pUd ); - if result < 1 - then begin - _oLcf.Free; _oLcf := nil; - exit; - end; - _oLcf.RegProcs( @NewLoadResString, @System.LoadResString ); -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function LoadLcfEx; -begin - _oLcf.Free; - _oLcf := TLcf.Create; - result := _oLcf.LoadLibEx( pwchr( sFileName ), pOpts ); - if result < 1 - then begin - _oLcf.Free; _oLcf := nil; - exit; - end; - _oLcf.RegProcs( @NewLoadResString, @System.LoadResString ); -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function TranslateComponent; -begin - result := false; - if _oLcf = nil then exit; - result := _oLcf.TranslateComponent( oComponent, _oLcf.iLCID ); -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function TranslateComponentEx; -begin - result := false; - if _oLcf = nil then exit; - result := _oLcf.TranslateComponent( oComponent, iLCID ); -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} - -{* ************************************************************************** *} - -type - - TProp = class - private - oLcf : TLcf; - sCompName : nstr; - sPropName : nstr; - wTranslation : wstr; - isTranslated : boolean; - public - function LoadFromResource( iLangIndex : integer; pRes : PByteArray ) : boolean; - procedure Translate( iCPage : UINT; oComponent : TComponent ); - end; - -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} - - TProps = class - private - oLcf : TLcf; - oComponent : TComponent; - oItems : TList; - public - constructor Create; - destructor Destroy; override; - function LoadFromResource( iLangIndex : integer ) : boolean; overload; - function LoadFromResource( iLangIndex : integer; - oClassType : TClass ) : boolean; overload; - end; - -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function TextToChar( const s : nstr; c : nchr; var iPos : integer ) : nstr; -var - iNextPos : integer; -begin - iNextPos := PosEx( c, s, iPos ); - if iNextPos = 0 - then result := Copy( s, iPos, Length( s ) - iPos + 1 ) - else begin - result := Copy( s, iPos, iNextPos - iPos ); - Inc( iNextPos ); - if iNextPos > Length( s ) then iNextPos := 0; - end; - iPos := iNextPos; -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function TProp.LoadFromResource; -var - sFullName : nstr; - pBytes : PByteArray; - iPos : integer; - iLength : integer; - iOffset : integer; -begin - SetLength( sFullName, TPLcResItemRec( pRes )^[ 0 ].iLength div sizeof( wchr ) ); - pBytes := pRes; - Move( pBytes^[ TPLcResItemRec( pRes )^[ 0 ].iOffset ], - sFullName[ 1 ], - TPLcResItemRec( pRes )^[ 0 ].iLength ); - iPos := 1; - sCompName := TextToChar( sFullName, '-', iPos ); - sPropName := TextToChar( sFullName, '-', iPos ); - iLength := TPLcResItemRec( pRes )^[ iLangIndex + 1 ].iLength; - iOffset := TPLcResItemRec( pRes )^[ iLangIndex + 1 ].iOffset; - isTranslated := iLength >= 0; - if isTranslated - then begin - SetLength( wTranslation, iLength div sizeof( wchr ) ); - Move( pBytes^[ iOffset ], pointer( wTranslation )^, iLength ); - end; - result := true; -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -procedure TProp.Translate; - - function FindObject( const sName : nstr ) : TObject; - begin - if SameText( sName, oComponent.Name ) - then begin - result := oComponent; - exit; - end; - result := oComponent.FindComponent( sName ); - end; - -type - TPropTypeFromName = ( ptfnGeneral, ptfnList, ptfnCollection ); - -const - AS_ENDS : array[ TPropTypeFromName ] of nchr = ( ' ', ')', '>' ); - - function ExtractPropName( - const sPropName : nstr; - var iType : TPropTypeFromName; - var iCollListIndex : integer ) : nstr; - var - iPos : integer; - begin - iType := ptfnGeneral; - iCollListIndex := 0; - iPos := Pos( '<', sPropName ); - if iPos >= 1 - then begin - iType := ptfnCollection; - end - else begin - iPos := Pos( '(', sPropName ); - if iPos >= 1 - then begin - iType := ptfnList; - end - else begin - result := sPropName; - exit; - end; - end; - result := Copy( sPropName, 1, iPos - 1 ); - Inc( iPos ); - iCollListIndex := StrToInt( TextToChar( sPropName, AS_ENDS[ iType ], - iPos ) ); - end; - - function FindPropInfo( - var oObject : TObject; - oPropNames : TStrings; - iIndex : integer; - var iTypeFromName : TPropTypeFromName; - var iCollListIndex : integer - ) : PPropInfo; - var - sPropName : nstr; - begin - sPropName := ExtractPropName( oPropNames[ iIndex ], - iTypeFromName, - iCollListIndex ); - - result := GetPropInfo( oObject.ClassInfo, sPropName ); - - if ( result <> nil ) - and ( iIndex < oPropNames.Count - 1 ) - then begin - if ( result^.PropType^.Kind = tkClass ) - then begin - oObject := GetObjectProp( oObject, sPropName ); - case iTypeFromName of - ptfnList : - begin - result := nil; - end; - ptfnCollection : - begin - oObject := ( oObject as TCollection ).Items - [ iCollListIndex ]; - if oObject <> nil - then result := FindPropInfo( oObject, - oPropNames, - iIndex + 1, - iTypeFromName, - iCollListIndex ); - end; - else - if oObject <> nil - then result := FindPropInfo( oObject, - oPropNames, - iIndex + 1, - iTypeFromName, - iCollListIndex ) - else result := nil; - end; - end - else result := nil; - end; - end; - -var - oObject : TObject; - iPos : integer; - oPropNames : TStrings; - pProp : PPropInfo; - wOldTranslation : wstr; - iTypeFromName : TPropTypeFromName; - iCollListIndex : integer; -begin - oObject := FindObject( sCompName ); - if oObject = nil then exit; - iPos := 1; - oPropNames := TStringList.Create; - try - while iPos > 0 - do begin - oPropNames.Add( TextToChar( sPropName, '.', iPos ) ); - end; - pProp := FindPropInfo( oObject, oPropNames, 0, - iTypeFromName, - iCollListIndex ); - if ( pProp <> nil ) - then begin - if pProp^.PropType^.Kind in [ tkString, tkLString, tkWString, tkUString ] - then begin - {asaq GetWideStrProp depricated {/asaq} - wOldTranslation := GetStrProp( oObject, nstr( pProp^.Name ) ); - if ( pProp^.SetProc <> nil ) and ( wOldTranslation <> wTranslation ) - then begin - SetWideStrProp( oObject, pProp, wTranslation ); - end; - end; - end - else begin - if oObject = nil then exit; - if ( oObject is TStrings ) and ( iTypeFromName = ptfnList ) - then begin - if ( iCollListIndex < ( oObject as TStrings ).Count ) - then begin - wOldTranslation := ( oObject as TStrings )[ iCollListIndex ]; - if wOldTranslation <> wTranslation - then begin - ( oObject as TStrings )[ iCollListIndex ] := wTranslation; - end; - end; - exit; - end; - if oObject is TCollection - then begin - exit; - end; - end; - finally - oPropNames.Free; - end; -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -constructor TProps.Create; -begin - oItems := TList.Create; -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -destructor TProps.Destroy; -var - i : integer; -begin - for i := 0 to oItems.Count - 1 do TObject( oItems[ i ] ).Free; - oItems.Free; - inherited; -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function TProps.LoadFromResource( iLangIndex : integer ) : boolean; -begin - result := LoadFromResource( iLangIndex, oComponent.ClassType ); -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function TProps.LoadFromResource( iLangIndex : integer; - oClassType : TClass ) : boolean; -var - iRes : HRSRC; - iGlobal : HGLOBAL; - iPropCount : integer; - oProp : TProp; - sClassName : wstr; - oClassParent : TClass; - n : integer; -begin - result := false; - oClassParent := oClassType.ClassParent; - if Assigned( oClassParent ) and oClassParent.InheritsFrom( TComponent ) - then LoadFromResource( iLangIndex, oClassParent ); - iRes := FindResource( oLcf.iLibHandle, pwchr( UpperCase( oClassType.ClassName ) ), RT_RCDATA ); - if iRes = 0 then exit; - iGlobal := LoadResource( oLcf.iLibHandle, iRes ); - if iGlobal = 0 then exit; - n := integer( pointer( iGlobal )^ ); - SetLength( sClassName, n div sizeof( wchr ) ); - Inc( iGlobal, sizeof( integer ) ); - Move( pointer( iGlobal )^, sClassName[ 1 ], n ); - Inc( iGlobal, n ); - iPropCount := integer( pointer( iGlobal )^ ); - Inc( iGlobal, sizeof( integer ) ); - while iPropCount > 0 - do begin - Dec( iPropCount ); - oProp := TProp.Create; - oProp.oLcf := oLcf; - if not oProp.LoadFromResource( iLangIndex, pointer( iGlobal + - Cardinal( TPLcResItemRec( pointer( iGlobal ) )^[ iPropCount ]. - iOffset ) ) ) - then oProp.Free - else oItems.Add( oProp ); - end; - result := true; -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} -function TLcf.TranslateComponent; -var - oProps : TProps; - oProp : TProp; - i : integer; - iPropLangIndex : integer; - iCPage : UINT; -begin - result := false; - if not GetLangIndex( iLCID, nil, @iPropLangIndex, iCPage ) then exit; - oProps := TProps.Create; - oProps.oLcf := Self; - oProps.oComponent := oComponent; - try - result := oProps.LoadFromResource( iPropLangIndex ); - if not result then exit; - for i := 0 to oProps.oItems.Count - 1 - do begin - oProp := oProps.oItems[ i ]; - if oProp.isTranslated then oProp.Translate( iCPage, oComponent ); - end; - finally - oProps.Free; - end; -end; -{* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *} - -{* ************************************************************************** *} - -initialization - -finalization - - _oLcf.Free; - -end. - - - diff --git a/components/HotKey/HotKey.dfm b/components/HotKey/HotKey.dfm new file mode 100644 index 0000000..b7863eb --- /dev/null +++ b/components/HotKey/HotKey.dfm @@ -0,0 +1,69 @@ +object HotkeyEdit: THotkeyEdit + Left = 0 + Top = 0 + Width = 353 + Height = 22 + TabOrder = 0 + OnResize = FrameResize + object Bevel1: TBevel + Left = 227 + Top = 0 + Width = 126 + Height = 22 + Align = alClient + Shape = bsSpacer + ExplicitLeft = 228 + ExplicitWidth = 86 + end + object chbWin: TCheckBox + Left = 172 + Top = 0 + Width = 55 + Height = 22 + Align = alLeft + Caption = 'WIN +' + TabOrder = 3 + OnClick = Changed + end + object chbAlt: TCheckBox + Left = 121 + Top = 0 + Width = 51 + Height = 22 + Align = alLeft + Caption = 'ALT +' + TabOrder = 2 + OnClick = Changed + end + object chbCtrl: TCheckBox + Left = 63 + Top = 0 + Width = 58 + Height = 22 + Align = alLeft + Caption = 'CTRL +' + TabOrder = 1 + OnClick = Changed + end + object chbShift: TCheckBox + Left = 0 + Top = 0 + Width = 63 + Height = 22 + Align = alLeft + Caption = 'SHIFT +' + TabOrder = 0 + OnClick = Changed + end + object htkKey: THotKey + Left = 255 + Top = 1 + Width = 86 + Height = 21 + AutoSize = False + HotKey = 112 + Modifiers = [] + TabOrder = 4 + OnChange = Changed + end +end diff --git a/components/HotKey/HotKey.pas b/components/HotKey/HotKey.pas new file mode 100644 index 0000000..3814b6b --- /dev/null +++ b/components/HotKey/HotKey.pas @@ -0,0 +1,224 @@ +{*******************************************************} +{ Linkbar - Windows desktop toolbar } +{ Copyright (c) 2010-2017 Asaq } +{*******************************************************} + +unit HotKey; + +interface + +uses + Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, + Vcl.Controls, Vcl.Forms, Vcl.ExtCtrls, Vcl.ComCtrls, Vcl.StdCtrls, + Vcl.Dialogs, Vcl.Menus; + +const + LB_HOTKEY_ID = 1; + +type + THotkeyInfo = record + private + const SSHIFT = 'Shift'; + SCTRL = 'Ctrl'; + SALT = 'Alt'; + SWIN = 'Win'; + SNONE = 'None'; + public + Modifiers: Word; // Winapi.Windows.MOD_... + KeyCode: Word; // Virtual Key Code + constructor Create(const AInteger: Integer); overload; + constructor Create(const AString: String); overload; + class operator NotEqual(const Lhs, Rhs: THotkeyInfo): Boolean; + class operator Implicit(A: THotkeyInfo): string; + class operator Implicit(A: THotkeyInfo): Integer; + function ToUserString: string; + end; + + THotkeyEdit = class(TFrame) + htkKey: THotKey; + chbWin: TCheckBox; + chbAlt: TCheckBox; + chbCtrl: TCheckBox; + chbShift: TCheckBox; + Bevel1: TBevel; + procedure Changed(Sender: TObject); + procedure FrameResize(Sender: TObject); + private + FOnChange: TNotifyEvent; + procedure SetHotkeyInfo(AHotKeyInfo: THotkeyInfo); + function GetHotkeyInfo: THotkeyInfo; + procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED; + public + constructor Create(AOwner: TComponent); override; + property HotkeyInfo: THotkeyInfo read GetHotkeyInfo write SetHotkeyInfo; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + end; + + TMyTaskDialog = class(TCustomTaskDialog) + protected + function CallbackProc(hwnd: HWND; msg: UINT; wParam: WPARAM; + lParam: LPARAM; lpRefData: LONG_PTR): HResult; override; + end; + + function RegisterHotkeyNotify(AWnd: HWND; AHotkeyInfo: THotkeyInfo; AWarnings: Boolean = True): Boolean; + function UnregisterHotkeyNotify(AWnd: HWND): Boolean; + function CheckHotkey(AWnd: HWND; AHotkeyInfo: THotkeyInfo): Boolean; + +implementation + +{$R *.dfm} + +uses Linkbar.Consts, Winapi.CommCtrl, Linkbar.Shell; + +{ THotKeyInfo } + +constructor THotkeyInfo.Create(const AInteger: Integer); +begin + Self.KeyCode := Word(AInteger); + Self.Modifiers := HiWord(AInteger); +end; + +constructor THotkeyInfo.Create(const AString: String); +begin + Create( StrToIntDef(AString, 0) ); +end; + +class operator THotkeyInfo.Implicit(A: THotkeyInfo): string; +begin + Result := HexDisplayPrefix + IntToHex(A, 8); +end; + +class operator THotkeyInfo.Implicit(A: THotkeyInfo): Integer; +begin + Result := (A.Modifiers shl 16) or A.KeyCode; +end; + +class operator THotkeyInfo.NotEqual(const Lhs, Rhs: THotkeyInfo): Boolean; +begin + Result := (Lhs.KeyCode <> Rhs.KeyCode) or (Lhs.Modifiers <> Rhs.Modifiers); +end; + +function THotkeyInfo.ToUserString: string; +begin + Result := ShortCutToText(KeyCode); + if Result = '' + then Result := 'None'; + + if (Modifiers and MOD_WIN > 0) then Result := SWIN + '+' + Result; + if (Modifiers and MOD_ALT > 0) then Result := SALT + '+' + Result; + if (Modifiers and MOD_CONTROL > 0) then Result := SCTRL + '+' + Result; + if (Modifiers and MOD_SHIFT > 0) then Result := SSHIFT + '+' + Result; +end; + +{ THotKeyEdit } + +constructor THotkeyEdit.Create(AOwner: TComponent); +begin + inherited; + htkKey.InvalidKeys := [hcNone, hcShift, hcCtrl, hcAlt, hcShiftCtrl, hcShiftAlt, hcCtrlAlt, hcShiftCtrlAlt]; + htkKey.Modifiers := []; + htkKey.HotKey := 0; +end; + +procedure THotkeyEdit.FrameResize(Sender: TObject); +begin + htkKey.BoundsRect := Bevel1.BoundsRect; +end; + +procedure THotkeyEdit.CMEnabledChanged(var Message: TMessage); +begin + chbShift.Enabled := Enabled; + chbCtrl.Enabled := Enabled; + chbAlt.Enabled := Enabled; + chbWin.Enabled := Enabled; + htkKey.Enabled := Enabled; +end; + +procedure THotkeyEdit.SetHotkeyInfo(AHotKeyInfo: THotKeyInfo); +begin + htkKey.HotKey := AHotKeyInfo.KeyCode; + chbShift.Checked := (AHotKeyInfo.Modifiers and MOD_SHIFT) > 0; + chbCtrl.Checked := (AHotKeyInfo.Modifiers and MOD_CONTROL) > 0; + chbAlt.Checked := (AHotKeyInfo.Modifiers and MOD_ALT) > 0; + chbWin.Checked := (AHotKeyInfo.Modifiers and MOD_WIN) > 0; +end; + +function THotkeyEdit.GetHotkeyInfo: THotkeyInfo; +begin + Result.KeyCode := htkKey.HotKey; + Result.Modifiers := 0; + if (chbShift.Checked) then Inc(Result.Modifiers, MOD_SHIFT); + if (chbCtrl.Checked) then Inc(Result.Modifiers, MOD_CONTROL); + if (chbAlt.Checked) then Inc(Result.Modifiers, MOD_ALT); + if (chbWin.Checked) then Inc(Result.Modifiers, MOD_WIN); +end; + +procedure THotkeyEdit.Changed(Sender: TObject); +begin + if Assigned(FOnChange) + then FOnChange(Self); +end; + +function RegisterHotkeyNotify(AWnd: HWND; AHotkeyInfo: THotkeyInfo; + AWarnings: Boolean = True): Boolean; +var err: string; + td: TMyTaskDialog; +begin + UnregisterHotkeyNotify(AWnd); + + if (AHotkeyInfo.KeyCode = 0) + then Exit(False); + + Result := RegisterHotKey(AWnd, LB_HOTKEY_ID, MOD_NOREPEAT or AHotkeyInfo.Modifiers, AHotkeyInfo.KeyCode); + + if (not Result) + and (AWarnings) + then begin + err := SysErrorMessage(GetLastError); + td := TMyTaskDialog.Create(nil); + try + td.Flags := td.Flags + [tfEnableHyperlinks]; + td.Caption := ' ' + APP_NAME_LINKBAR; + td.MainIcon := tdiNone; + td.Title := AHotkeyInfo.ToUserString; + td.Text := err; + td.ExpandButtonCaption := 'Learn More'; + td.ExpandedText := + 'Keyboard shortcuts in Windows: ' + #13 + + '' + URL_WINDOWS_HOTKEY + ''; + td.CommonButtons := [tcbOk]; + td.DefaultButton := tcbOk; + td.Execute; + finally + td.Free; + end; + end; +end; + +function UnregisterHotkeyNotify(AWnd: HWND): Boolean; +begin + Result := UnregisterHotKey(AWnd, LB_HOTKEY_ID); +end; + +function CheckHotkey(AWnd: HWND; AHotkeyInfo: THotkeyInfo): Boolean; +begin + Result := RegisterHotkeyNotify(AWnd, AHotkeyInfo); + UnregisterHotkeyNotify(AWnd); +end; + +{ TMyTaskDialog } + +function TMyTaskDialog.CallbackProc(hwnd: HWND; msg: UINT; wParam: WPARAM; + lParam: LPARAM; lpRefData: LONG_PTR): HResult; +begin + Result := S_OK; + if (msg = TDN_HYPERLINK_CLICKED) + then begin + if SameText(string(LPCWSTR(lParam)), 'hotkeys') + then LBShellExecute(hwnd, 'open', URL_WINDOWS_HOTKEY); + Exit; + end; + inherited; +end; + +end. diff --git a/components/Jumplist/JumpLists.Api.pas b/components/Jumplist/JumpLists.Api.pas index cac2cec..bcb2084 100644 --- a/components/Jumplist/JumpLists.Api.pas +++ b/components/Jumplist/JumpLists.Api.pas @@ -89,7 +89,7 @@ implementation uses Winapi.PropSys, Winapi.PropKey, Winapi.KnownFolders, Winapi.ShLwApi, Winapi.ObjectArray, Winapi.CommCtrl, System.Win.Registry, - Linkbar.OS, Linkbar.Loc; + Linkbar.OS, Linkbar.L10n; const // In Delphi XE3 the following constants are not defined @@ -654,13 +654,13 @@ function GetJumplist(const AAppId: PChar; AList: TJumplist; AMaxCount: Integer): if (iType = 1) then begin oGroup.eType := jgFrequent; - oGroup.Name := MUILoadResString(LB_FN_JUMPLIST, LB_RS_JL_FREQUENT); + oGroup.Name := L10NFind('Jumplist.Frequent', 'Frequent'); GetKnownCategory(AAppId, oGroup, ADLT_FREQUENT); end else if (iType = 2) then begin oGroup.eType := jgRecent; - oGroup.Name := MUILoadResString(LB_FN_JUMPLIST, LB_RS_JL_RECENT); + oGroup.Name := L10NFind('Jumplist.Recent', 'Recent'); GetKnownCategory(AAppId, oGroup, ADLT_RECENT); end; end @@ -684,7 +684,7 @@ function GetJumplist(const AAppId: PChar; AList: TJumplist; AMaxCount: Integer): Dec(groupIdx); oGroup := AList.Groups[customheader.iGroupCount+1]; end; - oGroup.Name := MUILoadResString(LB_FN_JUMPLIST, LB_RS_JL_TASKS); + oGroup.Name := L10NFind('Jumplist.Tasks', 'Tasks'); oGroup.eType := jgTasks; end; @@ -714,7 +714,7 @@ function GetJumplist(const AAppId: PChar; AList: TJumplist; AMaxCount: Integer): AList.Groups.Add(oGroup); oGroup := TJumpGroup.Create; oGroup.eType := jgRecent; - oGroup.Name := MUILoadResString(LB_FN_JUMPLIST, LB_RS_JL_RECENT); + oGroup.Name := L10NFind('Jumplist.Recent', 'Recent'); GetKnownCategory(AAppId, oGroup, ADLT_RECENT); AList.Groups.Add(oGroup); end; @@ -722,7 +722,7 @@ function GetJumplist(const AAppId: PChar; AList: TJumplist; AMaxCount: Integer): // update pinned items oGroupPinned := AList.Groups[0]; oGroupPinned.eType := jgPinned; - oGroupPinned.Name := MUILoadResString(LB_FN_JUMPLIST, LB_RS_JL_PINNED); + oGroupPinned.Name := L10NFind('Jumplist.Pinned', 'Pinned'); // read the DestList stream as described here: http://www.forensicswiki.org/wiki/Jump_Lists pStorage := nil; diff --git a/components/Jumplist/Jumplists.Form.pas b/components/Jumplist/Jumplists.Form.pas index fad16d0..ffeb484 100644 --- a/components/Jumplist/Jumplists.Form.pas +++ b/components/Jumplist/Jumplists.Form.pas @@ -26,6 +26,8 @@ TVtItem = record IsLatesPinned: Boolean; Pinnable: Boolean; Caption: string; + function IsSelectable: Boolean; + function IsHeader: Boolean; end; TVtList = TList; @@ -48,6 +50,7 @@ TFormJumpList = class(TForm) FAlign: TJumplistAlign; FVtList: TVtList; FPopupMenuVisible: Boolean; + FHotSelectedByMouse: Boolean; oBgBmp: TBitmap; oIconCache: TIconCache; RectBody: TRect; @@ -57,6 +60,7 @@ TFormJumpList = class(TForm) procedure OnFormContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); procedure OnFormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); + procedure CMDialogKey(var AMsg: TCMDialogKey); message CM_DIALOGKEY; procedure OnFormMouseLeave(Sender: TObject); procedure OnFormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure OnFormMouseDown(Sender: TObject; Button: TMouseButton; @@ -68,6 +72,7 @@ TFormJumpList = class(TForm) procedure OnJumpListRemove(Sender: TObject); procedure OnJumpListExecute(Sender: TObject); function ScaleDimension(const X: Integer): Integer; + procedure KeyboardControl(const AKeyCode: Word); private hImageList: HIMAGELIST; function ExtractIcon(AItem: IUnknown; AItemType: TJumpItemType): Integer; @@ -88,7 +93,7 @@ TFormJumpList = class(TForm) procedure SetHotIndex(AValue: integer); procedure AlphaBlendAndClose; function PinSelected: boolean; inline; - function Index: Integer; inline; + function Index: Integer;// inline; private TipHwnd: HWND; TipPinText: string; @@ -101,6 +106,8 @@ TFormJumpList = class(TForm) procedure PrepareTooltips; function GetDescription(const AItem: TVtItem; const AText: PChar; ASize: Integer): Boolean; procedure WMTimer(var Message: TMessage); message WM_TIMER; + private + TempX, TempY: Integer; protected procedure CreateParams(var Params: TCreateParams); override; procedure PaintWindow(DC: HDC); override; @@ -119,7 +126,7 @@ TFormJumpList = class(TForm) implementation uses Math, Vcl.Themes, Winapi.Dwmapi, Winapi.ShellAPI, Winapi.ShLwApi, - Winapi.ActiveX, Winapi.UxTheme, Linkbar.OS, Linkbar.Loc, Linkbar.Shell, + Winapi.ActiveX, Winapi.UxTheme, Linkbar.OS, Linkbar.L10n, Linkbar.Shell, Jumplists.Themes, ExplorerMenu, System.Win.Registry; const @@ -155,16 +162,27 @@ implementation TextColorItemSelected: TColor; TextColorItemNew: TColor; +{ TVtItem } + +function TVtItem.IsSelectable: Boolean; +begin + Result := Style in [vtItem, vtFooter]; +end; + +function TVtItem.IsHeader: Boolean; +begin + Result := not IsSelectable; +end; + // Macros from windowsx.h: // Important Do not use the LOWORD or HIWORD macros to extract the x- and y- // coordinates of the cursor position because these macros return incorrect results // on systems with multiple monitors. Systems with multiple monitors can have // negative x- and y- coordinates, and LOWORD and HIWORD treat the coordinates // as unsigned quantities. - -function MakePoint(const Param : DWord): TPoint; inline; +function MakePoint(const L: DWORD): TPoint; inline; Begin - Result := TPoint.Create(Param and $FFFF, Param shr 16); + Result := TPoint.Create(SmallInt(L and $FFFF), SmallInt(L shr 16)); End; procedure JumpListClose; @@ -449,8 +467,8 @@ constructor TFormJumpList.CreateNew(AOwner: TComponent; Dummy: Integer = 0); TipHideTime := TipShowTime * 10; // Get pin/unpin button hint text - TipUnpinText := StripHotkey( MUILoadResString(LB_FN_JUMPLIST, LB_RS_JL_UNPIN) ); - TipPinText := StripHotkey( MUILoadResString(LB_FN_JUMPLIST, LB_RS_JL_PIN) ); + TipUnpinText := StripHotkey( L10NFind('Jumplist.UnpinTip', 'Unpin from this list') ); + TipPinText := StripHotkey( L10NFind('Jumplist.PinTip', 'Pin to this list') ); LastPinUnpinHash := 0; TipHwnd := 0; @@ -747,26 +765,34 @@ procedure TFormJumpList.OnFormContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); var vi: TVtItem; shift: Boolean; + pt: TPoint; begin Handled := True; if (Index <> INDEX_NONE) then begin vi := FVtList[Index]; + + // Keyboard "Menu" button + if (MousePos.X = -1) + and (MousePos.Y = -1) + then pt := Point(vi.Rect.Left + ItemPadding + FIconSize div 2, vi.Rect.CenterPoint.Y) + else pt := MousePos; + if (vi.Style = vtItem) then begin FJumpItemIndex := MakeLong(vi.Item, vi.Group); - MapWindowPoints(Handle, HWND_DESKTOP, MousePos, 1); - JumpListPopupMenuPopup(MousePos.X, MousePos.Y); + MapWindowPoints(Handle, HWND_DESKTOP, pt, 1); + JumpListPopupMenuPopup(pt.X, pt.Y); Exit; end; if (vi.Style = vtFooter) then begin - MapWindowPoints(Handle, HWND_DESKTOP, MousePos, 1); + MapWindowPoints(Handle, HWND_DESKTOP, pt, 1); shift := (GetKeyState(VK_SHIFT) < 0); // TODO: may will be need AlphaBlendAndClose and process messages after invokecommand FPopupMenuVisible := True; - ExplorerMenuPopup(FWnd, FAppExe, MousePos, shift, 0); + ExplorerMenuPopup(FWnd, FAppExe, pt, shift, 0); FPopupMenuVisible := False; Exit; end; @@ -776,8 +802,87 @@ procedure TFormJumpList.OnFormContextPopup(Sender: TObject; MousePos: TPoint; procedure TFormJumpList.OnFormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin - if (Key = VK_ESCAPE) - then Close; + KeyboardControl(Key); +end; + +procedure TFormJumpList.KeyboardControl(const AKeyCode: Word); +var i: Integer; +begin + if (FVtList.Count = 0) + then Exit; + + FHotSelectedByMouse := False; + + case AKeyCode of + VK_ESCAPE: // Close Jumplist + begin + Close; + end; + VK_SPACE, VK_RETURN: // Run + begin + Click; + end; + VK_UP: // Select prev non-header item + begin + i := Index; + Dec(i); + if (i < 1) + then i := FVtList.Count-1; + if (not FVtList[i].IsSelectable) + then Dec(i); + HotIndex := i; + end; + VK_DOWN: // Select next non-header item + begin + i := Index; + Inc(i); + if (i >= FVtList.Count) + then i := 1; + if (not FVtList[i].IsSelectable) + then Inc(i); + HotIndex := i; + end; + VK_LEFT: // Unselect Pin + begin + i := Index; + if (i <> INDEX_NONE) + then HotIndex := i; + end; + VK_RIGHT: // Select Pin for pinnable item + begin + i := Index; + if (i <> INDEX_NONE) + and FVtList[i].Pinnable + then HotIndex := i or INDEX_PIN; + end; + VK_TAB: // Select first item for next group or footer item + begin + i := Index; + if (i < 1) + or (i = FVtList.Count-1) + then + i := 1 + else + while (i < FVtList.Count) do + begin + Inc(i); + if (FVtList[i].Style = vtFooter) + or (FVtList[i-1].IsHeader) + then Break; + end; + HotIndex := i; + end; + end; +end; + +procedure TFormJumpList.CMDialogKey(var AMsg: TCMDialogKey); +begin + if (AMsg.CharCode = VK_TAB) + then begin + KeyboardControl(VK_TAB); + AMsg.Result := 1; + end + else inherited; end; procedure TFormJumpList.OnFormMouseLeave(Sender: TObject); @@ -801,9 +906,6 @@ function TFormJumpList.GetItemIndexAt(AX, AY: Integer): Integer; Result := res; end; -var TempX: Integer = -1; - TempY: Integer = -1; - procedure TFormJumpList.OnFormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var idx: Integer; @@ -825,6 +927,8 @@ procedure TFormJumpList.OnFormMouseMove(Sender: TObject; Shift: TShiftState; X, else idx := INDEX_NONE; end; + FHotSelectedByMouse := True; + HotIndex := idx; end; @@ -1282,11 +1386,20 @@ procedure TFormJumpList.WMTimer(var Message: TMessage); else TipToolInfo.lpszText := PChar(TipPinText); end; - pt := MakePoint(GetMessagePos); - if (WindowFromPoint(pt) <> Handle) - then Exit; - - pt.Offset(TipPosOffset); + if FHotSelectedByMouse + then begin + pt := MakePoint(GetMessagePos); + if (WindowFromPoint(pt) <> Handle) + then Exit; + pt.Offset(TipPosOffset) + end + else begin + if (vi.Pinnable) + and PinSelected + then pt := Point(vi.Rect.Right - PinButtonWidth, vi.Rect.Bottom) + else pt := Point(vi.Rect.Left + ItemPadding + FIconSize, vi.Rect.Bottom); + MapWindowPoints(Handle, HWND_DESKTOP, pt, 1); + end; SendMessage(TipHwnd, TTM_UPDATETIPTEXT, 0, LParam(@TipToolInfo)); SendMessage(TipHwnd, TTM_TRACKPOSITION, 0, MakeLParam(pt.X, pt.Y)); @@ -1574,7 +1687,7 @@ procedure TFormJumpList.JumpListPopupMenuPopup(const X, Y: Integer); // Open mi := FPopupMenu.CreateMenuItem; - mi.Caption := MUILoadResString(shell32, LB_RS_JL_OPEN); + mi.Caption := L10NFind('Jumplist.Open', '&Open'); mi.Default := True; mi.OnClick := OnJumpListExecute; FPopupMenu.Items.Add(mi); @@ -1589,7 +1702,7 @@ procedure TFormJumpList.JumpListPopupMenuPopup(const X, Y: Integer); begin // Unpin mi := FPopupMenu.CreateMenuItem; - mi.Caption := MUILoadResString(LB_FN_JUMPLIST, LB_RS_JL_UNPIN); + mi.Caption := L10NFind('JumpList.Unpin', '&Unpin from this list'); mi.OnClick := OnJumpListUnPin; FPopupMenu.Items.Add(mi); end; @@ -1597,12 +1710,12 @@ procedure TFormJumpList.JumpListPopupMenuPopup(const X, Y: Integer); begin // Pin mi := FPopupMenu.CreateMenuItem; - mi.Caption := MUILoadResString(LB_FN_JUMPLIST, LB_RS_JL_PIN); + mi.Caption := L10NFind('JumpList.Pin', 'P&in to this list'); mi.OnClick := OnJumpListPin; FPopupMenu.Items.Add(mi); // Remove mi := FPopupMenu.CreateMenuItem; - mi.Caption := MUILoadResString(LB_FN_JUMPLIST, LB_RS_JL_REMOVE); + mi.Caption := L10NFind('JumpList.Remove', 'Remove &from this list'); mi.OnClick := OnJumpListRemove; FPopupMenu.Items.Add(mi); end; diff --git a/components/L10n/Linkbar.L10n.pas b/components/L10n/Linkbar.L10n.pas new file mode 100644 index 0000000..eb15d23 --- /dev/null +++ b/components/L10n/Linkbar.L10n.pas @@ -0,0 +1,277 @@ +{*******************************************************} +{ Linkbar - Windows desktop toolbar } +{ Copyright (c) 2010-2017 Asaq } +{*******************************************************} + +unit Linkbar.L10n; + +{$i linkbar.inc} + +interface + +uses + Winapi.Windows, System.Classes, Vcl.StdCtrls, Vcl.ComCtrls, Vcl.Menus, Vcl.Forms; + +const + // MUI + + // New shortcut file name + // shell32.dll.mui - String table - ? + LB_FN_NEWSHORTCUT = 'shell32.dll'; + LB_RS_NSC_FILENAME = 30397; + + // Autohide fail message + // explorerframe.dll.mui + LB_FN_TOOLBAR = 'explorerframe.dll'; + LB_RS_TB_AUTOHIDEALREADYEXISTS = 28676; + LB_RS_TB_NEWTOOLBAROPENDIALOGTITLE = 12387; + + // Invalid file name symbols + // shell32.dll.mui - String table - 257, 793 + LB_FN_INVALIDFILENAMECHARS = 'shell32.dll'; + LB_RS_IFNC_HINT = 4109; + + // Rename dialog need file name message + LB_FN_NEEDFILENAME = 'shell32.dll'; + LB_RS_NFN_CUE = 4123; + + procedure L10nLoad(const APath: string; AForcedLocale: string = ''); + function L10NFind(const AName: string; ADefault: string = ''): string; + function L10nMui(const AModuleName: String; const AStringID: Cardinal): String; overload; + function L10nMui(const AModule: HINST; const AStringID: Cardinal): String; overload; + procedure L10nControl(AControl: TForm; const AName: String); overload; + procedure L10nControl(AControl: TMenuItem; const AName: String); overload; + procedure L10nControl(AControl: TLabel; const AName: String); overload; + procedure L10nControl(AControl: TCheckbox; const AName: String); overload; + procedure L10nControl(AControl: TRadioButton; const AName: String); overload; + procedure L10nControl(AControl: TButton; const AName: String); overload; + procedure L10nControl(AControl: TTabSheet; const AName: String); overload; + procedure L10nControl(AControl: TComboBox; const ANames: array of String); overload; + +var + LbLongLang: Boolean = True deprecated; + Locale: string = ''; + +implementation + +uses + System.SysUtils, System.Types, System.StrUtils, System.Generics.Collections; + +type + TTranslations = class + private + type TTr = TDictionary; + private + class var tr: TTr; + class destructor Destroy; + public + constructor Create; + destructor Destroy; override; + procedure LoadFromFile(const AFileName, ALocaleName: string); + procedure LoadFromPath(const APath, ALocales: string); + function Find(const AName: string; ADefault: string = ''): string; + procedure Clear; + end; + +{ Return localized string by ModuleInstance and StringID } +function L10nMui(const AModule: HINST; const AStringID: Cardinal): String; +var p: PChar; +begin + if (AModule <> 0) and (AStringID < 65536) + then SetString(Result, p, LoadString(AModule, AStringID, @p, 0)) + else Result := 'resource_string_not_found'; +end; + +{ Return localized string by ModuleName and StringID } +function L10nMui(const AModuleName: String; const AStringID: Cardinal): String; +var h: THandle; +begin + h := LoadLibraryEx(PChar(AModuleName), 0, LOAD_LIBRARY_AS_DATAFILE); + Result := L10nMui(h, AStringID); + if (h <> 0) + then FreeLibrary(h); +end; + +procedure L10nControl(AControl: TForm; const AName: String); overload; +begin + AControl.Caption := L10NFind(AName, AControl.Caption); +end; + +procedure L10nControl(AControl: TMenuItem; const AName: String); overload; +begin + AControl.Caption := L10NFind(AName, AControl.Caption); +end; + +procedure L10nControl(AControl: TLabel; const AName: String); overload; +begin + AControl.Caption := L10NFind(AName, AControl.Caption); +end; + +procedure L10nControl(AControl: TCheckbox; const AName: String); overload; +begin + AControl.Caption := L10NFind(AName, AControl.Caption); +end; + +procedure L10nControl(AControl: TRadioButton; const AName: String); overload; +begin + AControl.Caption := L10NFind(AName, AControl.Caption); +end; + +procedure L10nControl(AControl: TButton; const AName: String); overload; +begin + AControl.Caption := L10NFind(AName, AControl.Caption); +end; + +procedure L10nControl(AControl: TTabSheet; const AName: String); overload; +begin + AControl.Caption := L10NFind(AName, AControl.Caption); +end; + +procedure L10nControl(AControl: TComboBox; const ANames: array of String); overload; +var i: Integer; +begin +{$IFDEF DEBUG} + Assert(AControl.Items.Count = Length(ANames)); +{$ENDIF} + for i := 0 to AControl.Items.Count-1 do + begin + AControl.Items[i] := L10NFind(ANames[i], AControl.Items[i]); + end; +end; + +var FTranslations: TTranslations; + +function Translations: TTranslations; +begin + if FTranslations = nil then + FTranslations := TTranslations.Create; + + Result := FTranslations; +end; + +{ TTranslations } + +constructor TTranslations.Create; +begin + tr := TTr.Create(78); +end; + +destructor TTranslations.Destroy; +begin + tr.Free; + inherited; +end; + +class destructor TTranslations.Destroy; +begin + FreeAndNil(FTranslations); +end; + +procedure TTranslations.LoadFromFile(const AFileName, ALocaleName: string); +var list: TStringList; + i, ii, j: Integer; + s, key, value: string; +begin + list := TStringList.Create; + try + list.LoadFromFile(AFileName); + // Find section + ii := list.Count; + for i := 0 to list.Count-1 do + begin + s := Copy(list[i], 2, Length(ALocaleName)); + if SameText(s, ALocaleName) + then begin + ii := i + 1; + Break; + end; + end; + + // Read translations + for i := ii to list.Count-1 do + begin + s := list[i]; + + if (Length(s) = 0) or (s[1] = '[') + then Break; + + j := Pos('=', s, 1); + if (j > 1) + then begin + key := LowerCase( Trim( Copy(s, 1, j - 1) ) ); + value := TrimLeft( Copy(s, j + 1, Length(s)) ); + if (key <> '') and (value <> '') + then tr.AddOrSetValue(key, value); + end; + end; + finally + list.Free; + end; +end; + +procedure TTranslations.LoadFromPath(const APath, ALocales: string); +var sda: TStringDynArray; + i: Integer; + fn: string; +begin + sda := SplitString(ALocales, ','); + for i := Length(sda)-1 downto 0 do + begin + fn := APath + sda[i] + '.ini'; + if FileExists(fn) + then Self.LoadFromFile(fn, sda[i]); + end; +end; + +procedure TTranslations.Clear; +begin + tr.Clear; +end; + +function TTranslations.Find(const AName: string; ADefault: string): string; +begin + if not tr.TryGetValue(LowerCase(AName), Result) + then begin + Result := ADefault; + {$IFDEF DEBUG} + MessageBox(0, PChar(Format('Key not found: "%s"'#13'Default value: "%s"', [AName, ADefault])), + PChar('Linkbar - L10n'), MB_OK or MB_ICONEXCLAMATION); + {$ENDIF} + end; +end; + +function GetLocaleNameFromLocaleID(ID: TLocaleID): string; +var i: Integer; +begin + Result := ''; + i := Languages.IndexOf(ID); + if (i <> - 1) + then Result := Languages.LocaleName[i]; +end; + +procedure L10nLoad(const APath: string; AForcedLocale: string = ''); +var languages: string; + localeId: Integer; +begin + Translations.Clear; + Locale := AForcedLocale; + + if (Locale = '') + then languages := PreferredUILanguages + else begin + // Convert to LocaleName if needed + localeId := StrToIntDef(Locale, -1); + if (localeId = -1) + then languages := Locale + else languages := GetLocaleNameFromLocaleID(localeId); + end; + + Translations.LoadFromPath(APath, languages); +end; + +function L10NFind(const AName: string; ADefault: string = ''): string; +begin + Result := Translations.Find(AName, ADefault); +end; + +end. \ No newline at end of file diff --git a/components/NewBar/Linkbar.Newbar.dfm b/components/NewBar/Linkbar.Newbar.dfm index 4d4be15..c058955 100644 --- a/components/NewBar/Linkbar.Newbar.dfm +++ b/components/NewBar/Linkbar.Newbar.dfm @@ -77,7 +77,7 @@ object BarCreatorWCl: TBarCreatorWCl Width = 404 Height = 17 Anchors = [akLeft, akTop, akRight] - Caption = 'Only for &me' + Caption = 'Only for &me (%s)' TabOrder = 1 TabStop = True ExplicitWidth = 408 @@ -126,6 +126,7 @@ object BarCreatorWCl: TBarCreatorWCl Width = 79 Height = 25 Anchors = [akTop, akRight] + Cancel = True Caption = 'C&ancel' TabOrder = 2 OnClick = btnCancelClick diff --git a/components/NewBar/Linkbar.Newbar.pas b/components/NewBar/Linkbar.Newbar.pas index ffea454..59d7bce 100644 --- a/components/NewBar/Linkbar.Newbar.pas +++ b/components/NewBar/Linkbar.Newbar.pas @@ -38,6 +38,7 @@ TBarCreatorWCl = class(TForm) FWorkinDirectoryPath: string; procedure UpdateThemeStyle; function ScaleDimension(const X: Integer): Integer; + procedure L10n; protected procedure WMSysColorChanged(var message : TMessage); message WM_SYSCOLORCHANGE; procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; @@ -51,7 +52,7 @@ implementation {$R *.dfm} uses ShlObj, System.IniFiles, Vcl.Themes, Linkbar.Common, - Linkbar.Shell, Linkbar.Consts, Linkbar.Loc, Linkbar.Themes, MyHint; + Linkbar.Shell, Linkbar.Consts, Linkbar.L10n, Linkbar.Themes, MyHint; function GetUserNameEx(NameFormat: DWORD; lpBuffer: LPWSTR; var nSize: DWORD): Boolean; stdcall; external 'secur32.dll' Name 'GetUserNameExW'; @@ -90,7 +91,7 @@ procedure TBarCreatorWCl.btnCancelClick(Sender: TObject); procedure TBarCreatorWCl.btnCreateClick(Sender: TObject); var lini: TIniFile; - lfilename: string; + lfilename, cmd: string; begin if rbAppDir.Checked then begin @@ -106,13 +107,26 @@ procedure TBarCreatorWCl.btnCreateClick(Sender: TObject); lini := TIniFile.Create(lfilename); lini.WriteString(INI_SECTION_MAIN, INI_DIR_LINKS, FWorkinDirectoryPath); lini.Free; - - LBCreateProcess( ParamStr(0), LBCreateCommandParam(CLK_LANG, IntToStr(LbLangID)) - + LBCreateCommandParam(CLK_FILE, lfilename) ); - + + cmd := LBCreateCommandParam(CLK_FILE, lfilename); + if (Locale <> '') + then cmd := LBCreateCommandParam(CLK_LANG, Locale) + cmd; + LBCreateProcess(ParamStr(0), cmd); + Close; end; +procedure TBarCreatorWCl.L10n; +begin + L10nControl(Self, 'New.Caption'); + L10nControl(Label1, 'New.ToWhom'); + L10nControl(rbAppDir, 'New.ForAll'); + L10nControl(rbUserDir, 'New.ForMe'); + L10nControl(lblWorkDir, 'New.Folder'); + L10nControl(btnCreate, 'New.Create'); + L10nControl(btnCancel, 'New.Cancel'); +end; + procedure TBarCreatorWCl.Button1Click(Sender: TObject); begin if FileOpenDialog_NL.Execute @@ -129,13 +143,13 @@ procedure TBarCreatorWCl.FormCreate(Sender: TObject); HintWindowClass := TTooltipHintWindow; Font.Name := Screen.IconFont.Name; - LbTranslateComponent(Self); + L10n; ReduceSysMenu(Handle); UpdateThemeStyle; - FileOpenDialog_NL.Title := MUILoadResString(LB_FN_TOOLBAR, LB_RS_TB_NEWTOOLBAROPENDIALOGTITLE); + FileOpenDialog_NL.Title := L10nMui(LB_FN_TOOLBAR, LB_RS_TB_NEWTOOLBAROPENDIALOGTITLE); InitiatedAppDir := ExtractFilePath(Application.ExeName) + DN_SHARED_BARS; InitiatedUserDir := GetLinkbarRoamingFolderPath + DN_USER_BARS; @@ -148,7 +162,7 @@ procedure TBarCreatorWCl.FormCreate(Sender: TObject); edtWorkDir.Color := Self.Color; if GetLoggedOnUserName(username) - then rbUserDir.Caption := rbUserDir.Caption + Format(' (%s)',[username]); + then rbUserDir.Caption := Format(rbUserDir.Caption,[username]); Label1.ShowHint := True; Label1.Hint := RemovePrefix(rbAppDir.Caption) diff --git a/components/RenameDialog/RenameDialog.pas b/components/RenameDialog/RenameDialog.pas index 8e70e81..845b1a1 100644 --- a/components/RenameDialog/RenameDialog.pas +++ b/components/RenameDialog/RenameDialog.pas @@ -27,6 +27,7 @@ TRenamingWCl = class(TForm) FInvalidFileNameCharsHintText: string; procedure SetPidl(APidl: PItemIDList); procedure ShowBalloonTip(const AText: string); + procedure L10n; protected procedure CreateParams(var Params: TCreateParams); override; procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; @@ -38,7 +39,7 @@ implementation {$R *.dfm} -uses Vcl.Clipbrd, Linkbar.Loc, Linkbar.Shell, Linkbar.Common; +uses Vcl.Clipbrd, Linkbar.Shell, Linkbar.Common, Linkbar.L10n; var FInvalidFileNameChars: TCharArray; @@ -57,7 +58,7 @@ procedure TRenamingWCl.FormCreate(Sender: TObject); var cue: String; begin Font.Name := Screen.IconFont.Name; - LbTranslateComponent(Self); + L10n; ReduceSysMenu(Handle); @@ -65,14 +66,21 @@ procedure TRenamingWCl.FormCreate(Sender: TObject); FInvalidFileNameChars := TCharArray.Create('"', '*', '/', ':', '<', '>', '?', '\', '|'); FInvalidFileNameCharsHintText := - MUILoadResString(GetModuleHandle(LB_FN_INVALIDFILENAMECHARS), LB_RS_IFNC_HINT); + L10nMui(GetModuleHandle(LB_FN_INVALIDFILENAMECHARS), LB_RS_IFNC_HINT); - cue := MUILoadResString(GetModuleHandle(LB_FN_NEEDFILENAME), LB_RS_NFN_CUE); + cue := L10nMui(GetModuleHandle(LB_FN_NEEDFILENAME), LB_RS_NFN_CUE); f_Edit_SetCueBannerText(edtFileName.Handle, PChar(cue)); btnOk.ModalResult := mrNone; end; +procedure TRenamingWCl.L10n; +begin + L10nControl(Self, 'Rename.Caption'); + L10nControl(btnOk, 'Rename.OK'); + L10nControl(btnCancel, 'Rename.Cancel'); +end; + procedure TRenamingWCl.SetPidl(APidl: PItemIDList); var ppszName: PChar; begin @@ -117,26 +125,21 @@ function IsValidFileNameChar(const AChar: Char): Boolean; Result := not IsCharInOrderedArray(AChar, FInvalidFileNameChars); end; -function HasValidFileNameChars(const FileName: string): Boolean; -var - PFileName: PChar; - FileNameLen: Integer; - Ch: Char; - I: Integer; +function HasInvalidFileNameCharsFix(var AFileName: string): Boolean; +var pname: PChar; + len, i, j: Integer; begin - // Result will become True if an invalid file name char is found - I := 0; - PFileName := PChar(FileName); - FileNameLen := Length(FileName); - Result := False; - while (not Result) and (I < FileNameLen) do + pname := PChar(AFileName); + len := Length(AFileName); + j := 0; + for i := 0 to len-1 do begin - Ch := PFileName[I]; - if not IsValidFileNameChar(Ch) - then Result := True - else Inc(I); + pname[j] := pname[i]; + if IsValidFileNameChar(pname[i]) + then Inc(j); end; - Result := not Result; + SetLength(AFileName, j); + Result := j <> len; end; procedure TRenamingWCl.btnOkClick(Sender: TObject); @@ -155,24 +158,31 @@ procedure TRenamingWCl.edtFileNameChange(Sender: TObject); end; procedure TRenamingWCl.edtFileNameKeyPress(Sender: TObject; var Key: Char); +var str: string; begin + // Ctrl+V if (Key = #$16) then begin - if Clipboard.HasFormat(CF_TEXT) - and HasValidFileNameChars(Clipboard.AsText) - then Exit; - end - else begin - if not IsCharInOrderedArray(Key, FInvalidFileNameChars) - then Exit; + Key := #0; + str := Clipboard.AsText; + if HasInvalidFileNameCharsFix(str) + then ShowBalloonTip(FInvalidFileNameCharsHintText); + edtFileName.SetSelText(str); + Exit; + end; + + // Other Keys + if not IsValidFileNameChar(Key) + then begin + Key := #0; + ShowBalloonTip(FInvalidFileNameCharsHintText); end; - Key := #0; - ShowBalloonTip(FInvalidFileNameCharsHintText); end; procedure TRenamingWCl.ShowBalloonTip(const AText: String); var ebt: TEditBalloonTip; begin + FillChar(ebt, SizeOf(ebt), 0); ebt.cbStruct := SizeOf(ebt); ebt.pszTitle := nil; ebt.pszText := Pointer(AText); diff --git a/components/SpinEdit/NewSpin.pas b/components/SpinEdit/NewSpin.pas index 3ab3b98..6ddf1ea 100644 --- a/components/SpinEdit/NewSpin.pas +++ b/components/SpinEdit/NewSpin.pas @@ -11,10 +11,6 @@ interface Windows, Classes, StdCtrls, ExtCtrls, Controls, Messages, SysUtils, Forms, Graphics, Menus, Buttons, ComCtrls; -const - InitRepeatPause = 400; { pause before repeat timer (ms) } - RepeatPause = 100; { pause before hint window displays (ms)} - type TTimerSpeedButton = class; @@ -173,6 +169,10 @@ TTimerSpeedButton = class(TUpDown) implementation uses Themes; + +const + InitRepeatPause = 400; { pause before repeat timer (ms) } + RepeatPause = 100; { pause before hint window displays (ms)} procedure Register; begin diff --git a/exe/CMD.txt b/exe/CMD.txt index 940ea79..8ea5361 100644 --- a/exe/CMD.txt +++ b/exe/CMD.txt @@ -4,7 +4,15 @@ Set startup delay -l[param] Set UI language -[param] = 1033 (English), 1036 (French), 1031 (German), 1041 (Japanese), 1049 (Russian) +[param] = 1033 or en-US (English) + 1036 or fr-FR (French) + 1031 or de-DE (German) + 1032 or el-GR (Greek) + 1041 or ja-JP (Japanese) + 1045 or pl-PL (Polish) + 1049 or ru-RU (Russian) + 2052 or zh-CN (Chinese-Simplified) + 1042 or ko-KR (Korean) -f[param] Set path to configuration file diff --git a/exe/Linkbar.lc3 b/exe/Linkbar.lc3 deleted file mode 100644 index 0c1ff55..0000000 Binary files a/exe/Linkbar.lc3 and /dev/null differ diff --git a/exe/Locales/de-DE.ini b/exe/Locales/de-DE.ini new file mode 100644 index 0000000..1940a01 --- /dev/null +++ b/exe/Locales/de-DE.ini @@ -0,0 +1,82 @@ +[de-DE] - German (Germany) +New.Caption = Neue Linkbar +New.ToWhom = Erstellen Sie Linkbar für: +New.ForAll = Jeder, der diesen Computer verwendet (alle Benutzer) +New.ForMe = Nur für mich (%s) +New.Folder = Wählen Sie einen Ordner: +New.Create = Erstellen +New.Cancel = Abbrechen +Menu.Shortcut = Neue Verknüpfung +Menu.Open = Offene Arbeitsverzeichnis +Menu.Create = Erstellen Linkbar... +Menu.Delete = Löschen Sie das Linkbar +Menu.Lock = Linkbar fixieren +Menu.Sort = Alphabetisch sortieren +Menu.Properties = Eigenschaften +Menu.Close = Schließen +Menu.CloseAll = Schließen Sie alle +Jumplist.Recent = Zuletzt verwendet +Jumplist.Frequent = Häufig +Jumplist.Tasks = Aufgaben +Jumplist.Pinned = Angeheftet +Jumplist.Open = Ö&ffnen +Jumplist.Pin = An diese Liste an&heften +Jumplist.Unpin = V&on dieser Liste lösen +Jumplist.Remove = &Aus Liste entfernen +Jumplist.PinTip = An diese Liste anheften +Jumplist.UnpinTip = Von dieser Liste lösen +Rename.Caption = Umbenennung +Rename.OK = OK +Rename.Cancel = Abbrechen +Color.Caption = Farbe +Color.OK = OK +Color.Cancel = Abbrechen +Delete.Title = Sie entfernen die Linkbar "%s" +Delete.Text = Arbeitsverzeichnis: %s +Delete.Verification = Löschen Arbeitsverzeichnis +Message.FileNotFound = Datei existiert nicht +Message.DeleteShortcut = Verknüpfung löschen? +Properties.View = Ansicht +Properties.Appearance = Konfigurieren Sie Aussehen +Properties.Position = Position auf dem Bildschirm: +Properties.Left = Links +Properties.Top = Oben +Properties.Right = Rechts +Properties.Bottom = Unten +Properties.IconSize = Symbolgröße: +Properties.BgColor = Hintergrundfarbe: +Properties.Margins = Ränder (horizontal / vertikal): +Properties.Order = Reihenfolge der Verknüpfungen: +Properties.LtR = Links nach rechts +Properties.UtD = Oben nach unten +Properties.TextPos = Textpositionierung: +Properties.Without = Ohne Text +Properties.TextWidth = Textbreite / Einzug: +Properties.TextColor = Textfarbe: +Properties.GlowSize = Glühengröße: +Properties.AlwaysOnTop = Linkbar immer im Vordergrund halten +Properties.PageAutoHide = Automatische Ausblenden +Properties.AutoHide = Konfigurieren Sie das automatische Ausblenden +Properties.Hide = Ausblenden: +Properties.Automatically = Automatisch +Properties.Show = Anzeigen: +Properties.MouseHover = Mausbewegung +Properties.MouseLC = Maus Linksklick +Properties.MouseRC = Maus Rechtsklick +Properties.Delay = Verzögerung, ms: +Properties.HotKey = Tastenkombination: +Properties.Transparent = Transparent wenn Ausblenden +Properties.Additional = Ansicht +Properties.Jumplists = Sprunglisten +Properties.No = Nein +Properties.ForW7 = Für Windows 7: +Properties.Style1 = Verwenden Sie Stil wie Taskleiste mit kombinierten Tasten +Properties.ForW8 = Für Windows 8/8.1: +Properties.AeroGlass = AeroGlass-Unterstützung aktivieren (separat installiert) +Properties.About = Über +Properties.Version = Version: %s +Properties.SystemInfo = Systeminformationen: +Properties.Localizer = Localizer: Asaq +Properties.OK = OK +Properties.Cancel = Abbrechen +Properties.Apply = Übernehmen \ No newline at end of file diff --git a/exe/Locales/el-GR.ini b/exe/Locales/el-GR.ini new file mode 100644 index 0000000..2a3b63e --- /dev/null +++ b/exe/Locales/el-GR.ini @@ -0,0 +1,82 @@ +[el-GR] - Greek (Greece) +New.Caption = Νέα γραμμή σύνδεσης +New.ToWhom = Δημιουργία γραμμής σύνδεσης για: +New.ForAll = &Οποιονδήποτε χρησιμοποιεί αυτόν τον υπολογιστή (όλοι οι χρήστες) +New.ForMe = Μόνο για &μένα (%s) +New.Folder = Επιλέξτε έναν φάκελο: +New.Create = &Δημιουργία +New.Cancel = Άκυρο +Menu.Shortcut = Νέα συντόμευση +Menu.Open = Άνοιγμα φακέλου εργασίας +Menu.Create = Δημιουργία γραμμής σύνδεσης... +Menu.Delete = Διαγραφή της γραμμής σύνδεσης +Menu.Lock = Κλείδωμα της γραμμής σύνδεσης +Menu.Sort = Ταξινόμηση αλφαβητικά +Menu.Properties = Ιδιότητες +Menu.Close = Κλείσιμο +Menu.CloseAll = Κλείσιμο όλων +Jumplist.Recent = Πρόσφατα +Jumplist.Frequent = Στοιχεία που επιλέγονται συχνότερα +Jumplist.Tasks = Εργασίες +Jumplist.Pinned = Καρφιτσωμένα +Jumplist.Open = Άν&οιγμα +Jumplist.Pin = &Καρφίτσωμα σε αυτήν τη λίστα +Jumplist.Unpin = &Ξεκαρφίτσωμα από αυτήν τη λίστα +Jumplist.Remove = Κατά&ργηση από τη λίστα +Jumplist.PinTip = Καρφίτσωμα σε αυτήν τη λίστα +Jumplist.UnpinTip = Ξεκαρφίτσωμα από αυτήν τη λίστα +Rename.Caption = Μετονομασία +Rename.OK = Εντάξει +Rename.Cancel = Άκυρο +Color.Caption = Χρώμα +Color.OK = Εντάξει +Color.Cancel = Άκυρο +Delete.Title = Θα διαγράψετε τη γραμμή σύνδεσης "%s" +Delete.Text = Κατάλογος εργασίας: %s +Delete.Verification = Διαγραφή καταλόγου εργασίας +Message.FileNotFound = Το αρχείο δεν υπάρχει +Message.DeleteShortcut = Διαγραφή σύνδεσης; +Properties.View = Προβολή +Properties.Appearance = Ρύθμιση εμφάνισης +Properties.Position = Θέση στην οθόνη: +Properties.Left = Αριστερά +Properties.Top = Πάνω +Properties.Right = Δεξιά +Properties.Bottom = Κάτω +Properties.IconSize = Μέγεθος εικονιδίου: +Properties.BgColor = Χρώμα φόντου: +Properties.Margins = Περιθώρια (οριζόντια / κάθετα): +Properties.Order = Σειρά των συντομεύσεων: +Properties.LtR = Αριστερά προς δεξιά +Properties.UtD = Πάνω προς κάτω +Properties.TextPos = Θέση κειμένου: +Properties.Without = Χωρίς κείμενο +Properties.TextWidth = Πλάτος/Εσοχή κειμένου: +Properties.TextColor = Χρώμα κειμένου: +Properties.GlowSize = Μέγεθος λάμψης: +Properties.AlwaysOnTop = Πάντα στην κορυφή η γραμμή σύνδεσης +Properties.PageAutoHide = Αυτόματη απόκρυψη +Properties.AutoHide = Ρύθμιση αυτόματης απόκρυψης +Properties.Hide = Απόκρυψη: +Properties.Automatically = Αυτόματα +Properties.Show = Εμφάνιση: +Properties.MouseHover = Παραμονή του δείκτη +Properties.MouseLC = Αριστερό κλικ ποντικιού +Properties.MouseRC = Δεξί κλικ ποντικιού +Properties.Delay = Καθυστέρηση (ms): +Properties.HotKey = Συνδυασμός κλειδιών: +Properties.Transparent = Διαφανές όταν είναι κρυμμένο +Properties.Additional = Πρόσθετα +Properties.Jumplists = Οι λίστες συντομεύσεων +Properties.No = Οχι +Properties.ForW7 = Για Windows 7 +Properties.Style1 = Χρήση στυλ, όπως της γραμμής εργασιών με συνδυασμό κουμπιών +Properties.ForW8 = Για Windows 8/8.1 +Properties.AeroGlass = Ενεργ/ση υποστήριξης AeroGlass (εγκαθίσταται χωριστά) +Properties.About = Περί +Properties.Version = Έκδοση: %s +Properties.SystemInfo = Πληροφορίες συστήματος: +Properties.Localizer = Μεταφραστής: geogeo.gr +Properties.OK = &Εντάξει +Properties.Cancel = Ά&κυρο +Properties.Apply = Εφαρμογή \ No newline at end of file diff --git a/exe/Locales/en-US.ini b/exe/Locales/en-US.ini new file mode 100644 index 0000000..4d152ce --- /dev/null +++ b/exe/Locales/en-US.ini @@ -0,0 +1,82 @@ +[en-US] - English (United States) +New.Caption = New linkbar +New.ToWhom = Create linkbar for: +New.ForAll = &Anyone who uses this computer (all users) +New.ForMe = Only for &me (%s) +New.Folder = Choose a folder: +New.Create = Create +New.Cancel = Cancel +Menu.Shortcut = New shortcut +Menu.Open = Open working directory +Menu.Create = Create linkbar... +Menu.Delete = Delete the linkbar +Menu.Lock = Lock the linkbar +Menu.Sort = Sort alphabetically +Menu.Properties = Properties +Menu.Close = Close +Menu.CloseAll = Close all +Jumplist.Recent = Recent +Jumplist.Frequent = Frequent +Jumplist.Tasks = Tasks +Jumplist.Pinned = Pinned +Jumplist.Open = &Open +Jumplist.Pin = P&in to this list +Jumplist.Unpin = &Unpin from this list +Jumplist.Remove = Remove &from this list +Jumplist.PinTip = Pin to this list +Jumplist.UnpinTip = Unpin from this list +Rename.Caption = Renaming +Rename.OK = OK +Rename.Cancel = Cancel +Color.Caption = Color +Color.OK = OK +Color.Cancel = Cancel +Delete.Title = You remove the linkbar "%s" +Delete.Text = Working directory: %s +Delete.Verification = Delete working directory +Message.FileNotFound = File does not exists +Message.DeleteShortcut = Delete shortcut? +Properties.View = View +Properties.Appearance = Configure appearance +Properties.Position = Position on screen: +Properties.Left = Left +Properties.Top = Top +Properties.Right = Right +Properties.Bottom = Bottom +Properties.IconSize = Icon size: +Properties.BgColor = Background color: +Properties.Margins = Margins (horizontal/vertical): +Properties.Order = Order of shortcuts: +Properties.LtR = Left to right +Properties.UtD = Up to down +Properties.TextPos = Text position: +Properties.Without = Without text +Properties.TextWidth = Text width/indent: +Properties.TextColor = Text color: +Properties.GlowSize = Glow size: +Properties.AlwaysOnTop = Keep the Linkbar on top of other windows +Properties.PageAutoHide = AutoHide +Properties.AutoHide = Configure auto-hide +Properties.Hide = Hide: +Properties.Automatically = Automatically +Properties.Show = Show: +Properties.MouseHover = Mouse hover +Properties.MouseLC = Mouse left-click +Properties.MouseRC = Mouse right-click +Properties.Delay = Delay, ms: +Properties.HotKey = Keyboard shortcut: +Properties.Transparent = Transparent when hidden +Properties.Additional = Additional +Properties.Jumplists = Jumplists +Properties.No = No +Properties.ForW7 = For Windows 7 +Properties.Style1 = Use style like taskbar with combined buttons +Properties.ForW8 = For Windows 8/8.1 +Properties.AeroGlass = Enable AeroGlass support (installed separately) +Properties.About = About +Properties.Version = Version: %s +Properties.SystemInfo = System info: +Properties.Localizer = localizer: Asaq +Properties.OK = OK +Properties.Cancel = Cancel +Properties.Apply = Apply \ No newline at end of file diff --git a/exe/Locales/fr-FR.ini b/exe/Locales/fr-FR.ini new file mode 100644 index 0000000..b7a6208 --- /dev/null +++ b/exe/Locales/fr-FR.ini @@ -0,0 +1,82 @@ +[fr-FR] - French (France) +New.Caption = Nouvelle linkbar +New.ToWhom = Créer la linkbar: +New.ForAll = Pour tous les utilisateurs (de cette machine) +New.ForMe = Seulement pour moi (%s) +New.Folder = Choisir une dossier: +New.Create = Créer +New.Cancel = Annuler +Menu.Shortcut = Nouveau raccourci +Menu.Open = Ouvrir le répertoire de travail +Menu.Create = Créer une linkbar... +Menu.Delete = Supprimer la linkbar +Menu.Lock = Verrouiller la linkbar +Menu.Sort = Classer par ordre alphabétique +Menu.Properties = Propriétés +Menu.Close = Fermer +Menu.CloseAll = Fermer tout +Jumplist.Recent = Récent +Jumplist.Frequent = Fréquent +Jumplist.Tasks = Tâches +Jumplist.Pinned = Épinglé +Jumplist.Open = &Ouvrir +Jumplist.Pin = Ép&ingler à cette liste +Jumplist.Unpin = &Détacher de cette liste +Jumplist.Remove = Suppri&mer de cette liste +Jumplist.PinTip = Épingler à cette liste +Jumplist.UnpinTip = Détacher de cette liste +Rename.Caption = Changement de nom +Rename.OK = OK +Rename.Cancel = Annuler +Color.Caption = Couleur +Color.OK = OK +Color.Cancel = Annuler +Delete.Title = Vous supprimez la linkbar « %s » +Delete.Text = Le répertoire de travail: %s +Delete.Verification = Supprimer le répertoire de travail +Message.FileNotFound = Fichier n’existe pas +Message.DeleteShortcut = Supprimer le raccourci? +Properties.View = Vue +Properties.Appearance = Configurer l’apparence +Properties.Position = Position sur l’écran: +Properties.Left = À gauche +Properties.Top = En haut +Properties.Right = À droite +Properties.Bottom = En bas +Properties.IconSize = Taille des icônes: +Properties.BgColor = Couleur de fond: +Properties.Margins = Marges (horizontales/verticales): +Properties.Order = Ordre des raccourcis: +Properties.LtR = De gauche à droit +Properties.UtD = De haute en bas +Properties.TextPos = Position du texte: +Properties.Without = Sans texte +Properties.TextWidth = Largeur du texte/le retrait: +Properties.TextColor = Couleur de texte: +Properties.GlowSize = Taille glow: +Properties.AlwaysOnTop = Conserver la Linkbar au-dessus des autres fenêtres +Properties.PageAutoHide = Masquage automatique +Properties.AutoHide = Configurer le masquage automatique +Properties.Hide = Masquer: +Properties.Automatically = Automatiquement +Properties.Show = Afficher: +Properties.MouseHover = Passant la souris +Properties.MouseLC = Clic-gauche +Properties.MouseRC = Clic-droit +Properties.Delay = Retard (ms): +Properties.HotKey = Combinaison de clés: +Properties.Transparent = Transparente quand masquée +Properties.Additional = En outre +Properties.Jumplists = Les listes de raccourcis +Properties.No = Non +Properties.ForW7 = Pour Windows 7 +Properties.Style1 = Utilizer le style comme la barre des tâches avec les boutons combinés +Properties.ForW8 = Pour Windows 8/8.1 +Properties.AeroGlass = Activer le support d’AeroGlass (installer séparément) +Properties.About = À propos +Properties.Version = Version: %s +Properties.SystemInfo = Informations système: +Properties.Localizer = localisation: nth_mkr +Properties.OK = OK +Properties.Cancel = Annuler +Properties.Apply = Appliquer \ No newline at end of file diff --git a/exe/Locales/ja-JP.ini b/exe/Locales/ja-JP.ini new file mode 100644 index 0000000..57a8543 --- /dev/null +++ b/exe/Locales/ja-JP.ini @@ -0,0 +1,82 @@ +[ja-JP] - Japanese (Japan) +New.Caption = 新規 リンクバー +New.ToWhom = リンクバーを作成する範囲: +New.ForAll = このコンピューターを使用する全員(すべてのユーザー) +New.ForMe = 現ユーザーのみ (%s) +New.Folder = フォルダの選択: +New.Create = 作成 +New.Cancel = キャンセル +Menu.Shortcut = 新しいショートカット +Menu.Open = 作業ディレクトリを開く +Menu.Create = リンクバーを作成... +Menu.Delete = リンクバーを削除 +Menu.Lock = リンクバーを固定 +Menu.Sort = アルファベット順にソート +Menu.Properties = プロパティ +Menu.Close = 閉じる +Menu.CloseAll = すべて閉じる +Jumplist.Recent = 最近使ったもの +Jumplist.Frequent = よく使うもの +Jumplist.Tasks = タスク +Jumplist.Pinned = いつも表示 +Jumplist.Open = 開く(&O) +Jumplist.Pin = いつも表示する(&I) +Jumplist.Unpin = いつも表示するものから外す(&U) +Jumplist.Remove = この一覧から削除(&F) +Jumplist.PinTip = いつも表示する +Jumplist.UnpinTip = いつも表示するものから外す +Rename.Caption = 名称変更 +Rename.OK = OK +Rename.Cancel = キャンセル +Color.Caption = 色 +Color.OK = OK +Color.Cancel = キャンセル +Delete.Title = 削除するツールバー 「%s」 +Delete.Text = 作業ディレクトリ: %s +Delete.Verification = 作業ディレクトリを削除します +Message.FileNotFound = ファイルが存在しません +Message.DeleteShortcut = リンクを削除しますか? +Properties.View = 外観設定 +Properties.Appearance = 外観設定 +Properties.Position = スクリーン上の位置: +Properties.Left = 左 +Properties.Top = 上 +Properties.Right = 右 +Properties.Bottom = 下 +Properties.IconSize = アイコンサイズ: +Properties.BgColor = 背景色: +Properties.Margins = 選択幅 (横幅/縦幅): +Properties.Order = ショートカットの順番: +Properties.LtR = 左から右へ +Properties.UtD = 上から下へ +Properties.TextPos = 文字位置: +Properties.Without = 文字非表示 +Properties.TextWidth = 文字幅/字下げ: +Properties.TextColor = テキストの色: +Properties.GlowSize = グローサイズ: +Properties.AlwaysOnTop = リンクバーをほかのウィンドウの手前に表示する +Properties.PageAutoHide = 自動非表示 +Properties.AutoHide = 自動非表示設定 +Properties.Hide = 非表示: +Properties.Automatically = 自動 +Properties.Show = 表示: +Properties.MouseHover = マウス オーバー +Properties.MouseLC = マウス 左クリック +Properties.MouseRC = マウス 右クリック +Properties.Delay = 遅延 (ミリ秒): +Properties.HotKey = キーの組み合わせ: +Properties.Transparent = 非表示時に透明化 +Properties.Additional = 拡張設定 +Properties.Jumplists = ジャンプ リスト +Properties.No = いいえ +Properties.ForW7 = Windows 7 +Properties.Style1 = 標準のタスクバーと同一のスタイルを利用 +Properties.ForW8 = Windows 8/8.1の場合 +Properties.AeroGlass = AeroGlassをサポート (別途インストール) +Properties.About = ソフトについて +Properties.Version = バージョン: %s +Properties.SystemInfo = システム情報: +Properties.Localizer = 翻訳者: Takahiro +Properties.OK = OK +Properties.Cancel = キャンセル +Properties.Apply = 適用 \ No newline at end of file diff --git a/exe/Locales/ko-KR.ini b/exe/Locales/ko-KR.ini new file mode 100644 index 0000000..3d8cfc3 --- /dev/null +++ b/exe/Locales/ko-KR.ini @@ -0,0 +1,82 @@ +[ko-KR] - Korean (Korea) +New.Caption = 툴바 새로 만들기 +New.ToWhom = 에 대한 툴바 생성: +New.ForAll = 이 컴퓨터를 사용하는 사람 (모든 유저) +New.ForMe = 특정 사용자 (%s) +New.Folder = 폴더 선택: +New.Create = 생성 +New.Cancel = 취소 +Menu.Shortcut = 바로 가기 만들기 +Menu.Open = 대상 폴더 열기 +Menu.Create = 툴바 새로 만들기... +Menu.Delete = 툴바 삭제 +Menu.Lock = 툴바 잠금 +Menu.Sort = 알파벳순으로 정렬 +Menu.Properties = 환경 설정 +Menu.Close = 종료 +Menu.CloseAll = 모두 종료 +Jumplist.Recent = 최근 항목 +Jumplist.Frequent = 자주 사용하는 항목 +Jumplist.Tasks = 작업 +Jumplist.Pinned = 고정됨 +Jumplist.Open = 열기(&O) +Jumplist.Pin = 이 목록에 고정(&I) +Jumplist.Unpin = 이 목록에서 제거(&U) +Jumplist.Remove = 이 목록에서 제거(&F) +Jumplist.PinTip = 이 목록에 고정 +Jumplist.UnpinTip = 이 목록에서 제거 +Rename.Caption = 이름 바꾸기 +Rename.OK = 확인 +Rename.Cancel = 취소 +Color.Caption = 색깔 +Color.OK = 확인 +Color.Cancel = 취소 +Delete.Title = 툴바 삭제 "%s" +Delete.Text = 대상 폴더: %s +Delete.Verification = 작업 디렉토리 삭제 +Message.FileNotFound = 파일이 존재하지 않습니다. +Message.DeleteShortcut = 바로 가기 삭제? +Properties.View = 보기 +Properties.Appearance = 모양 구성 +Properties.Position = 화면상의 위치 : +Properties.Left = 왼쪽 +Properties.Top = 위 +Properties.Right = 오른쪽 +Properties.Bottom = 아래 +Properties.IconSize = 아이콘 크기: +Properties.BgColor = 배경색: +Properties.Margins = 여백(가로/세로): +Properties.Order = 바로 가기 순서: +Properties.LtR = 왼쪽에서 오른쪽으로 +Properties.UtD = 위에서 아래로 +Properties.TextPos = 텍스트 위치: +Properties.Without = 텍스트 표시하지 않음 +Properties.TextWidth = 텍스트 너비 / 들여 쓰기: +Properties.TextColor = 텍스트 색: +Properties.GlowSize = 글로우 크기: +Properties.AlwaysOnTop = 툴바 표시 줄을 항상 위로 유지 +Properties.PageAutoHide = 자동 숨김 +Properties.AutoHide = 자동 숨기기 설정 +Properties.Hide = 툴바 숨김: +Properties.Automatically = 자동으로 +Properties.Show = 툴바 표시: +Properties.MouseHover = 툴바를 마우스에 가져갔을 때 +Properties.MouseLC = 툴바를 마우스로 클릭할 때 +Properties.MouseRC = 툴바를 마우스로 우클릭할 때 +Properties.Delay = 지연 시간: +Properties.HotKey = 단축키: +Properties.Transparent = 숨겨진 상태시 투명화 +Properties.Additional = 추가 기능 +Properties.Jumplists = 점프 목록은 +Properties.No = 아니 +Properties.ForW7 = 윈도우 7 +Properties.Style1 = 작업 표시 줄과 같은 스타일 사용 +Properties.ForW8 = 윈도우 7 8/8.1 +Properties.AeroGlass = AeroGlass 지원 사용 (별도 설치) +Properties.About = 정보 +Properties.Version = 번역: %s +Properties.SystemInfo = 시스템 정보: +Properties.Localizer = 로컬 라이저: 미유키로즈 +Properties.OK = 확인 +Properties.Cancel = 취소 +Properties.Apply = 적용 \ No newline at end of file diff --git a/exe/Locales/pl-PL.ini b/exe/Locales/pl-PL.ini new file mode 100644 index 0000000..2e74ed1 --- /dev/null +++ b/exe/Locales/pl-PL.ini @@ -0,0 +1,82 @@ +[pl-PL] - Polish (Poland) +New.Caption = Nowy pasek łączy +New.ToWhom = Utwórz pasek łączy dla: +New.ForAll = &Każdego, kto używa tego komputera (wszyscy użytkownicy) +New.ForMe = Tylko dla &mnie (%s) +New.Folder = Wybierz folder: +New.Create = Utwórz +New.Cancel = Anuluj +Menu.Shortcut = Nowy skrót +Menu.Open = Otwórz katalog roboczy +Menu.Create = Utwórz pasek łączy... +Menu.Delete = Usuń pasek łączy +Menu.Lock = Zablokuj pasek łączy +Menu.Sort = Sortuj alfabetycznie +Menu.Properties = Właściwości +Menu.Close = Zamknij +Menu.CloseAll = Zamknij wszystkie +Jumplist.Recent = Najnowsze +Jumplist.Frequent = Częste +Jumplist.Tasks = Zadania +Jumplist.Pinned = Zakotwiczony +Jumplist.Open = &Otwórz +Jumplist.Pin = P&rzypnij do tej listy +Jumplist.Unpin = &Odepnij z tej listy +Jumplist.Remove = Usuń &z tej listy +Jumplist.PinTip = Przypnij do tej listy +Jumplist.UnpinTip = Odepnij z tej listy +Rename.Caption = Zmiana nazwy +Rename.OK = OK +Rename.Cancel = Anuluj +Color.Caption = Kolor +Color.OK = OK +Color.Cancel = Anuluj +Delete.Title = Usuniesz pasek łączy "%s" +Delete.Text = Katalog roboczy: %s +Delete.Verification = Usuń katalog roboczy +Message.FileNotFound = Plik nie istnieje +Message.DeleteShortcut = Usunąć skrót? +Properties.View = Widok +Properties.Appearance = Konfiguracja wyglądu +Properties.Position = Pozycja na ekranie: +Properties.Left = Z lewej +Properties.Top = Na górze +Properties.Right = Z prawej +Properties.Bottom = Na dole +Properties.IconSize = Rozmiar ikon: +Properties.BgColor = Kolor tła: +Properties.Margins = Marginesy (poziomy/pionowy): +Properties.Order = Kolejność skrótów: +Properties.LtR = Od lewej do prawej +Properties.UtD = Do dołu +Properties.TextPos = Pozycja tekstu: +Properties.Without = Bez tekstu +Properties.TextWidth = Tekst szerokość/wcięcie: +Properties.TextColor = Kolor tekstu: +Properties.GlowSize = Rozmiar poświaty: +Properties.AlwaysOnTop = Trzymaj pasek łączy na wierzchu +Properties.PageAutoHide = Automatycznego ukrywania +Properties.AutoHide = Konfiguracja automatycznego ukrywania +Properties.Hide = Ukryj: +Properties.Automatically = Automatycznie +Properties.Show = Pokaż: +Properties.MouseHover = Przesunięcie myszy +Properties.MouseLC = Lewy klik myszy +Properties.MouseRC = Prawy klik myszy +Properties.Delay = Opóźnienie, ms: +Properties.HotKey = Skrót klawiszowy: +Properties.Transparent = Przezroczysty, kiedy ukryty +Properties.Additional = Dodatkowo +Properties.Jumplists = Listy szybkiego dostępu +Properties.No = Nie +Properties.ForW7 = Dla Windows 7 +Properties.Style1 = Użyj stylu jak w pasku zadań z połączonymi przyciskami +Properties.ForW8 = Dla Windows 8/8.1 +Properties.AeroGlass = Włącz wsparcie dla AeroGlass (zainstalowane oddzielnie) +Properties.About = O Linkbar +Properties.Version = Wersja: %s +Properties.SystemInfo = Informacje o systemie: +Properties.Localizer = lokalizator: Galileusz +Properties.OK = OK +Properties.Cancel = Anuluj +Properties.Apply = Zastosuj \ No newline at end of file diff --git a/exe/Locales/ru-RU.ini b/exe/Locales/ru-RU.ini new file mode 100644 index 0000000..9e521a1 --- /dev/null +++ b/exe/Locales/ru-RU.ini @@ -0,0 +1,82 @@ +[ru-RU] - Russian (Russia) +New.Caption = Новая панелька +New.ToWhom = Создать панельку: +New.ForAll = Для всех пользователей компьютера +New.ForMe = Для меня (%s) +New.Folder = Выбор папки: +New.Create = Создать +New.Cancel = Отмена +Menu.Shortcut = Новый ярлык +Menu.Open = Открыть рабочий каталог +Menu.Create = Создать панельку... +Menu.Delete = Удалить панельку +Menu.Lock = Закрепить панельку +Menu.Sort = Сортировать по алфавиту +Menu.Properties = Свойства +Menu.Close = Закрыть +Menu.CloseAll = Закрыть все +Jumplist.Recent = Последние +Jumplist.Frequent = Часто используемые +Jumplist.Tasks = Задачи +Jumplist.Pinned = Закреплено +Jumplist.Open = &Открыть +Jumplist.Pin = &Закрепить в списке +Jumplist.Unpin = &Изъять из списка +Jumplist.Remove = Удалить &из этого списка +Jumplist.PinTip = Закрепить в списке +Jumplist.UnpinTip = Изъять из списка +Rename.Caption = Переименование +Rename.OK = OK +Rename.Cancel = Отмена +Color.Caption = Цвет +Color.OK = OK +Color.Cancel = Отмена +Delete.Title = Вы удаляете панельку "%s" +Delete.Text = Рабочий каталог: %s +Delete.Verification = Удалить рабочий каталог +Message.FileNotFound = Файл не существует +Message.DeleteShortcut = Удалить ярлык? +Properties.View = Вид +Properties.Appearance = Настройте внешний вид +Properties.Position = Положение на экране: +Properties.Left = Слева +Properties.Top = Сверху +Properties.Right = Cправа +Properties.Bottom = Cнизу +Properties.IconSize = Размер значков: +Properties.BgColor = Цвет фона: +Properties.Margins = Поля (горизонтальные/вертикальные): +Properties.Order = Порядок ярлыков: +Properties.LtR = Слева направо +Properties.UtD = Сверху вниз +Properties.TextPos = Положение текста: +Properties.Without = Без текста +Properties.TextWidth = Ширина/отступ текста: +Properties.TextColor = Цвет текста: +Properties.GlowSize = Размер тени: +Properties.AlwaysOnTop = Отображать панельку поверх остальных окон +Properties.PageAutoHide = Автоскрытие +Properties.AutoHide = Настройте автоскрытие +Properties.Hide = Скрывать: +Properties.Automatically = Автоматически +Properties.Show = Показывать: +Properties.MouseHover = При наведении +Properties.MouseLC = По левому клику +Properties.MouseRC = По правому клику +Properties.Delay = Задержка (мс): +Properties.HotKey = Сочетание клавиш: +Properties.Transparent = Прозрачная когда скрыта +Properties.Additional = Дополнительно +Properties.Jumplists = Списки переходов +Properties.No = Нет +Properties.ForW7 = Для Windows 7 +Properties.Style1 = Использовать стиль панели задач с группировкой +Properties.ForW8 = Для Windows 8/8.1 +Properties.AeroGlass = Включить поддержку AeroGlass (устанавливается отдельно) +Properties.About = О программе +Properties.Version = Версия: %s +Properties.SystemInfo = Информация о системе: +Properties.Localizer = локализатор: Asaq +Properties.OK = OK +Properties.Cancel = Отмена +Properties.Apply = Применить \ No newline at end of file diff --git a/exe/Locales/zh-CN.ini b/exe/Locales/zh-CN.ini new file mode 100644 index 0000000..dfbd020 --- /dev/null +++ b/exe/Locales/zh-CN.ini @@ -0,0 +1,82 @@ +[zh-CN] - Chinese (Simplified) +New.Caption = 新建 Linkbar +New.ToWhom = 为以下用户创建: +New.ForAll = 所有使用此计算机的用户(所有用户) +New.ForMe = 仅为我创建(%s) +New.Folder = 选择文件夹: +New.Create = 新建 +New.Cancel = 取消 +Menu.Shortcut = 添加 快捷方式 +Menu.Open = 打开工作目录 +Menu.Create = 新建 Linkbar... +Menu.Delete = 删除 Linkbar +Menu.Lock = 锁定 Linkbar +Menu.Sort = 按 A-Z 顺序排列 +Menu.Properties = 偏好设置 +Menu.Close = 关闭 +Menu.CloseAll = 关闭所有 +JumpList.Recent = 最近 +JumpList.Frequent = 常用 +JumpList.Tasks = 任务 +JumpList.Pinned = 已固定 +Jumplist.Open = 打开 +JumpList.Pin = 锁定到此列表 +JumpList.Unpin = 从此列表解锁 +JumpList.Remove = 从列表中删除 +JumpList.PinTip = 锁定到此列表 +JumpList.UnpinTip = 从此列表解锁 +Rename.Caption = 重命名 +Rename.OK = 确定 +Rename.Cancel = 取消 +Color.Caption = 颜色 +Color.OK = 确定 +Color.Cancel = 取消 +Delete.Title = 已移除 Linkbar "%s" +Delete.Text = 工作目录路径 %s +Delete.Verification = 删除工作目录 +Message.FileNotFound = 文件不存在 +Message.DeleteShortcut = 是否删除快捷方式? +Properties.View = 视图设置 +Properties.Appearance = 外观配置 +Properties.Position = 屏幕位置: +Properties.Left = 左边 +Properties.Top = 顶部 +Properties.Right = 右边 +Properties.Bottom = 底部 +Properties.IconSize = 图标大小: +Properties.BgColor = 背景颜色: +Properties.Margins = 边框大小(水平宽度/垂直长度): +Properties.Order = 快捷方式排序: +Properties.LtR = 从左到右 +Properties.UtD = 从上往下 +Properties.TextPos = 字体位置: +Properties.Without = 不显示文字 +Properties.TextWidth = 字体间距/缩进: +Properties.TextColor = 字体颜色: +Properties.GlowSize = 发光大小: +Properties.AlwaysOnTop = Linkbar 保持在其他窗口的前端 +Properties.PageAutoHide = 自动隐藏 +Properties.AutoHide = 配置自动隐藏 +Properties.Hide = 隐藏: +Properties.Automatically = 自动 +Properties.Show = 显示: +Properties.MouseHover = 鼠标靠近 +Properties.MouseLC = 鼠标左键 +Properties.MouseRC = 鼠标右键 +Properties.Delay = 延迟,毫秒: +Properties.HotKey = 键盘快捷键: +Properties.Transparent = 隐藏时透明显示 +Properties.Additional = 附加设置 +Properties.Jumplists = 跳转列表 +Properties.No = 没有 +Properties.ForW7 = 针对 Windows7 +Properties.Style1 = 使用纽扣式风格任务栏 +Properties.ForW8 = 针对 Windows8/8.1 +Properties.AeroGlass = 开启毛玻璃特效支持(需另行安装) +Properties.About = 关于 +Properties.Version = 版本号:%s +Properties.SystemInfo = 系统信息: +Properties.Localizer = 翻译者:Hue Liu +Properties.OK = 确定 +Properties.Cancel = 取消 +Properties.Apply = 应用 \ No newline at end of file diff --git a/exe/README.txt b/exe/README.txt index 9e5966a..339ba24 100644 --- a/exe/README.txt +++ b/exe/README.txt @@ -8,10 +8,10 @@ Note: 1) Linkbar support Windows Vista and above 2) Linkbar work with .lnk, .url and .website files -Version: 1.6.6 +Version: 1.6.7 License type: Freeware OS: Windows Vista/7/8/8.1/10 -Languages: English (default), French, German, Japanese, Russian, localization support (see LOCALIZATION.TXT) +Languages: English (default), Chinese-Simplified, French, German, Greek, Japanese, Korean, Polish, Russian, localization support Email: linkbar@yandex.ru =============================================================================== @@ -23,11 +23,11 @@ Email: linkbar@yandex.ru - Classic Shell - DelLocXE - GunSmoker-a blog +- Localizers - MSDN - Near users - Ru-Board community - StartIsBack -- Takahiro - Unknown programmers from internet =============================================================================== @@ -35,6 +35,9 @@ Email: linkbar@yandex.ru == Links =============================================================================== +- Source code: + https://github.com/ATGH15102AFMLD/Linkbar + - Project page on Sourceforge: https://sourceforge.net/projects/linkbar/ @@ -52,6 +55,26 @@ Email: linkbar@yandex.ru == History =============================================================================== +== Version 1.6.7 general release (Dec, 2017): + +add: New localization system. Simple and clear +add: Chinese-Simplified localization (Hue Liu) +add: Greek localization (geogeo.gr) +add: Korean localization (미유키로즈) +add: Polish localization (Galileusz) +add: AutoHide by Keyboard shortcut +add: Restoring the panels after restarting Explorer.exe +add: Keyboard control. Arrows, Spacebar/Enter, Menu, F2, Delete(+Shift) and Esc supported +add: Jumplist keyboard control +add: Option for disable Jumplists +add: Option "Keep the Linkbar on top of other windows" +del: Old localization files - Linkbar.lc3, LOCALIZATION.txt +fix: Exception on closing if the Properties is open +fix: Multiple separators in Shell menu (e.g. for a shortcut to an HTML-file) +fix: Incorrect behavior in negative desktop coordinates + +=============================================================================== + == Version 1.6.6 general release (Feb, 2017): add: German localization (Asaq) diff --git a/src/AccessBar.pas b/src/AccessBar.pas index 14e9212..c330a9d 100644 --- a/src/AccessBar.pas +++ b/src/AccessBar.pas @@ -14,10 +14,6 @@ interface Messages, SysUtils, Classes, Controls, Forms, ShellApi, Vcl.Dialogs, Linkbar.Consts, Linkbar.OS; -const - APPBAR_CALLBACK = WM_USER + 1; - CUSTOM_ABN_FULLSCREENAPP = WM_USER + 2; - type TQuerySizingEvent = procedure(Sender: TObject; AVertical: Boolean; var AWidth, AHeight: Integer) of object; @@ -26,7 +22,6 @@ interface THiddenForm = class (TCustomForm) private - FAccessHandle: THandle; protected procedure CreateParams(var Params: TCreateParams); override; @@ -39,6 +34,9 @@ THiddenForm = class (TCustomForm) end; TAccessBar = class(TComponent) + private + const + HWND_STYLE: array[Boolean] of HWND = (HWND_NOTOPMOST, HWND_TOPMOST); private gABRegistered: boolean; FOwnerOriginalWndProc: TWndMethod; @@ -49,8 +47,10 @@ TAccessBar = class(TComponent) FQueryAutoHide: TQueryHideEvent; FHandle: HWND; FBoundRect: TRect; + FStayOnTop: Boolean; // special form for autohide ahform: THiddenForm; + FTaskbarCreated: UINT; procedure SetAutoHide(const AValue: boolean); procedure SetSide(const AValue: TScreenAlign); procedure AppBWndProc(var Msg: TMessage); @@ -71,6 +71,7 @@ TAccessBar = class(TComponent) procedure AppBarPosChanged; procedure AppBarFullScreenApp(AEnabled: Boolean); published + property StayOnTop: Boolean read FStayOnTop write FStayOnTop; property AutoHide: boolean read FAutoHide write SetAutoHide; property Side: TScreenAlign read FSide write SetSide default saTop; property QuerySizing: TQuerySizingEvent read FQuerySizing write FQuerySizing; @@ -83,13 +84,49 @@ TAccessBar = class(TComponent) implementation -uses Types, Math, Linkbar.Loc; +uses Types, Math, Linkbar.L10n; const + APPBAR_CALLBACK = WM_USER + 1; + APPBAR_FULLSCREENAPP = WM_USER + 2; + APPBAR_TASKBARSTARTED = WM_USER + 3; + // Multi Monitor support, introduced in Windows 8 ABM_GETAUTOHIDEBAREX = $0000000b; ABM_SETAUTOHIDEBAREX = $0000000c; +procedure ChangeWindowMessageFilterEx(const AWnd: HWND; const AMessage: UINT); +const MSGFLT_ALLOW = 1; +type + CHANGEFILTERSTRUCT = packed record + cbSize: DWORD; + ExtStatus: DWORD; + end; + TChangeFilterStruct = CHANGEFILTERSTRUCT; + PChangeFilterStruct = ^TChangeFilterStruct; + + TChangeWindowMessageFilter = function (hWnd: HWND; Message: UINT; Action: DWORD): BOOL; stdcall; + TChangeWindowMessageFilterEx = function (hWnd: HWND; Message: UINT; Action: DWORD; pChangeFilterStruct: PChangeFilterStruct): BOOL; stdcall; + +var proc: TChangeWindowMessageFilter; + procEx: TChangeWindowMessageFilterEx; +begin + @procEx := GetProcAddress(GetModuleHandle(user32), 'ChangeWindowMessageFilterEx'); + if Assigned(procEx) + then begin + if not procEx(AWnd, AMessage, MSGFLT_ALLOW, nil) + then MessageBox(0, PChar(SysErrorMessage(GetLastError)), nil, MB_OK); + end + else begin + @proc := GetProcAddress(GetModuleHandle(user32), 'ChangeWindowMessageFilter'); + if Assigned(proc) + then begin + if not proc(AWnd, AMessage, MSGFLT_ALLOW) + then MessageBox(0, PChar(SysErrorMessage(GetLastError)), nil, MB_OK); + end; + end; +end; + function IsVertical(const AEdge: TScreenAlign): Boolean; inline; begin Result := (AEdge = saLeft) or (AEdge = saRight); @@ -123,8 +160,8 @@ constructor THiddenForm.CreateNew(AOwner: TComponent; Dummy: Integer = 0); rabd.hWnd := Self.Handle; rabd.uCallbackMessage := APPBAR_CALLBACK; FAccessHandle := 0; - if SHAppBarMessage(ABM_NEW, rabd) = 0 then - raise Exception.Create(SysErrorMessage(GetLastError())); + if SHAppBarMessage(ABM_NEW, rabd) = 0 + then raise Exception.Create(SysErrorMessage(GetLastError())); end; procedure THiddenForm.CreateParams(var Params: TCreateParams); @@ -141,8 +178,8 @@ destructor THiddenForm.Destroy; FillChar(rabd, SizeOf(rabd), 0); rabd.cbSize := SizeOf(rabd); rabd.hWnd := Self.Handle; - if SHAppBarMessage(ABM_REMOVE, rabd) = 0 then - raise Exception.Create(SysErrorMessage(GetLastError())); + if SHAppBarMessage(ABM_REMOVE, rabd) = 0 + then raise Exception.Create(SysErrorMessage(GetLastError())); inherited Destroy; end; @@ -158,8 +195,8 @@ procedure THiddenForm.SetMonitor(const AMonitorNum: Integer); rabd.rc.Width := 0; rabd.rc.Height := 0; - if SHAppBarMessage(ABM_SETPOS, rabd) = 0 then - raise Exception.Create(SysErrorMessage(GetLastError())); + if SHAppBarMessage(ABM_SETPOS, rabd) = 0 + then raise Exception.Create(SysErrorMessage(GetLastError())); MoveWindow(Handle, rabd.rc.Left, rabd.rc.Top, 0, 0, False); end; @@ -169,7 +206,7 @@ procedure THiddenForm.WndProc(var Msg: TMessage); if Msg.Msg = APPBAR_CALLBACK then begin if (Msg.wParam = ABN_FULLSCREENAPP) and IsWindow(FAccessHandle) - then SendMessage(FAccessHandle, CUSTOM_ABN_FULLSCREENAPP, 0, Msg.lParam); + then SendMessage(FAccessHandle, APPBAR_FULLSCREENAPP, 0, Msg.lParam); end else inherited WndProc(Msg); end; @@ -183,44 +220,31 @@ procedure TAccessBar.RegisterAppBar; var rabd: TAppBarData; begin if gABRegistered then exit; - // check if we are not in the Delphi IDE - if not (csDesigning in ComponentState) then - begin - // make sure we get the notification messages - FOwnerOriginalWndProc := TWinControl(Owner).WindowProc; - TWinControl(Owner).WindowProc := AppBWndProc; - FillChar(rabd, SizeOf(rabd), 0); - rabd.cbSize:= SizeOf(rabd); - rabd.hWnd := FHandle; - rabd.uCallbackMessage:= APPBAR_CALLBACK; - // register the application bar within the system - if SHAppBarMessage(ABM_NEW, rabd) = 0 then - raise Exception.Create(SysErrorMessage(GetLastError())); + FillChar(rabd, SizeOf(rabd), 0); + rabd.cbSize:= SizeOf(rabd); + rabd.hWnd := FHandle; + rabd.uCallbackMessage:= APPBAR_CALLBACK; + // register the application bar within the system + if SHAppBarMessage(ABM_NEW, rabd) = 0 + then raise Exception.Create(SysErrorMessage(GetLastError())); - gABRegistered := TRUE; - end; + gABRegistered := TRUE; end; procedure TAccessBar.UnregisterAppBar; var rabd: TAppBarData; begin if not gABRegistered then exit; - // check if the form is not being destroyed and not in the Delphi IDE - if not (csDesigning in ComponentState) then - begin - if not (csDestroying in ComponentState) then - TWinControl(Owner).WindowProc := FOwnerOriginalWndProc; - FillChar(rabd, SizeOf(rabd), 0); - rabd.cbSize:= SizeOf(rabd); - rabd.hWnd := FHandle; - // remove the application bar - if SHAppBarMessage(ABM_REMOVE, rabd) = 0 then - raise Exception.Create(SysErrorMessage(GetLastError())); - gABRegistered := FALSE; - FBoundRect := TRect.Empty; - end; + FillChar(rabd, SizeOf(rabd), 0); + rabd.cbSize:= SizeOf(rabd); + rabd.hWnd := FHandle; + // remove the application bar + if SHAppBarMessage(ABM_REMOVE, rabd) = 0 + then raise Exception.Create(SysErrorMessage(GetLastError())); + gABRegistered := FALSE; + FBoundRect := TRect.Empty; end; constructor TAccessBar.Create(AOwner: TComponent); @@ -236,6 +260,16 @@ constructor TAccessBar.Create(AOwner: TComponent); // for Delphi we only use descendants of TCustomForm if (AOwner is TCustomForm) then begin + // make sure we are the only one + for I:=0 to AOwner.ComponentCount -1 do + begin + if (AOwner.Components[I] is TAccessBar) and (AOwner.Components[I] <> Self) + then raise Exception.Create('Ooops, you need only *ONE* of these'); + end; + + FOwnerOriginalWndProc := TWinControl(Owner).WindowProc; + TWinControl(Owner).WindowProc := AppBWndProc; + FHandle := TWinControl(AOwner).Handle; ahform := THiddenForm.CreateNew(nil); ahform.AccessHandle := FHandle; @@ -243,12 +277,10 @@ constructor TAccessBar.Create(AOwner: TComponent); FBoundRect := TRect.Empty; - // make sure we are the only one - for I:=0 to AOwner.ComponentCount -1 do - begin - if (AOwner.Components[I] is TAccessBar) and (AOwner.Components[I] <> Self) then - raise Exception.Create('Ooops, you need only *ONE* of these'); - end; + FTaskbarCreated := RegisterWindowMessage('TaskbarCreated'); + if (FTaskbarCreated = 0) + then raise Exception.Create(SysErrorMessage(GetLastError)); + ChangeWindowMessageFilterEx(FHandle, FTaskbarCreated); end else raise Exception.Create('Sorry, can''t do this only with TCustomForms'); @@ -266,6 +298,8 @@ constructor TAccessBar.Create2(AOwner: TComponent; iSide: TScreenAlign; iAutoHid destructor TAccessBar.Destroy; begin + TWinControl(Owner).WindowProc := FOwnerOriginalWndProc; + if Assigned(ahform) then begin ahform.FAccessHandle := 0; @@ -286,8 +320,6 @@ procedure TAccessBar.AppBarQuerySetPos; iHeight, iWidth: Integer; rabd: TAppBarData; begin - if (csDesigning in ComponentState) then Exit; - if not InRange(MonitorNum, 0, Screen.MonitorCount-1) then MonitorNum := Screen.PrimaryMonitor.MonitorNum; @@ -299,8 +331,8 @@ procedure TAccessBar.AppBarQuerySetPos; if not AutoHide then // query the new position - if SHAppBarMessage(ABM_QUERYPOS, rabd) = 0 then - raise Exception.Create(SysErrorMessage(GetLastError())); + if SHAppBarMessage(ABM_QUERYPOS, rabd) = 0 + then raise Exception.Create(SysErrorMessage(GetLastError())); iWidth := rabd.rc.Width; iHeight := rabd.rc.Height; @@ -330,9 +362,9 @@ procedure TAccessBar.AppBarQuerySetPos; end; // set the new size - if not AutoHide then - if SHAppBarMessage(ABM_SETPOS, rabd) = 0 then - raise Exception.Create(SysErrorMessage(GetLastError())); + if (not AutoHide) + and (SHAppBarMessage(ABM_SETPOS, rabd) = 0) + then raise Exception.Create(SysErrorMessage(GetLastError())); // request the new size if Assigned(FQuerySized) @@ -389,6 +421,21 @@ procedure TAccessBar.AppBWndProc(var Msg: TMessage); var rabd: TAppBarData; begin case Msg.Msg of + APPBAR_TASKBARSTARTED: + begin + // TODO: Check logic + if (AutoHide) + then + SetSide(FSide) + else begin + UnregisterAppBar; + RegisterAppBar; + end; + end; + APPBAR_FULLSCREENAPP: + begin + Self.AppBarFullScreenApp(Msg.LParam <> 0); + end; APPBAR_CALLBACK: begin case Msg.wParam of @@ -411,6 +458,10 @@ procedure TAccessBar.AppBWndProc(var Msg: TMessage); SHAppBarMessage(ABM_ACTIVATE, rabd); inherited; end; + else begin + if (Msg.Msg = FTaskbarCreated) + then PostMessage(FHandle, APPBAR_TASKBARSTARTED, 0, 0); + end; end; // call the original WndProc if Assigned(FOwnerOriginalWndProc) then FOwnerOriginalWndProc(Msg); @@ -422,8 +473,6 @@ procedure TAccessBar.AppBarSetAutoHide(AEnabled: Boolean); rabd: TAppBarData; hr: Cardinal; begin - if (csDesigning in ComponentState) then Exit; - FillChar(rabd, SizeOf(rabd), 0); rabd.cbSize := SizeOf(rabd); rabd.hWnd := FHandle; @@ -450,31 +499,32 @@ procedure TAccessBar.AppBarSetAutoHide(AEnabled: Boolean); if Assigned(FQueryAutoHide) then FQueryAutoHide(Self, TRUE); - SetWindowPos(FHandle, HWND_TOPMOST, 0, 0, 0, 0, + SetWindowPos(FHandle, HWND_STYLE[FStayOnTop], 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER); AppBarQuerySetPos; - end else begin - FAutoHide := FALSE; - RegisterAppBar; + end + else begin + FAutoHide := FALSE; + RegisterAppBar; - SetWindowPos(FHandle, HWND_TOPMOST, 0, 0, 0, 0, - SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER); + SetWindowPos(FHandle, HWND_STYLE[FStayOnTop], 0, 0, 0, 0, + SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER); - AppBarQuerySetPos; - if Assigned(FQueryAutoHide) - then FQueryAutoHide(Self, FALSE); - if AEnabled then - begin - td := TTaskDialog.Create(Self.Owner); - td.MainIcon := tdiInformation; - td.Caption := APP_NAME_LINKBAR; - td.Title := ''; - td.text := MUILoadResString(LB_FN_TOOLBAR, LB_RS_TB_AUTOHIDEALREADYEXISTS); - td.CommonButtons := [tcbOk]; - td.Execute; - td.Free; - end; + AppBarQuerySetPos; + if Assigned(FQueryAutoHide) + then FQueryAutoHide(Self, FALSE); + if AEnabled then + begin + td := TTaskDialog.Create(Self.Owner); + td.MainIcon := tdiInformation; + td.Caption := APP_NAME_LINKBAR; + td.Title := ''; + td.text := L10nMui(LB_FN_TOOLBAR, LB_RS_TB_AUTOHIDEALREADYEXISTS); + td.CommonButtons := [tcbOk]; + td.Execute; + td.Free; + end; end; end; @@ -486,10 +536,9 @@ procedure TAccessBar.AppBarPosChanged; procedure TAccessBar.AppBarFullScreenApp(AEnabled: Boolean); var Flags: HWND; begin - Flags := HWND_BOTTOM; - - if not AEnabled and AutoHide - then Flags := HWND_TOPMOST; + if AEnabled + then Flags := HWND_BOTTOM + else Flags := HWND_STYLE[FStayOnTop]; SetWindowPos(FHandle, Flags, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER); diff --git a/src/ExplorerMenu.pas b/src/ExplorerMenu.pas index e8d4eeb..8baa152 100644 --- a/src/ExplorerMenu.pas +++ b/src/ExplorerMenu.pas @@ -97,6 +97,32 @@ function BitmapFromIcon(AIcon: HICON; ASize: integer): HBITMAP; procedure ExplorerMenuPopup(const AWnd: HWND; const APidl: PItemIDList; const AScrPt: TPoint; const AShift: Boolean; const ASubMenu: HMENU); + + procedure RemoveMultipleSeparators(const AMenu: HMENU); + var i, count: Integer; + separator: Boolean; + mi: TMenuItemInfo; + begin + FillChar(mi, SizeOf(mi), 0); + mi.cbSize := SizeOf(mi); + mi.fMask := MIIM_FTYPE; + separator := True; + count := GetMenuItemCount(AMenu); + i := 0; + while (i < count) do + begin + mi.fType := 0; + if (GetMenuItemInfo(AMenu, i, True, mi)) + and (mi.fType = MFT_SEPARATOR) + and separator + then DeleteMenu(AMenu, i, MF_BYPOSITION) + else Inc(i); + separator := mi.fType = MFT_SEPARATOR + end; + if (count > 0) and separator + then DeleteMenu(AMenu, count-1, MF_BYPOSITION); + end; + var CoInit: HRESULT; Menu: HMenu; @@ -112,7 +138,6 @@ procedure ExplorerMenuPopup(const AWnd: HWND; const APidl: PItemIDList; miinfo: TMenuItemInfo; hIco: HICON; hbmp: HBITMAP; - hr: HRESULT; iconsize: Integer; begin CoInit := CoInitializeEx(nil, COINIT_MULTITHREADED); @@ -163,12 +188,10 @@ procedure ExplorerMenuPopup(const AWnd: HWND; const APidl: PItemIDList; miinfo.dwTypeData := PChar('Linkbar'); InsertMenuItem(Menu, insertBefore, True, miinfo); - hr := S_OK; + // Icon for Linkbar submenu item iconsize := GetSystemMetrics(SM_CXSMICON); - hIco := LoadImage(HInstance, MakeIntResource('MAINICON'), IMAGE_ICON, - iconsize, iconsize, LR_DEFAULTCOLOR); {} - if Succeeded(hr) - and (hIco <> 0) + hIco := LoadImage(HInstance, MakeIntResource('MAINICON'), IMAGE_ICON, iconsize, iconsize, LR_DEFAULTCOLOR); + if (hIco <> 0) then begin hbmp := BitmapFromIcon(hIco, GetSystemMetrics(SM_CXSMICON)); DestroyIcon(hIco); @@ -178,6 +201,9 @@ procedure ExplorerMenuPopup(const AWnd: HWND; const APidl: PItemIDList; miinfo.hbmpItem := hbmp; SetMenuItemInfo(Menu, insertBefore, True, miinfo); end; + + // Sometimes menus have multiple separators e.g. for html shortcut. In Explorer.exe there is no such + RemoveMultipleSeparators(Menu); end; ICMenu.QueryInterface(IContextMenu2, g_cm2); diff --git a/src/LBToolbar.pas b/src/LBToolbar.pas index e8d1bbe..c6977b6 100644 --- a/src/LBToolbar.pas +++ b/src/LBToolbar.pas @@ -7,7 +7,7 @@ {$i linkbar.inc} -{;$define CHACE_BB_ICON} // chache Bit Bucket icon +{;$define CHACE_BB_ICON} // chache Bit Bucket icon. However, if the user changes the icon of the Bit Bucket, this is incorrect. interface @@ -60,10 +60,6 @@ implementation uses Winapi.ActiveX, Winapi.ShellAPI, System.Win.ComObj, Winapi.KnownFolders, Linkbar.OS, Linkbar.Consts, Linkbar.Shell; -const - ICON_SHIELD_FLAG = $08000; // draw the shield overlay - ICON_INDEX_MASK = ICON_SHIELD_FLAG - 1; - var FKnownFolderManager: IKnownFolderManager; @@ -130,14 +126,10 @@ function CheckBitBucket(const APidl: PItemIDList): Boolean; and (pidl <> APidl) then CoTaskMemFree(pidl); - if Succeeded(hr) - then begin - if Succeeded( pKnownFolder.GetId(id) ) - then begin - if (id = FOLDERID_RecycleBinFolder) - then Result := True; - end; - end; + Result := Succeeded(hr) + and Assigned(pKnownFolder) + and Succeeded( pKnownFolder.GetId(id) ) + and (id = FOLDERID_RecycleBinFolder); end; //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Linkbar.Consts.pas b/src/Linkbar.Consts.pas index cb93a96..a35a32a 100644 --- a/src/Linkbar.Consts.pas +++ b/src/Linkbar.Consts.pas @@ -20,11 +20,15 @@ interface TAutoShowMode = (smMouseHover = 0, smMouseClickLeft = 1, smMouseClickRight = 2); + TJumplistShowMode = (jsmDisabled = 0, jsmMouseClickRight = 1); + const APP_NAME_LINKBAR = 'Linkbar'; URL_WEB = 'https://sourceforge.net/projects/linkbar/'; URL_EMAIL = 'linkbar@yandex.ru'; + URL_WINDOWS_HOTKEY = 'https://support.microsoft.com/en-ie/help/12445/windows-keyboard-shortcuts'; + // Supported extentions ES_ARRAY: array[0..2] of string = ('.lnk', '.url', '.website'); @@ -37,6 +41,7 @@ interface DN_SHARED_BARS = 'Shared bars\'; DN_USER_BARS = 'User bars\'; + DN_LOCALES = 'Locales/'; EXT_LBR = '.lbr'; MASK_LBR = '*' + EXT_LBR; @@ -70,9 +75,12 @@ interface ITEM_NONE = -1; ITEM_ALL = -1; + TIMER_AUTO_HIDE_DELAY = 300; + DEF_AUTOHIDE = False; DEF_AUTOHIDE_TRANSPARENCY = False; DEF_AUTOHIDE_SHOWMODE = Integer(Low(TAutoShowMode)); + DEF_AUTOHIDE_HOTKEY = '$0007004C'; // Shift+Ctrl+Alt+L DEF_DIR_LINKS = '.\links'; DEF_EDGE = Integer(saTop); DEF_HINT_SHOW = True; @@ -91,7 +99,9 @@ interface DEF_TXTCOLOR = $00000000; DEF_USECOLOR = False; DEF_GLOWSIZE = 12; - DEF_ENABLE_AG = False; + DEF_ENABLE_AG = False; + DEF_JUMPLISTSHOWMODE = Integer(jsmMouseClickRight); + DEF_STAYONTOP = True; // INI sections INI_SECTION_MAIN = 'Main'; { Main } @@ -100,6 +110,7 @@ interface INI_AUTOHIDE = 'autohide'; INI_AUTOHIDE_TRANSPARENCY = 'autohidetransparency'; INI_AUTOHIDE_SHOWMODE = 'autohideshowmode'; + INI_AUTOHIDE_HOTKEY = 'autohidehotkey'; INI_DIR_LINKS = 'dirlinks'; INI_EDGE = 'edge'; INI_HINT_SHOW = 'hintshow'; @@ -120,6 +131,8 @@ interface INI_USETXTCOLOR = 'usetxtcolor'; INI_TXTCOLOR = 'txtcolor'; { Text color } INI_GLOWSIZE = 'glowsize'; + INI_JUMPLISTSHOWMODE = 'jumplistshowmode'; + INI_STAYONTOP = 'stayontop'; INI_ENABLE_AG = 'enableaeroglass'; diff --git a/src/Linkbar.Loc.pas b/src/Linkbar.Loc.pas deleted file mode 100644 index 4e23862..0000000 --- a/src/Linkbar.Loc.pas +++ /dev/null @@ -1,108 +0,0 @@ -{*******************************************************} -{ Linkbar - Windows desktop toolbar } -{ Copyright (c) 2010-2017 Asaq } -{*******************************************************} - -unit Linkbar.Loc; - -{$i linkbar.inc} - -interface - -uses Windows, SysUtils, Classes, LcUnitXe; - -const - // explorerframe.dll.mui - LB_FN_TOOLBAR = 'explorerframe.dll'; - LB_RS_TB_AUTOHIDEALREADYEXISTS = 28676; - LB_RS_TB_NEWTOOLBAROPENDIALOGTITLE = 12387; - - // New shortcut - // shell32.dll.mui - String table - ? - LB_FN_NEWSHORTCUT = 'shell32.dll'; - LB_RS_NSC_FILENAME = 30397; - - // Jumplists - // explorer.exe.mui - String table - 21 - LB_FN_JUMPLIST = 'explorer.exe'; - LB_RS_JL_PINNED = 326; - LB_RS_JL_RECENT = 327; - LB_RS_JL_FREQUENT = 328; - LB_RS_JL_TASKS = 329; - LB_RS_JL_UNPIN = 330; // En: Unpin from this list - LB_RS_JL_PIN = 331; // En: Pin to this list - LB_RS_JL_REMOVE = 8225; // En: Remove from this list - - // Invalid file name symbols - // shell32.dll.mui - String table - 257, 793 - LB_FN_INVALIDFILENAMECHARS = 'shell32.dll'; - LB_RS_IFNC_HINT = 4109; - - // Rename dialog need file name - LB_FN_NEEDFILENAME = 'shell32.dll'; - LB_RS_NFN_CUE = 4123; - // and "Open" - LB_RS_JL_OPEN = 12850; - - function MUILoadResString(const AModuleName: String; const AStringID: Cardinal): String; overload; - function MUILoadResString(const AModule: HINST; const AStringID: Cardinal): String; overload; - - function LbTranslateInit(ALCID: LCID): Integer; - function LbTranslateComponent(AComponent: TComponent): Boolean; - function LbLongLang: Boolean; - -var - LbLangID: LCID = 0; - -implementation - -uses Linkbar.Consts; - -function MUILoadResString(const AModule: HINST; const AStringID: Cardinal): String; -var p: PChar; -begin - if (AModule <> 0) and (AStringID < 65536) - then SetString(Result, p, LoadString(AModule, AStringID, @p, 0)) - else Result := 'resource_string_not_found'; -end; - -function MUILoadResString(const AModuleName: String; const AStringID: Cardinal): String; -var h: THandle; -begin - h := LoadLibraryEx(PChar(AModuleName), 0, LOAD_LIBRARY_AS_DATAFILE); - Result := MUILoadResString(h, AStringID); - if (h <> 0) - then FreeLibrary(h); -end; - -function LCIDTo36LanguageID(ALCID: LCID): LCID; -begin - if (ALCID = 0) - then ALCID := TLanguages.UserDefaultLocale; - case Lo(ALCID) of - LANG_ENGLISH : Result := $0409; // English (US) - LANG_FRENCH : Result := $040C; // French - LANG_JAPANESE: Result := $0411; // Japanese - LANG_RUSSIAN : Result := $0419; // Russian - LANG_GERMAN : Result := $0407; // German (Germany) - else Result := ALCID; // Use default language English-US - end; -end; - -function LbTranslateInit(ALCID: LCID): Integer; -begin - LbLangID := LCIDTo36LanguageID(ALCID); - Result := LcUnitXe.LoadLcf( ExtractFilePath(ParamStr(0)) + FN_LOCALIZATION, LbLangID, nil, nil ); -end; - -function LbTranslateComponent(AComponent: TComponent): Boolean; -begin - Result := LcUnitXe.TranslateComponent(AComponent); -end; - -function LbLongLang: Boolean; -begin - Result := (LbLangID = $040C); -end; - -end. diff --git a/src/Linkbar.ResStr.pas b/src/Linkbar.ResStr.pas deleted file mode 100644 index d1220ed..0000000 --- a/src/Linkbar.ResStr.pas +++ /dev/null @@ -1,25 +0,0 @@ -{*******************************************************} -{ Linkbar - Windows desktop toolbar } -{ Copyright (c) 2010-2017 Asaq } -{*******************************************************} - -unit Linkbar.ResStr; - -{$i linkbar.inc} - -interface - -resourcestring - - RS_FILENOTFOUND = 'File does not exists'; - RS_Q_DELETELINK = 'Delete shortcut?'; - - RS_REMDLG_TITLE = 'You remove the linkbar "%s"'; - RS_REMDLG_TEXT = 'Working directory: %s'; - RS_REMDLG_VERIFICATIONTEXT = 'Delete working directory'; - - RS_FILE_ALREADY_EXISTS = 'File with this name already exists'; - -implementation - -end. diff --git a/src/Linkbar.Settings.dfm b/src/Linkbar.Settings.dfm index 7cd58d7..df791a5 100644 --- a/src/Linkbar.Settings.dfm +++ b/src/Linkbar.Settings.dfm @@ -17,41 +17,29 @@ object FrmProperties: TFrmProperties FormStyle = fsStayOnTop OldCreateOrder = False ParentBiDiMode = False - Position = poScreenCenter + Position = poDesigned OnClose = FormClose OnDestroy = FormDestroy OnMouseWheel = FormMouseWheel DesignSize = ( - 383 - 517) + 408 + 409) PixelsPerInch = 96 TextHeight = 14 object pgc1: TPageControl Left = 5 Top = 6 - Width = 374 - Height = 470 - ActivePage = tsAdditionally + Width = 399 + Height = 361 + ActivePage = tsView Align = alCustom Anchors = [akLeft, akTop, akRight] TabOrder = 0 - object tsOptions: TTabSheet + object tsView: TTabSheet Caption = 'View' - ExplicitLeft = 0 - ExplicitTop = 0 - ExplicitWidth = 0 - ExplicitHeight = 0 DesignSize = ( - 366 - 441) - object lblSection2: TLabel - Left = 8 - Top = 296 - Width = 108 - Height = 14 - Caption = 'Configure auto-hide' - Transparent = True - end + 391 + 332) object lblSection1: TLabel Left = 8 Top = 8 @@ -63,7 +51,7 @@ object FrmProperties: TFrmProperties object pnlDummy11: TPanel Left = 8 Top = 227 - Width = 346 + Width = 371 Height = 22 Anchors = [akLeft, akTop, akRight] BevelOuter = bvNone @@ -72,18 +60,18 @@ object FrmProperties: TFrmProperties object chbUseTxtColor: TCheckBox Left = 0 Top = 0 - Width = 160 + Width = 185 Height = 22 Align = alLeft Anchors = [akLeft, akTop, akRight, akBottom] Caption = 'Text color:' TabOrder = 0 - OnClick = OptionsChanged + OnClick = Changed end object clbTextColor: TColorBox - Left = 196 + Left = 208 Top = 0 - Width = 150 + Width = 163 Height = 22 Align = alRight DefaultColorColor = clWhite @@ -97,10 +85,11 @@ object FrmProperties: TFrmProperties object pnlDummy1: TPanel Left = 8 Top = 31 - Width = 346 + Width = 371 Height = 22 Anchors = [akLeft, akTop, akRight] BevelOuter = bvNone + Color = clRed ShowCaption = False TabOrder = 0 object lblScreenEdge: TLabel @@ -114,14 +103,14 @@ object FrmProperties: TFrmProperties ExplicitHeight = 14 end object cbbScreenPosition: TComboBox - Left = 196 + Left = 208 Top = 0 - Width = 150 + Width = 163 Height = 22 Align = alRight Style = csDropDownList TabOrder = 0 - OnChange = OptionsChanged + OnChange = Changed Items.Strings = ( 'Left' 'Top' @@ -132,7 +121,7 @@ object FrmProperties: TFrmProperties object pnlDummy2: TPanel Left = 8 Top = 59 - Width = 346 + Width = 371 Height = 22 Anchors = [akLeft, akTop, akRight] BevelOuter = bvNone @@ -142,37 +131,29 @@ object FrmProperties: TFrmProperties Left = 0 Top = 0 Width = 51 - Height = 14 + Height = 22 Align = alLeft Caption = 'Icon size:' Layout = tlCenter - end - object bvlSpacer1: TBevel - Left = 192 - Top = 0 - Width = 4 - Height = 22 - Align = alRight - Shape = bsSpacer - ExplicitLeft = 194 + ExplicitHeight = 14 end object nseIconSize: TnSpinEdit - Left = 196 + Left = 208 Top = 0 - Width = 150 + Width = 163 Height = 22 Align = alRight MaxValue = 0 MinValue = 0 TabOrder = 0 Value = 0 - OnChange = OptionsChanged + OnChange = Changed end end object pnlDummy3: TPanel Left = 8 Top = 115 - Width = 346 + Width = 371 Height = 22 Anchors = [akLeft, akTop, akRight] BevelOuter = bvNone @@ -182,49 +163,49 @@ object FrmProperties: TFrmProperties Left = 0 Top = 0 Width = 153 - Height = 14 + Height = 22 Align = alLeft Caption = 'Margins (horizontal/vertical):' Layout = tlCenter + ExplicitHeight = 14 end object bvlSpacer2: TBevel - Left = 269 + Left = 287 Top = 0 - Width = 4 + Width = 5 Height = 22 Align = alRight Shape = bsSpacer - ExplicitLeft = 268 end object nseMarginH: TnSpinEdit - Left = 196 + Left = 208 Top = 0 - Width = 73 + Width = 79 Height = 22 Align = alRight MaxValue = 0 MinValue = 0 TabOrder = 0 Value = 0 - OnChange = OptionsChanged + OnChange = Changed end object nseMarginV: TnSpinEdit - Left = 273 + Left = 292 Top = 0 - Width = 73 + Width = 79 Height = 22 Align = alRight MaxValue = 0 MinValue = 0 TabOrder = 1 Value = 0 - OnChange = OptionsChanged + OnChange = Changed end end object pnlDummy4: TPanel Left = 8 Top = 143 - Width = 346 + Width = 371 Height = 22 Anchors = [akLeft, akTop, akRight] BevelOuter = bvNone @@ -241,14 +222,14 @@ object FrmProperties: TFrmProperties ExplicitHeight = 14 end object cbbItemOrder: TComboBox - Left = 196 + Left = 208 Top = 0 - Width = 150 + Width = 163 Height = 22 Align = alRight Style = csDropDownList TabOrder = 0 - OnChange = OptionsChanged + OnChange = Changed Items.Strings = ( 'Left to right' 'Up to down') @@ -257,7 +238,7 @@ object FrmProperties: TFrmProperties object pnlDummy5: TPanel Left = 8 Top = 171 - Width = 346 + Width = 371 Height = 22 Anchors = [akLeft, akTop, akRight] BevelOuter = bvNone @@ -274,14 +255,14 @@ object FrmProperties: TFrmProperties ExplicitHeight = 14 end object cbbTextLayout: TComboBox - Left = 196 + Left = 208 Top = 0 - Width = 150 + Width = 163 Height = 22 Align = alRight Style = csDropDownList TabOrder = 0 - OnChange = OptionsChanged + OnChange = Changed Items.Strings = ( 'Without text' 'Left' @@ -293,7 +274,7 @@ object FrmProperties: TFrmProperties object pnlDummy6: TPanel Left = 8 Top = 199 - Width = 346 + Width = 371 Height = 22 Anchors = [akLeft, akTop, akRight] BevelOuter = bvNone @@ -303,313 +284,415 @@ object FrmProperties: TFrmProperties Left = 0 Top = 0 Width = 105 - Height = 14 + Height = 22 Align = alLeft Caption = 'Text width/indent:' Layout = tlCenter + ExplicitHeight = 14 end object bvlSpacer3: TBevel - Left = 269 + Left = 287 Top = 0 - Width = 4 + Width = 5 Height = 22 Align = alRight Shape = bsSpacer - ExplicitLeft = 268 end object nseTextWidth: TnSpinEdit - Left = 196 + Left = 208 Top = 0 - Width = 73 + Width = 79 Height = 22 Align = alRight MaxValue = 0 MinValue = 0 TabOrder = 0 Value = 0 - OnChange = OptionsChanged + OnChange = Changed end object nseTextOffset: TnSpinEdit - Left = 273 + Left = 292 Top = 0 - Width = 73 + Width = 79 Height = 22 Align = alRight MaxValue = 0 MinValue = 0 TabOrder = 1 Value = 0 - OnChange = OptionsChanged + OnChange = Changed end end - object pnlDummy7: TPanel + object pnlDummy10: TPanel Left = 8 - Top = 317 - Width = 346 - Height = 21 + Top = 87 + Width = 371 + Height = 22 Anchors = [akLeft, akTop, akRight] BevelOuter = bvNone ShowCaption = False - TabOrder = 9 - object lbl2: TLabel - Left = 0 + TabOrder = 2 + object btnBgColorShowHide: TSpeedButton + Left = 348 Top = 0 - Width = 28 - Height = 14 - Align = alLeft - Caption = 'Hide:' - Layout = tlCenter + Width = 23 + Height = 22 + Align = alRight + Caption = '...' + OnClick = btnBgColorClick end - object chbAutoHide: TCheckBox - Left = 196 + object edtColorBg: TEdit + Tag = 3 + Left = 208 Top = 0 - Width = 150 - Height = 21 + Width = 140 + Height = 22 Align = alRight - Caption = 'Automatically' + Alignment = taCenter + CharCase = ecUpperCase + MaxLength = 8 + TabOrder = 1 + Text = 'FFFFFFFF' + OnChange = edtColorBgChange + OnKeyPress = edtColorBgKeyPress + end + object chbUseBkgColor: TCheckBox + Left = 0 + Top = 0 + Width = 185 + Height = 22 + Align = alLeft + Anchors = [akLeft, akTop, akRight, akBottom] + Caption = 'Background color:' TabOrder = 0 - OnClick = OptionsChanged + OnClick = Changed end end - object pnlDummy8: TPanel + object pnlDummy12: TPanel Left = 8 - Top = 344 - Width = 346 + Top = 255 + Width = 371 Height = 22 Anchors = [akLeft, akTop, akRight] BevelOuter = bvNone ShowCaption = False - TabOrder = 10 - object lbl1: TLabel + TabOrder = 8 + object lblGlowSize: TLabel Left = 0 Top = 0 - Width = 35 + Width = 54 Height = 22 Align = alLeft - Caption = 'Show:' + Caption = 'Glow size:' Layout = tlCenter ExplicitHeight = 14 end - object cbbAutoShowMode: TComboBox - Left = 196 + object nseGlowSize: TnSpinEdit + Left = 208 Top = 0 - Width = 150 + Width = 163 Height = 22 Align = alRight - Style = csDropDownList + MaxValue = 16 + MinValue = 0 TabOrder = 0 - OnChange = OptionsChanged - Items.Strings = ( - 'Mouse hover' - 'Mouse left-click' - 'Mouse right-click') + Value = 0 + OnChange = Changed + end + end + object pnlDummy13: TPanel + Left = 8 + Top = 283 + Width = 371 + Height = 21 + Anchors = [akLeft, akTop, akRight] + BevelOuter = bvNone + ShowCaption = False + TabOrder = 9 + object chbStayOnTop: TCheckBox + Left = 0 + Top = 0 + Width = 371 + Height = 21 + Align = alClient + Caption = 'Always on top' + TabOrder = 0 + OnClick = Changed + ExplicitWidth = 348 end end + end + object tsAutohide: TTabSheet + Caption = 'Autohide' + ImageIndex = 3 + DesignSize = ( + 391 + 332) + object lblSection2: TLabel + Left = 8 + Top = 8 + Width = 108 + Height = 14 + Caption = 'Configure auto-hide' + Transparent = True + end object chbAutoHideTransparency: TCheckBox Left = 8 - Top = 412 - Width = 345 + Top = 183 + Width = 370 Height = 17 Anchors = [akLeft, akTop, akRight] Caption = 'Transparent when hidden' - TabOrder = 12 - OnClick = OptionsChanged + TabOrder = 5 + OnClick = Changed end - object pnlDummy9: TPanel + object pnlDelay: TPanel Left = 8 - Top = 372 - Width = 346 + Top = 84 + Width = 371 Height = 22 Anchors = [akLeft, akTop, akRight] BevelOuter = bvNone + ParentColor = True ShowCaption = False - TabOrder = 11 - object Label3: TLabel + TabOrder = 2 + object lblDelay: TLabel Left = 0 Top = 0 Width = 56 - Height = 14 + Height = 22 Align = alLeft Caption = 'Delay, ms:' Layout = tlCenter - end - object bvlSpacer4: TBevel - Left = 192 - Top = 0 - Width = 4 - Height = 22 - Align = alRight - Shape = bsSpacer - ExplicitLeft = 194 + ExplicitHeight = 14 end object nseAutoShowDelay: TnSpinEdit - Left = 196 + Left = 208 Top = 0 - Width = 150 + Width = 163 Height = 22 Align = alRight MaxValue = 60000 MinValue = 0 TabOrder = 0 Value = 0 - OnChange = OptionsChanged + OnChange = Changed end end - object pnlDummy10: TPanel + object pnlDummy7: TPanel Left = 8 - Top = 87 - Width = 346 - Height = 22 + Top = 29 + Width = 371 + Height = 21 Anchors = [akLeft, akTop, akRight] BevelOuter = bvNone ShowCaption = False - TabOrder = 2 - object btnBgColorShowHide: TSpeedButton - Left = 322 + TabOrder = 0 + object lbl2: TLabel + Left = 0 Top = 0 - Width = 24 - Height = 22 - Align = alRight - Caption = '...' - OnClick = btnBgColorClick + Width = 28 + Height = 21 + Align = alLeft + Caption = 'Hide:' + Layout = tlCenter + ExplicitHeight = 14 end - object edtColorBg: TEdit - Tag = 3 - Left = 196 + object chbAutoHide: TCheckBox + Left = 208 Top = 0 - Width = 126 - Height = 22 + Width = 163 + Height = 21 Align = alRight - Alignment = taCenter - CharCase = ecUpperCase - MaxLength = 8 - TabOrder = 1 - Text = 'FFFFFFFF' - OnChange = edtColorBgChange - OnKeyPress = edtColorBgKeyPress - end - object chbUseBkgColor: TCheckBox - Left = 0 - Top = 0 - Width = 160 - Height = 22 - Align = alLeft - Anchors = [akLeft, akTop, akRight, akBottom] - Caption = 'Background color:' + Caption = 'Automatically' TabOrder = 0 - OnClick = OptionsChanged + OnClick = Changed end end - object pnlDummy12: TPanel + object pnlDummy8: TPanel Left = 8 - Top = 255 - Width = 346 + Top = 56 + Width = 371 Height = 22 Anchors = [akLeft, akTop, akRight] BevelOuter = bvNone + ParentColor = True ShowCaption = False - TabOrder = 8 - object lblGlowSize: TLabel + TabOrder = 1 + object lblShow: TLabel Left = 0 Top = 0 - Width = 54 - Height = 14 + Width = 35 + Height = 22 Align = alLeft - Caption = 'Glow size:' + Caption = 'Show:' Layout = tlCenter + ExplicitHeight = 14 end - object bvlSpacer5: TBevel - Left = 192 + object cbbAutoShowMode: TComboBox + Left = 208 Top = 0 - Width = 4 + Width = 163 Height = 22 Align = alRight - Shape = bsSpacer - ExplicitLeft = 194 + Style = csDropDownList + TabOrder = 0 + OnChange = Changed + Items.Strings = ( + 'Mouse hover' + 'Mouse left-click' + 'Mouse right-click') end - object nseGlowSize: TnSpinEdit - Left = 196 + end + object pnlHotkey: TPanel + Left = 8 + Top = 108 + Width = 371 + Height = 22 + Anchors = [akLeft, akTop, akRight] + BevelOuter = bvNone + ParentColor = True + ShowCaption = False + TabOrder = 3 + object lblHotKey: TLabel + Left = 0 Top = 0 - Width = 150 + Width = 105 Height = 22 - Align = alRight - MaxValue = 16 - MinValue = 0 - TabOrder = 0 - Value = 0 - OnChange = OptionsChanged + Align = alLeft + Caption = 'Keyboard shortcut:' + Layout = tlCenter + ExplicitHeight = 14 end end + object pnlHotkeyEdit: TPanel + Left = 8 + Top = 136 + Width = 371 + Height = 22 + Anchors = [akLeft, akTop, akRight] + BevelOuter = bvNone + ParentColor = True + ShowCaption = False + TabOrder = 4 + end end object tsAdditionally: TTabSheet Caption = 'Additional' ImageIndex = 1 - ExplicitLeft = 0 - ExplicitTop = 0 - ExplicitWidth = 0 - ExplicitHeight = 0 + DesignSize = ( + 391 + 332) + object lblSectionWin7: TLabel + Left = 8 + Top = 98 + Width = 82 + Height = 14 + Caption = 'For Windows 7' + Transparent = True + end object lblSectionWin8: TLabel Left = 8 - Top = 82 + Top = 149 Width = 105 Height = 14 Caption = 'For Windows 8/8.1' Transparent = True end - object lblSectionWin7: TLabel + object lblJumplist: TLabel Left = 8 Top = 8 - Width = 82 + Width = 48 Height = 14 - Caption = 'For Windows 7' + Caption = 'Jumplists' Transparent = True end - object chbAeroGlass: TCheckBox + object pnlLightStyle: TPanel Left = 8 - Top = 118 - Width = 343 - Height = 17 - Align = alCustom + Top = 110 + Width = 371 + Height = 34 Anchors = [akLeft, akTop, akRight] - Caption = 'Enable AeroGlass support (installed separately)' + BevelOuter = bvNone + ParentColor = True + ShowCaption = False TabOrder = 1 - WordWrap = True - OnClick = OptionsChanged + object chbLightStyle: TCheckBox + Left = 0 + Top = 0 + Width = 371 + Height = 34 + Align = alTop + Caption = 'Use style like taskbar with combined buttons' + TabOrder = 0 + WordWrap = True + OnClick = Changed + end end - object chbLightStyle: TCheckBox + object chbAeroGlass: TCheckBox Left = 8 - Top = 28 - Width = 343 - Height = 48 + Top = 185 + Width = 368 + Height = 17 Align = alCustom Anchors = [akLeft, akTop, akRight] - Caption = 'Use style like taskbar with combined buttons' - TabOrder = 0 + Caption = 'Enable AeroGlass support (installed separately)' + TabOrder = 2 WordWrap = True - OnClick = OptionsChanged + OnClick = Changed end object chbShowHints: TCheckBox - Left = 3 - Top = 371 + Left = 8 + Top = 216 Width = 367 Height = 17 Align = alCustom Caption = 'Show hints' - TabOrder = 2 + TabOrder = 3 Visible = False - OnClick = OptionsChanged + OnClick = Changed + end + object pnlJumplistShowMode: TPanel + Left = 8 + Top = 31 + Width = 371 + Height = 22 + Anchors = [akLeft, akTop, akRight] + BevelOuter = bvNone + Color = clRed + ShowCaption = False + TabOrder = 0 + object lblJumplistShowMode: TLabel + Left = 0 + Top = 0 + Width = 35 + Height = 22 + Align = alLeft + Caption = 'Show:' + Layout = tlCenter + ExplicitHeight = 14 + end + object cbbJumplistShowMode: TComboBox + Left = 208 + Top = 0 + Width = 163 + Height = 22 + Align = alRight + Style = csDropDownList + TabOrder = 0 + OnChange = Changed + Items.Strings = ( + 'Disabled' + 'Mouse right-click') + end end end object tsAbout: TTabSheet Caption = 'About' ImageIndex = 1 - ExplicitLeft = 0 - ExplicitTop = 0 - ExplicitWidth = 0 - ExplicitHeight = 0 DesignSize = ( - 366 - 441) + 391 + 332) object lblVer: TLabel Left = 8 Top = 8 @@ -650,13 +733,13 @@ object FrmProperties: TFrmProperties object lblSysInfo: TLabel Left = 8 Top = 135 - Width = 347 - Height = 60 + Width = 372 + Height = 70 Anchors = [akLeft, akTop, akRight] AutoSize = False - Caption = 'lblSysInfo' + Caption = 'lblSysInfo'#13#10'1'#13#10'2'#13#10'3'#13#10'4' + PopupMenu = pmSysInfo WordWrap = True - ExplicitWidth = 361 end object linkEmail: TLinkLabel Left = 46 @@ -681,8 +764,8 @@ object FrmProperties: TFrmProperties end end object btnApply: TButton - Left = 298 - Top = 488 + Left = 324 + Top = 374 Width = 80 Height = 25 Anchors = [akTop, akRight] @@ -691,8 +774,8 @@ object FrmProperties: TFrmProperties OnClick = DialogButtonClick end object btnCancel: TButton - Left = 214 - Top = 488 + Left = 240 + Top = 374 Width = 80 Height = 25 Anchors = [akTop, akRight] @@ -712,4 +795,12 @@ object FrmProperties: TFrmProperties TabOrder = 1 OnClick = DialogButtonClick end + object pmSysInfo: TPopupMenu + Left = 168 + Top = 80 + object imCopy: TMenuItem + Caption = 'Copy' + OnClick = imCopyClick + end + end end diff --git a/src/Linkbar.Settings.pas b/src/Linkbar.Settings.pas index d0ab94e..f9e292f 100644 --- a/src/Linkbar.Settings.pas +++ b/src/Linkbar.Settings.pas @@ -11,12 +11,13 @@ interface uses Windows, SysUtils, Classes, Forms, StdCtrls, NewSpin, ExtCtrls, Controls, mUnit, - Vcl.ComCtrls, Winapi.Messages, Vcl.Buttons, ColorPicker, VCLTee.TeCanvas; + Vcl.ComCtrls, Winapi.Messages, Vcl.Buttons, ColorPicker, VCLTee.TeCanvas, + Vcl.Menus, HotKey; type TFrmProperties = class(TForm) pgc1: TPageControl; - tsOptions: TTabSheet; + tsView: TTabSheet; tsAbout: TTabSheet; lblScreenEdge: TLabel; lblIconSize: TLabel; @@ -52,7 +53,7 @@ TFrmProperties = class(TForm) lblSection2: TLabel; lblSection1: TLabel; pnlDummy8: TPanel; - lbl1: TLabel; + lblShow: TLabel; cbbAutoShowMode: TComboBox; pnlDummy7: TPanel; lbl2: TLabel; @@ -64,8 +65,8 @@ TFrmProperties = class(TForm) chbLightStyle: TCheckBox; chbAeroGlass: TCheckBox; lblSysInfo: TLabel; - pnlDummy9: TPanel; - Label3: TLabel; + pnlDelay: TPanel; + lblDelay: TLabel; nseAutoShowDelay: TnSpinEdit; pnlDummy10: TPanel; btnBgColorShowHide: TSpeedButton; @@ -75,13 +76,23 @@ TFrmProperties = class(TForm) chbUseTxtColor: TCheckBox; bvlSpacer2: TBevel; bvlSpacer3: TBevel; - bvlSpacer1: TBevel; - bvlSpacer4: TBevel; pnlDummy12: TPanel; lblGlowSize: TLabel; - bvlSpacer5: TBevel; nseGlowSize: TnSpinEdit; clbTextColor: TColorBox; + pmSysInfo: TPopupMenu; + imCopy: TMenuItem; + pnlLightStyle: TPanel; + pnlHotkey: TPanel; + lblHotKey: TLabel; + pnlHotkeyEdit: TPanel; + tsAutohide: TTabSheet; + pnlJumplistShowMode: TPanel; + lblJumplistShowMode: TLabel; + cbbJumplistShowMode: TComboBox; + lblJumplist: TLabel; + pnlDummy13: TPanel; + chbStayOnTop: TCheckBox; procedure FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean); procedure linkEmailLinkClick(Sender: TObject; const Link: string; @@ -89,7 +100,7 @@ TFrmProperties = class(TForm) procedure linkWebLinkClick(Sender: TObject; const Link: string; LinkType: TSysLinkType); procedure DialogButtonClick(Sender: TObject); - procedure OptionsChanged(Sender: TObject); + procedure Changed(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure btnCancelClick(Sender: TObject); @@ -97,6 +108,7 @@ TFrmProperties = class(TForm) procedure SpeedButton2Click(Sender: TObject); procedure edtColorBgKeyPress(Sender: TObject; var Key: Char); procedure edtColorBgChange(Sender: TObject); + procedure imCopyClick(Sender: TObject); protected procedure CreateParams(var Params: TCreateParams); override; procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; @@ -105,9 +117,12 @@ TFrmProperties = class(TForm) FColorPicker: TfrmColorPicker; FBackgroundColor: Cardinal; FTextColor: Cardinal; + edtHotKey: THotKeyEdit; + FCanChanged: Boolean; procedure SetBackgroundColor(AValue: Cardinal); procedure SetTextColor(AValue: Cardinal); function ScaleDimension(const X: Integer): Integer; + procedure L10n; public constructor Create(AOwner: TLinkbarWcl); reintroduce; property BackgroundColor: Cardinal read FBackgroundColor write SetBackgroundColor; @@ -123,7 +138,7 @@ implementation uses Math, Graphics, Linkbar.Consts, Linkbar.OS, Linkbar.Shell, Linkbar.Themes, - Linkbar.Loc, Linkbar.Common; + Linkbar.L10n, Linkbar.Common, Vcl.Clipbrd; function TFrmProperties.ScaleDimension(const X: Integer): Integer; begin @@ -150,14 +165,25 @@ procedure TFrmProperties.CreateParams(var Params: TCreateParams); constructor TFrmProperties.Create(AOwner: TLinkbarWcl); var - lang: TLanguages; maxlabelwidth, ctrlwidth, y1: integer; VO1, VO2, VO3: Integer; begin + FCanChanged := False; + inherited Create(AOwner); + FLinkbar := AOwner; Font.Name := Screen.MenuFont.Name; - LbTranslateComponent(Self); + + // Create editors + edtHotKey := THotKeyEdit.Create(pnlHotkeyEdit); + edtHotKey.Parent := pnlHotkeyEdit; + edtHotKey.Align := alClient; + edtHotKey.OnChange := Changed; + FColorPicker := TfrmColorPicker.Create(Self); + FColorPicker.Font := Font; + + L10n; ReduceSysMenu(Handle); @@ -165,8 +191,6 @@ constructor TFrmProperties.Create(AOwner: TLinkbarWcl); VO2 := ScaleDimension(9); VO3 := ScaleDimension(12); - FLinkbar := AOwner; - pgc1.ActivePageIndex := 0; maxlabelwidth := 0; @@ -185,7 +209,7 @@ constructor TFrmProperties.Create(AOwner: TLinkbarWcl); lblVer.Font := lblSection1.Font; // --------------------------------------------------------------------------- - // Page Options + // Page View // --------------------------------------------------------------------------- // Position on screen -------------------------------------------------------- pnlDummy1.Top := lblSection1.BoundsRect.Bottom + VO1; @@ -201,10 +225,6 @@ constructor TFrmProperties.Create(AOwner: TLinkbarWcl); pnlDummy10.Top := pnlDummy2.BoundsRect.Bottom + VO1; pnlDummy10.Height := pnlDummy1.Height; - FColorPicker := TfrmColorPicker.Create(Self); - FColorPicker.Font := Font; - LbTranslateComponent(FColorPicker); - // Margins ------------------------------------------------------------------- pnlDummy3.Top := pnlDummy10.BoundsRect.Bottom + VO1; pnlDummy3.Height := pnlDummy1.Height; @@ -248,7 +268,14 @@ constructor TFrmProperties.Create(AOwner: TLinkbarWcl); nseGlowSize.MaxValue := GLOW_SIZE_MAX; nseGlowSize.Value := FLinkbar.GlowSize; - lblSection2.Top := pnlDummy12.BoundsRect.Bottom + VO1*2; + pnlDummy13.Top := pnlDummy12.BoundsRect.Bottom + VO1; + pnlDummy13.Height := pnlDummy1.Height; + + // --------------------------------------------------------------------------- + // Page AutoHide + // --------------------------------------------------------------------------- + + //lblSection2.Top := pnlDummy12.BoundsRect.Bottom + VO1*2; pnlDummy7.Top := lblSection2.BoundsRect.Bottom + VO1; pnlDummy7.Height := pnlDummy1.Height; @@ -256,32 +283,39 @@ constructor TFrmProperties.Create(AOwner: TLinkbarWcl); pnlDummy8.Top := pnlDummy7.BoundsRect.Bottom + VO1; pnlDummy8.Height := pnlDummy1.Height; - pnlDummy9.Top := pnlDummy8.BoundsRect.Bottom + VO1; - pnlDummy9.Height := pnlDummy1.Height; + pnlDelay.Top := pnlDummy8.BoundsRect.Bottom + VO1; + pnlDelay.Height := pnlDummy1.Height; + + pnlHotkey.Top := pnlDelay.BoundsRect.Bottom + VO1; + pnlHotkey.Height := pnlDummy1.Height; - chbAutoHideTransparency.Top := pnlDummy9.BoundsRect.Bottom + VO3; + pnlHotkeyEdit.Top := pnlHotkey.BoundsRect.Bottom + VO1; + pnlHotkeyEdit.Height := pnlDummy1.Height; + + chbAutoHideTransparency.Top := pnlHotkeyEdit.BoundsRect.Bottom + VO3; // --------------------------------------------------------------------------- // Page Additionally // --------------------------------------------------------------------------- + lblJumplist.Font := lblSection1.Font; + pnlJumplistShowMode.Top := lblJumplist.BoundsRect.Bottom + VO1; + pnlJumplistShowMode.Height := pnlDummy1.Height; lblSectionWin7.Font := lblSection1.Font; - if LbLongLang - then chbLightStyle.Height := chbLightStyle.Height * 2; - chbLightStyle.Top := lblSectionWin7.BoundsRect.Bottom + VO1; - chbLightStyle.Hint := chbLightStyle.Caption; - chbLightStyle.ShowHint := True; + lblSectionWin7.Top := pnlJumplistShowMode.BoundsRect.Bottom + VO1*2; + pnlLightStyle.Top := lblSectionWin7.BoundsRect.Bottom + VO1; lblSectionWin8.Font := lblSection1.Font; - lblSectionWin8.Top := chbLightStyle.BoundsRect.Bottom + VO1*2; + lblSectionWin8.Top := pnlLightStyle.BoundsRect.Bottom + VO1*2; chbAeroGlass.Top := lblSectionWin8.BoundsRect.Bottom + VO1; - pgc1.Height := tsOptions.Top + chbAutoHideTransparency.BoundsRect.Bottom - + VO2 + tsOptions.Left; + pgc1.Height := tsView.Top + pnlDummy13.BoundsRect.Bottom + + VO2 + tsView.Left; btnOk.Top := pgc1.BoundsRect.Bottom + ScaleDimension(8); btnCancel.Top := btnOk.Top; btnApply.Top := btnOk.Top; - ClientWidth := maxlabelwidth + ctrlwidth + (pnlDummy1.Left + tsOptions.Left + pgc1.Left) * 2; + // Calc Client Width & Height + ClientWidth := maxlabelwidth + ctrlwidth + (pnlDummy1.Left + tsView.Left + pgc1.Left) * 2; if IsWindows7 then y1 := 5 else y1 := 8; ClientHeight := btnOk.BoundsRect.Bottom + ScaleDimension(y1); @@ -297,17 +331,18 @@ constructor TFrmProperties.Create(AOwner: TLinkbarWcl); cbbAutoShowMode.ItemIndex := Ord(FLinkbar.AutoShowMode); nseAutoShowDelay.Value := FLinkbar.AutoShowDelay; chbLightStyle.Checked := FLinkbar.IsLightStyle; - chbUseBkgColor.Checked := FLinkbar.UseBkgColor; chbUseTxtColor.Checked := FLinkbar.UseTxtColor; + cbbJumplistShowMode.ItemIndex := Ord(FLinkbar.JumplistShowMode); + chbStayOnTop.Checked := FLinkbar.StayOnTop; + + edtHotKey.HotkeyInfo := FLinkbar.HotkeyInfo; BackgroundColor := FLinkbar.BkgColor; TextColor := FLinkbar.TxtColor; chbAeroGlass.Checked := FLinkbar.EnableAeroGlass; - OptionsChanged(nil); - { Disable OS-dependent options } // Windows 7 lblSectionWin7.Enabled := IsWindows7; @@ -316,20 +351,70 @@ constructor TFrmProperties.Create(AOwner: TLinkbarWcl); lblSectionWin8.Enabled := IsWindows8And8Dot1; chbAeroGlass.Enabled := IsWindows8And8Dot1; - lblVer.Caption := lblVer.Caption + ' ' + VersionToString; + lblVer.Caption := Format(lblVer.Caption, [VersionToString]); linkWeb.Caption := '' + URL_WEB + ''; linkEmail.Caption := '' + URL_EMAIL + ''; - lang := TLanguages.Create; lblSysInfo.Caption := TOSVersion.ToString - + '; LCID ' - + IntToStr(lang.UserDefaultLocale) + ' (' + IntToHex(lang.UserDefaultLocale, 3) + ')' - + ' ' + lang.NameFromLocaleID[lang.UserDefaultLocale]; - lang.Free; + + ' ' + Languages.LocaleName[Languages.IndexOf(Languages.UserDefaultLocale)] + + ' ' + IntToStr(Languages.UserDefaultLocale) + + ' (' + IntToHex(Languages.UserDefaultLocale, 3) + ')' + + ' ' + Languages.NameFromLocaleID[Languages.UserDefaultLocale]; + FCanChanged := True; + Changed(nil); btnApply.Enabled := False; end; +procedure TFrmProperties.L10n; +begin + // Tabs + L10nControl(tsView, 'Properties.View'); + L10nControl(tsAutoHide, 'Properties.PageAutoHide'); + L10nControl(tsAdditionally, 'Properties.Additional'); + L10nControl(tsAbout, 'Properties.About'); + // View + L10nControl(lblSection1, 'Properties.Appearance'); + L10nControl(lblScreenEdge, 'Properties.Position'); + L10nControl(cbbScreenPosition, ['Properties.Left', 'Properties.Top', 'Properties.Right', 'Properties.Bottom']); + L10nControl(lblIconSize, 'Properties.IconSize'); + L10nControl(chbUseBkgColor, 'Properties.BgColor'); + L10nControl(lblMargin, 'Properties.Margins'); + L10nControl(lblOrder, 'Properties.Order'); + L10nControl(cbbItemOrder, ['Properties.LtR', 'Properties.UtD']); + L10nControl(Label1, 'Properties.TextPos'); + L10nControl(cbbTextLayout, ['Properties.Without' , 'Properties.Left', 'Properties.Top', 'Properties.Right', 'Properties.Bottom']); + L10nControl(Label6, 'Properties.TextWidth'); + L10nControl(chbUseTxtColor, 'Properties.TextColor'); + L10nControl(lblGlowSize, 'Properties.GlowSize'); + L10nControl(chbStayOnTop, 'Properties.AlwaysOnTop'); + // Autohide + L10nControl(lblSection2, 'Properties.AutoHide'); + L10nControl(lbl2, 'Properties.Hide'); + L10nControl(chbAutoHide, 'Properties.Automatically'); + L10nControl(lblShow, 'Properties.Show'); + L10nControl(cbbAutoShowMode, ['Properties.MouseHover', 'Properties.MouseLC', 'Properties.MouseRC']); + L10nControl(lblDelay, 'Properties.Delay'); + L10nControl(lblHotKey, 'Properties.HotKey'); + L10nControl(chbAutoHideTransparency, 'Properties.Transparent'); + // Additional + L10nControl(lblJumplist, 'Properties.Jumplists'); + L10nControl(lblJumplistShowMode, 'Properties.Show'); + L10nControl(cbbJumplistShowMode, ['Properties.No', 'Properties.MouseRC']); + L10nControl(lblSectionWin7, 'Properties.ForW7'); + L10nControl(chbLightStyle, 'Properties.Style1'); + L10nControl(lblSectionWin8, 'Properties.ForW8'); + L10nControl(chbAeroGlass, 'Properties.AeroGlass'); + // About + L10nControl(lblVer, 'Properties.Version'); + L10nControl(lblLocalizer, 'Properties.Localizer'); + L10nControl(Label2, 'Properties.SystemInfo'); + // Buttons + L10nControl(btnOk, 'Properties.Ok'); + L10nControl(btnCancel, 'Properties.Cancel'); + L10nControl(btnApply, 'Properties.Apply'); +end; + procedure TFrmProperties.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := caFree; @@ -358,12 +443,17 @@ procedure TFrmProperties.FormMouseWheel(Sender: TObject; Shift: TShiftState; end; end; +procedure TFrmProperties.imCopyClick(Sender: TObject); +begin + Clipboard.AsText := lblSysInfo.Caption; +end; + procedure TFrmProperties.linkEmailLinkClick(Sender: TObject; const Link: string; LinkType: TSysLinkType); begin if not SendShellEmail(Application.Handle, URL_EMAIL, APP_NAME_LINKBAR, - 'Version: ' + VersionToString + lblVer.Caption + '%0D%0A' + 'OS: ' + lblSysInfo.Caption) then begin end; @@ -375,8 +465,11 @@ procedure TFrmProperties.linkWebLinkClick(Sender: TObject; const Link: string; LBShellExecute(0, 'open', URL_WEB); end; -procedure TFrmProperties.OptionsChanged(Sender: TObject); +procedure TFrmProperties.Changed(Sender: TObject); begin + if (not FCanChanged) + then Exit; + btnApply.Enabled := True; // Color additional options @@ -387,15 +480,25 @@ procedure TFrmProperties.OptionsChanged(Sender: TObject); // Autohide additional options cbbAutoShowMode.Enabled := chbAutoHide.Checked; chbAutoHideTransparency.Enabled := chbAutoHide.Checked; - lbl1.Enabled := chbAutoHide.Checked; - Label3.Enabled := chbAutoHide.Checked - and (TAutoShowMode(cbbAutoShowMode.ItemIndex)= smMouseHover); - nseAutoShowDelay.Enabled := Label3.Enabled; + lblShow.Enabled := chbAutoHide.Checked; + // Mouse-Hover Delay + lblDelay.Enabled := chbAutoHide.Checked; + nseAutoShowDelay.Enabled := lblDelay.Enabled; + // Hotkey + lblHotKey.Enabled := chbAutoHide.Checked; + edtHotKey.Enabled := lblHotKey.Enabled; // Text additional options Label6.Enabled := cbbTextLayout.ItemIndex > 0; nseTextWidth.Enabled := cbbTextLayout.ItemIndex > 0; nseTextOffset.Enabled := cbbTextLayout.ItemIndex > 0; + + // Check Hotkey + if ((Sender = edtHotKey) and (FLinkbar.HotkeyInfo <> edtHotKey.HotkeyInfo)) + or + ((Sender = chbAutoHide) and chbAutoHide.Checked) + then CheckHotkey(Handle, edtHotKey.HotkeyInfo); + end; procedure TFrmProperties.btnCancelClick(Sender: TObject); @@ -441,6 +544,8 @@ procedure TFrmProperties.DialogButtonClick(Sender: TObject); EnsureRange(nseMarginV.Value, MARGIN_MIN, MARGIN_MAX) ); FLinkbar.AutoHideTransparency := chbAutoHideTransparency.Checked; + FLinkbar.JumplistShowMode := TJumplistShowMode(cbbJumplistShowMode.ItemIndex); + FLinkbar.StayOnTop := chbStayOnTop.Checked; FLinkbar.UpdateItemSizes; @@ -450,6 +555,8 @@ procedure TFrmProperties.DialogButtonClick(Sender: TObject); if (temp_ah = FLinkbar.AutoHide) then FLinkbar.AutoHide := chbAutohide.Checked; + FLinkbar.HotkeyInfo := edtHotKey.HotkeyInfo; + if (Sender = btnOk) then begin Close; @@ -469,7 +576,7 @@ procedure TFrmProperties.edtColorBgChange(Sender: TObject); if (Sender = clbTextColor) then FTextColor := clbTextColor.Selected; - OptionsChanged(Sender); + Changed(Sender); end; procedure TFrmProperties.edtColorBgKeyPress(Sender: TObject; var Key: Char); diff --git a/src/Linkbar.Shell.pas b/src/Linkbar.Shell.pas index 8311b24..9f129d4 100644 --- a/src/Linkbar.Shell.pas +++ b/src/Linkbar.Shell.pas @@ -47,7 +47,7 @@ interface implementation -uses Linkbar.OS, Linkbar.Consts, Linkbar.Loc, StrUtils, Graphics; +uses StrUtils, Graphics, Linkbar.OS, Linkbar.Consts, Linkbar.L10n; type TSHExtractIconsW = function(pszFileName: LPCWSTR; nIconIndex: Integer; cxIcon, @@ -263,7 +263,7 @@ function NewShortcut(const APath: string): HRESULT; cmd: string; begin Result := S_FALSE; - lnkname := MUILoadResString(GetModuleHandle(LB_FN_NEWSHORTCUT), LB_RS_NSC_FILENAME); + lnkname := L10nMui(GetModuleHandle(LB_FN_NEWSHORTCUT), LB_RS_NSC_FILENAME); if PathMakeUniqueName(filename, MAX_PATH, 'scut.lnk', PChar(lnkname + '.lnk'), PChar(APath)) then begin hFile := CreateFile(filename, GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); diff --git a/src/Linkbar.Themes.pas b/src/Linkbar.Themes.pas index 4fff65d..6e4e255 100644 --- a/src/Linkbar.Themes.pas +++ b/src/Linkbar.Themes.pas @@ -96,7 +96,7 @@ procedure ThemeSetWindowAttribute(AWnd: HWND); if IsWindows10 then begin // Set window accent policy - // http://withinrafael.com/adding-the-aero-glass-blur-to-your-windows-10-apps/ + // https://withinrafael.com/2015/07/08/adding-the-aero-glass-blur-to-your-windows-10-apps/ if Assigned(UDwmSetWindowCompositionAttributeProc) then begin AccentPolicy.AccentState := U_WCA_ACCENT_STATE_ENABLE_BLURBEHIND; diff --git a/src/Linkbar.dpr b/src/Linkbar.dpr index 9255960..0095e01 100644 --- a/src/Linkbar.dpr +++ b/src/Linkbar.dpr @@ -8,8 +8,6 @@ program Linkbar; {$i linkbar.inc} uses - Linkbar.ResStr, // If this unit not place first then 32- and 64-bit verision have - // different resource string identificator Windows, SysUtils, Forms, @@ -24,7 +22,7 @@ uses mUnit in 'mUnit.pas', Linkbar.Newbar, Linkbar.Shell, - Linkbar.Loc, + Linkbar.L10n, Linkbar.Settings in 'Linkbar.Settings.pas' {FrmProperties}; {$R *.res} @@ -71,9 +69,8 @@ begin //----------------------- // Apply localization //----------------------- - if FindCmdLineSwitch(CLK_LANG, cmd, True) - then LbTranslateInit( StrToIntDef(cmd, 0) ) - else LbTranslateInit(0); + FindCmdLineSwitch(CLK_LANG, cmd, True); + L10nLoad(ExtractFilePath(ParamStr(0)) + DN_LOCALES, cmd); if FindCmdLineSwitch(CLK_NEW, True) then begin @@ -129,10 +126,11 @@ begin Continue; end; - LBCreateProcess(ParamStr(0), - LBCreateCommandParam(CLK_LANG, IntToStr(LbLangID)) - + LBCreateCommandParam(CLK_FILE, sl[i]) - ); + cmd := LBCreateCommandParam(CLK_FILE, sl[i]); + if (Locale <> '') + then cmd := LBCreateCommandParam(CLK_LANG, Locale) + cmd; + + LBCreateProcess(ParamStr(0), cmd); Inc(CreatedPanels); end; diff --git a/src/mUnit.dfm b/src/mUnit.dfm index 9518464..f8b3158 100644 --- a/src/mUnit.dfm +++ b/src/mUnit.dfm @@ -12,10 +12,10 @@ object LinkbarWcl: TLinkbarWcl Font.Style = [] FormStyle = fsStayOnTop OldCreateOrder = False - Position = poDefault OnContextPopup = FormContextPopup OnCreate = FormCreate OnDestroy = FormDestroy + OnKeyDown = FormKeyDown OnMouseDown = FormMouseDown OnMouseEnter = FormMouseEnter OnMouseLeave = FormMouseLeave @@ -59,10 +59,10 @@ object LinkbarWcl: TLinkbarWcl GroupIndex = 2 OnClick = imLockBarClick end - object imSortAlphabetically: TMenuItem + object imSortAlphabet: TMenuItem Caption = 'Sort alphabetically' GroupIndex = 2 - OnClick = imSortAlphabeticallyClick + OnClick = imSortAlphabetClick end object imProperties: TMenuItem Caption = 'Properties' diff --git a/src/mUnit.pas b/src/mUnit.pas index ab7c13e..e0012bd 100644 --- a/src/mUnit.pas +++ b/src/mUnit.pas @@ -14,7 +14,7 @@ interface Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, System.UITypes, IniFiles, Menus, Vcl.ExtCtrls, Winapi.ShlObj, DDForms, Cromis.DirectoryWatch, - AccessBar, LBToolbar, Linkbar.Consts, Linkbar.Hint, Linkbar.Taskbar; + AccessBar, LBToolbar, Linkbar.Consts, Linkbar.Hint, Linkbar.Taskbar, HotKey; type @@ -32,7 +32,7 @@ TLinkbarWcl = class(TLinkbarCustomFrom) imOpenWorkdir: TMenuItem; imLockBar: TMenuItem; N3: TMenuItem; - imSortAlphabetically: TMenuItem; + imSortAlphabet: TMenuItem; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormMouseDown(Sender: TObject; Button: TMouseButton; @@ -53,7 +53,8 @@ TLinkbarWcl = class(TLinkbarCustomFrom) procedure imLockBarClick(Sender: TObject); procedure FormContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); - procedure imSortAlphabeticallyClick(Sender: TObject); + procedure imSortAlphabetClick(Sender: TObject); + procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); private CBmpSelectedItem: TBitmap; CBmpDropPosition: TBitmap; @@ -78,13 +79,17 @@ TLinkbarWcl = class(TLinkbarCustomFrom) FButtonCenter: TPoint; FGripSize: Integer; FHintShow: Boolean; + FHotkeyInfo: THotkeyInfo; + FHotkeyPressed: Boolean; FItemMargin: TSize; FIconSize: Integer; FIsLightStyle: Boolean; FItemOrder: TItemOrder; + FJumplistShowMode: TJumplistShowMode; FLockLinkbar: Boolean; FLockHotIndex: Boolean; FSortAlphabetically: Boolean; + FStayOnTop: Boolean; FBkgColor: Cardinal; FTxtColor: Cardinal; FUseBkgColor: Boolean; @@ -97,12 +102,15 @@ TLinkbarWcl = class(TLinkbarCustomFrom) FTextHeight: Integer; FIconOffset: TPoint; FTextRect: TRect; + IconsInLine, IconLinesCount: integer; + FPrevForegroundWnd: HWND; procedure UpdateWindowSize; procedure SetScreenAlign(AValue: TScreenAlign); procedure SetAutoHide(AValue: Boolean); procedure SetItemOrder(AValue: TItemOrder); procedure SetPressedIndex(AValue: integer); procedure SetHotIndex(AValue: integer); + procedure SetHotkeyInfo(AValue: THotkeyInfo); procedure SetButtonSize(AValue: TSize); procedure SetIconSize(AValue: integer); procedure SetIsLightStyle(AValue: Boolean); @@ -111,6 +119,7 @@ TLinkbarWcl = class(TLinkbarCustomFrom) procedure SetTextOffset(AValue: Integer); procedure SetTextWidth(AValue: Integer); procedure SetSortAlphabetically(AValue: Boolean); + procedure SetStayOnTop(AValue: Boolean); function GetScreenAlign: TScreenAlign; procedure DrawBackground(const ABitmap: TBitmap; const AClipRect: TRect); procedure DrawCaption(const ABitmap: TBitmap; const AIndex: Integer; @@ -128,6 +137,7 @@ TLinkbarWcl = class(TLinkbarCustomFrom) function CheckItem(AIndex: Integer): Boolean; function ScaleDimension(const X: Integer): Integer; inline; private + procedure L10n; procedure LoadProperties(const AFileName: string); procedure SaveProperties; private @@ -152,6 +162,7 @@ TLinkbarWcl = class(TLinkbarCustomFrom) var AWidth, AHeight: Integer); procedure QuerySizedEvent(Sender: TObject; const AX, AY, AWidth, AHeight: Integer); procedure QueryHideEvent(Sender: TObject; AEnabled: boolean); + function IsItemIndex(const AIndex: Integer): Boolean; private FRemoved: boolean; procedure DoPopupMenuItemExecute(const ACmd: Integer); @@ -175,6 +186,8 @@ TLinkbarWcl = class(TLinkbarCustomFrom) procedure CreateParams(var Params: TCreateParams); override; procedure CreateWnd; override; procedure WndProc(var Msg: TMessage); override; + procedure WmHotKey(var Msg: TMessage); message WM_HOTKEY; + procedure CMDialogKey(var Msg: TCMDialogKey); message CM_DIALOGKEY; protected FAutoHiden: Boolean; FCanAutoHide: Boolean; @@ -183,8 +196,8 @@ TLinkbarWcl = class(TLinkbarCustomFrom) FAfterAutoHideBound: TRect; FAutoShowDelay: Integer; procedure DoAutoHide; - procedure _DoAutoShow; - procedure _DoDelayedAutoShow; + procedure DoAutoShow; + procedure DoDelayedAutoShow; procedure OnFormJumplistDestroy(Sender: TObject); public procedure UpdateItemSizes; @@ -193,10 +206,12 @@ TLinkbarWcl = class(TLinkbarCustomFrom) property AutoHideTransparency: Boolean read FAutoHideTransparency write FAutoHideTransparency; property AutoShowMode: TAutoShowMode read FAutoShowMode write FAutoShowMode; property ButtonSize: TSize read FButtonSize write SetButtonSize; + property HotkeyInfo: THotkeyInfo read FHotkeyInfo write SetHotkeyInfo; property ItemMargin: TSize read FItemMargin write SetItemMargin; property IconSize: Integer read FIconSize write SetIconSize; property IsLightStyle: Boolean read FIsLightStyle write SetIsLightStyle; property ItemOrder: TItemOrder read FItemOrder write SetItemOrder; + property JumplistShowMode: TJumplistShowMode read FJumplistShowMode write FJumplistShowMode; property TextLayout: TTextLayout read FTextLayout write SetTextLayout; property TextOffset: Integer read FTextOffset write SetTextOffset; property TextWidth: Integer read FTextWidth write SetTextWidth; @@ -211,6 +226,7 @@ TLinkbarWcl = class(TLinkbarCustomFrom) property UseBkgColor: Boolean read FUseBkgColor write FUseBkgColor; property UseTxtColor: Boolean read FUseTxtColor write FUseTxtColor; property GlowSize: Integer read FGlowSize write FGlowSize; + property StayOnTop: Boolean read FStayOnTop write SetStayOnTop; private FEnableAeroGlass: Boolean; procedure SetEnableAeroGlass(AValue: Boolean); @@ -222,8 +238,6 @@ TLinkbarWcl = class(TLinkbarCustomFrom) var LinkbarWcl: TLinkbarWcl; - IconsInLine, - IconLinesCount: integer; FPreferencesFileName: string; implementation @@ -233,7 +247,7 @@ implementation uses Types, Math, Dialogs, StrUtils, ExplorerMenu, Linkbar.Settings, Linkbar.Shell, Linkbar.Themes, Linkbar.OS, JumpLists.Api, JumpLists.Form, - Linkbar.ResStr, Linkbar.Loc, RenameDialog, + Linkbar.L10n, RenameDialog, Themes; const @@ -242,6 +256,7 @@ implementation WM_LB_SHELLNOTIFY = WM_USER + 88; TIMER_AUTO_SHOW = 15; + TIMER_AUTO_HIDE = 16; function IsValidPreferenceFile(const AFileName: string): Boolean; var ini: TMemIniFile; @@ -355,7 +370,9 @@ function TLinkbarWcl.CheckItem(AIndex: Integer): Boolean; Result := FileExists(fn); if not Result then begin - if MessageDlg( RS_FILENOTFOUND + #13 + fn + #13 + RS_Q_DELETELINK, + if MessageDlg( L10NFind('Message.FileNotFound', 'File does not exists') + + #13 + fn + #13 + + L10NFind('Message.DeleteShortcut', 'Delete shortcut?'), mtConfirmation, [mbOK, mbCancel], 0, mbCancel) = mrOk then begin Items.Delete(AIndex); @@ -704,6 +721,7 @@ procedure TLinkbarWcl.LoadProperties(const AFileName: string); DEF_AUTOHIDE_TRANSPARENCY); FAutoShowMode := TAutoShowMode(IniFile.ReadInteger(INI_SECTION_MAIN, INI_AUTOHIDE_SHOWMODE, DEF_AUTOHIDE_SHOWMODE)); + FHotkeyInfo.Create( IniFile.ReadString(INI_SECTION_MAIN, INI_AUTOHIDE_HOTKEY, DEF_AUTOHIDE_HOTKEY) ); FIconSize := IniFile.ReadInteger(INI_SECTION_MAIN, INI_ICON_SIZE, DEF_ICON_SIZE); FItemMargin.cx := IniFile.ReadInteger(INI_SECTION_MAIN, INI_MARGINX, DEF_MARGINX); FItemMargin.cy := IniFile.ReadInteger(INI_SECTION_MAIN, INI_MARGINY, DEF_MARGINY); @@ -729,6 +747,8 @@ procedure TLinkbarWcl.LoadProperties(const AFileName: string); FGlowSize := IniFile.ReadInteger(INI_SECTION_MAIN, INI_GLOWSIZE, DEF_GLOWSIZE); FHintShow := IniFile.ReadBool(INI_SECTION_DEV, INI_HINT_SHOW, DEF_HINT_SHOW); + StayOnTop := IniFile.ReadBool(INI_SECTION_MAIN, INI_STAYONTOP, DEF_STAYONTOP); + FJumplistShowMode := TJumplistShowMode(IniFile.ReadInteger(INI_SECTION_MAIN, INI_JUMPLISTSHOWMODE, DEF_JUMPLISTSHOWMODE)); finally IniFile.Free; end; @@ -739,6 +759,7 @@ procedure TLinkbarWcl.LoadProperties(const AFileName: string); FAutoHide := DEF_AUTOHIDE; FAutoHideTransparency := DEF_AUTOHIDE_TRANSPARENCY; FAutoShowMode := TAutoShowMode(DEF_AUTOHIDE_SHOWMODE); + FHotkeyInfo.Create(DEF_AUTOHIDE_HOTKEY); FIconSize := DEF_ICON_SIZE; FItemMargin := TSize.Create(DEF_MARGINX, DEF_MARGINY); @@ -758,6 +779,8 @@ procedure TLinkbarWcl.LoadProperties(const AFileName: string); FAutoShowDelay := DEF_AUTOSHOW_DELAY; FSortAlphabetically := DEF_SORT_AB; + StayOnTop := DEF_STAYONTOP; + FJumplistShowMode := TJumplistShowMode(DEF_JUMPLISTSHOWMODE); end; { Check values } @@ -770,7 +793,10 @@ procedure TLinkbarWcl.LoadProperties(const AFileName: string); // Screen edge if ( FScreenEdge < Low(TScreenAlign) ) or ( FScreenEdge > High(TScreenAlign) ) then FScreenEdge := TScreenAlign(DEF_EDGE); - + // Jumplists + if ( FJumplistShowMode < Low(TJumplistShowMode) ) or ( FJumplistShowMode > High(TJumplistShowMode) ) + then FJumplistShowMode := TJumplistShowMode(DEF_JUMPLISTSHOWMODE); + FIconSize := EnsureRange(FIconSize, ICON_SIZE_MIN, ICON_SIZE_MAX); FItemMargin.cx := EnsureRange(FItemMargin.cx, MARGIN_MIN, MARGIN_MAX); FItemMargin.cy := EnsureRange(FItemMargin.cy, MARGIN_MIN, MARGIN_MAX); @@ -801,6 +827,10 @@ procedure TLinkbarWcl.LoadProperties(const AFileName: string); FDragingItem := False; ExpAeroGlassEnabled := FEnableAeroGlass; + + // Register Hotkey + if (AutoHide) + then RegisterHotkeyNotify(Handle, FHotkeyInfo); end; procedure TLinkbarWcl.SaveProperties; @@ -840,6 +870,7 @@ procedure TLinkbarWcl.SaveProperties; IniFile.WriteBool(INI_SECTION_MAIN, INI_AUTOHIDE, AutoHide); IniFile.WriteBool(INI_SECTION_MAIN, INI_AUTOHIDE_TRANSPARENCY, FAutoHideTransparency); IniFile.WriteInteger(INI_SECTION_MAIN, INI_AUTOHIDE_SHOWMODE, Integer(AutoShowMode)); + IniFile.WriteString(INI_SECTION_MAIN, INI_AUTOHIDE_HOTKEY, HotkeyInfo); IniFile.WriteInteger(INI_SECTION_MAIN, INI_ICON_SIZE, IconSize); IniFile.WriteInteger(INI_SECTION_MAIN, INI_MARGINX, ItemMargin.cx); @@ -868,6 +899,10 @@ procedure TLinkbarWcl.SaveProperties; IniFile.WriteInteger(INI_SECTION_MAIN, INI_GLOWSIZE, FGlowSize); + IniFile.WriteBool(INI_SECTION_MAIN, INI_STAYONTOP, FStayOnTop); + // Jumplists + IniFile.WriteInteger(INI_SECTION_MAIN, INI_JUMPLISTSHOWMODE, Integer(JumplistShowMode)); + IniFile.UpdateFile; finally IniFile.Free; @@ -894,7 +929,8 @@ procedure TLinkbarWcl.CreateWnd; procedure TLinkbarWcl.FormCreate(Sender: TObject); begin - LbTranslateComponent(Self); + L10n; + oHint := TTooltip32.Create(Handle); pMenu.Items.RethinkHotkeys; @@ -912,11 +948,10 @@ procedure TLinkbarWcl.FormCreate(Sender: TObject); GetOrCreateFilesList(WorkDir + LINKSLIST_FILE_NAME); - oHint := TTooltip32.Create(Handle); - UpdateItemSizes; oAppBar := TAccessBar.Create2(self, FScreenEdge, FALSE); + oAppBar.StayOnTop := StayOnTop; oAppBar.MonitorNum := FMonitorNum; oAppBar.QuerySizing := QuerySizingEvent; oAppBar.QuerySized := QuerySizedEvent; @@ -928,13 +963,35 @@ procedure TLinkbarWcl.FormCreate(Sender: TObject); BitBucketNotify := RegisterBitBucketNotify(Handle, WM_LB_SHELLNOTIFY); end; +procedure TLinkbarWcl.L10n; +begin + L10nControl(imNewShortcut, 'Menu.Shortcut'); + L10nControl(imOpenWorkdir, 'Menu.Open'); + L10nControl(imAddBar, 'Menu.Create'); + L10nControl(imRemoveBar, 'Menu.Delete'); + L10nControl(imLockBar, 'Menu.Lock'); + L10nControl(imSortAlphabet, 'Menu.Sort'); + L10nControl(imProperties, 'Menu.Properties'); + L10nControl(imClose, 'Menu.Close'); + L10nControl(imCloseAll, 'Menu.CloseAll'); +end; + procedure TLinkbarWcl.FormDestroy(Sender: TObject); begin - StopDirWatch; DeregisterBitBucketNotify(BitBucketNotify); - if not FRemoved + UnregisterHotkeyNotify(Handle); + + if Assigned(FrmProperties) + then FrmProperties.Free; + + oAppBar.Free; + StopDirWatch; + + if (not FRemoved) then SaveProperties; + ThemeCloseData; + if Assigned(oHint) then oHint.Free; if Assigned(BmpMain) then BmpMain.Free; if Assigned(BmpBtn) then BmpBtn.Free; @@ -943,6 +1000,136 @@ procedure TLinkbarWcl.FormDestroy(Sender: TObject); if Assigned(Items) then Items.Free; end; +function TLinkbarWcl.IsItemIndex(const AIndex: Integer): Boolean; +begin + Result := (AIndex >= 0) and (AIndex < Items.Count); +end; + +procedure TLinkbarWcl.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); +begin +{$IFNDEF DEBUG} + //if (Shift <> []) then Exit; +{$ENDIF} + + if (Items.Count = 0) then Exit; + + case Key of + VK_SPACE, VK_RETURN: // Run + begin + if IsItemIndex(HotIndex) + then begin + oHint.Cancel; + DoExecuteItem(HotIndex); + end; + Exit; + end; + VK_ESCAPE: // Deselect + begin + HotIndex := ITEM_NONE; + Exit; + end; + VK_F2: // Rename + begin + if IsItemIndex(HotIndex) + then begin + oHint.Cancel; + DoRenameItem(HotIndex); + end; + Exit; + end; + VK_DELETE: + begin + if IsItemIndex(HotIndex) + then begin + oHint.Cancel; + SHDeleteOp(Handle, Items[HotIndex].FileName, GetKeyState(VK_SHIFT) >= 0); + end; + Exit; + end; + // Arrows + VK_LEFT, VK_RIGHT, VK_DOWN, VK_UP: + begin + // No hot item: + // Left/Up - last + // Right/Down - first + if (HotIndex = ITEM_NONE) + then begin + if (Key in [VK_LEFT, VK_UP]) + then HotIndex := Items.Count-1 + else HotIndex := 0; + Exit; + end; + + // One-line panel: + // Left/Up - prev + // Right/Down - next + if (IconLinesCount = 1) + then begin + if (Key in [VK_LEFT, VK_UP]) + then HotIndex := Max(HotIndex - 1, 0) + else HotIndex := Min(HotIndex + 1, Items.Count-1); + Exit; + end; + + // Multi-line panel: + case Key of + VK_LEFT: + begin + if (ItemOrder = ioLeftToRight) + then HotIndex := Max(HotIndex - 1, 0) + else begin + if (oAppBar.Vertical) + then HotIndex := Max(HotIndex - IconsInLine, 0) + else HotIndex := Max(HotIndex - IconLinesCount, 0); + end; + end; + VK_RIGHT: + begin + if (ItemOrder = ioLeftToRight) + then HotIndex := Min(HotIndex + 1, Items.Count-1) + else begin + if (oAppBar.Vertical) + then HotIndex := Min(HotIndex + IconsInLine, Items.Count-1) + else HotIndex := Min(HotIndex + IconLinesCount, Items.Count-1) + end; + end; + VK_UP: + begin + if (ItemOrder = ioUpToDown) + then HotIndex := Max(HotIndex - 1, 0) + else begin + if (oAppBar.Vertical) + then HotIndex := Max(HotIndex - IconLinesCount, 0) + else HotIndex := Max(HotIndex - IconsInLine, 0) + end; + end; + VK_DOWN: + begin + if (ItemOrder = ioUpToDown) + then HotIndex := Min(HotIndex + 1, Items.Count-1) + else begin + if (oAppBar.Vertical) + then HotIndex := Min(HotIndex + IconLinesCount, Items.Count-1) + else HotIndex := Min(HotIndex + IconsInLine, Items.Count-1) + end; + end; + end; + end; + else + Exit; + end; +end; + +procedure TLinkbarWcl.CMDialogKey(var Msg: TCMDialogKey); +begin + if (Msg.CharCode = VK_TAB) + then begin + HotIndex := HotIndex + 1; + Exit; + end; + inherited; +end; + function TLinkbarWcl.ItemIndexByPoint(const APt: TPoint; const ALastIndex: integer = ITEM_NONE): Integer; var @@ -983,9 +1170,16 @@ procedure TLinkbarWcl.FormMouseDown(Sender: TObject; Button: TMouseButton; end; end; -procedure TLinkbarWcl.FormMouseMove(Sender: TObject; Shift: TShiftState; X, - Y: Integer); +var + prevX: Integer = -MaxInt; + prevY: Integer = -MaxInt; + +procedure TLinkbarWcl.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin + if (X = prevX) and (Y = prevY) + then Exit; + prevX := X; prevY := Y; + if FAutoHiden then Exit; if Self.IsDragDrop then Exit; @@ -1044,8 +1238,9 @@ procedure TLinkbarWcl.FormMouseUp(Sender: TObject; Button: TMouseButton; or ( (AutoShowMode = smMouseClickRight) and (Button = mbRight) ) then begin + if PtInRect(Rect(0,0,Width,Height), Point(X, Y)) - then _DoAutoShow; + then DoAutoShow; end; Exit; end; @@ -1094,7 +1289,7 @@ procedure TLinkbarWcl.DoDragItem(X, Y: Integer); procedure TLinkbarWcl.DoExecuteItem(const AIndex: Integer); begin - if AIndex <> ITEM_NONE + if (AIndex <> ITEM_NONE) then begin if CheckItem(AIndex) then OpenByDefaultVerb(Handle, Items[AIndex].Pidl); @@ -1237,7 +1432,7 @@ procedure TLinkbarWcl.DoPopupMenu(APt: TPoint; AShift: Boolean); and (FLockLinkbar) then Flags := Flags or MF_CHECKED; - if (pMenu.Items[i] = imSortAlphabetically) + if (pMenu.Items[i] = imSortAlphabet) and (FSortAlphabetically) then Flags := Flags or MF_CHECKED; @@ -1320,31 +1515,34 @@ procedure TLinkbarWcl.DoPopupJumplist(APt: TPoint; AShift: Boolean); fjl: TFormJumpList; maxcount: Integer; begin - item := Items[FItemPopup]; - - { Check and show Jumplist } - maxcount := GetJumpListMaxCount; - if (maxcount > 0) - and GetAppInfoForLink(item.Pidl, appid) - and HasJumpList(appid) + if (FJumplistShowMode <> jsmDisabled) then begin - oHint.Cancel; - r := item.Rect; - case ScreenAlign of - saLeft: pt := Point(r.Right, r.Bottom); - saRight: pt := Point(r.Left, r.Bottom); - saTop: pt := Point(r.CenterPoint.X, r.Bottom); - saBottom: pt := Point(r.CenterPoint.X, r.Top); - end; - MapWindowPoints(Handle, 0, pt, 1); - fjl := TFormJumpList.CreateNew(Self); - fjl.OnDestroy := OnFormJumplistDestroy; - if fjl.Popup(Handle, pt.X, pt.Y, JUMPLIST_ALIGN[ScreenAlign], appid, - item.Pidl, maxcount) + item := Items[FItemPopup]; + + { Check and show Jumplist } + maxcount := GetJumpListMaxCount; + if (maxcount > 0) + and GetAppInfoForLink(item.Pidl, appid) + and HasJumpList(appid) then begin - FLockHotIndex := True; - FLockAutoHide := True; - Exit; + oHint.Cancel; + r := item.Rect; + case ScreenAlign of + saLeft: pt := Point(r.Right, r.Bottom); + saRight: pt := Point(r.Left, r.Bottom); + saTop: pt := Point(r.CenterPoint.X, r.Bottom); + saBottom: pt := Point(r.CenterPoint.X, r.Top); + end; + MapWindowPoints(Handle, 0, pt, 1); + fjl := TFormJumpList.CreateNew(Self); + fjl.OnDestroy := OnFormJumplistDestroy; + if fjl.Popup(Handle, pt.X, pt.Y, JUMPLIST_ALIGN[ScreenAlign], appid, + item.Pidl, maxcount) + then begin + FLockHotIndex := True; + FLockAutoHide := True; + Exit; + end; end; end; @@ -1365,8 +1563,10 @@ procedure TLinkbarWcl.FormContextPopup(Sender: TObject; MousePos: TPoint; if (pt.X = -1) and (pt.Y = -1) then begin // Pressed keyboard key "Menu" - pt := Point(0, 0); - FItemPopup := ITEM_NONE; + FItemPopup := HotIndex; + if IsItemIndex(FItemPopup) + then pt := Items[HotIndex].Rect.CenterPoint + else pt := Point(0, 0); end else FItemPopup := ItemIndexByPoint(pt); @@ -1512,6 +1712,9 @@ procedure TLinkbarWcl.SetHotIndex(AValue: integer); HA: TAlignment; VA: TVerticalAlignment; begin + if not IsItemIndex(AValue) + then AValue := ITEM_NONE; + if (FLockHotIndex) or (AValue = FHotIndex) then Exit; @@ -1579,6 +1782,15 @@ procedure TLinkbarWcl.SetHotIndex(AValue: integer); end; end; +procedure TLinkbarWcl.SetHotkeyInfo(AValue: THotkeyInfo); +begin + FHotkeyInfo := AValue; + if (AutoHide) + // (AutoShowMode = smHotKey) + then RegisterHotkeyNotify(Handle, FHotkeyInfo) + else UnregisterHotkeyNotify(Handle); +end; + procedure TLinkbarWcl.SetScreenAlign(AValue: TScreenAlign); begin FScreenEdge := AValue; @@ -1597,6 +1809,17 @@ procedure TLinkbarWcl.SetSortAlphabetically(AValue: Boolean); end; end; +procedure TLinkbarWcl.SetStayOnTop(AValue: Boolean); +const FORM_STYLE: array[Boolean] of TFormStyle = (fsNormal, fsStayOnTop); +begin + if FStayOnTop = AValue then Exit; + FStayOnTop := AValue; + Self.FormStyle := FORM_STYLE[FStayOnTop]; + + if Assigned(oAppBar) + then oAppBar.StayOnTop := FStayOnTop; +end; + procedure TLinkbarWcl.QuerySizingEvent(Sender: TObject; AVertical: Boolean; var AWidth, AHeight: Integer); begin @@ -1686,10 +1909,6 @@ procedure TLinkbarWcl.WndProc(var Msg: TMessage); var i: Integer; begin case Msg.Msg of - CUSTOM_ABN_FULLSCREENAPP: - begin - oAppBar.AppBarFullScreenApp(Msg.LParam <> 0); - end; // DWM Messaages WM_THEMECHANGED: begin @@ -1733,6 +1952,8 @@ procedure TLinkbarWcl.WndProc(var Msg: TMessage); WM_KILLFOCUS: begin Msg.Result := 0; + if (csDestroying in ComponentState) + then Exit; FCanAutoHide := not Assigned(FrmProperties); DoAutoHide; end; @@ -1776,11 +1997,19 @@ procedure TLinkbarWcl.WndProc(var Msg: TMessage); { Delayed auto show (timer) } WM_TIMER: begin - if (Msg.WParam = TIMER_AUTO_SHOW) - then begin - KillTimer(Handle, TIMER_AUTO_SHOW); - _DoAutoShow; - Exit; + case Msg.WParam of + TIMER_AUTO_SHOW: + begin + KillTimer(Handle, TIMER_AUTO_SHOW); + DoAutoShow; + Exit; + end; + TIMER_AUTO_HIDE: + begin + KillTimer(Handle, TIMER_AUTO_HIDE); + DoAutoHide; + Exit; + end; end; end else @@ -1788,6 +2017,65 @@ procedure TLinkbarWcl.WndProc(var Msg: TMessage); end; end; +function SetForegroundWindowInternal(AWnd: HWND): HWND; +var ip: TInput; // This structure will be used to create the keyboard input event. +begin + Result := 0; + + if not IsWindow(AWnd) + then Exit; + + Result := GetForegroundWindow; + + // Set up a generic keyboard event. + FillChar(ip, SizeOf(ip), 0); + ip.Itype := INPUT_KEYBOARD; + ip.ki.wScan := 0; // hardware scan code for key + ip.ki.time := 0; + ip.ki.dwExtraInfo := 0; + + // Press the "Alt" key + ip.ki.wVk := VK_MENU; // virtual-key code for the "Alt" key + ip.ki.dwFlags := 0; // 0 for key press + SendInput(1, ip, SizeOf(ip)); + + //Sleep(100); //Sometimes SetForegroundWindow will fail and the window will flash instead of it being show. Sleeping for a bit seems to help. + Application.ProcessMessages; + + SetForegroundWindow(AWnd); + + // Release the "Alt" key + ip.ki.dwFlags := KEYEVENTF_KEYUP; // for key release + SendInput(1, ip, sizeof(ip)); +end; + +procedure TLinkbarWcl.WmHotKey(var Msg: TMessage); +begin + if (Msg.Msg = WM_HOTKEY) + and (Msg.WParam = LB_HOTKEY_ID) + and (Msg.LParamHi = FHotkeyInfo.KeyCode) + and (Msg.LParamLo = FHotkeyInfo.Modifiers) + and AutoHide + //and (FAutoShowMode = smHotkey) + then begin + FHotkeyPressed := True; + if (FAutoHiden) + then begin + DoAutoShow; + FPrevForegroundWnd := SetForegroundWindowInternal(Handle); + end + else begin + SetForegroundWindowInternal(FPrevForegroundWnd); + // Linkbar will be hidden when it loses Focus + //DoAutoHide; + end; + FHotkeyPressed := False; + Exit; + end; + + inherited; +end; + procedure TLinkbarWcl.UpdateBitBuckets; begin Items.BitBucketUpdateIcon; @@ -1860,9 +2148,12 @@ procedure TLinkbarWcl.imLockBarClick(Sender: TObject); end; procedure TLinkbarWcl.imAddBarClick(Sender: TObject); +var cmd: string; begin - LBCreateProcess( ParamStr(0), LBCreateCommandParam(CLK_NEW, '') - + LBCreateCommandParam(CLK_LANG, IntToStr(LbLangID)) ); + cmd := LBCreateCommandParam(CLK_NEW, ''); + if (Locale <> '') + then cmd := cmd + LBCreateCommandParam(CLK_LANG, Locale); + LBCreateProcess(ParamStr(0), cmd); end; procedure TLinkbarWcl.imNewShortcutClick(Sender: TObject); @@ -1883,9 +2174,9 @@ procedure TLinkbarWcl.imRemoveBarClick(Sender: TObject); try td.Caption := ' ' + APP_NAME_LINKBAR; td.MainIcon := tdiNone; - td.Title := Format(RS_REMDLG_TITLE, [PanelName]); - td.Text := Format(RS_REMDLG_TEXT, [WorkDir]); - td.VerificationText := RS_REMDLG_VERIFICATIONTEXT + Format('%*s', [24, ' ']); + td.Title := Format( L10NFind('Delete.Title', 'You remove the linkbar "%s"'), [PanelName] ); + td.Text := Format( L10NFind('Delete.Text', 'Working directory: %s'), [WorkDir] ); + td.VerificationText := L10NFind('Delete.Verification', 'Delete working directory') + Format('%*s', [24, ' ']); td.CommonButtons := [tcbOk, tcbCancel]; td.DefaultButton := tcbCancel; @@ -1907,7 +2198,7 @@ procedure TLinkbarWcl.imRemoveBarClick(Sender: TObject); end; end; -procedure TLinkbarWcl.imSortAlphabeticallyClick(Sender: TObject); +procedure TLinkbarWcl.imSortAlphabetClick(Sender: TObject); begin SortAlphabetically := not SortAlphabetically; end; @@ -1921,9 +2212,15 @@ function TLinkbarWcl.ScaleDimension(const X: Integer): Integer; Result := MulDiv(X, Self.PixelsPerInch, 96); end; -function MakePoint(const Param : DWord): TPoint; inline; +// Macros from windowsx.h: +// Important Do not use the LOWORD or HIWORD macros to extract the x- and y- +// coordinates of the cursor position because these macros return incorrect results +// on systems with multiple monitors. Systems with multiple monitors can have +// negative x- and y- coordinates, and LOWORD and HIWORD treat the coordinates +// as unsigned quantities. +function MakePoint(const L: DWORD): TPoint; inline; Begin - Result := TPoint.Create(Param and $FFFF, Param shr 16); + Result := TPoint.Create(SmallInt(L and $FFFF), SmallInt(L shr 16)); End; procedure TLinkbarWcl.DoAutoHide; @@ -1936,7 +2233,6 @@ procedure TLinkbarWcl.DoAutoHide; if FCanAutoHide and not FAutoHiden then begin - FAutoHiden := True; r := FBeforeAutoHideBound; case ScreenAlign of @@ -1952,15 +2248,14 @@ procedure TLinkbarWcl.DoAutoHide; end; end; -procedure TLinkbarWcl._DoAutoShow; +procedure TLinkbarWcl.DoAutoShow; +var pt: TPoint; begin - if (not AutoHide) - then Exit; - - if ( WindowFromPoint(MakePoint(GetMessagePos)) <> Handle ) - then Exit; - - if FAutoHiden + pt := MakePoint(GetMessagePos); + if (AutoHide) + and (FAutoHiden) + and (FHotkeyPressed or (WindowFromPoint(pt) = Handle)) + //(FAutoShowMode <> smHotKey) then begin FAutoHiden := False; MoveWindow(Handle, FBeforeAutoHideBound.Left, FBeforeAutoHideBound.Top, @@ -1970,13 +2265,13 @@ procedure TLinkbarWcl._DoAutoShow; end; end; -procedure TLinkbarWcl._DoDelayedAutoShow; +procedure TLinkbarWcl.DoDelayedAutoShow; begin if (not AutoHide) then Exit; if (FAutoShowDelay = 0) - then _DoAutoShow + then DoAutoShow else SetTimer(Handle, TIMER_AUTO_SHOW, FAutoShowDelay, nil); end; @@ -1985,14 +2280,14 @@ procedure TLinkbarWcl.FormMouseEnter(Sender: TObject); if AutoHide and FAutoHiden and (FAutoShowMode = smMouseHover) - then _DoDelayedAutoShow; + then DoDelayedAutoShow; end; procedure TLinkbarWcl.FormMouseLeave(Sender: TObject); begin HotIndex := -1; if (FAutoShowMode = smMouseHover) or FCanAutoHide - then DoAutoHide; + then SetTimer(Handle, TIMER_AUTO_HIDE, TIMER_AUTO_HIDE_DELAY, nil);// DoAutoHide; end; //////////////////////////////////////////////////////////////////////////////// @@ -2130,7 +2425,7 @@ procedure TLinkbarWcl.DoDragEnter(const pt: TPoint); and FAutoHiden then begin FCanAutoHide := False; - _DoAutoShow; + DoAutoShow; end; end; @@ -2149,7 +2444,7 @@ procedure TLinkbarWcl.DoDragLeave; if AutoHide and not Active then begin FCanAutoHide := True; - DoAutoHide; + SetTimer(Handle, TIMER_AUTO_HIDE, TIMER_AUTO_HIDE_DELAY, nil); // DoAutoHide; end; end;