{----------------------------------------------------------------------------- The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/MPL-1.1.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is: JvgUtils.PAS, released on 2003-01-15. The Initial Developer of the Original Code is Andrey V. Chudin, [chudin att yandex dott ru] Portions created by Andrey V. Chudin are Copyright (C) 2003 Andrey V. Chudin. All Rights Reserved. Contributor(s): Michael Beck [mbeck att bigfoot dott com]. Burov Dmitry, translation of russian text. You may retrieve the latest version of this file at the Project JEDI's JVCL home page, located at http://jvcl.sourceforge.net Known Issues: -----------------------------------------------------------------------------} // $Id: JvgUtils.pas 10612 2006-05-19 19:04:09Z jfudickar $ unit JvgUtils; {$I jvcl.inc} interface uses {$IFDEF USEJVCL} {$IFDEF UNITVERSIONING} JclUnitVersioning, {$ENDIF UNITVERSIONING} {$ENDIF USEJVCL} Windows, Messages, Graphics, ExtCtrls, SysUtils, Classes, Controls, Forms, MMSystem, JvgTypes, JvgCommClasses, Jvg3DColors; type TJvgPublicWinControl = class(TWinControl) public procedure PaintWindow(DC: HDC); override; procedure RecreateWnd; property Font; property OnEnter; property OnExit; property Color; end; function IsEven(I: Integer): Boolean; function InchesToPixels(DC: HDC; Value: Single; IsHorizontal: Boolean): Integer; function CentimetersToPixels(DC: HDC; Value: Single; IsHorizontal: Boolean): Integer; procedure SwapInt(var I1, I2: Integer); function Spaces(Count: Integer): string; function DupStr(const Str: string; Count: Integer): string; function DupChar(C: Char; Count: Integer): string; procedure Msg(const AMsg: string); function RectW(R: TRect): Integer; function RectH(R: TRect): Integer; function IncColor(AColor: Longint; AOffset: Byte): Longint; function DecColor(AColor: Longint; AOffset: Byte): Longint; function IsItAFilledBitmap(Bmp: TBitmap): Boolean; procedure DrawTextInRectWithAlign(DC: HDC; R: TRect; const Text: string; HAlign: TglHorAlign; VAlign: TglVertAlign; Style: TglTextStyle; Fnt: TFont; Flags: UINT); procedure DrawTextInRect(DC: HDC; R: TRect; const Text: string; Style: TglTextStyle; Fnt: TFont; Flags: UINT); procedure ExtTextOutExt(DC: HDC; X, Y: Integer; R: TRect; const Text: string; Style: TglTextStyle; ADelineated, ASupress3D: Boolean; FontColor, DelinColor, HighlightColor, ShadowColor: TColor; Illumination: TJvgIllumination; Gradient: TJvgGradient; Font: TFont); procedure DrawBox(DC: HDC; var R: TRect; Style: TglBoxStyle; BackgrColor: Longint; ATransparent: Boolean); function DrawBoxEx(DC: HDC; ARect: TRect; Borders: TglSides; BevelInner, BevelOuter: TPanelBevel; Bold: Boolean; BackgrColor: Longint; ATransparent: Boolean): TRect; procedure GradientBox(DC: HDC; R: TRect; Gradient: TJvgGradient; PenStyle, PenWidth: Integer); procedure ChangeBitmapColor(Bitmap: TBitmap; FromColor, ToColor: TColor); procedure DrawBitmapExt(DC: HDC; { DC - background & result} SourceBitmap: TBitmap; R: TRect; X, Y: Integer; //...X,Y _in_ rect! BitmapOption: TglWallpaperOption; DrawState: TglDrawState; ATransparent: Boolean; TransparentColor: TColor; DisabledMaskColor: TColor); procedure CreateBitmapExt(DC: HDC; { DC - background & result} SourceBitmap: TBitmap; R: TRect; X, Y: Integer; //...X,Y _in_ rect! BitmapOption: TglWallpaperOption; DrawState: TglDrawState; ATransparent: Boolean; TransparentColor: TColor; DisabledMaskColor: TColor); procedure BringParentWindowToTop(Wnd: TWinControl); function GetParentForm(Control: TControl): TForm; procedure GetWindowImageFrom(Control: TWinControl; X, Y: Integer; ADrawSelf, ADrawChildWindows: Boolean; DC: HDC); procedure GetWindowImage(Control: TWinControl; ADrawSelf, ADrawChildWindows: Boolean; DC: HDC); procedure GetParentImageRect(Control: TControl; Rect: TRect; DC: HDC); function CreateRotatedFont(F: TFont; Escapement: Integer): HFONT; function FindMainWindow(const AWndClass, AWndTitle: string): THandle; procedure CalcShadowAndHighlightColors(BaseColor: TColor; Colors: TJvgLabelColors); function CalcMathString(AExpression: string): Single; function IIF(AExpression: Boolean; IfTrue, IfFalse: Variant): Variant; overload; function IIF(AExpression: Boolean; const IfTrue, IfFalse: string): string; overload; function GetTransparentColor(Bitmap: TBitmap; AutoTrColor: TglAutoTransparentColor): TColor; procedure TypeStringOnKeyboard(const S: string); //function NextStringGridCell( Grid: TStringGrid ): Boolean; procedure DrawTextExtAligned(Canvas: TCanvas; const Text: string; R: TRect; Alignment: TglAlignment; WordWrap: Boolean); procedure LoadComponentFromTextFile(Component: TComponent; const FileName: string); procedure SaveComponentToTextFile(Component: TComponent; const FileName: string); function ComponentToString(Component: TComponent): string; procedure StringToComponent(Component: TComponent; const Value: string); function PlayWaveResource(const ResName: string): Boolean; function UserName: string; function ComputerName: string; function CreateIniFileName: string; function ExpandString(const Str: string; Len: Integer): string; function Transliterate(const Str: string; RusToLat: Boolean): string; function IsSmallFonts: Boolean; function SystemColorDepth: Integer; function GetFileType(const FileName: string): TglFileType; function FindControlAtPt(Control: TWinControl; Pt: TPoint; MinClass: TClass): TControl; function StrPosExt(const Str1, Str2: PChar; Str2Len: DWORD): PChar; assembler; {$IFDEF glDEBUG} function DeleteObject(P1: HGDIOBJ): BOOL; stdcall; {$ENDIF glDEBUG} {$IFNDEF USEJVCL} function DrawText(Canvas: TCanvas; Text: PAnsiChar; Len: Integer; var R: TRect; WinFlags: Integer): Integer; overload; function DrawText(Canvas: TCanvas; const Text: string; Len: Integer; var R: TRect; WinFlags: Integer): Integer; overload; function PtInRectExclusive(R: TRect; Pt: TPoint): Boolean; function CanvasMaxTextHeight(Canvas: TCanvas): Integer; {$ENDIF !USEJVCL} {$IFDEF USEJVCL} {$IFDEF UNITVERSIONING} const UnitVersioning: TUnitVersionInfo = ( RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_32/run/JvgUtils.pas $'; Revision: '$Revision: 10612 $'; Date: '$Date: 2006-05-19 21:04:09 +0200 (ven., 19 mai 2006) $'; LogPath: 'JVCL\run' ); {$ENDIF UNITVERSIONING} {$ENDIF USEJVCL} implementation uses JvJCLUtils, {$IFDEF USEJVCL} ShlObj, Math, JvResources, JvConsts, {$ELSE} ShlObj, Math, {$ENDIF USEJVCL} JvVCL5Utils; {$IFNDEF USEJVCL} resourcestring RsERightBracketsNotFound = 'Right brackets not found'; RsERightBracketHavntALeftOnePosd = 'Right bracket havn''t a left one. Pos: %d'; RsEDivideBy = 'Divide by 0'; RsEDuplicateSignsAtPos = 'Duplicate signs at Pos: %d'; RsEExpressionStringIsEmpty = 'Expression string is empty.'; {$IFDEF glDEBUG} RsEObjectMemoryLeak = 'object memory leak'; {$ENDIF glDEBUG} const ROP_DSPDxax = $00E20746; {$ENDIF !USEJVCL} { debug func } {$IFDEF glDEBUG} function DeleteObject(P1: HGDIOBJ): BOOL; stdcall; begin Result := Windows.DeleteObject(P1); if not Result then raise Exception.CreateRes(@RsEObjectMemoryLeak); end; {$ENDIF glDEBUG} procedure TJvgPublicWinControl.PaintWindow(DC: HDC); begin inherited PaintWindow(DC); end; procedure TJvgPublicWinControl.RecreateWnd; begin inherited RecreateWnd; end; function IsEven(I: Integer): Boolean; begin Result := not Odd(I); end; procedure SwapInt(var I1, I2: Integer); var Tmp: Integer; begin Tmp := I1; I1 := I2; I2 := Tmp; end; function Spaces(Count: Integer): string; var I: Integer; begin Result := ''; for I := 1 to Count do Result := Result + ' '; end; function DupChar(C: Char; Count: Integer): string; var I: Integer; begin Result := ''; for I := 1 to Count do Result := Result + C; end; function DupStr(const Str: string; Count: Integer): string; var I: Integer; begin Result := ''; for I := 1 to Count do Result := Result + Str; end; { Modal window with (i) icon and single OK button } procedure Msg(const AMsg: string); begin MessageBox(GetForegroundWindow, PChar(AMsg), '', MB_APPLMODAL or MB_ICONINFORMATION or MB_OK); end; { Checks if point is inside rect. Rect's borders are not part of rect } { // (andreas) make Delphi 5 compiler happy function IsPointInRect(P: TPoint; R: TRect): Boolean; begin Result := PtInRect(R, P); // Result := (P.X > R.Left) and (P.X < R.Right) and (P.Y > R.Top) and (P.Y < R.Bottom); end; } { Rect's width } function RectW(R: TRect): Integer; begin Result := R.Right - R.Left; end; { Rect's height } function RectH(R: TRect): Integer; begin Result := R.Bottom - R.Top; end; { Increases components of the colour with given offset } function IncColor(AColor: Longint; AOffset: Byte): Longint; var R, G, B: Byte; begin if AColor < 0 then AColor := GetSysColor(AColor and $FF); R := Min(255, GetRValue(AColor) + AOffset); G := Min(255, GetGValue(AColor) + AOffset); B := Min(255, GetBValue(AColor) + AOffset); Result := RGB(R, G, B); end; { Decreases components of the colour with given offset } function DecColor(AColor: Longint; AOffset: Byte): Longint; var R, G, B: Byte; begin if AColor < 0 then AColor := GetSysColor(AColor and $FF); R := Max(0, GetRValue(AColor) - AOffset); G := Max(0, GetGValue(AColor) - AOffset); B := Max(0, GetBValue(AColor) - AOffset); Result := RGB(R, G, B); end; function InchesToPixels(DC: HDC; Value: Single; IsHorizontal: Boolean): Integer; const LogPixels: array [Boolean] of Integer = (LOGPIXELSY, LOGPIXELSX); begin Result := Round(Value * GetDeviceCaps(DC, LogPixels[IsHorizontal]));// * 1.541 / 10); end; function CentimetersToPixels(DC: HDC; Value: Single; IsHorizontal: Boolean): Integer; const LogPixels: array [Boolean] of Integer = (LOGPIXELSY, LOGPIXELSX); begin Result := Round(Value * GetDeviceCaps(DC, LogPixels[IsHorizontal])/2.54);// * 1.541 / 2.54 / 10); end; { Checks wheter bitmap object is created and is having size } function IsItAFilledBitmap(Bmp: TBitmap): Boolean; begin with Bmp do Result := Assigned(Bmp) and (Width <> 0) and (Height <> 0); end; { Renders text wth alignment, given style and given font DC - Handle of canvas HAlign, VAlign - Alingment horizontal and vertical Style - Style (embossed, with shadow, etc) Flags - Extra parameters for Windows.DrawText } procedure DrawTextInRectWithAlign(DC: HDC; R: TRect; const Text: string; HAlign: TglHorAlign; VAlign: TglVertAlign; Style: TglTextStyle; Fnt: TFont; Flags: UINT); begin case HAlign of fhaLeft: Flags := Flags or DT_LEFT; fhaCenter: Flags := Flags or DT_CENTER; fhaRight: Flags := Flags or DT_RIGHT; end; case VAlign of fvaTop: Flags := Flags or DT_TOP; fvaCenter: Flags := Flags or DT_VCENTER; fvaBottom: Flags := Flags or DT_BOTTOM; end; DrawTextInRect(DC, R, Text, Style, Fnt, Flags); end; { Renders text with alignment, given style and given font DC - Handle of canvas Style - Style (embossed, with shadow, etc) Flags - Extra parameters for Windows.DrawText } procedure DrawTextInRect(DC: HDC; R: TRect; const Text: string; Style: TglTextStyle; Fnt: TFont; Flags: UINT); var OldBkMode: Integer; OldFont: Windows.HFONT; FontColor: TColor; ShadowColor, HighlightColor: TColor; begin if not Assigned(Fnt) then Exit; if Flags = 0 then Flags := DT_LEFT or DT_VCENTER or DT_SINGLELINE; OldBkMode := SetBkMode(DC, Ord(Transparent)); FontColor := Fnt.Color; ShadowColor := clBtnShadow; HighlightColor := clBtnHighlight; OldFont := SelectObject(DC, Fnt.Handle); case Style of fstRaised: begin SetTextColor(DC, ColorToRGB(HighlightColor)); OffsetRect(R, -1, -1); Windows.DrawText(DC, PChar(Text), Length(Text), R, Flags); SetTextColor(DC, ColorToRGB(ShadowColor)); OffsetRect(R, 2, 2); Windows.DrawText(DC, PChar(Text), Length(Text), R, Flags); SetTextColor(DC, ColorToRGB(FontColor)); OffsetRect(R, -1, -1); Windows.DrawText(DC, PChar(Text), Length(Text), R, Flags); end; fstRecessed: begin SetTextColor(DC, ColorToRGB(ShadowColor)); OffsetRect(R, -1, -1); Windows.DrawText(DC, PChar(Text), Length(Text), R, Flags); SetTextColor(DC, ColorToRGB(HighlightColor)); OffsetRect(R, 2, 2); Windows.DrawText(DC, PChar(Text), Length(Text), R, Flags); SetTextColor(DC, ColorToRGB(FontColor)); OffsetRect(R, -1, -1); Windows.DrawText(DC, PChar(Text), Length(Text), R, Flags); end; fstPushed: begin SetTextColor(DC, ColorToRGB(HighlightColor)); Windows.DrawText(DC, PChar(Text), Length(Text), R, Flags); SetTextColor(DC, ColorToRGB(ShadowColor)); OffsetRect(R, -1, -1); Windows.DrawText(DC, PChar(Text), Length(Text), R, Flags); end; fstShadow: begin SetTextColor(DC, ColorToRGB(ShadowColor)); OffsetRect(R, 2, 2); Windows.DrawText(DC, PChar(Text), Length(Text), R, Flags); SetTextColor(DC, ColorToRGB(FontColor)); OffsetRect(R, -2, -2); Windows.DrawText(DC, PChar(Text), Length(Text), R, Flags); end; else begin SetTextColor(DC, ColorToRGB(FontColor)); Windows.DrawText(DC, PChar(Text), Length(Text), R, Flags); end; end; SelectObject(DC, OldFont); SetBkMode(DC, OldBkMode); end; { Renders text wth given style, countouring option and given colours fo 3D effects DC - Handle of canvas Style - Style (embossed, with shadow, etc) ADelineated - Contour of color of DelinColor FontColor, DelinColor, HighlightColor, ShadowColor - Colors of font and 3D effects Illumination - Not used Gradient - Gradient for filling letters of text } procedure ExtTextOutExt(DC: HDC; X, Y: Integer; R: TRect; const Text: string; Style: TglTextStyle; ADelineated, ASupress3D: Boolean; FontColor, DelinColor, HighlightColor, ShadowColor: TColor; Illumination: TJvgIllumination; Gradient: TJvgGradient; Font: TFont); var OldBkMode, X1, Y1, I, ShadowDepth: Integer; OldFont: Windows.HFONT; procedure DrawMain(ADelineated: Boolean; S: Integer); begin if ADelineated then begin if not ASupress3D then begin SetTextColor(DC, ColorToRGB(DelinColor)); ExtTextOut(DC, X + S, Y + S, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); ExtTextOut(DC, X + 2 + S, Y + 2 + S, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); ExtTextOut(DC, X + S, Y + S + 2, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); ExtTextOut(DC, X + S + 2, Y + S, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); end; SetTextColor(DC, ColorToRGB(FontColor)); if Assigned(Gradient) then Gradient.TextOut(DC, Text, R, X + S + 1, Y + S + 1) else ExtTextOut(DC, X + S + 1, Y + S + 1, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); end else begin SetTextColor(DC, ColorToRGB(FontColor)); if Assigned(Gradient) then Gradient.TextOut(DC, Text, R, X + S, Y + S) else ExtTextOut(DC, X + S, Y + S, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); end; end; begin if not Assigned(Font) then Exit; OldFont := SelectObject(DC, Font.Handle); OldBkMode := SetBkMode(DC, TRANSPARENT); if ADelineated then begin X1 := 4; Y1 := 4; end else begin X1 := 2; Y1 := 2; end; if Style = fstNone then begin X1 := X1 div 2 - 1; Y1 := Y1 div 2 - 1; end; if Style = fstShadow then begin X1 := X1 div 2 - 1; Y1 := Y1 div 2 - 1; end; if Assigned(Illumination) then ShadowDepth := Illumination.ShadowDepth else ShadowDepth := 2; case Style of fstRaised: begin if not ASupress3D then begin SetTextColor(DC, ColorToRGB(HighlightColor)); ExtTextOut(DC, X, Y, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); SetTextColor(DC, ColorToRGB(ShadowColor)); ExtTextOut(DC, X + X1, Y + Y1, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); end; DrawMain(ADelineated, 1); end; fstRecessed: begin if not ASupress3D then begin SetTextColor(DC, ColorToRGB(ShadowColor)); ExtTextOut(DC, X, Y, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); SetTextColor(DC, ColorToRGB(HighlightColor)); ExtTextOut(DC, X + X1, Y + Y1, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); end; DrawMain(ADelineated, 1); end; fstPushed: begin SetTextColor(DC, ColorToRGB(HighlightColor)); ExtTextOut(DC, X + 1, Y + 1, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); SetTextColor(DC, ColorToRGB(ShadowColor)); ExtTextOut(DC, X, Y, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); end; fstShadow: begin if not ASupress3D then begin SetTextColor(DC, ColorToRGB(ShadowColor)); ExtTextOut(DC, X + X1 + ShadowDepth, Y + Y1 + ShadowDepth, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); end; DrawMain(ADelineated, 0); end; fstVolumetric: begin if not ASupress3D then begin SetTextColor(DC, ColorToRGB(ShadowColor)); for I := 1 to ShadowDepth do ExtTextOut(DC, X + I, Y + I, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); end; DrawMain(ADelineated, 0); end; else DrawMain(ADelineated, 0); // SetTextColor( DC , ColorToRGB(FontColor) ); // ExtTextOut( DC, X, Y, ETO_CLIPPED, @R, PChar(Text), Length(Text), nil); end; SelectObject(DC, OldFont); SetBkMode(DC, OldBkMode); end; { Draws rect with given 3D style DC - Handle of canvas Style - Style (fbsFlat, fbsCtl3D, fbsStatusControl, fbsRecessed, fbsRaised, fbsRaisedFrame, fbsRecessedFrame) BackgrColor - Background Color if FTransparen is False } procedure DrawBox(DC: HDC; var R: TRect; Style: TglBoxStyle; BackgrColor: Longint; ATransparent: Boolean); const FBorderWidth = 1; begin case Style of fbsFlat: begin end; fbsCtl3D: begin R.Top := R.Top + 2; R.Left := R.Left + 2; R.Right := R.Right - 2; R.Bottom := R.Bottom - 1; // Frame3D(Canvas, R,clBtnShadow,clBtnHighlight,1); end; // fbsStatusControl: fbsRaised: begin InflateRect(R, -2, -2); DrawEdge(DC, R, BDR_RAISEDOUTER, BF_BOTTOMRIGHT); // black Dec(R.Bottom); Dec(R.Right); DrawEdge(DC, R, BDR_RAISEDINNER, BF_TOPLEFT); // btnhilite Inc(R.Top); Inc(R.Left); DrawEdge(DC, R, BDR_RAISEDINNER, BF_BOTTOMRIGHT or BF_MIDDLE); // btnshadow end; fbsRecessed: begin R.Bottom := R.Bottom - 1; DrawEdge(DC, R, BDR_SUNKENINNER, BF_TOPLEFT); // black DrawEdge(DC, R, BDR_SUNKENOUTER, BF_BOTTOMRIGHT); // btnhilite Dec(R.Bottom); Dec(R.Right); Inc(R.Top); Inc(R.Left); DrawEdge(DC, R, BDR_SUNKENOUTER, BF_TOPLEFT or BF_MIDDLE); // btnshadow Inc(R.Top); Inc(R.Left); end; fbsRaisedFrame: begin DrawEdge(DC, R, BDR_RAISEDOUTER, BF_BOTTOMRIGHT); // black Dec(R.Bottom); Dec(R.Right); DrawEdge(DC, R, BDR_RAISEDINNER, BF_TOPLEFT); // btnhilite Inc(R.Top); Inc(R.Left); DrawEdge(DC, R, BDR_RAISEDINNER, BF_BOTTOMRIGHT or BF_MIDDLE); // btnshadow InflateRect(R, -FBorderWidth, -FBorderWidth); DrawEdge(DC, R, BDR_SUNKENINNER, BF_TOPLEFT); // black DrawEdge(DC, R, BDR_SUNKENOUTER, BF_BOTTOMRIGHT); // btnhilite Dec(R.Bottom); Dec(R.Right); Inc(R.Top); Inc(R.Left); DrawEdge(DC, R, BDR_SUNKENOUTER, BF_TOPLEFT or BF_MIDDLE); // btnshadow Inc(R.Top); Inc(R.Left); end; fbsRecessedFrame: begin DrawEdge(DC, R, BDR_SUNKENINNER, BF_TOPLEFT); // black DrawEdge(DC, R, BDR_SUNKENOUTER, BF_BOTTOMRIGHT); // btnhilite Dec(R.Bottom); Dec(R.Right); Inc(R.Top); Inc(R.Left); DrawEdge(DC, R, BDR_SUNKENOUTER, BF_TOPLEFT or BF_MIDDLE); // btnshadow Inc(R.Top); Inc(R.Left); InflateRect(R, -FBorderWidth, -FBorderWidth); DrawEdge(DC, R, BDR_RAISEDOUTER, BF_BOTTOMRIGHT); // black Dec(R.Bottom); Dec(R.Right); DrawEdge(DC, R, BDR_RAISEDINNER, BF_TOPLEFT); // btnhilite Inc(R.Top); Inc(R.Left); DrawEdge(DC, R, BDR_RAISEDINNER, BF_BOTTOMRIGHT or BF_MIDDLE); // btnshadow end; end; end; { Draws rect with given 3D style and specifing borders DC - Handle of canvas Borders - Borders for drawing BevelInner, BevelOuter - Borders' styles Bold - Bold border(frame) BackgrColor - Background Color if ATransparent is False } function DrawBoxEx(DC: HDC; ARect: TRect; Borders: TglSides; BevelInner, BevelOuter: TPanelBevel; Bold: Boolean; BackgrColor: Longint; ATransparent: Boolean): TRect; var I: Word; BPen, LPen, SPen, OldPen: HPEN; HBackgrBrush, HOldBrush: HBRUSH; R, R1: TRect; BColor, HColor, SColor: Longint; LogOldPen: TLOGPEN; PenWidth: UINT; procedure SetDefColors; begin BColor := GetSysColor(COLOR_3DDKSHADOW); HColor := GetSysColor(COLOR_3DHILIGHT); SColor := GetSysColor(COLOR_3DSHADOW); end; procedure DrawBevel(Bevel: TPanelBevel); begin if fsdLeft in Borders then begin case Bevel of bvRaised: begin SelectObject(DC, LPen); MoveToEx(DC, R.Left, R.Top, nil); LineTo(DC, R.Left, R.Bottom + 1); Inc(R1.Left); //.if Bold then Inc(R1.Left); end; bvLowered: if Bold then begin SelectObject(DC, BPen); MoveToEx(DC, R.Left, R.Top, nil); LineTo(DC, R.Left, R.Bottom); Inc(R1.Left); SelectObject(DC, SPen); if fsdBottom in Borders then I := 0 else I := 1; MoveToEx(DC, R.Left + 1, R.Top + 1, nil); LineTo(DC, R.Left + 1, R.Bottom + I); //SetPixel(DC, R.Left, R.Bottom-1, SColor); Inc(R1.Left); end else begin SelectObject(DC, SPen); MoveToEx(DC, R.Left, R.Top, nil); LineTo(DC, R.Left, R.Bottom); Inc(R1.Left); end; bvSpace: begin SelectObject(DC, SPen); MoveToEx(DC, R.Left, R.Top, nil); LineTo(DC, R.Left, R.Bottom); Inc(R1.Left); end; end; end; if fsdTop in Borders then begin case Bevel of bvRaised: begin SelectObject(DC, LPen); MoveToEx(DC, R.Left, R.Top, nil); LineTo(DC, R.Right, R.Top); Inc(R1.Top); //.if Bold then Inc(R1.Top); end; bvLowered: if Bold then begin SelectObject(DC, BPen); MoveToEx(DC, R.Left, R.Top, nil); LineTo(DC, R.Right, R.Top); Inc(R1.Top); SelectObject(DC, SPen); MoveToEx(DC, R.Left + 1, R.Top + 1, nil); LineTo(DC, R.Right, R.Top + 1); //SetPixel(DC, R.Right-1, R.Top+1, SColor); Inc(R1.Top); end else begin SelectObject(DC, SPen); MoveToEx(DC, R.Left, R.Top, nil); LineTo(DC, R.Right, R.Top); Inc(R1.Top); end; bvSpace: begin SelectObject(DC, SPen); MoveToEx(DC, R.Left, R.Top, nil); LineTo(DC, R.Right, R.Top); Inc(R1.Top); end; end; end; if fsdRight in Borders then begin case Bevel of bvRaised: if Bold then begin SelectObject(DC, BPen); MoveToEx(DC, R.Right, R.Top, nil); LineTo(DC, R.Right, R.Bottom + 1); Dec(R1.Right); SelectObject(DC, SPen); MoveToEx(DC, R.Right - 1, R.Top + 1, nil); LineTo(DC, R.Right - 1, R.Bottom + 1); //SetPixel(DC, R.Right-1, R.Bottom-1, SColor); Dec(R1.Right); end else begin SelectObject(DC, SPen); MoveToEx(DC, R.Right, R.Top, nil); LineTo(DC, R.Right, R.Bottom + 1); Dec(R1.Right); end; bvLowered: begin SelectObject(DC, LPen); MoveToEx(DC, R.Right, R.Top, nil); LineTo(DC, R.Right, R.Bottom); Dec(R1.Right); //. if Bold then Dec(R1.Right); end; bvSpace: begin SelectObject(DC, SPen); MoveToEx(DC, R.Right, R.Top, nil); LineTo(DC, R.Right, R.Bottom); Dec(R1.Right); end; end; end; if fsdBottom in Borders then begin case Bevel of bvRaised: if Bold then begin SelectObject(DC, BPen); if fsdLeft in Borders then I := 1 else I := 0; MoveToEx(DC, R.Left {+1}, R.Bottom, nil); LineTo(DC, R.Right, R.Bottom); Dec(R1.Bottom); SelectObject(DC, SPen); MoveToEx(DC, R.Left + I {+I}, R.Bottom - 1, nil); LineTo(DC, R.Right, R.Bottom - 1); //SetPixel(DC, R.Right-1+I, R.Bottom-1, SColor); Dec(R1.Bottom); end else begin SelectObject(DC, SPen); MoveToEx(DC, R.Left, R.Bottom, nil); LineTo(DC, R.Right, R.Bottom); Dec(R1.Bottom); end; bvLowered: begin SelectObject(DC, LPen); // if Borders.Left then I:=1 else I:=0; MoveToEx(DC, R.Left, R.Bottom {-1}, nil); LineTo(DC, R.Right + 1, R.Bottom {-1}); Dec(R1.Bottom); //. if Bold then Dec(R1.Bottom); //Dec(R1.Bottom); end; bvSpace: begin SelectObject(DC, SPen); MoveToEx(DC, R.Left, R.Bottom {-1}, nil); LineTo(DC, R.Right + 1, R.Bottom {-1}); Dec(R1.Bottom); end; end; end; end; begin try if Assigned(glGlobalData.lp3DColors) then with TJvg3DColors(glGlobalData.lp3DColors) do begin BColor := ColorToRGB(DkShadow); HColor := ColorToRGB(Highlight); SColor := ColorToRGB(Shadow); end else SetDefColors; except end; LPen := CreatePen(PS_SOLID, 1, HColor); OldPen := SelectObject(DC, LPen); DeleteObject(SelectObject(DC, OldPen)); FillChar(LogOldPen, SizeOf(LogOldPen), 0); GetObject(OldPen, SizeOf(LogOldPen), @LogOldPen); if LogOldPen.lopnWidth.X = 0 then PenWidth := 1 else PenWidth := LogOldPen.lopnWidth.X; BPen := CreatePen(LogOldPen.lopnStyle, PenWidth, BColor); LPen := CreatePen(LogOldPen.lopnStyle, PenWidth, HColor); SPen := CreatePen(LogOldPen.lopnStyle, PenWidth, SColor); SelectObject(DC, LPen); R1 := ARect; R := ARect; if BevelOuter <> bvNone then DrawBevel(BevelOuter); R := R1; // if (BevelOuter = bvRaised)and(BevelInner = bvLowered)and Bold then // begin Dec(R.Top); Dec(R.Left); end; if BevelInner <> bvNone then DrawBevel(BevelInner); SelectObject(DC, OldPen); DeleteObject(BPen); DeleteObject(LPen); DeleteObject(SPen); if not ATransparent then begin HBackgrBrush := CreateSolidBrush(ColorToRGB(BackgrColor)); HOldBrush := SelectObject(DC, HBackgrBrush); R := R1; {Dec(R.Top);Dec(R.Left);} Inc(R.Right); Inc(R.Bottom); FillRect(DC, R, HBackgrBrush); DeleteObject(SelectObject(DC, HOldBrush)); end; Result := R1; end; { Draws TJvgGradient gradient } procedure GradientBox(DC: HDC; R: TRect; Gradient: TJvgGradient; PenStyle, PenWidth: Integer); begin Gradient.Draw(DC, R, PenStyle, PenWidth); end; { Replaces bitmap's color } procedure ChangeBitmapColor(Bitmap: TBitmap; FromColor, ToColor: TColor); var IWidth, IHeight: Integer; DRect, SRect: TRect; MonoBMP, OldBMP: HBITMAP; MonoDC: HDC; begin if (Bitmap.Width or Bitmap.Height) = 0 then Exit; IWidth := Bitmap.Width; IHeight := Bitmap.Height; DRect := Rect(0, 0, IWidth, IHeight); SRect := DRect; MonoDC := CreateCompatibleDC(Bitmap.Canvas.Handle); MonoBMP := CreateBitmap(IWidth, IHeight, 1, 1, nil); OldBMP := SelectObject(MonoDC, MonoBMP); try with Bitmap.Canvas do { Convert FromColor to ToColor } begin Bitmap.Canvas.Brush.Color := FromColor; {copy Bitmap to MonoBMP} BitBlt(MonoDC, 0, 0, IWidth, IHeight, Handle, 0, 0, cmSrcCopy); Brush.Color := ToColor; SetTextColor(Handle, clBlack); SetBkColor(Handle, clWhite); BitBlt(Handle, 0, 0, IWidth, IHeight, MonoDC, 0, 0, ROP_DSPDxax); end; finally DeleteObject(SelectObject(MonoDC, OldBMP)); DeleteDC(MonoDC); end; end; { Paints bitmap. Transparent, disabled, multiplied, etc } procedure DrawBitmapExt(DC: HDC; { DC - background & result} SourceBitmap: TBitmap; R: TRect; X, Y: Integer; //...X,Y _in_ rect! BitmapOption: TglWallpaperOption; DrawState: TglDrawState; ATransparent: Boolean; TransparentColor: TColor; DisabledMaskColor: TColor); begin CreateBitmapExt(DC, SourceBitmap, R, X, Y, BitmapOption, DrawState, ATransparent, TransparentColor, DisabledMaskColor); end; //..DrawBitmap algorithm borrow from Delphi2 VCL Sources { create bimap based on SourceBitmap and write new bitmap to DC } procedure CreateBitmapExt(DC: HDC; {target DC} SourceBitmap: TBitmap; R: TRect; X, Y: Integer; //...X,Y _in_ rect! BitmapOption: TglWallpaperOption; DrawState: TglDrawState; ATransparent: Boolean; TransparentColor: TColor; DisabledMaskColor: TColor); const ROP_DSPDxax = $00E20746; var X1, Y1, H, W: Integer; D, D1: Double; TmpImage, MonoBMP: TBitmap; IWidth, IHeight: Integer; IRect, ORect: TRect; // DestDC: HDC; BmpInfo: Windows.TBitmap; PtSize, PtOrg: TPoint; MemDC, ImageDC: HDC; OldBMP, OldMonoBMP, OldScreenImageBMP, OldMemBMP: HBITMAP; HMonoBMP, ScreenImageBMP, MemBMP: HBITMAP; MonoDC, ScreenImageDC: HDC; OldBkColor: COLORREF; SavedIHeight: Integer; procedure BitBltWorks; begin if ATransparent then begin { create copy of drawing image } BitBlt(MemDC, 0, 0, IWidth, IHeight, ImageDC, 0, 0, SRCCOPY); if DrawState = fdsDisabled then TransparentColor := clBtnFace; OldBkColor := SetBkColor(MemDC, ColorToRGB(TransparentColor)); { create monohrome mask: TransparentColor -> white, other color -> black } BitBlt(MonoDC, 0, 0, IWidth, IHeight, MemDC, 0, 0, SRCCOPY); SetBkColor(MemDC, OldBkColor); {create copy of screen image} BitBlt(ScreenImageDC, 0, 0, IWidth, IHeight, DC, X1, Y1, SRCCOPY); { put monochrome mask } BitBlt(ScreenImageDC, 0, 0, IWidth, IHeight, MonoDC, 0, 0, SRCAND); BitBlt(MonoDC, 0, 0, IWidth, IHeight, MonoDC, 0, 0, NOTSRCCOPY); { put inverse monochrome mask } BitBlt(MemDC, 0, 0, IWidth, IHeight, MonoDC, 0, 0, SRCAND); { merge Screen screen image(MemDC) and Screen image(ScreenImageDC) } BitBlt(MemDC, 0, 0, IWidth, IHeight, ScreenImageDC, 0, 0, SRCPAINT); { to screen } // DSTINVERT MERGEPAINT BitBlt(DC, X1, Y1, IWidth, IHeight, MemDC, 0, 0, SRCCOPY); end else BitBlt(DC, X1, Y1, IWidth, IHeight, ImageDC, 0, 0, SRCCOPY); end; begin if (SourceBitmap.Width = 0) or (SourceBitmap.Height = 0) then Exit; X := X + R.Left; Y := Y + R.Top; X1 := X; Y1 := Y; OldBMP := 0; OldMemBMP := 0; OldMonoBMP := 0; OldScreenImageBMP := 0; MemDC := 0; ImageDC := 0; // MonoBMP := 0; // ScreenImageBMP := 0; // MemBMP := 0; MonoDC := 0; ScreenImageDC := 0; IWidth := SourceBitmap.Width; //Min( SourceBitmap.Width, R.Right-R.Left ); IHeight := SourceBitmap.Height; //Min( SourceBitmap.Height, R.Bottom-R.Top ); TmpImage := TBitmap.Create; try TmpImage.Width := IWidth; TmpImage.Height := IHeight; IRect := Rect(0, 0, IWidth, IHeight); ORect := Rect(0, 0, IWidth, IHeight); TmpImage.Canvas.Brush.Color := TransparentColor; TmpImage.Canvas.FillRect(Rect(0, 0, IWidth, IHeight)); case DrawState of fdsDefault: BitBlt(TmpImage.Canvas.Handle, 0, 0, IWidth, IHeight, SourceBitmap.Canvas.Handle, 0, 0, SRCCOPY); fdsDelicate: begin with TmpImage.Canvas do BitBlt(Handle, 0, 0, IWidth, IHeight, SourceBitmap.Canvas.Handle, 0, 0, SRCCOPY); { Convert white to clBtnHighlight } ChangeBitmapColor(TmpImage, clWhite, clBtnHighlight); { Convert gray to clBtnShadow } ChangeBitmapColor(TmpImage, clGray, clBtnShadow); { Convert transparent color to clBtnFace } // ChangeBitmapColor(TmpImage,ColorToRGB(}TransparentColor),clBtnFace); end; fdsDisabled: begin if DisabledMaskColor <> 0 then ChangeBitmapColor(TmpImage, DisabledMaskColor, clBlack); MonoBMP := TBitmap.Create; try { Create a disabled version } with MonoBMP do begin Assign(SourceBitmap); Canvas.Brush.Color := 0; Width := IWidth; if Monochrome then begin Canvas.Font.Color := clWhite; Monochrome := False; Canvas.Brush.Color := clWhite; end; Monochrome := True; end; with TmpImage.Canvas do begin Brush.Color := clBtnFace; FillRect(IRect); Brush.Color := clBtnHighlight; SetTextColor(Handle, 0); SetBkColor(Handle, clWhite); BitBlt(Handle, 1, 1, IWidth, IHeight, MonoBMP.Canvas.Handle, 0, 0, ROP_DSPDxax); Brush.Color := clBtnShadow; SetTextColor(Handle, 0); SetBkColor(Handle, clWhite); BitBlt(Handle, 0, 0, IWidth, IHeight, MonoBMP.Canvas.Handle, 0, 0, ROP_DSPDxax); end; finally MonoBMP.Free; end; end; end; with TmpImage.Canvas do if (BitmapOption = fwoStretch) or (BitmapOption = fwoPropStretch) then begin MemDC := CreateCompatibleDC(DC); MemBMP := CreateCompatibleBitmap(TmpImage.Canvas.Handle, R.Right - R.Left, R.Bottom - R.Top); OldMemBMP := SelectObject(MemDC, MemBMP); W := R.Right - R.Left; H := R.Bottom - R.Top; if BitmapOption = fwoPropStretch then begin D1 := W / IWidth; D := H / IHeight; if D > D1 then D := D1; //...D == Min W := Trunc(IWidth * D); H := Trunc(IHeight * D); end; StretchBlt(MemDC, 0, 0, W, H, Handle, 0, 0, IWidth, IHeight, SRCCOPY); IWidth := W; IHeight := H; TmpImage.Width := W; TmpImage.Height := H; BitBlt(Handle, 0, 0, IWidth, IHeight, MemDC, 0, 0, SRCCOPY); DeleteObject(SelectObject(MemDC, OldMemBMP)); DeleteDC(MemDC); end; ImageDC := CreateCompatibleDC(DC); if ATransparent then begin MemDC := CreateCompatibleDC(DC); ScreenImageDC := CreateCompatibleDC(DC); MonoDC := CreateCompatibleDC(DC); HMonoBMP := CreateBitmap(IWidth, IHeight, 1, 1, nil); ScreenImageBMP := CreateCompatibleBitmap(TmpImage.Canvas.Handle, IWidth, IHeight); MemBMP := CreateCompatibleBitmap(TmpImage.Canvas.Handle, IWidth, IHeight); OldMonoBMP := SelectObject(MonoDC, HMonoBMP); OldScreenImageBMP := SelectObject(ScreenImageDC, ScreenImageBMP); OldMemBMP := SelectObject(MemDC, MemBMP); end; OldBMP := SelectObject(ImageDC, TmpImage.Handle); if OldBMP <> 0 then begin SetMapMode(ImageDC, GetMapMode(DC)); GetObject(TmpImage.Handle, SizeOf(Windows.TBitmap), @BmpInfo); PtSize.X := BmpInfo.bmWidth; PtOrg.X := 0; PtSize.Y := BmpInfo.bmHeight; PtOrg.Y := 0; if ATransparent then begin DPtoLP(DC, PtSize, 1); DPtoLP(MemDC, PtOrg.Y, 1); end; if BitmapOption = fwoTile then begin //SavedIWidth:=IWidth; SavedIHeight := IHeight; while X1 < R.Right do begin //IWidth:=SavedIWidth; //SavedIWidth:=IWidth; if X1 + IWidth > R.Right then IWidth := R.Right - X1; while Y1 < R.Bottom do begin IHeight := SavedIHeight; // SavedIHeight:=IHeight; if Y1 + IHeight > R.Bottom then IHeight := R.Bottom - Y1; BitBltWorks; Inc(Y1, IHeight); end; Inc(X1, IWidth); Y1 := Y; end; end else BitBltWorks; end; finally DeleteObject(SelectObject(ImageDC, OldBMP)); DeleteDC(ImageDC); if ATransparent then begin DeleteObject(SelectObject(MonoDC, OldMonoBMP)); DeleteObject(SelectObject(ScreenImageDC, OldScreenImageBMP)); DeleteObject(SelectObject(MemDC, OldMemBMP)); DeleteDC(MonoDC); DeleteDC(ScreenImageDC); DeleteDC(MemDC); end; TmpImage.Free; end; end; { Brings parent window to front } procedure BringParentWindowToTop(Wnd: TWinControl); begin if Wnd is TForm then BringWindowToTop(Wnd.Handle) else if Wnd.Parent is TWinControl then BringParentWindowToTop(Wnd.Parent); end; { Gives parent window of TForm class } function GetParentForm(Control: TControl): TForm; begin if Control is TForm then Result := TForm(Control) else if Control.Parent is TWinControl then Result := GetParentForm(Control.Parent) else Result := nil; end; { Paints TWinControl with all its content onto DC with offset(shift) X,Y ...from rxLib... :( very sorry } procedure GetWindowImageFrom(Control: TWinControl; X, Y: Integer; ADrawSelf, ADrawChildWindows: Boolean; DC: HDC); var I, Count, SaveIndex: Integer; begin if Control = nil then Exit; Count := Control.ControlCount; { Copy self image } if ADrawSelf then begin SaveIndex := SaveDC(DC); SetViewportOrgEx(DC, X, Y, nil); TJvgPublicWinControl(Control).PaintWindow(DC); RestoreDC(DC, SaveIndex); end; { Copy images of graphic controls } for I := 0 to Count - 1 do begin if Control.Controls[I] <> nil then begin if Control.Controls[I] = Control then Break; if (Control.Controls[I] is TWinControl) and ADrawChildWindows then GetWindowImageFrom(TWinControl(Control.Controls[I]), TWinControl(Control.Controls[I]).Left, TWinControl(Control.Controls[I]).Top, True {ADrawSelf}, ADrawChildWindows, DC) else with Control.Controls[I] do if Visible then begin SaveIndex := SaveDC(DC); SetViewportOrgEx(DC, Left + X, Top + Y, nil); Perform(WM_PAINT, Longint(DC), 0); RestoreDC(DC, SaveIndex); end; end; end; end; { Paints(renders) TWinControl with all its content onto DC with offset (0,0) } procedure GetWindowImage(Control: TWinControl; ADrawSelf, ADrawChildWindows: Boolean; DC: HDC); begin GetWindowImageFrom(Control, 0, 0, ADrawSelf, ADrawChildWindows, DC); end; { Paints parent TWinControl with all its contents onto DC with limit of Rect } procedure GetParentImageRect(Control: TControl; Rect: TRect; DC: HDC); var I, Count, X, Y, SaveIndex: Integer; R, SelfR, CtlR: TRect; begin if Control.Parent = nil then Exit; Count := Control.Parent.ControlCount; SelfR := Bounds(Control.Left, Control.Top, Control.Width, Control.Height); // OffsetRect( Rect, Control.Left, Control.Top ); IntersectRect(SelfR, SelfR, Rect); X := -Rect.Left; Y := -Rect.Top; { Copy parent control image } SaveIndex := SaveDC(DC); SetViewportOrgEx(DC, X, Y, nil); IntersectClipRect(DC, 0, 0, Rect.Right, Rect.Bottom); TJvgPublicWinControl(Control.Parent).PaintWindow(DC); RestoreDC(DC, SaveIndex); { Copy images of graphic controls } for I := 0 to Count - 1 do begin if (Control.Parent.Controls[I] <> nil) and not (Control.Parent.Controls[I] is TWinControl) then begin if Control.Parent.Controls[I] = Control then Break; with Control.Parent.Controls[I] do begin CtlR := Bounds(Left, Top, Width, Height); if IntersectRect(R, SelfR, CtlR) and Visible then begin SaveIndex := SaveDC(DC); SetViewportOrgEx(DC, Left + X, Top + Y, nil); IntersectClipRect(DC, 0, 0, Width, Height); Perform(WM_PAINT, Longint(DC), 0); RestoreDC(DC, SaveIndex); end; end; end; end; end; {-create a rotated font based on the font object F} function CreateRotatedFont(F: TFont; Escapement: Integer): HFONT; var LF: TLogFont; begin FillChar(LF, SizeOf(LF), #0); with LF do begin lfHeight := F.Height; // lfWidth := 8;//FHeight div 4; lfEscapement := Escapement; lfOrientation := 0; if fsBold in F.Style then lfWeight := FW_BOLD else lfWeight := FW_NORMAL; // if FFontWeight <> fwDONTCARE then lfWeight:=uFontWeight; lfItalic := Ord(fsItalic in F.Style); lfUnderline := Ord(fsUnderline in F.Style); lfStrikeOut := Ord(fsStrikeOut in F.Style); lfCharSet := F.CHARSET; StrPCopy(lfFaceName, F.Name); lfQuality := DEFAULT_QUALITY; {everything else as default} lfOutPrecision := OUT_DEFAULT_PRECIS; lfClipPrecision := CLIP_DEFAULT_PRECIS; case F.Pitch of fpVariable: lfPitchAndFamily := VARIABLE_PITCH; fpFixed: lfPitchAndFamily := FIXED_PITCH; else lfPitchAndFamily := DEFAULT_PITCH; end; end; Result := CreateFontIndirect(LF); end; { Returns main window of application } function FindMainWindow(const AWndClass, AWndTitle: string): THandle; begin Result := 0; if (AWndClass <> '') or (AWndTitle <> '') then Result := FindWindow(PChar(AWndClass), PChar(AWndTitle)); end; { Calculates colors of shadow and lighted border for given base color. } procedure CalcShadowAndHighlightColors(BaseColor: TColor; Colors: TJvgLabelColors); var R, G, B: Byte; begin with Colors do begin if (BaseColor and $80000000) <> 0 then BaseColor := GetSysColor(BaseColor and $FF); B := (BaseColor and $00FF0000) shr 16; G := (BaseColor and $0000FF00) shr 8; R := BaseColor and $000000FF; if AutoShadow then begin {if RG then limit:=R else limit:=G; if B>limit then limit:=B;//...Max if (255-limit)= '0') and (CurrChar <= '9') then begin while (CurrChar >= '0') and (CurrChar <= '9') do begin Result := Result * 10 + Ord(CurrChar) - Ord('0'); NextChar; if Point then Inc(PointDepth); if (CurrChar = '.') or (CurrChar = ',') then begin NextChar; Point := True; end; end; if PointDepth <> 0 then Result := Result / (10.0 * PointDepth); end else begin case CurrChar of '-': begin NextChar; Result := -1.0 * Result; end; '(': begin Inc(BracketsCount); NextChar; Result := Expression; while CurrChar = ' ' do NextChar; if CurrChar <> ')' then begin raise Exception.CreateRes(@RsERightBracketsNotFound); CalcResult := False; Result := 0; end else NextChar; end; // '.': Point := True; // ',': Point := True; end; end; if CurrChar = ')' then begin Dec(BracketsCount); if BracketsCount < 0 then raise Exception.CreateResFmt(@RsERightBracketHavntALeftOnePosd, [ExpressionPtr - 1]); end; end; function TestForMulDiv: Single; var Denominator: Single; begin Result := DigitsToValue; // . . .test For digits, signs And brackets while True do begin case CurrChar of // Case "-": NextChar '*': begin NextChar; Result := Result * DigitsToValue; end; '/': begin NextChar; Denominator := DigitsToValue; if Denominator <> 0 then Result := Result / Denominator else begin CalcResult := False; raise Exception.CreateRes(@RsEDivideBy); end; end; else Break; end; end; end; function Expression: Single; begin Result := TestForMulDiv; //...test for '*' and '/' while True do case CurrChar of //...TestFor_AddSub ' ': NextChar; '+': begin NextChar; if CurrChar in ['+', '-', '/', '*'] then raise Exception.CreateResFmt(@RsEDuplicateSignsAtPos , [ExpressionPtr - 1]); Result := Result + TestForMulDiv; end; '-': begin NextChar; if CurrChar in ['+', '-', '/', '*'] then raise Exception.CreateResFmt(@RsEDuplicateSignsAtPos, [ExpressionPtr - 1]); Result := Result - TestForMulDiv; end; else Break; end; end; begin ExpressionPtr := 0; BracketsCount := 0; AExpression := Trim(AExpression); ExpressionLength := Length(AExpression); if ExpressionLength = 0 then raise Exception.CreateRes(@RsEExpressionStringIsEmpty); CalcResult := True; NextChar; Result := Expression; end; { Ternary operator: X ? Y : Z } function IIF(AExpression: Boolean; IfTrue, IfFalse: Variant): Variant; overload; begin if AExpression then Result := IfTrue else Result := IfFalse; end; function IIF(AExpression: Boolean; const IfTrue, IfFalse: string): string; overload; begin if AExpression then Result := IfTrue else Result := IfFalse; end; { Returns colour of Leftmost/Rightmost Top/Bottom pixel of bitmap } function GetTransparentColor(Bitmap: TBitmap; AutoTrColor: TglAutoTransparentColor): TColor; var X, Y: Integer; begin if (AutoTrColor = ftcUser) or not IsItAFilledBitmap(Bitmap) then Result := 0 else begin case AutoTrColor of ftcLeftTopPixel: begin X := 0; Y := 0; end; ftcLeftBottomPixel: begin X := 0; Y := Bitmap.Height - 1; end; ftcRightTopPixel: begin X := Bitmap.Width - 1; Y := 0; end; else {ftcRightBottomPixel} begin X := Bitmap.Width - 1; Y := Bitmap.Height - 1; end; end; Result := GetPixel(Bitmap.Canvas.Handle, X, Y); end; end; procedure TypeStringOnKeyboard(const S: string); var I: Integer; VK: Byte; begin for I := 1 to Length(S) do begin if Ord(S[I]) > 32 then VK := Ord(S[I]) - 32 else VK := Ord(S[I]); keybd_event(VK, 0, 0, 0); keybd_event(VK, 0, KEYEVENTF_KEYUP, 0); end; end; {function NextStringGridCell( Grid: TStringGrid ): Boolean; var R: TRect; I: Integer; begin with Grid do begin if Cols[Selection.Left][Selection.Top]='' then begin Result := True; Exit; end; Result := not ((Grid.Selection.Top = RowCount-1)and(Grid.Selection.Left = if Result then if Selection.Top = RowCount-1 then begin Perform( wM_KEYDOWN, VK_TAB, 1); for I:=1 to RowCount-FixedRows-1 do Perform( wM_KEYDOWN, VK_UP, 1); end else begin Perform( wM_KEYDOWN, VK_DOWN, 1); end; // Grid.SetFocus; Grid.EditorMode:=False; Grid.EditorMode:=True; end; end; } procedure DrawTextExtAligned(Canvas: TCanvas; const Text: string; R: TRect; Alignment: TglAlignment; WordWrap: Boolean); const Alignments: array [TglAlignment] of Word = (DT_LEFT, DT_RIGHT, DT_CENTER, 0); WordWraps: array [Boolean] of Word = (0, DT_WORDBREAK); var DrawPos, Pos1, Pos2, LineWidth, LineNo, LexemCount, TextHeight: Integer; Width: Integer; Lexem: string; Size: TSize; Stop, BroadwiseLine: Boolean; function GetNextLexem(var Pos1, Pos2: Integer; TrimLeft: Boolean): string; var Pos: Integer; begin Pos := Pos1; if Text[Pos] = ' ' then repeat Inc(Pos); until (Pos > Length(Text)) or (Text[Pos] <> ' '); Pos2 := Pos; if TrimLeft and (LineNo > 0) then Pos1 := Pos; repeat Inc(Pos2); until (Pos2 > Length(Text)) or (Text[Pos2] = ' '); Result := Copy(Text, Pos1, Pos2 - Pos1); end; procedure DrawLine(AdditSpace: Cardinal); var I, DrawPos1, DrawPos2: Integer; Lexem: string; Size: TSize; X, X1: Single; begin DrawPos1 := DrawPos; DrawPos2 := DrawPos; X := 0; X1 := 0; LineWidth := 0; for I := 1 to LexemCount do begin Lexem := GetNextLexem(DrawPos1, DrawPos2, I = 1); // if LexemCount=1 then Lexem:=Lexem+' '; GetTextExtentPoint32(Canvas.Handle, PChar(Lexem), Length(Lexem), Size); Inc(LineWidth, Trunc(X)); X := X + Size.cx; if (Trunc(X) > Width) and (LexemCount > 1) then Exit; if (LexemCount > 1) and BroadwiseLine then X := X + AdditSpace / (LexemCount - 1); TextOut(Canvas.Handle, R.Left + Trunc(X1), R.Top + LineNo * TextHeight, PChar(Lexem), Length(Lexem)); X1 := X; DrawPos1 := DrawPos2; end; end; begin if Text = '' then Exit; if Alignment <> ftaBroadwise then begin Windows.DrawText(Canvas.Handle, PChar(Text), Length(Text), R, DT_EXPANDTABS or WordWraps[WordWrap] or Alignments[Alignment]); Exit; end; Width := R.Right - R.Left; {Height := R.Bottom - R.Top;} LineWidth := 0; LineNo := 0; DrawPos := 1; Pos1 := 1; Pos2 := 1; LexemCount := 0; TextHeight := 0; Stop := False; BroadwiseLine := True; repeat Lexem := GetNextLexem(Pos1, Pos2, LexemCount = 0); // if LexemCount=0 then Lexem:=Lexem+' '; GetTextExtentPoint32(Canvas.Handle, PChar(Lexem), Length(Lexem), Size); Inc(LineWidth, Size.cx); Inc(LexemCount); if TextHeight < Size.cy then TextHeight := Size.cy; if (LineWidth > Width) or (Pos2 >= Length(Text)) then begin if LineWidth > Width then begin if LexemCount = 1 then Pos1 := Pos2; if LexemCount > 1 then Dec(LexemCount); DrawLine(Width - (LineWidth - Size.cx)); DrawPos := Pos1; Inc(LineNo); LexemCount := 0; LineWidth := 0; Stop := Pos1 > Length(Text); end else begin BroadwiseLine := False; //ftoBroadwiseLastLine; DrawLine(Width - LineWidth); Inc(LineNo); Stop := True; end; end else Pos1 := Pos2; until Stop; // if FAutoSize then Height := Max( 12, LineNo*TextHeight ); end; { Deserialization: loading component from text file } procedure LoadComponentFromTextFile(Component: TComponent; const FileName: string); var MemStream: TMemoryStream; FileStream: TFileStream; begin MemStream := TMemoryStream.Create; FileStream := TFileStream.Create(FileName, fmOpenRead); try ObjectTextToBinary(FileStream, MemStream); MemStream.Position := 0; MemStream.ReadComponent(Component); finally MemStream.Free; FileStream.Free; end; end; { Serializing component to string } function ComponentToString(Component: TComponent): string; var MemStream: TMemoryStream; StringStream: TStringStream; begin StringStream := TStringStream.Create(' '); MemStream := TMemoryStream.Create; try MemStream.WriteComponent(Component); MemStream.Position := 0; ObjectBinaryToText(MemStream, StringStream); StringStream.Position := 0; Result := StringStream.DataString; finally MemStream.Free; StringStream.Free; end; end; { Serialization: writing component to text file } procedure SaveComponentToTextFile(Component: TComponent; const FileName: string); var MemStream: TMemoryStream; FileStream: TFileStream; begin FileStream := TFileStream.Create(FileName, fmCreate or fmOpenWrite); try MemStream := TMemoryStream.Create; try MemStream.WriteComponent(Component); MemStream.Position := 0; ObjectBinaryToText(MemStream, FileStream); finally MemStream.Free; end; finally FileStream.Free; end; end; { Deserializing component from string } procedure StringToComponent(Component: TComponent; const Value: string); var StrStream: TStringStream; MemStream: TMemoryStream; begin StrStream := TStringStream.Create(Value); try MemStream := TMemoryStream.Create; try ObjectTextToBinary(StrStream, MemStream); MemStream.Position := 0; MemStream.ReadComponent(Component); // Result := BinStream.ReadComponent(nil); finally MemStream.Free; end; finally StrStream.Free; end; end; { Plays WAV resource } function PlayWaveResource(const ResName: string): Boolean; var WaveHandle: THandle; WavePointer: Pointer; begin Result := False; WaveHandle := FindResource(HInstance, PChar(ResName), RT_RCDATA); if WaveHandle <> 0 then begin WaveHandle := LoadResource(HInstance, WaveHandle); if WaveHandle <> 0 then begin WavePointer := LockResource(WaveHandle); Result := sndPlaySound(WavePointer, SND_MEMORY or SND_ASYNC); UnlockResource(WaveHandle); FreeResource(WaveHandle); end; end; end; { User name for current thread } // JVCL4: Should go to JvJCLUtils.pas as "GetUserName: string" function UserName: string; var Name: array [0..127] of Char; Len: DWORD; begin Len := SizeOf(Name); GetUserName(Name, Len); Result := Name; end; { PC name } // JVCL4: Should go to JvJCLUtils.pas as "GetComputerName: string" function ComputerName: string; begin Result := JvJCLUtils.GetComputerName; end; { Creates ini-file with the same name to project's file - use ChangeFileExt } function CreateIniFileName: string; begin Result := ParamStr(0); SetLength(Result, Length(Result) - Length(ExtractFileExt(Result))); Result := Result + '.ini'; end; { Expands string with spaces up to given Length } function ExpandString(const Str: string; Len: Integer): string; var I: Integer; begin Result := Str; if Length(Result) >= Len then Exit; SetLength(Result, Len); for I := 1 to Length(Result) do if I <= Length(Str) then Result[I] := Str[I] else Result[I] := ' '; end; { Transliterating string Rus <-> Lat } function Transliterate(const Str: string; RusToLat: Boolean): string; const LAT: string = 'ABVGDEGZIIKLMNOPRSTUFHC___"Y''EUYabvgdegziiklmnoprstufhc___"y''euy+'; RUS: string = 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ+'; LATRUS: array [1..52, 1..2] of Char = ( ('A', 'À'), ('B', 'Á'), ('C', 'Ö'), ('D', 'Ä'), ('E', 'Å'), ('F', 'Ô'), ('G', 'Æ'), ('H', 'Õ'), ('I', 'È'), ('J', 'É'), ('K', 'Ê'), ('L', 'Ë'), ('M', 'Ì'), ('N', 'Í'), ('O', 'Î'), ('P', 'Ï'), ('Q', #0), ('R', 'Ð'), ('S', 'Ñ'), ('T', 'Ò'), ('U', 'Ó'), ('V', 'Â'), ('W', #0), ('X', #0), ('Y', 'Û'), ('Z', 'Ç'), ('a', 'à'), ('b', 'á'), ('c', 'ö'), ('d', 'ä'), ('e', 'å'), ('f', 'ô'), ('g', 'æ'), ('h', 'õ'), ('i', 'è'), ('j', 'é'), ('k', 'ê'), ('l', 'ë'), ('m', 'ì'), ('n', 'í'), ('o', 'î'), ('p', 'ï'), ('q', #0), ('r', 'ð'), ('s', 'ñ'), ('t', 'ò'), ('u', 'ó'), ('v', 'â'), ('w', #0), ('x', #0), ('y', 'û'), ('z', 'ç') ); TRANS_PAIRCOUNT = 14; TRANS_PAIR: array [1..TRANS_PAIRCOUNT, Boolean] of string = (('õ', 'kh'), ('ö', 'ts'), ('÷', 'ch'), ('ø', 'sh'), ('ù', 'shch'), ('þ', 'iu'), ('ÿ', 'ia'), ('Õ', 'Kh'), ('Ö', 'Ts'), ('×', 'Ñh'), ('Ø', 'Sh'), ('Ù', 'Shch'), ('Þ', 'Iu'), ('ß', 'Ia')); var I, J: Integer; begin Result := Str; for I := 1 to TRANS_PAIRCOUNT do Result := StringReplace(Result, TRANS_PAIR[I, not RusToLat], TRANS_PAIR[I, RusToLat], [rfReplaceAll]); if RusToLat then begin for I := 1 to Length(Result) do if Result[I] in ['À'..'ÿ'] then Result[I] := LAT[Ord(Result[I]) - Ord('À') + 1]; end else for I := 1 to Length(Result) do if Result[I] in ['A'..'z'] then for J := 1 to 52 do if Result[I] = LATRUS[J, 1] then begin Result[I] := LATRUS[J, 2]; Break; end; end; { Function returns True, if font is small } function IsSmallFonts: Boolean; var DC: HDC; begin DC := GetDC(HWND_DESKTOP); Result := (GetDeviceCaps(DC, LOGPIXELSX) = 96); { For large font it would be 120 } ReleaseDC(HWND_DESKTOP, DC); end; { Color depth in system: 8, 16 or 32 bits } function SystemColorDepth: Integer; var DC: HDC; begin DC := GetDC(HWND_DESKTOP); Result := GetDeviceCaps(DC, BITSPIXEL); ReleaseDC(HWND_DESKTOP, DC); end; function GetFileType(const FileName: string): TglFileType; var Ext: string; I: Integer; const Extensions: array [0..3] of string = ('.gif', '.jpeg', '.jpg', '.bmp'); Types: array [0..4] of TglFileType = (fftGif, fftJpeg, fftJpeg, fftBmp, fftUndefined); begin Result := fftUndefined; Ext := ExtractFileExt(FileName); for I := Low(Extensions) to High(Extensions) do if SameFileName(Ext, Extensions[I]) then begin Result := Types[I]; Break; end; end; { Looks for upper(topmost) control at given point } function FindControlAtPt(Control: TWinControl; Pt: TPoint; MinClass: TClass): TControl; var I: Integer; begin Result := nil; for I := Control.ControlCount - 1 downto 0 do if (Control.Controls[I] is MinClass) and PtInRect(Control.Controls[I].BoundsRect, Pt) then begin Result := Control.Controls[I]; Break; end; end; { StrPosExt - Looks for position of one string inside another with given length Outperforms StrPos on long strings in 10-100 times (1-2 orders) } function StrPosExt(const Str1, Str2: PChar; Str2Len: DWORD): PChar; assembler; asm PUSH EDI PUSH ESI PUSH EBX OR EAX,EAX // Str1 JE @@2 // If Str1 is empty - get out OR EDX,EDX // Str2 JE @@2 // If Str2 is empty - get out MOV EBX,EAX MOV EDI,EDX // Setting offset for SCASB - substring Str2 XOR AL,AL // Zero AL push ECX // String length MOV ECX,0FFFFFFFFH // to be assured it will never underflow REPNE SCASB // Searching for end of Str2 substring NOT ECX // Inverting ECX - getting string length +1 DEC ECX // And here is exact length JE @@2 // length = 0? get out! MOV ESI,ECX // Saving substring length in ESI pop ECX SUB ECX,ESI // ECX := Length(Str1) - Length(Str2) JBE @@2 // Length(substring) > Length(containing string) ? get out! MOV EDI,EBX // EDI points to the beginning od Str1 LEA EBX,[ESI-1] // EBX - length of comparision of strings @@1: MOV ESI,EDX // ESI - offset of Str2 string LODSB // Loading 1st byte of substring into AL REPNE SCASB // Searching that very char in EDI string JNE @@2 // Char not found? get out! MOV EAX,ECX // Saving difference of lengths of strings PUSH EDI // Saving current offset of search MOV ECX,EBX REPE CMPSB // per-byte comparision of strings POP EDI MOV ECX,EAX JNE @@1 // If strings do not match - searching for 1st substring's char again LEA EAX,[EDI-1] JMP @@3 @@2: XOR EAX,EAX @@3: POP EBX POP ESI POP EDI end; {$IFNDEF USEJVCL} function DrawText(Canvas: TCanvas; Text: PAnsiChar; Len: Integer; var R: TRect; WinFlags: Integer): Integer; overload; begin Result := Windows.DrawText(Canvas.Handle, Text, Len, R, WinFlags); end; function DrawText(Canvas: TCanvas; const Text: string; Len: Integer; var R: TRect; WinFlags: Integer): Integer; overload; begin Result := DrawText(Canvas, PChar(Text), Len, R, WinFlags and not DT_MODIFYSTRING); // make sure the string cannot be modified end; function PtInRectExclusive(R: TRect; Pt: TPoint): Boolean; begin R.Left := R.Left + 1; R.Top := R.Top + 1; Result := PtInRect(R, Pt); end; function CanvasMaxTextHeight(Canvas: TCanvas): Integer; var tt: TTextMetric; begin // (ahuser) Qt returns different values for TextHeight('Ay') and TextHeigth(#1..#255) {$IFDEF VisualCLX} Canvas.Start; // if it is called outside a paint event RequiredState(Canvas, [csHandleValid, csFontValid, csBrushValid]); {$ENDIF VisualCLX} GetTextMetrics(Canvas.Handle, tt); {$IFDEF VisualCLX} Canvas.Stop; {$ENDIF VisualCLX} Result := tt.tmHeight; end; {$ENDIF !USEJVCL} {$IFDEF USEJVCL} {$IFDEF UNITVERSIONING} initialization RegisterUnitVersion(HInstance, UnitVersioning); finalization UnregisterUnitVersion(HInstance); {$ENDIF UNITVERSIONING} {$ENDIF USEJVCL} end.