lazarus/lcl/interfaces/customdrawn/customdrawnwinapi.inc
Maxim Ganetsky f0eb9b849d IDE, LCL: Lazarus help output refactoring by n7800, issue #40690:
1. The text has been slightly corrected and made more uniform.
2. The parameters are sorted in some logical order, starting with the more "global" ones. A long list of values for debugging is located at the end. Now all parameters are visible at once, without scrolling.
3. Indentations fixed.
4. The list of values for the --skip-checks parameter is listed in a column, similar to the values for the --debug-enable parameter. This is easier to read and does not create a very long line, which is visible in the screenshot.
5. The "LCL Interface specific options:" header is displayed only if such parameters exist.
6. Changed max line length to a more standard 80.
7. Help output has been moved in a nested function.
8. Removed unused code.
2024-01-20 05:04:42 +03:00

6379 lines
191 KiB
PHP

{%MainUnit customdrawnint.pp}
{******************************************************************************
All CustomDrawn backend independent Winapi implementations.
!! Keep alphabetical !!
******************************************************************************
Implementation
******************************************************************************
*****************************************************************************
This file is part of the Lazarus Component Library (LCL)
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
}
//##apiwiz##sps## // Do not remove, no wizard declaration before this line
{------------------------------------------------------------------------------
Function: Arc
Params: DC: HDC; Left,Top,Right,Bottom,angle1,angle2 : Integer
Returns: Boolean
------------------------------------------------------------------------------}
function TCDWidgetSet.Arc(DC: HDC; Left,Top,Right,Bottom,angle1,angle2 : Integer): Boolean;
var
LazDC: TLazCanvas absolute DC;
begin
{$ifdef VerboseCDWinAPI}
DebugLn(Format(':>[WinAPI Polygon] DC=%s', [dbghex(DC)]));
{$endif}
if not IsValidDC(DC) then Exit(False);
//LazDC.Arc(...);
Result := True;
end;
(*{------------------------------------------------------------------------------
Function: AngleChord
Params: DC: HDC; x1, y1, x2, y2, angle1, angle2: Integer
Returns: Boolean
------------------------------------------------------------------------------}
function TQtWidgetSet.AngleChord(DC: HDC; x1, y1, x2, y2, angle1, angle2: Integer): Boolean;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI AngleChord] DC: ', dbghex(DC));
{$endif}
Result := IsValidDC(DC);
if Result then
QPainter_drawChord(TQtDeviceContext(DC).Widget, x1, y1, x2, y2, Angle1, Angle2);
end;*)
{------------------------------------------------------------------------------
Function: BeginPaint
Params:
Returns:
This function is Called:
- Once on every OnPaint event
------------------------------------------------------------------------------}
function TCDWidgetSet.BeginPaint(Handle: hWnd; Var PS : TPaintStruct): hdc;
begin
{$ifdef VerboseCDDrawing}
DebugLn('Trace:> [WinAPI BeginPaint] Handle=', dbghex(Handle));
{$endif}
Result := 0;
if Handle = 0 then Exit;
(* Widget := TQtWidget(Handle);
if Widget <> nil then
DC := TQtDeviceContext.Create(Widget.PaintData.PaintWidget, True)
else
DC := TQtDeviceContext.Create(nil, True);
PS.hdc := HDC(DC);
if Handle<>0 then
begin
// if current handle has paintdata information,
// setup hdc with it
//DC.DebugClipRect('BeginPaint: Before');
if Widget.PaintData.ClipRegion <> nil then
begin
//Write('>>> Setting Paint ClipRegion: ');
//DebugRegion('PaintData.ClipRegion: ', Widget.PaintData.ClipRegion);
DC.setClipRegion(Widget.PaintData.ClipRegion);
DC.setClipping(True);
end;
if Widget.PaintData.ClipRect <> nil then
begin
New(DC.vClipRect);
DC.vClipRect^ := Widget.PaintData.ClipRect^;
end;
end;
Result := PS.hdc;
{$ifdef VerboseQtWinAPI}
WriteLn('Trace:< [WinAPI BeginPaint] Result=', dbghex(Result));
{$endif}*)
end;
function TCDWidgetSet.BitBlt(DestDC: HDC; X, Y, Width, Height: Integer; SrcDC: HDC; XSrc, YSrc: Integer; Rop: DWORD): Boolean;
begin
{$ifdef VerboseCDDrawing}
WriteLn('Trace:> [TCDWidgetSet.BitBlt]');
{$endif}
Result := StretchBlt(DestDC, X, Y, Width, Height, SrcDC, XSrc, YSrc, Width,
Height, ROP);
{$ifdef VerboseCDDrawing}
WriteLn('Trace:< [TCDWidgetSet.BitBlt]');
{$endif}
end;
(*function TQtWidgetSet.CallNextHookEx(hHk: HHOOK; ncode : Integer; wParam: WParam; lParam : LParam) : Integer;
begin
{$ifdef VerboseQtWinAPI_MISSING_IMPLEMENTATION}
WriteLn('***** [WinAPI TQtWidgetSet.CallNextHookEx] missing implementation ');
{$endif}
Result := 0;
end;
function TQtWidgetSet.CallWindowProc(lpPrevWndFunc : TFarProc; Handle : HWND; Msg : UINT; wParam: WParam; lParam : lParam) : Integer;
begin
{$ifdef VerboseQtWinAPI_MISSING_IMPLEMENTATION}
WriteLn('***** [WinAPI TQtWidgetSet.CallWindowProc] missing implementation ');
{$endif}
Result := -1;
end;
{------------------------------------------------------------------------------
Method: ClientToScreen
Params: Handle -
Returns:
------------------------------------------------------------------------------}
function TQtWidgetSet.ClientToScreen(Handle: HWND; var P: TPoint) : Boolean;
var
APoint: TQtPoint;
Pt: TPoint;
begin
Result := IsValidHandle(Handle);
if Result then
begin
APoint := QtPoint(P.X, P.Y);
QWidget_mapToGlobal(TQtWidget(Handle).GetContainerWidget, @APoint, @APoint);
if TQtWidget(Handle).ChildOfComplexWidget = ccwScrollingWinControl then
begin
Pt := TQtCustomControl(Handle).viewport.ScrolledOffset;
dec(APoint.X, Pt.X);
dec(APoint.Y, Pt.Y);
end;
P := Point(APoint.x, APoint.y);
end;
end;*)
{------------------------------------------------------------------------------
Method: ClipboardFormatToMimeType
Params: FormatID - a registered format identifier (can't be a predefined format)
Returns: the corresponding mime type as string
------------------------------------------------------------------------------}
function TCDWidgetSet.ClipboardFormatToMimeType(FormatID: TClipboardFormat): string;
begin
{$ifdef VerboseCDClipboard}
DebugLn(Format('[TCDWidgetSet.ClipboardFormatToMimeType] FormatID=%d', [FormatID]));
{$endif}
if FClipBoardFormats.Count > Integer(FormatID) then
Result := FClipBoardFormats[FormatID]
else
Result := '';
end;
function TCDWidgetSet.ClipboardGetFormats(ClipboardType: TClipboardType;
var Count: integer; var List: PClipboardFormat): boolean;
var
i: Integer;
Str: string;
begin
{$ifdef VerboseCDClipboard}
DebugLn('[TCDWidgetSet.GenericClipboardGetFormats]');
{$endif}
Result := False;
Count := 0;
List := nil;
Count := FClipBoardFormats.Count;
GetMem(List, Count * SizeOf(TClipboardFormat));
for i := 0 to Count - 1 do
begin
Str := FClipBoardFormats.Strings[i];
List[i] := ClipboardRegisterFormat(Str);
end;
Result := True;
end;
{------------------------------------------------------------------------------
Method: ClipboardRegisterFormat
Params: AMimeType - a string (usually a MIME type) identifying a new format
type to register
Returns: the registered Format identifier (TClipboardFormat)
------------------------------------------------------------------------------}
function TCDWidgetSet.ClipboardRegisterFormat(const AMimeType: string): TClipboardFormat;
var
Index: Integer;
begin
Index := FClipBoardFormats.IndexOf(AMimeType);
if Index < 0 then
Index := FClipBoardFormats.Add(AMimeType);
Result := Index;
{$ifdef VerboseCDClipboard}
DebugLn(Format('[TCDWidgetSet.ClipboardRegisterFormat] AMimeType=%s Result=%d', [AMimeType, Index]));
{$endif}
end;
{------------------------------------------------------------------------------
Function: CombineRgn
Params: Dest, Src1, Src2, fnCombineMode
Returns: longint
Combine the 2 Source Regions into the Destination Region using the specified
Combine Mode. The Destination must already be initialized. The Return value
is the Destination's Region type, or ERROR.
The Combine Mode can be one of the following:
RGN_AND : Gets a region of all points which are in both source regions
RGN_COPY : Gets an exact copy of the first source region
RGN_DIFF : Gets a region of all points which are in the first source
region but not in the second.(Source1 - Source2)
RGN_OR : Gets a region of all points which are in either the first
source region or in the second.(Source1 + Source2)
RGN_XOR : Gets all points which are in either the first Source Region
or in the second, but not in both.
The result can be one of the following constants
Error
NullRegion
SimpleRegion
ComplexRegion
------------------------------------------------------------------------------}
function TCDWidgetSet.CombineRgn(Dest, Src1, Src2: HRGN; fnCombineMode: Longint): Longint;
var
DestRgn: TLazRegion absolute Dest;
Src1Rgn: TLazRegion absolute Src1;
Src2Rgn: TLazRegion absolute Src2;
begin
Result := ERROR;
if not IsValidGDIObject(Dest) or not IsValidGDIObject(Src1) then Exit;
if (fnCombineMode<>RGN_COPY) and not IsValidGDIObject(Src2) then Exit;
// If the operation is a copy, execute it now, as it will not involve Src2
// The common code would not work in this case
if fnCombineMode = RGN_COPY then
begin
if Dest <> Src1 then DestRgn.Assign(Src1Rgn);
Result := DestRgn.GetRegionKind();
Exit;
end;
// Now operations which involve Src2, consider both cases: Dest=Src1 and Dest<>Src1
if Dest = Src1 then
DestRgn.CombineWith(Src2Rgn, fnCombineMode)
else
begin
DestRgn.Assign(Src1Rgn);
DestRgn.CombineWith(Src2Rgn, fnCombineMode);
end;
Result := DestRgn.GetRegionKind();
end;
{------------------------------------------------------------------------------
Method: CreateBitmap
Params:
Returns:
This functions is for TBitmap support.
Specifically it is utilized on when a handle for a bitmap is needed
------------------------------------------------------------------------------}
function TCDWidgetSet.CreateBitmap(Width, Height: Integer;
Planes, BitCount: Longint; BitmapBits: Pointer): HBITMAP;
var
lRawImage: TRawImage;
lMask: HBitmap;
NewBits: Pointer;
NewBitsSize: PtrUInt;
RSS: PtrUInt;
ARowStride: PtrUInt;
begin
{$ifdef VerboseCDBitmap}
DebugLn('Trace:> [WinAPI CreateBitmap]',
' Width:', dbgs(Width),
' Height:', dbgs(Height),
' Planes:', dbgs(Planes),
' BitCount:', dbgs(BitCount),
' BitmapBits: ', dbgs(BitmapBits));
{$endif}
// for win32 data is aligned to WORD
// for ARM speed optimization the best is realign data to DWORD
Result := 0;
NewBits := nil;
lRawImage.Init;
case BitCount of
1: lRawImage.Description.Init_BPP1(Width, Height);
15, 16: lRawImage.Description.Init_BPP16_R5G6B5(Width, Height);
24: lRawImage.Description.Init_BPP24_B8G8R8_BIO_TTB(Width, Height);
32: lRawImage.Description.Init_BPP32_A8R8G8B8_BIO_TTB(Width, Height);
else
lRawImage.Description.Init_BPP32_A8R8G8B8_BIO_TTB(Width, Height);
end;
RSS := GetBytesPerLine(Width, BitCount, rileWordBoundary);
if BitmapBits <> nil then
begin
{$ifdef VerboseCDBitmap}
DebugLn('Trace: [WinAPI CreateBitmap] BitmapBits <> nil');
{$endif}
ARowStride := GetBytesPerLine(Width, BitCount, rileDWordBoundary);
if not CopyImageData(Width, Height, RSS, BitCount, BitmapBits, Types.Rect(0, 0, Width, Height),
riloBottomToTop, riloBottomToTop, rileDWordBoundary, NewBits, NewBitsSize) then
begin
{$ifdef VerboseCDBitmap}
DebugLn('Trace: [WinAPI CreateBitmap] CopyImageData failed');
{$endif}
// this was never tested
ARowStride := RSS;
NewBitsSize := RSS * Height;
NewBits := AllocMem(NewBitsSize);
System.Move(BitmapBits^, NewBits^, NewBitsSize);
end;
lRawImage.Data := NewBits;
lRawImage.DataSize := NewBitsSize;
//Result := HBitmap(TQtImage.Create(NewBits, Width, Height, ARowStride, Format, True));
RawImage_CreateBitmaps(lRawImage, Result, lMask, True);
end
else
begin
{$ifdef VerboseCDBitmap}
DebugLn('Trace: [WinAPI CreateBitmap] Creating Data');
{$endif}
lRawImage.CreateData(True);
RawImage_CreateBitmaps(lRawImage, Result, lMask, True);
end;
{$ifdef VerboseCDBitmap}
DebugLn('Trace:< [WinAPI CreateBitmap] Bitmap:', dbghex(Result));
{$endif}
end;
{------------------------------------------------------------------------------
Function: CreateBrushIndirect
Params: none
Returns: Nothing
------------------------------------------------------------------------------}
function TCDWidgetSet.CreateBrushIndirect(const LogBrush: TLogBrush): HBRUSH;
var
lBrush: TFPCustomBrush;
begin
lBrush := TFPCustomBrush.Create;
Result := HBRUSH(lBrush);
{$ifdef VerboseCDDrawing}
DebugLn(Format(':>[TCDWidgetSet.CreateBrushIndirect] Style: %d, Color: %8x Result:%x',
[LogBrush.lbStyle, LogBrush.lbColor, Result]));
{$endif}
// brush color
lBrush.FPColor := TColorToFPColor(LogBrush.lbColor);
// brush style
case LogBrush.lbStyle of
BS_NULL: lBrush.Style := bsClear; // Same as BS_HOLLOW.
BS_SOLID: lBrush.Style := bsSolid;
{ BS_HATCHED: // Hatched brushes.
begin
case LogBrush.lbHatch of
HS_BDIAGONAL: QtBrush.Style := QtBDiagPattern;
HS_CROSS: QtBrush.Style := QtCrossPattern;
HS_DIAGCROSS: QtBrush.Style := QtDiagCrossPattern;
HS_FDIAGONAL: QtBrush.Style := QtFDiagPattern;
HS_HORIZONTAL: QtBrush.Style := QtHorPattern;
HS_VERTICAL: QtBrush.Style := QtVerPattern;
else
QtBrush.Style := QtSolidPattern;
end;
end;
BS_DIBPATTERN, // A pattern brush defined by a device-independent
// bitmap (DIB) specification. If lbStyle is BS_DIBPATTERN, the
// lbHatch member contains a handle to a packed DIB.Windows 95:
// Creating brushes from bitmaps or DIBs larger than 8x8 pixels
// is not supported. If a larger bitmap is given, only a portion
// of the bitmap is used.
BS_DIBPATTERN8X8, // Same as BS_DIBPATTERN.
BS_DIBPATTERNPT, // A pattern brush defined by a device-independent
// bitmap (DIB) specification. If lbStyle is BS_DIBPATTERNPT, the
// lbHatch member contains a pointer to a packed DIB.
BS_PATTERN, // Pattern brush defined by a memory bitmap.
BS_PATTERN8X8: // Same as BS_PATTERN.
begin
QtBrush.setTextureImage(TQtImage(LogBrush.lbHatch).FHandle);
QtBrush.Style := QtTexturePattern;
end; }
else
DebugLn(Format('Unsupported Brush Style %d',[LogBrush.lbStyle]));
end;
{$ifdef VerboseCDDrawing}
DebugLn(':<[WinAPI CreateBrushIndirect] Result: ', dbghex(Result));
{$endif}
end;
(*function TQtWidgetSet.CreateCaret(Handle: HWND; Bitmap: hBitmap; Width, Height: Integer): Boolean;
begin
Result := (Handle <> 0) and
QtCaret.CreateCaret(TQtWidget(Handle), Bitmap, Width, Height);
end;*)
{ In LCL-CustomDrawn it is completely irrelevant if a Bitmap is compatible with the screen,
so just create any standard bitmap }
function TCDWidgetSet.CreateCompatibleBitmap(DC: HDC; Width, Height: Integer): HBITMAP;
begin
Result := CreateBitmap(Width, Height, 1, 32, nil);
end;
{------------------------------------------------------------------------------
Function: CreateCompatibleDC
Params: DC - handle to memory device context
Returns: handle to a memory device context
Creates a memory device context (DC) compatible with the specified device.
This is utilized for example for creating a Canvas for a Bitmap, by later using
SelectObject to select the bitmap
------------------------------------------------------------------------------}
function TCDWidgetSet.CreateCompatibleDC(DC: HDC): HDC;
begin
{$ifdef VerboseCDDrawing}
DebugLn('[WinAPI CreateCompatibleDC] DC: ', dbghex(DC));
{$endif}
Result := HDC(TLazCanvas.Create(nil));
end;
{------------------------------------------------------------------------------
Function: CreateEllipticRgn
Params: p1 - X position of the top-left corner
p2 - Y position of the top-left corner
p3 - X position of the bottom-right corner
p4 - Y position of the bottom-right corner
Returns: HRGN
------------------------------------------------------------------------------}
function TCDWidgetSet.CreateEllipticRgn(p1, p2, p3, p4: Integer): HRGN;
var
lRegion: TLazRegion;
begin
{$ifdef VerboseCDRegions}
DebugLn('[WinAPI CreateEllipticRgn] ');
{$endif}
lRegion := TLazRegion.Create;
lRegion.AddEllipse(p1, p2, p3, p4);
Result := HRGN(lRegion);
end;
{------------------------------------------------------------------------------
Function: CreateFontIndirect
Params: const LogFont: TLogFont
Returns: HFONT
Creates a font GDIObject.
------------------------------------------------------------------------------}
function TCDWidgetSet.CreateFontIndirect(const LogFont: TLogFont): HFONT;
begin
Result := CreateFontIndirectEx(LogFont, '');
end;
{------------------------------------------------------------------------------
Function: CreateFontIndirectEx
Params: const LogFont: TLogFont
Returns: HFONT
Creates a font GDIObject.
------------------------------------------------------------------------------}
function TCDWidgetSet.CreateFontIndirectEx(const LogFont: TLogFont; const LongFontName: string): HFONT;
var
lFont: TLazCDCustomFont;
// FamilyName: string;
begin
{$ifdef VerboseCDDrawing}
DebugLn(Format('[TCDWidgetSet.CreateFontIndirectEx] LongFontName=%s lfHeight=%d',
[LongFontName, LogFont.lfHeight]));
{$endif}
lFont := TLazCDCustomFont.Create;
Result := HFONT(lFont);
{$ifndef CD_UseNativeText}
lFont.ftFont.Name := BackendGetFontPath(LogFont, LongFontName);
lFont.ftFont.Hinted := true;
lFont.ftFont.ClearType := true;
lFont.ftFont.Quality := grqHighQuality;
{$endif}
(*const
QStyleStategy: array [DEFAULT_QUALITY..CLEARTYPE_NATURAL_QUALITY] of QFontStyleStrategy = (
{ DEFAULT_QUALITY } QFontPreferDefault,
{ DRAFT_QUALITY } QFontPreferMatch,
{ PROOF_QUALITY } QFontPreferQuality,
{ NONANTIALIASED_QUALITY } QFontNoAntialias,
{ ANTIALIASED_QUALITY } QFontPreferAntialias,
{ CLEARTYPE_QUALITY } QFontPreferAntialias,
{ CLEARTYPE_NATURAL_QUALITY } QFontPreferAntialias
);*)
lFont.Size := Abs(LogFont.lfHeight);
lFont.ftFont.SizeInPoints := lFont.Size;
(* // Some values at available on Qt documentation at a table
// Others are guesses. The best would be to test different values for those
// See: http://doc.trolltech.com/4.1/qfont.html#Weight-enum
case LogFont.lfWeight of
FW_THIN : QtFont.setWeight(10);
FW_EXTRALIGHT : QtFont.setWeight(15);
FW_LIGHT : QtFont.setWeight(25);
FW_NORMAL : QtFont.setWeight(50);
FW_MEDIUM : QtFont.setWeight(55);
FW_SEMIBOLD : QtFont.setWeight(63);
FW_BOLD : QtFont.setWeight(75);
FW_EXTRABOLD : QtFont.setWeight(80);
FW_HEAVY : QtFont.setWeight(87);
end;
QtFont.Angle := LogFont.lfEscapement;
//LogFont.lfOrientation;
QtFont.setItalic(LogFont.lfItalic = High(Byte));
QtFont.setUnderline(LogFont.lfUnderline = High(Byte));
QtFont.setStrikeOut(LogFont.lfStrikeOut = High(Byte));
FamilyName := StrPas(LogFont.lfFaceName);
if (CompareText(FamilyName, 'default') <> 0) then
QtFont.setFamily(FamilyName)
else
QtFont.setFamily(UTF16ToUTF8(GetDefaultAppFontName));
if (LogFont.lfQuality >= Low(QStyleStategy)) and (LogFont.lfQuality <= High(QStyleStategy)) then
QtFont.setStyleStrategy(QStyleStategy[LogFont.lfQuality]);*)
end;
function TCDWidgetSet.CreateIconIndirect(IconInfo: PIconInfo): HICON;
//var
// AIcon: TCDIcon;
{ APixmap, ATemp: QPixmapH;
AMask: QBitmapH;}
begin
Result := 0;
{ if IsValidGDIObject(IconInfo^.hbmColor) then
begin
APixmap := QPixmap_create();
QPixmap_fromImage(APixmap, TQtImage(IconInfo^.hbmColor).FHandle);
if IconInfo^.hbmMask <> 0 then
begin
ATemp := QPixmap_create();
QPixmap_fromImage(ATemp, TQtImage(IconInfo^.hbmMask).FHandle);
AMask := QBitmap_create(ATemp);
QPixmap_setMask(APixmap, AMask);
QPixmap_destroy(ATemp);
QBitmap_destroy(AMask);
end;
if IconInfo^.fIcon then
begin
AIcon := TQtIcon.Create;
AIcon.addPixmap(APixmap);
Result := HICON(AIcon);
end else
Result := HCURSOR(TQtCursor.Create(APixmap, IconInfo^.xHotspot, IconInfo^.yHotspot));
QPixmap_destroy(APixmap);
end;}
end;
(*{------------------------------------------------------------------------------
Function: CreatePatternBrush
Params: HBITMAP
Returns: HBRUSH
------------------------------------------------------------------------------}
function TCDWidgetSet.CreatePatternBrush(ABitmap: HBITMAP): HBRUSH;
{var
Image: QImageH;
QtBrush: TQtBrush;}
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI CreatePatternBrush]',' Bitmap=', dbghex(ABitmap));
{$endif}
Result := 0;
{ if ABitmap = 0 then
exit;
QtBrush := TQtBrush.Create(True);
Image := QImage_create(TQtImage(ABitmap).FHandle);
try
QtBrush.setTextureImage(Image);
finally
QImage_destroy(Image);
end;
Result := //HBRUSH(QtBrush);}
end;*)
{------------------------------------------------------------------------------
Function: CreatePenIndirect
Params: none
Returns: HPEN
------------------------------------------------------------------------------}
function TCDWidgetSet.CreatePenIndirect(const LogPen: TLogPen): HPEN;
var
lPen: TFPCustomPen;
begin
lPen := TFPCustomPen.Create;
Result := HBRUSH(lPen);
{$ifdef VerboseCDDrawing}
DebugLn(Format(':>[TCDWidgetSet.CreatePenIndirect] Style: %d, Color: %8x Result:"%x',
[LogPen.lopnStyle, LogPen.lopnColor, Result]));
{$endif}
lPen.FPColor := TColorToFPColor(LogPen.lopnColor);
case LogPen.lopnStyle and PS_STYLE_MASK of
PS_SOLID: lPen.Style := psSolid;
PS_DASH: lPen.Style := psDash;
PS_DOT: lPen.Style := psDot;
PS_DASHDOT: lPen.Style := psDashDot;
PS_DASHDOTDOT:lPen.Style := psDashDotDot;
PS_NULL: lPen.Style := psClear;
else
lPen.Style := psSolid;
end;
lPen.Width := Max(1, LogPen.lopnWidth.X);
end;
{------------------------------------------------------------------------------
Function: CreatePolygonRgn
Params: none
Returns: HRGN
------------------------------------------------------------------------------}
function TCDWidgetSet.CreatePolygonRgn(Points: PPoint; NumPts: Integer; FillMode: integer): HRGN;
var
lLazRegion: TLazRegion;
lPoints: array of TPoint;
i: Integer;
lFillMode: TLazRegionFillMode;
begin
lLazRegion := TLazRegion.Create;
SetLength(lPoints, NumPts);
for i := 0 to NumPts-1 do
lPoints[i] := Points[i];
{fillmode can be ALTERNATE or WINDING as msdn says}
if FillMode = ALTERNATE then lFillMode := rfmOddEven
else lFillMode := rfmWinding;
lLazRegion.AddPolygon(lPoints, lFillMode);
Result := HRGN(lLazRegion);
{$ifdef VerboseCDWinAPI}
DebugLn('[WinAPI CreatePolygonRgn] Result: ', dbghex(Result));
{$endif}
end;
{------------------------------------------------------------------------------
Function: CreateRectRgn
Params: none
Returns: HRGN
------------------------------------------------------------------------------}
function TCDWidgetSet.CreateRectRgn(X1,Y1,X2,Y2 : Integer): HRGN;
var
lLazRegion: TLazRegion;
begin
lLazRegion := TLazRegion.Create;
lLazRegion.SetAsSimpleRectRegion(Types.Rect(X1, Y1, X2, Y2));
Result := HRGN(lLazRegion);
{$ifdef VerboseCDWinAPI}
DebugLn('Trace: [WinAPI CreateRectRgn] Result: ', dbghex(Result));
{$endif}
end;
{------------------------------------------------------------------------------
Procedure: DeleteCriticalSection
Params: var CritSection: TCriticalSection
Returns: Nothing
------------------------------------------------------------------------------}
procedure TCDWidgetSet.DeleteCriticalSection(var CritSection: TCriticalSection);
var
ACritSec: System.PRTLCriticalSection;
begin
ACritSec:=System.PRTLCriticalSection(CritSection);
System.DoneCriticalsection(ACritSec^);
Dispose(ACritSec);
CritSection:=0;
end;
{------------------------------------------------------------------------------
Function: DeleteDC
Params: none
Returns: Nothing
------------------------------------------------------------------------------}
function TCDWidgetSet.DeleteDC(hDC: HDC): Boolean;
begin
{$ifdef VerboseCDWinAPI}
DebugLn('[WinAPI DeleteDC] Handle: ', dbghex(hDC));
{$endif}
Result := False;
if not IsValidDC(hDC) then exit;
Result := True;
TLazCanvas(hDC).Free;
end;
{------------------------------------------------------------------------------
Function: DeleteObject
Params: none
Returns: Nothing
------------------------------------------------------------------------------}
function TCDWidgetSet.DeleteObject(GDIObject: HGDIOBJ): Boolean;
var
aObject: TObject;
{$if defined(VerboseCDDrawing) or defined(VerboseCDBitmap)}
ObjType: string;
{$endif}
begin
{$if defined(VerboseCDDrawing) or defined(VerboseCDBitmap)}
DebugLn('Trace:> [WinAPI DeleteObject] GDIObject: ', dbghex(GDIObject));
ObjType := 'Unidentifyed';
{$endif}
Result := False;
if GDIObject = 0 then Exit(True);
if not IsValidGDIObject(GDIObject) then Exit;
aObject := TObject(GDIObject);
(* if (aObject is TQtResource) and TQtResource(aObject).FShared then
Exit(True);*)
{------------------------------------------------------------------------------
Font
------------------------------------------------------------------------------}
if aObject is TFPCustomFont then
begin
{$if defined(VerboseCDDrawing) or defined(VerboseCDBitmap)}
ObjType := 'Font';
{$endif}
end
{------------------------------------------------------------------------------
Brush
------------------------------------------------------------------------------}
else if aObject is TFPCustomBrush then
begin
{$if defined(VerboseCDDrawing) or defined(VerboseCDBitmap)}
ObjType := 'Brush';
{$endif}
end
{------------------------------------------------------------------------------
Image
------------------------------------------------------------------------------}
else if aObject is TCDBitmap then
begin
{$if defined(VerboseCDDrawing) or defined(VerboseCDBitmap)}
ObjType := 'Image';
{$endif}
end
{------------------------------------------------------------------------------
Region
------------------------------------------------------------------------------}
else if aObject is TLazRegion then
begin
{$if defined(VerboseCDDrawing) or defined(VerboseCDBitmap)}
ObjType := 'Region';
{$endif}
end
{------------------------------------------------------------------------------
Pen
------------------------------------------------------------------------------}
else if aObject is TFPCustomPen then
begin
{$if defined(VerboseCDDrawing) or defined(VerboseCDBitmap)}
ObjType := 'Pen';
{$endif}
end;
(* if AObject is TQtResource then
if TQtResource(AObject).Owner <> nil then
begin
// this is an owned (default) resource, let owner free it
DebugLn('WARNING: Trying to Free a default resource');
AObject := nil;
end;*)
if AObject <> nil then
begin
//WriteLn('Delete object: ', PtrUInt(AObject));
FreeThenNil(AObject);
end;
Result := True;
{$if defined(VerboseCDDrawing) or defined(VerboseCDBitmap)}
DebugLn('Trace:< [WinAPI DeleteObject] Result=', dbgs(Result), ' ObjectType=', ObjType);
{$endif}
end;
(*function TQtWidgetSet.DestroyCaret(Handle: HWND): Boolean;
begin
Result := (Handle <> 0) and QtCaret.DestroyCaret;
end;
{------------------------------------------------------------------------------
Method: DestroyIcon
Params: Handle
Returns: Result of destroying
------------------------------------------------------------------------------}
function TQtWidgetSet.DestroyIcon(Handle: HICON): Boolean;
begin
Result := (Handle <> 0) and
(
(TObject(Handle) is TQtIcon) or
(TObject(Handle) is TQtCursor)
);
if Result then
TObject(Handle).Free;
end;
{------------------------------------------------------------------------------
Method: DPtoLP
Params: DC: HDC; var Points; Count: Integer
Returns: Boolean
------------------------------------------------------------------------------}
function TQtWidgetSet.DPtoLP(DC: HDC; var Points; Count: Integer): BOOL;
var
P: PPoint;
QtPoint: TQtPoint;
Matrix: QTransformH;
MatrixInv: QTransformH;
QtDC: TQtDeviceContext;
Inverted: Boolean;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI DPtoLP] ');
{$endif}
Result := False;
if not IsValidDC(DC) then
Exit;
QtDC := TQtDeviceContext(DC);
Matrix := QTransform_create;
MatrixInv := QTransform_create;
QPainter_combinedTransform(QtDC.Widget, Matrix);
P := @Points;
try
while Count > 0 do
begin
Dec(Count);
Inverted := QTransform_isInvertible(Matrix);
QTransform_inverted(Matrix, MatrixInv, @Inverted);
QtPoint.X := P^.X;
QtPoint.Y := P^.Y;
QTransform_map(MatrixInv, PQtPoint(@QtPoint), PQtPoint(@QtPoint));
P^.X := QtPoint.X;
P^.Y := QtPoint.Y;
Inc(P);
end;
Result := True;
finally
QTransform_destroy(MatrixInv);
QTransform_destroy(Matrix);
end;
end;
{------------------------------------------------------------------------------
Method: DrawEdge
Params: DC: HDC; var Rect: TRect; edge: Cardinal; grfFlags: Cardinal
Returns: Boolean
------------------------------------------------------------------------------}
function TQtWidgetSet.DrawEdge(DC: HDC; var Rect: TRect; edge: Cardinal; grfFlags: Cardinal): Boolean;
var
Brush: HBRUSH;
ColorDark, ColorLight: TColorRef;
ClientRect: TRect;
QtDC: TQtDeviceContext;
procedure InternalDrawEdge(Outer: Boolean; const R: TRect);
var
X1, Y1, X2, Y2: Integer;
ColorLeftTop, ColorRightBottom: TColor;
EdgeQtColor: TQColor;
APen, OldPen: TQtPen;
begin
X1 := R.Left;
Y1 := R.Top;
X2 := R.Right;
Y2 := R.Bottom;
ColorLeftTop := clNone;
ColorRightBottom := clNone;
if Outer then
begin
if Edge and BDR_RAISEDOUTER <> 0 then
begin
ColorLeftTop := ColorLight;
ColorRightBottom := ColorDark;
end
else if Edge and BDR_SUNKENOUTER <> 0 then
begin
ColorLeftTop := ColorDark;
ColorRightBottom := ColorLight;
end;
end
else
begin
if Edge and BDR_RAISEDINNER <> 0 then
begin
ColorLeftTop := ColorLight;
ColorRightBottom := ColorDark;
end
else if Edge and BDR_SUNKENINNER <> 0 then
begin
ColorLeftTop := ColorDark;
ColorRightBottom := ColorLight;
end;
end;
if grfFlags and BF_DIAGONAL = 0 then
begin
APen := TQtPen.Create(True);
ColorRefToTQColor(TColorRef(ColorLeftTop), EdgeQtColor);
APen.setColor(EdgeQtColor);
OldPen := QtDC.setPen(APen);
if grfFlags and BF_LEFT <> 0 then
QtDC.DrawLine(X1, Y1, X1, Y2);
if grfFlags and BF_TOP <> 0 then
QtDC.DrawLine(X1, Y1, X2, Y1);
QtDC.setPen(OldPen);
APen.Free;
APen := TQtPen.Create(True);
ColorRefToTQColor(TColorRef(ColorRightBottom), EdgeQtColor);
APen.setColor(EdgeQtColor);
OldPen := QtDC.SetPen(APen);
if grfFlags and BF_RIGHT <> 0 then
QtDC.DrawLine(X2, Y1, X2, Y2);
if grfFlags and BF_BOTTOM <> 0 then
QtDC.DrawLine(X1, Y2, X2, Y2);
QtDC.SetPen(OldPen);
APen.Free;
end
else
begin
APen := TQtPen.Create(True);
ColorRefToTQColor(TColorRef(ColorLeftTop), EdgeQtColor);
APen.setColor(EdgeQtColor);
OldPen := QtDC.setPen(APen);
if (grfFlags and BF_DIAGONAL_ENDTOPLEFT = BF_DIAGONAL_ENDTOPLEFT) or
(grfFlags and BF_DIAGONAL_ENDBOTTOMRIGHT = BF_DIAGONAL_ENDBOTTOMRIGHT) then
QtDC.DrawLine(X1, Y1, X2, Y2)
else
QtDC.DrawLine(X1, Y2, X2, Y1);
QtDC.setPen(OldPen);
APen.Free;
end;
end;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI DrawEdge] ');
{$endif}
Result := False;
if not IsValidDC(DC) or IsRectEmpty(Rect) then exit;
QtDC := TQtDeviceContext(DC);
ClientRect := Rect;
Dec(ClientRect.Right, 1);
Dec(ClientRect.Bottom, 1);
QtDC.save;
try
ColorDark := ColorToRGB(cl3DDkShadow);
ColorLight := ColorToRGB(cl3DLight);
if grfFlags and BF_FLAT <> 0 then
ColorLight := clSilver;
if grfFlags and BF_MONO <> 0 then
begin
ColorDark := TColorRef(clBlack);
ColorLight := TColorRef(clWhite);
end;
try
if Edge and (BDR_SUNKENOUTER or BDR_RAISEDOUTER) <> 0 then
InternalDrawEdge(True, ClientRect);
InflateRect(ClientRect, -1, -1);
if grfFlags and BF_MONO = 0 then
begin
ColorLight := ColorToRGB(clBtnHiLight);
ColorDark := ColorToRGB(clBtnShadow);
end;
if Edge and (BDR_SUNKENINNER or BDR_RAISEDINNER) <> 0 then
begin
InternalDrawEdge(False, ClientRect);
InflateRect(ClientRect, -1, -1);
end;
finally
end;
inc(ClientRect.Right);
inc(ClientRect.Bottom);
if grfFlags and BF_MIDDLE <> 0 then
begin
Brush := CreateSolidBrush(TColorRef(clBtnFace));
try
FillRect(DC, ClientRect, Brush);
finally
DeleteObject(Brush);
end;
end;
if grfFlags and BF_ADJUST <> 0 then
Rect := ClientRect;
Result := True;
finally
QtDC.Restore;
end;
end;*)
{------------------------------------------------------------------------------
Method: DrawFocusRect
Params: DC: HDC; const Rect: TRect
Returns: Boolean
------------------------------------------------------------------------------}
function TCDWidgetSet.DrawFocusRect(DC: HDC; const Rect: TRect): boolean;
var
LazDC: TLazCanvas absolute DC;
begin
{$ifdef VerboseCDWinAPI}
DebugLn(Format('[DrawFocusRect] DC: %x', [PtrUInt(DC)]));
{$endif}
Result := False;
if not IsValidDC(DC) then exit;
// Drawer.DrawFocusRect alters the Pen and Brush, so we save the state here
LazDC.SaveState();
GetDefaultDrawer().DrawFocusRect(LazDC, Types.Point(Rect.Left, Rect.Top),
Types.Size(Rect.Right - Rect.Left, Rect.Bottom - Rect.Top));
LazDC.RestoreState(-1);
Result := True;
end;
function TCDWidgetSet.DrawFrameControl(DC: HDC; const Rect: TRect; uType,
uState: Cardinal): Boolean;
var
LazDC: TLazCanvas absolute DC;
lControlStateEx: TCDControlStateEx;
lState: TCDControlState;
lSize: Types.TSize;
begin
Result := False;
if not IsValidDC(DC) then
begin
{$ifdef VerboseCDDrawing}
DebugLn(':<[WinAPI DrawFrameControl] Invalid DC!');
{$endif}
Exit(False);
end;
case uType of
DFC_BUTTON:
begin
lSize := Types.Size(Rect.Right-Rect.Left, Rect.Bottom-Rect.Top);
if (DFCS_BUTTONPUSH and uState) <> 0 then
lControlStateEx := TCDButtonStateEx.Create
else
lControlStateEx := TCDControlStateEx.Create;
try
lControlStateEx.Font := TFont.Create;
lControlStateEx.ParentRGBColor := clSilver;
lControlStateEx.FPParentRGBColor := colSilver;
lControlStateEx.RGBColor := GetDefaultDrawer().FallbackPalette.BtnFace;
lControlStateEx.FPRGBColor := TColorToFPColor(lControlStateEx.RGBColor);
//if uState and DFCS_FLAT <> 0 then lState := [csfEnabled];
if uState and DFCS_INACTIVE = 0 then lState := lState + [csfEnabled];
if uState and DFCS_PUSHED <> 0 then lState := lState + [csfSunken];
if (uState and $1F) in [DFCS_BUTTONCHECK, DFCS_BUTTON3STATE] then
begin
//Element := QStyleCE_CheckBox
end
else if (DFCS_BUTTONRADIO and uState) <> 0 then
begin
//Element := QStyleCE_RadioButton
end
else if (DFCS_BUTTONPUSH and uState) <> 0 then
begin
GetDefaultDrawer().DrawButton(LazDC, Types.Point(0,0), lSize, lState, TCDButtonStateEx(lControlStateEx));
end
else if (DFCS_BUTTONRADIOIMAGE and uState) <> 0 then
begin
//Element := QStyleCE_RadioButton
//TODO: what to implement here ?
end
else if (DFCS_BUTTONRADIOMASK and uState) <> 0 then
begin
//Element := QStyleCE_RadioButton
//TODO: what to implement here ?
end;
finally
lControlStateEx.Font.Free;
lControlStateEx.Free;
end;
end;
DFC_CAPTION: ; // title bar captions
DFC_MENU: ; // menu
DFC_SCROLL:
begin
end;//DrawScrollBarArrows;
end;
{function uStatetoQStyleState: QStyleState;
begin
Result := QStyleState_None;
if (uState and DFCS_INACTIVE = 0) then
Result := Result or QStyleState_Enabled;
if (uState and DFCS_PUSHED <> 0) then
Result := Result or QStyleState_MouseOver or QStyleState_Sunken
else
Result := Result or QStyleState_Raised;
if (uState and DFCS_CHECKED <> 0) then
Result := Result or QStyleState_On
else
Result := Result or QStyleState_Off;
if ((uState and DFCS_HOT <> 0) or (uState and DFCS_PUSHED <> 0)) then
Result := Result or QStyleState_MouseOver or QStyleState_Active;
if (uType <> DFC_BUTTON) and
((uState and DFCS_FLAT <> 0) and not (uState and DFCS_PUSHED <> 0)) then
Result := Result and not QStyleState_Raised;
// DFCS_TRANSPARENT = 2048;
//DFCS_ADJUSTRECT = 8192;
//DFCS_FLAT = 16384;
//DFCS_MONO = 32768;
end;
procedure DrawScrollBarArrows;
var
Opt: QStyleOptionH;
Element: QStylePrimitiveElement;
State: QStyleState;
begin
//TODO: DFCS_SCROLLCOMBOBOX and DFCS_SCROLLSIZEGRIP
State := uStatetoQStyleState;
Element := QStylePE_CustomBase;
if (uState and $1F) in [DFCS_SCROLLUP] then
Element := QStylePE_IndicatorArrowUp
else
if (uState and $1F) in [DFCS_SCROLLDOWN] then
Element := QStylePE_IndicatorArrowDown
else
if (uState and $1F) in [DFCS_SCROLLLEFT] then
Element := QStylePE_IndicatorArrowLeft
else
if (uState and $1F) in [DFCS_SCROLLRIGHT] then
Element := QStylePE_IndicatorArrowRight;
if Element = QStylePE_CustomBase then
exit;
Opt := QStyleOption_create(1, 0);
QStyleOption_setRect(Opt, @Rect);
QStyleOption_setState(Opt, State);
QStyle_drawPrimitive(QApplication_style(), Element, Opt, Painter, Widget);
QStyleOption_destroy(Opt);
end;}
end;
(*{------------------------------------------------------------------------------
Method: DrawText
Params: DC, Str, Count, Rect, Flags
Returns: If the string was drawn, or CalcRect run
if DT_CALCRECT is one of the Flags passed to this function, then:
* DrawText should not draw the text, but determine the size that would be required to write it.
* If there are multiple lines of text, this function will keep Rect.Width fixed and
expand Rect.Height to fit the text.
* If there is one line of text, Rect is reduced or expanded to fit it.
* The result will the height of the text.
------------------------------------------------------------------------------}
function TQtWidgetSet.DrawText(DC: HDC; Str: PChar; Count: Integer;
var ARect: TRect; Flags: Cardinal): Integer;
var
WideStr: WideString;
R: TRect;
QtDC: TQtDeviceContext;
F: Integer;
Pt: TPoint;
ClipRect: TRect;
B: Boolean;
S: String;
i: Integer;
procedure CalculateOffsetWithAngle(const AFontAngle: Integer;
var TextLeft,TextTop: Integer);
var
OffsX, OffsY: integer;
Angle: Integer;
Size: TSize;
begin
OffsX := R.Right - R.Left;
OffsY := R.Bottom - R.Top;
Size.cX := OffsX;
Size.cy := OffsY;
Angle := AFontAngle div 10;
if Angle < 0 then
Angle := 360 + Angle;
if Angle <= 90 then
begin
OffsX := 0;
OffsY := Trunc(Size.cx * sin(Angle * Pi / 180));
end else
if Angle <= 180 then
begin
OffsX := Trunc(Size.cx * -cos(Angle * Pi / 180));
OffsY := Trunc(Size.cx * sin(Angle * Pi / 180) +
Size.cy * cos((180 - Angle) * Pi / 180));
end else
if Angle <= 270 then
begin
OffsX := Trunc(Size.cx * -cos(Angle * Pi / 180) +
Size.cy * sin((Angle - 180) * Pi / 180));
OffsY := Trunc(Size.cy * sin((270 - Angle) * Pi / 180));
end else
if Angle <= 360 then
begin
OffsX := Trunc(Size.cy * sin((360 - Angle) * Pi / 180));
OffsY := 0;
end;
TextTop := OffsY;
TextLeft := OffsX;
end;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI DrawText] DC: ', dbghex(DC), ' Str: ', string(Str),
' CalcRect: ', dbgs((Flags and DT_CALCRECT) = DT_CALCRECT),' ARect ',dbgs(ARect));
{$endif}
Result := 0;
if not IsValidDC(DC) then
Exit;
QtDC :=TQtDeviceContext(DC);
if Count >= 0 then
WideStr := GetUtf8String(Copy(Str, 1, Count))
else
WideStr := GetUtf8String(Str);
B := QtDC.getClipping;
if B and
(Flags and DT_NOCLIP = DT_NOCLIP) and
(Flags and DT_WORDBREAK = DT_WORDBREAK) then
begin
ClipRect := QtDC.getClipRegion.getBoundingRect;
//this is just to get same behaviour as gtk2 and win32
//IMO, we should change ARect.Left and/or ARect.Top if smaller than
//clip rect (map to clipRect). Then multiline text is drawn ok.
//look at issue http://bugs.freepascal.org/view.php?id=17678 . zeljko.
if (ARect.Left < ClipRect.Left) or (ARect.Top < ClipRect.Top) then
begin
{$note remove ifdef if I'm wrong about DT_WORDBREAK OBSERVATION}
{$IFDEF QT_DRAWTEXT_MAP_TO_CLIPRECT}
if ARect.Left < ClipRect.Left then
ARect.Left := ClipRect.Left;
if ARect.Top < ClipRect.Top then
ARect.Top := ClipRect.Top;
{$ELSE}
Flags := Flags and not DT_WORDBREAK;
{$ENDIF}
end;
end;
F := DTFlagsToQtFlags(Flags);
QtDC.Metrics.BoundingRect(@R, @ARect, F, @WideStr);
//TODO: result should be different when DT_VCENTER or DT_BOTTOM is set
Result := R.Bottom - R.Top;
if (Flags and DT_CALCRECT) = DT_CALCRECT then
begin
if (Flags and DT_WORDBREAK = DT_WORDBREAK) and
((R.Bottom - R.Top) > (ARect.Bottom - ARect.Top)) then
// MSDN says do not touch rect width when we have DT_WORDBREAK flag
// and new text is multiline (if R height > ARect height).See #17329.
else
ARect.Right := ARect.Left + R.Right - R.Left;
ARect.Bottom := ARect.Top + R.Bottom - R.Top;
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI DrawText] Rect=', dbgs(ARect));
{$endif}
Exit;
end;
// if our Font.Orientation <> 0 we must recalculate X,Y offset
// also it works only with DT_TOP DT_LEFT. Qt can handle multiline
// text in this case too.
Pt := Point(0, 0);
if (QtDC.Font.Angle <> 0) and
(Flags and DT_VCENTER = 0) and (Flags and DT_CENTER = 0) and
(Flags and DT_RIGHT = 0) and (Flags and DT_BOTTOM = 0) then
begin
Pt := Point(ARect.Left, ARect.Top);
CalculateOffsetWithAngle(QtDC.font.Angle, Pt.X, Pt.Y);
end;
// we cannot fit into rectangle, so use DT_SINGLELINE.See #17329.
// http://msdn.microsoft.com/en-us/library/dd162498%28v=VS.85%29.aspx
if B and
(Flags and DT_NOCLIP = DT_NOCLIP) and
(Flags and DT_WORDBREAK = DT_WORDBREAK) and
(Flags and DT_SINGLELINE = DT_SINGLELINE) and
((R.Bottom - R.Top) >= (ARect.Bottom - ARect.Top)) then
begin
Flags := Flags and not DT_WORDBREAK;
F := DTFlagsToQtFlags(Flags);
end;
{$warning HARDCODED WORKAROUND for qt-4.7.1 QPainter bug.}
{ Bug triggers when we try to paint multiline text which contains 1
space. eg "Save project\nCtrl+S". In this case QPainter draws
Save
project (in two lines, so Ctrl+S is invisible. See issue #18631.
But does not trigger with qt-4.6.XX and maybe with 4.7.0.
Opened nokia issue: http://bugreports.qt.nokia.com/browse/QTBUG-17020
UPDATE: it's fixed in qt-4.7.4 git and qt-4.8}
if (QtVersionMajor = 4) and (QtVersionMinor = 7) and (QtVersionMicro < 4) and
(Flags and DT_WORDBREAK = DT_WORDBREAK) and
((Flags and DT_VCENTER = DT_VCENTER) or (Flags and DT_CENTER = DT_CENTER))
and not (Flags and DT_NOCLIP = DT_NOCLIP) and
not (Flags and DT_MODIFYSTRING = DT_MODIFYSTRING) and
not (Flags and DT_END_ELLIPSIS = DT_END_ELLIPSIS) then
begin
S := StrPas(Str);
if length(S) > 0 then
begin
i := Pos(' ', S);
if (AnsiPos(LineEnding, S) > i) and
(S[length(S)] <> LineEnding) then
begin
Flags := Flags and not DT_WORDBREAK;
F := DTFlagsToQtFlags(Flags);
end;
end;
end;
if (Flags and DT_MODIFYSTRING = DT_MODIFYSTRING) and
(Flags and DT_END_ELLIPSIS = DT_END_ELLIPSIS) and
(Flags and DT_WORDBREAK = 0) then
begin
// windows are removing trailing spaces in this case
// and we are doing same thing too.
WideStr := TrimLeft(WideStr);
with ARect do
WideStr := QtDC.Metrics.elidedText(WideStr, QtElideRight, Right - Left, 0);
end;
with ARect do
QtDC.DrawText(Left + Pt.X, Top + Pt.Y, Right-Left, Bottom-Top, F, @WideStr);
end;*)
{------------------------------------------------------------------------------
Method: Ellipse
Params: X1, Y1, X2, Y2
Returns: Nothing
Use Ellipse to draw a filled circle or ellipse.
------------------------------------------------------------------------------}
function TCDWidgetSet.Ellipse(DC: HDC; X1, Y1, X2, Y2: Integer): Boolean;
var
LazDC: TLazCanvas absolute DC;
R: TRect;
begin
{$ifdef VerboseCDDrawing}
DebugLn(Format(':>[WinAPI Ellipse] DC=%s', [dbghex(DC)]));
{$endif}
if not IsValidDC(DC) then
begin
{$ifdef VerboseCDDrawing}
DebugLn(':<[WinAPI Rectangle] Invalid DC!');
{$endif}
Exit(False);
end;
// R := NormalizeRect(Rect(X1, Y1, X2, Y2));
// if IsRectEmpty(R) then Exit(True);
LazDC.Ellipse(X1, Y1, X2, Y2);
Result := True;
end;
(*function TQtWidgetSet.EnableScrollBar(Wnd: HWND; wSBflags, wArrows: Cardinal): Boolean;
begin
{maybe we can put creating of scrollbar here instead of SetScrollInfo() }
Result := False;
{$ifdef VerboseQtWinAPI_MISSING_IMPLEMENTATION}
WriteLn('***** [WinAPI TQtWidgetSet.EnableScrollbar] missing implementation ');
{$endif}
end;
function TQtWidgetSet.EnableWindow(hWnd: HWND; bEnable: Boolean): Boolean;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI EnableWindow] ');
{$endif}
Result := False;
if HWND <> 0 then
begin
Result := not TQtWidget(hwnd).getEnabled;
TQtWidget(hWnd).setEnabled(bEnable);
end;
end;
{------------------------------------------------------------------------------
Function: EndPaint
Params:
Returns:
------------------------------------------------------------------------------}
function TQtWidgetSet.EndPaint(Handle: hwnd; var PS: TPaintStruct): Integer;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI EndPaint] Handle: ', dbghex(Handle),
' PS.HDC: ', dbghex(PS.HDC));
{$endif}
Result := 1;
if IsValidDC(PS.HDC) and (TObject(PS.HDC) is TQtDeviceContext) then
begin
{$ifdef VerboseQtWinAPI}
WriteLn('Freeing resources');
{$endif}
TQtDeviceContext(PS.HDC).Free;
end;
end;*)
{------------------------------------------------------------------------------
Procedure: EnterCriticalSection
Params: var CritSection: TCriticalSection
Returns: Nothing
------------------------------------------------------------------------------}
procedure TCDWidgetSet.EnterCriticalSection(var CritSection: TCriticalSection);
var
ACritSec: System.PRTLCriticalSection;
begin
ACritSec:=System.PRTLCriticalSection(CritSection);
System.EnterCriticalsection(ACritSec^);
end;
{$ifndef CD_UseNativeMonitors}
function TCDWidgetSet.EnumDisplayMonitors(hdc: HDC; lprcClip: PRect;
lpfnEnum: MonitorEnumProc; dwData: LPARAM): LongBool;
begin
Result := lpfnEnum(1, 0, nil, dwData);
end;
{$endif}
(*
function CharsetToQtCharSet(const ALCLCharset: Byte): QFontDatabaseWritingSystem;
begin
Result := QFontDatabaseAny;
case ALCLCharset of
SYMBOL_CHARSET: Result := QFontDatabaseSymbol;
FCS_ISO_8859_1 .. FCS_ISO_8859_4,
FCS_ISO_8859_9,FCS_ISO_8859_10,
FCS_ISO_8859_15,
EASTEUROPE_CHARSET: Result := QFontDatabaseLatin;
FCS_ISO_8859_5,
RUSSIAN_CHARSET: Result := QFontDatabaseCyrillic;
FCS_ISO_8859_6,
ARABIC_CHARSET: Result := QFontDatabaseArabic;
FCS_ISO_8859_7,
GREEK_CHARSET: Result := QFontDatabaseGreek;
FCS_ISO_8859_8,
HEBREW_CHARSET: Result := QFontDatabaseHebrew;
SHIFTJIS_CHARSET: Result := QFontDatabaseJapanese;
HANGEUL_CHARSET: Result := QFontDatabaseKorean;
GB2312_CHARSET: Result := QFontDatabaseSimplifiedChinese;
CHINESEBIG5_CHARSET: Result := QFontDatabaseTraditionalChinese;
THAI_CHARSET: Result := QFontDatabaseThai;
end;
end;
function QtCharsetToCharset(AWritingSystem: QFontDatabaseWritingSystem;
AList: TFPList): Byte;
begin
Result := DEFAULT_CHARSET;
case AWritingSystem of
QFontDatabaseAny:
begin
Result := FCS_ISO_10646_1;
AList.Add(TObject(PtrUInt(Result)));
end;
QFontDatabaseSymbol:
begin
Result := SYMBOL_CHARSET;
AList.Add(TObject(PtrUInt(Result)));
end;
QFontDatabaseThai:
begin
Result := THAI_CHARSET;
AList.Add(TObject(PtrUInt(Result)));
end;
QFontDatabaseTraditionalChinese:
begin
Result := CHINESEBIG5_CHARSET;
AList.Add(TObject(PtrUInt(Result)));
end;
QFontDatabaseSimplifiedChinese:
begin
Result := GB2312_CHARSET;
AList.Add(TObject(PtrUInt(Result)));
end;
QFontDatabaseKorean:
begin
Result := HANGEUL_CHARSET;
AList.Add(TObject(PtrUInt(Result)));
end;
QFontDatabaseJapanese:
begin
Result := SHIFTJIS_CHARSET;
AList.Add(TObject(PtrUInt(Result)));
end;
QFontDatabaseHebrew:
begin
Result := HEBREW_CHARSET;
AList.Add(TObject(PtrUInt(Result)));
AList.Add(TObject(PtrUInt(FCS_ISO_8859_8)));
end;
QFontDatabaseGreek:
begin
Result := GREEK_CHARSET;
AList.Add(TObject(PtrUInt(Result)));
AList.Add(TObject(PtrUInt(FCS_ISO_8859_7)));
end;
QFontDatabaseArabic:
begin
Result := ARABIC_CHARSET;
AList.Add(TObject(PtrUInt(Result)));
end;
QFontDatabaseCyrillic:
begin
Result := RUSSIAN_CHARSET;
AList.Add(TObject(PtrUInt(Result)));
AList.Add(TObject(PtrUInt(FCS_ISO_8859_5)));
end;
QFontDatabaseLatin:
begin
Result := FCS_ISO_10646_1;
AList.Add(TObject(PtrUInt(Result)));
AList.Add(TObject(PtrUInt(ANSI_CHARSET)));
AList.Add(TObject(PtrUInt(FCS_ISO_8859_1)));
AList.Add(TObject(PtrUInt(FCS_ISO_8859_2)));
AList.Add(TObject(PtrUInt(FCS_ISO_8859_3)));
AList.Add(TObject(PtrUInt(FCS_ISO_8859_4)));
AList.Add(TObject(PtrUInt(FCS_ISO_8859_9)));
AList.Add(TObject(PtrUInt(FCS_ISO_8859_10)));
AList.Add(TObject(PtrUInt(FCS_ISO_8859_15)));
AList.Add(TObject(PtrUInt(EASTEUROPE_CHARSET)));
end;
end;
end;
{------------------------------------------------------------------------------
Function: EnumFontFamiliesEx
Params:
hdc
[in] Handle to the device context.
lpLogfont
[in] Pointer to a LOGFONT structure that contains information about the
fonts to enumerate. The function examines the following members.
Member Description
lfCharset If set to DEFAULT_CHARSET, the function enumerates all fonts
in all character sets. If set to a valid character set value,
the function enumerates only fonts in the specified character
set.
lfFaceName If set to an empty string, the function enumerates one font
in each available typeface name. If set to a valid typeface
name, the function enumerates all fonts with the
specified name.
lfPitchAndFamily Must be set to zero for all language versions of
the operating system.
lpEnumFontFamExProc
[in] Pointer to the application definedcallback function. For more
information, see the EnumFontFamExProc function.
lParam
[in] Specifies an applicationdefined value. The function passes this value
to the callback function along with font information.
dwFlags
This parameter is not used and must be zero.
Returns:
The return value is the last value returned by the callback function.
This value depends on which font families are available for the
specified device.
------------------------------------------------------------------------------}
function TQtWidgetSet.EnumFontFamiliesEx(DC: HDC; lpLogFont: PLogFont; Callback: FontEnumExProc; Lparam: LParam; Flags: dword): longint;
var
EnumLogFont: TEnumLogFontEx;
Metric: TNewTextMetricEx;
FontList: TStringList;
FontType: Integer;
FontDB: QFontDatabaseH;
i: Integer;
y: Integer;
AStyle: String;
StylesCount: Integer;
StylesList: QStringListH;
ScriptList: QStringListH;
CharsetList: TFPList;
function QtGetFontFamiliesDefault(var List:TStringList;
const AWritingSystem: QFontDatabaseWritingSystem = QFontDatabaseAny):integer;
var
StrLst: QStringlistH;
WStr: WideString;
j: integer;
begin
Result := -1;
StrLst := QStringList_create;
try
QFontDatabase_families(FontDB, StrLst, AWritingSystem);
Result := QStringList_size(StrLst);
for j := 0 to Result - 1 do
begin
QStringList_at(StrLst, @WStr, j);
List.Add(UTF16ToUTF8(WStr));
end;
finally
QStringList_destroy(StrLst);
end;
end;
function QtGetFontFamilies(var List: TStringList;
const APitch: Byte;
const AFamilyName: String;
const AWritingSystem: QFontDatabaseWritingSystem = QFontDatabaseAny): Integer;
var
StrLst: QStringlistH;
NewList: QStringListH;
WStr: WideString;
j: integer;
begin
Result := -1;
StrLst := QStringList_create();
NewList := QStringList_create();
try
QFontDatabase_families(FontDB, StrLst, AWritingSystem);
for j := 0 to QStringList_size(StrLst) - 1 do
begin
QStringList_at(StrLst, @WStr, j);
if APitch <> DEFAULT_PITCH then
begin
case APitch of
FIXED_PITCH, MONO_FONT:
begin
if QFontDatabase_isFixedPitch(FontDB, @WStr) then
QStringList_append(NewList, @WStr);
end;
VARIABLE_PITCH:
begin
if QFontDatabase_isScalable(FontDB, @WStr) then
QStringList_append(NewList, @WStr);
end;
end;
end else
QStringList_append(NewList, @WStr);
end;
if AFamilyName <> '' then
begin
for j := QStringList_size(NewList) - 1 downto 0 do
begin
QStringList_at(NewList, @WStr, j);
if UTF16ToUTF8(WStr) <> AFamilyName then
QStringList_removeAt(NewList, j);
end;
end;
for j := 0 to QStringList_size(NewList) - 1 do
begin
QStringList_at(NewList, @WStr, j);
List.Add(UTF16ToUTF8(WStr));
end;
Result := List.Count;
finally
QStringList_destroy(StrLst);
QStringList_destroy(NewList);
end;
end;
function GetStyleAt(AIndex: Integer): String;
var
WStr: WideString;
begin
Result := '';
if (AIndex >= 0) and (AIndex < QStringList_size(StylesList)) then
begin
QStringList_at(StylesList, @WStr, AIndex);
Result := UTF16ToUTF8(WStr);
end;
end;
function GetWritingSystems(AFontName: String; AList: QStringListH;
ACharsetList: TFPList): Boolean;
var
WStr: WideString;
Arr: TPtrIntArray;
j: Integer;
begin
Result := False;
QStringList_clear(AList);
if Assigned(CharSetList) then
CharSetList.Clear;
WStr := UTF8ToUTF16(AFontName);
QFontDatabase_writingSystems(FontDB, @Arr, @WStr);
Result := length(Arr) > 0;
for j := 0 to High(Arr) do
begin
if Assigned(ACharsetList) then
QtCharsetToCharset(QFontDatabaseWritingSystem(Arr[j]), ACharsetList);
QFontDatabase_writingSystemName(@WStr, QFontDatabaseWritingSystem(Arr[j]));
QStringList_append(AList, @WStr);
end;
end;
function FillLogFontA(AFontName: String; var ALogFontA: TLogFontA;
var AMetric: TNewTextMetricEx; var AFontType: Integer;
out AStyle: String): Integer;
var
Font: QFontH;
WStr: WideString;
begin
WStr := UTF8ToUTF16(AFontName);
Font := QFont_create(@WStr);
ALogFontA.lfItalic := Byte(QFont_italic(Font));
ALogFontA.lfWeight := QFont_weight(Font);
ALogFontA.lfHeight := QFont_pointSize(Font);
ALogFontA.lfUnderline := Byte(QFont_underline(Font));
ALogFontA.lfStrikeOut := Byte(QFont_strikeOut(Font));
if QFont_styleStrategy(Font) = QFontPreferBitmap then
AFontType := AFontType or RASTER_FONTTYPE;
if QFont_styleStrategy(Font) = QFontPreferDevice then
AFontType := AFontType or DEVICE_FONTTYPE;
if not (QFont_styleStrategy(Font) = QFontPreferDefault) then
AFontType := AFontType and not TRUETYPE_FONTTYPE;
QStringList_clear(StylesList);
QFontDatabase_styles(FontDB, StylesList, @WStr);
AStyle := '';
Result := QStringList_size(StylesList);
if Result > 0 then
AStyle := GetStyleAt(0);
// fill script and charset list
GetWritingSystems(AFontName, ScriptList, CharsetList);
QFont_destroy(Font);
end;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI EnumFontFamiliesEx] Charset=',lpLogFont^.lfCharSet,
' face ',lpLogFont^.lfFaceName,' pitchAndFamily=',lpLogFont^.lfPitchAndFamily);
{$endif}
Result := 0;
Metric.ntmentm.ntmAvgWidth := 0; // just to shutup compiler
FontDB := QFontDatabase_create();
try
if (lpLogFont^.lfCharSet = DEFAULT_CHARSET) and
(lpLogFont^.lfFaceName= '') and
(lpLogFont^.lfPitchAndFamily = 0) then
begin
FontType := 0;
FontList := TStringList.create;
try
if QtGetFontFamiliesDefault(FontList) > 0 then
begin
for i := 0 to FontList.Count - 1 do
begin
EnumLogFont.elfLogFont.lfFaceName := FontList[i];
Result := Callback(EnumLogFont, Metric, FontType, LParam);
end;
end;
finally
FontList.free;
end;
end else
begin
Result := 0;
FontType := TRUETYPE_FONTTYPE;
FontList := TStringList.create;
StylesList := QStringList_create();
ScriptList := QStringList_create();
CharsetList := TFPList.Create;
try
if QtGetFontFamilies(FontList, lpLogFont^.lfPitchAndFamily,
lpLogFont^.lfFaceName, CharsetToQtCharSet(lpLogFont^.lfCharSet)) > 0 then
begin
StylesList := QStringList_create();
for i := 0 to FontList.Count - 1 do
begin
EnumLogFont.elfLogFont.lfFaceName := FontList[i];
EnumLogFont.elfLogFont.lfPitchAndFamily := lpLogFont^.lfPitchAndFamily;
EnumLogFont.elfFullName := FontList[i];
StylesCount := FillLogFontA(FontList[i], EnumLogFont.elfLogFont, Metric, FontType,
AStyle);
EnumLogFont.elfStyle := AStyle;
if CharSetList.Count > 0 then
EnumLogFont.elfLogFont.lfCharSet := PtrUInt(CharsetList.Items[0]);
Result := Callback(EnumLogFont, Metric, FontType, LParam);
for y := 1 to StylesCount - 1 do
begin
AStyle := GetStyleAt(y);
EnumLogFont.elfStyle := AStyle;
Result := Callback(EnumLogFont, Metric, FontType, LParam);
end;
for y := 1 to CharsetList.Count - 1 do
begin
EnumLogFont.elfLogFont.lfCharSet := PtrUInt(CharsetList.Items[y]);
Result := Callback(EnumLogFont, Metric, FontType, LParam);
end;
end;
end;
finally
FontList.free;
QStringList_destroy(StylesList);
CharSetList.Free;
end;
end;
finally
QFontDatabase_destroy(FontDB);
end;
end;
{------------------------------------------------------------------------------
Function: ExcludeClipRect
Params: none
Returns: Nothing
------------------------------------------------------------------------------}
function TQtWidgetSet.ExcludeClipRect(dc: hdc; Left, Top, Right, Bottom : Integer) : Integer;
var
Region: QRegionH;
ClipRegion: QRegionH;
ExRegion: QRegionH;
QtDC: TQtDeviceContext;
R: TRect;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI ExcludeClipRect]');
{$endif}
Result := ERROR;
if not IsValidDC(DC) then Exit;
QtDC := TQtDeviceContext(DC);
{ExcludeClipRect on X11 paint engine is pretty slow with complex regions
eg. setting clipRegion with hundreds of rects (usually created by
calling ExcludeClipRect for many children on widget) dramatically kills
performance of our application.
To get rid of it we are using trick from webkit. If numRects is over
25 then create an new rect region with boundsRect of NewRegion.
see issue http://bugs.freepascal.org/view.php?id=19698.
If you want accurate ExcludeClipRect use graphicssystem Raster or
see comment in TQtWidgetSet.ExtSelectClipRgn}
ExRegion := QRegion_create(Left, Top, Right - Left, Bottom - Top, QRegionRectangle);
Region := QRegion_create;
ClipRegion := QRegion_create;
try
QPainter_clipRegion(QtDC.Widget, ClipRegion);
QRegion_subtracted(ClipRegion, Region, ExRegion);
// only for X11 paintEngine.
if (QPaintEngine_type(QtDC.PaintEngine) = QPaintEngineX11) and
not QRegion_isEmpty(Region) and
(QRegion_numRects(Region) > 25) then
begin
QRegion_boundingRect(Region, @R);
QRegion_setRects(Region, @R, 1);
end;
QtDC.setClipRegion(Region);
QtDC.setClipping(True);
if QRegion_isEmpty(Region) then
Result := NULLREGION
else
if QRegion_numRects(Region) = 1 then
Result := SIMPLEREGION
else
Result := COMPLEXREGION;
finally
QRegion_destroy(ClipRegion);
QRegion_destroy(Region);
QRegion_destroy(ExRegion);
end;
end;*)
function TCDWidgetSet.ExtCreatePen(dwPenStyle, dwWidth: DWord;
const lplb: TLogBrush; dwStyleCount: DWord; lpStyle: PDWord): HPEN;
var
lPen: TFPCustomPen;
begin
lPen := TFPCustomPen.Create;
Result := HBRUSH(lPen);
// QtPen.IsExtPen := True;
// {$ifdef VerboseCDDrawing}
// DebugLn(Format(':>[TCDWidgetSet.ExtCreatePen] Style: %d, Color: %8x Result:"%x',
// [LogPen.lopnStyle, LogPen.lopnColor, Result]));
// {$endif}
case dwPenStyle and PS_STYLE_MASK of
PS_SOLID: lPen.Style := psSolid;
PS_DASH: lPen.Style := psDash;
PS_DOT: lPen.Style := psDot;
PS_DASHDOT: lPen.Style := psDashDot;
PS_DASHDOTDOT:lPen.Style := psDashDotDot;
// PS_USERSTYLE: QtPen.setStyle(QtCustomDashLine);
PS_NULL: lPen.Style := psClear;
else
lPen.Style := psSolid;
end;
lPen.Width := 1;
if (dwPenStyle and PS_TYPE_MASK) = PS_COSMETIC then
lPen.Width := 1
else if (dwPenStyle and PS_TYPE_MASK) = PS_GEOMETRIC then
begin
lPen.Width := dwWidth;
{case dwPenStyle and PS_JOIN_MASK of
PS_JOIN_ROUND: QtPen.setJoinStyle(QtRoundJoin);
PS_JOIN_BEVEL: QtPen.setJoinStyle(QtBevelJoin);
PS_JOIN_MITER: QtPen.setJoinStyle(QtMiterJoin);
end;
case dwPenStyle and PS_ENDCAP_MASK of
PS_ENDCAP_ROUND: QtPen.setCapStyle(QtRoundCap);
PS_ENDCAP_SQUARE: QtPen.setCapStyle(QtSquareCap);
PS_ENDCAP_FLAT: QtPen.setCapStyle(QtFlatCap);
end;}
end;
{ if (dwPenStyle and PS_STYLE_MASK) = PS_USERSTYLE then
QtPen.setDashPattern(lpStyle, dwStyleCount);}
lPen.FPColor := TColorToFPColor(ColorToRGB(lplb.lbColor));
Result := HPEN(lPen);
end;
function TCDWidgetSet.ExtSelectClipRGN(dc: hdc; rgn: hrgn; Mode: Longint) : Integer;
var
LazDC: TLazCanvas absolute DC;
lRegion: TLazRegion absolute rgn;
begin
{$ifdef VerboseCDWinAPI}
DebugLn('[TCDWidgetSet.SelectClipRGN] DC=', dbgs(DC),' RGN=', dbghex(RGN));
{$endif}
Result := ERROR;
// Activating this code break the drawing of TStringGrid. ToDo: Find out why
{ if not IsValidDC(DC) then exit;
// RGN=0 indicates that the clipping region should be removed
if (RGN = 0) then
begin
TLazCanvas(LazDC.ClipRegion).Clear;
LazDC.Clipping := False;
Result := NullRegion;
Exit;
end;
if LazDC.ClipRegion = nil then
LazDC.ClipRegion := TLazRegion.Create;
// Never use LazDC.ClipRegion := RGN because we really need to make a copy of it
// The original handle might be freed afterwards
CombineRgn(HRGN(LazDC.ClipRegion), HRGN(LazDC.ClipRegion), RGN, Mode);
LazDC.Clipping := True;
Result := TLazRegion(RGN).GetRegionKind();}
end;
{$ifndef CD_UseNativeText}
{------------------------------------------------------------------------------
Function: ExtTextOut
Params: none
Returns: Nothing
------------------------------------------------------------------------------}
function TCDWidgetSet.ExtTextOut(DC: HDC; X, Y: Integer; Options: Longint;
Rect: PRect; Str: PChar; Count: Longint; Dx: PInteger): Boolean;
var
lDestCanvas: TLazCanvas absolute DC;
lDestIntfImage: TLazIntfImage;
lFontSize: Integer;
FTDrawer: TIntfFreeTypeDrawer;
ftFont: TFreeTypeFont;
RealX, RealY: Integer;
FreeFTFont: Boolean = false;
lLogFont: TLogFont;
begin
{$ifdef VerboseCDText}
DebugLn(Format(':>[WinAPI ExtTextOut] DC=%x Str=%s X=%d Y=%d',
[DC, StrPas(Str), X, Y]));
{$endif}
Result := False;
if (Str = nil) or (Str = '') then Exit;
if ((Options and (ETO_OPAQUE + ETO_CLIPPED)) <> 0) and (Rect = nil) then
exit;
if Rect <> nil then Rect^ := Bounds(0, 0, 0, 0);
if not IsValidDC(DC) then Exit;
lDestIntfImage := TLazIntfImage(lDestCanvas.Image);
if (lDestCanvas.Font = nil) or (lDestCanvas.Font.Size = 0) then lFontSize := DefaultFontSize
else lFontSize := Abs(lDestCanvas.Font.Size);
// Preparations finished, draw it using LazFreeType
FTDrawer := TIntfFreeTypeDrawer.Create(lDestIntfImage);
ftFont := TFreeTypeFont(lDestCanvas.ExtraFontData);
if ftFont = nil then
begin
ftFont := TFreeTypeFont.Create;
ftFont.Name := BackendGetFontPath(lLogFont, '');
ftFont.Hinted := true;
ftFont.ClearType := true;
ftFont.Quality := grqHighQuality;
FreeFTFont := True;
end;
try
ftFont.SizeInPoints:= lFontSize;
//lFontSize:= MulDiv(lFontSize,72,ftFont.DPI); // convert points to pixels
lFontSize := Round(ftFont.TextHeight(Str) * 0.75);// ToDo: Find out why this 75% factor works
RealX := X + lDestCanvas.WindowOrg.X + lDestCanvas.BaseWindowOrg.X;
RealY := Y + lDestCanvas.WindowOrg.Y + lDestCanvas.BaseWindowOrg.Y + lFontSize;
FTDrawer.DrawText(Str, ftFont, RealX, RealY, lDestCanvas.Font.FPColor, 255);
finally
if FreeFTFont then ftFont.Free;
FTDrawer.Free;
end;
{$ifdef VerboseCDText}
DebugLn(':<[WinAPI ExtTextOut]');
{$endif}
Result := True;
{ if ((Options and ETO_OPAQUE) <> 0) then
QtDC.fillRect(Rect^.Left, Rect^.Top, Rect^.Right - Rect^.Left, Rect^.Bottom - Rect^.Top);
if Str <> nil then
begin
if Count >= 0 then
WideStr := GetUtf8String(Copy(Str, 1, Count))
else
WideStr := GetUtf8String(Str);
if (Options and ETO_CLIPPED <> 0) then
begin
B := QtDC.getClipping;
if not B then
begin
QtDC.save;
QtDC.setClipRect(Rect^);
end;
QtDC.drawText(X, Y, Rect^.Right - Rect^.Left, Rect^.Bottom - Rect^.Top, 0, @WideStr);
if not B then
QtDC.restore;
end else
QtDC.drawText(X, Y, @WideStr);
end;}
Result := True;
end;
{$endif}
{------------------------------------------------------------------------------
Function: FillRect
Params: none
Returns: Nothing
------------------------------------------------------------------------------}
function TCDWidgetSet.FillRect(DC: HDC; const Rect: TRect; Brush: HBRUSH): Boolean;
var
LazDC: TLazCanvas absolute DC;
lOldBrush: HGDIOBJ;
begin
Result := False;
{$ifdef VerboseCDDrawing}
DebugLn('[WinAPI FillRect Rect=', dbgs(Rect),' Brush=', dbghex(Brush));
{$endif}
if not IsValidDC(DC) then
exit;
if not IsValidGdiObject(Brush) then
exit;
lOldBrush := SelectObject(DC, Brush);
LazDC.FillRect(Rect);
SelectObject(DC, lOldBrush);
Result := True;
end;
{------------------------------------------------------------------------------
Function: FillRgn
Params: DC: HDC; RegionHnd: HRGN; hbr: HBRUSH
Returns: Boolean
------------------------------------------------------------------------------}
function TCDWidgetSet.FillRgn(DC: HDC; RegionHnd: HRGN; hbr: HBRUSH): Bool;
var
LazDC: TLazCanvas absolute DC;
lRegion: TLazRegion absolute RegionHnd;
lRegionRect: TRect;
lOldBrush: HGDIOBJ;
lOldRegion: TLazRegion;
begin
{$ifdef VerboseCDWinAPI}
DebugLn('[TCDWidgetSet.FillRgn] Rgn=', dbgs(RegionHnd),' Brush=', dbghex(hbr));
{$endif}
Result := False;
if not IsValidDC(DC) then exit;
if hbr = 0 then Exit;
if RegionHnd = 0 then Exit;
lOldBrush := SelectObject(DC, hbr);
try
lOldRegion := TLazRegion.Create;
lOldRegion.Assign(TLazRegion(LazDC.ClipRegion));
lRegionRect := lRegion.GetBoundingRect();
LazDC.Rectangle(lRegionRect);
finally
TLazRegion(LazDC.ClipRegion).Assign(lOldRegion);
lOldRegion.Free;
SelectObject(DC, lOldBrush);
end;
Result := True;
end;
{------------------------------------------------------------------------------
Function: Frame3D
Params: none
Returns: Nothing
Draws a 3d border in the native drawer style.
------------------------------------------------------------------------------}
function TCDWidgetSet.Frame3d(DC : HDC; var ARect : TRect;
const FrameWidth : integer; const Style : TBevelCut) : boolean;
var
LazDC: TLazCanvas;
begin
{$ifdef VerboseCDWinAPI}
DebugLn('[TCDWidgetSet.Frame3d Rect=', dbgs(ARect));
{$endif}
Result := False;
if not IsValidDC(DC) then exit;
LazDC := TLazCanvas(DC);
GetDefaultDrawer().DrawFrame3D(LazDC, Types.Point(ARect.Left, ARect.Top),
Types.Size(ARect), FrameWidth, Style);
InflateRect(ARect, -FrameWidth, -FrameWidth);
Result := True;
end;
{------------------------------------------------------------------------------
Function: FrameRect
Params: none
Returns: Nothing
------------------------------------------------------------------------------}
function TCDWidgetSet.FrameRect(DC: HDC; const ARect: TRect; hBr: HBRUSH): Integer;
var
LazDC: TLazCanvas absolute DC;
lOldBrush, lOldPen, lFramePen, lFrameBrush: HGDIOBJ;
lLogPen: TLogPen;
lLogBrush: TLogBrush;
begin
Result := 0;
{$ifdef VerboseCDDrawing}
DebugLn('[WinAPI FillRect Rect=', dbgs(ARect),' Brush=', dbghex(hBr));
{$endif}
if not IsValidDC(DC) then
exit;
if not IsValidGdiObject(hBr) then
exit;
// Creates temporary pen and brush to help the drawing
lLogPen.lopnStyle := PS_SOLID;
lLogPen.lopnWidth := Types.Point(1, 1);
lLogPen.lopnColor := FPColorToTColor(TFPCustomBrush(hBR).FPColor);
lFramePen := CreatePenIndirect(lLogPen);
lLogBrush.lbStyle := BS_NULL;
lFrameBrush := CreateBrushIndirect(lLogBrush);
// Do the drawing
lOldBrush := SelectObject(DC, lFrameBrush);
lOldPen := SelectObject(DC, lFramePen);
LazDC.Rectangle(ARect);
SelectObject(DC, lOldBrush);
SelectObject(DC, lOldPen);
// Delete the helper objects
DeleteObject(lFramePen);
DeleteObject(lFrameBrush);
Result := 1;
end;
(*function TQtWidgetSet.GetActiveWindow: HWND;
var
Widget: QWidgetH;
W: TQtWidget;
SubW: TQtWidget;
Area: QMdiAreaH;
begin
Widget := QApplication_activeWindow;
if Widget <> nil then
begin
W := QtObjectFromWidgetH(Widget);
if W <> nil then
begin
if TQtMainWindow(W).MDIAreaHandle <> nil then
begin
Area := QMdiAreaH(TQtMainWindow(W).MDIAreaHandle.Widget);
SubW := QtObjectFromWidgetH(QMdiArea_activeSubWindow(Area));
if SubW <> nil then
Result := HWND(SubW)
else
Result := HWND(W);
end else
Result := HWND(W);
end;
end else
Result := 0;
end;
{------------------------------------------------------------------------------
Method: TQtWidgetSet.GetBitmapBits
Params: none
Returns:
------------------------------------------------------------------------------}
function TQtWidgetSet.GetBitmapBits(Bitmap: HBITMAP; Count: Longint; Bits: Pointer): Longint;
var
Image: QImageH;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI GetBitmapBits]',' Bitmap=', dbghex(Bitmap),' Count=',Count);
{$endif}
Result := 0;
if (Bitmap = 0) or (Count <= 0) then
Exit;
Image := QImage_create(TQtImage(Bitmap).FHandle);
try
Result := (QImage_width(Image) * QImage_height(Image) * QImage_depth(Image) + 7) div 8;
if Count < Result then
Result := Count;
if Result > 0 then
Move(QImage_bits(Image)^, Bits^, Result);
finally
QImage_destroy(Image);
end;
end;
function TQtWidgetSet.GetBkColor(DC: HDC): TColorRef;
var
QtDC: TQtDeviceContext;
begin
Result := CLR_INVALID;
if not IsValidDC(DC) then Exit;
QtDC := TQtDeviceContext(DC);
Result := QtDC.GetBkColor;
end;
function TQtWidgetSet.GetCapture: HWND;
var
w: QWidgetH;
Widget: TQtWidget;
{$IFDEF MSWINDOWS}
AWin: HWND;
{$ENDIF}
begin
{$IFDEF MSWINDOWS}
AWin := Windows.GetCapture;
if AWin <> 0 then
w := QWidget_find(AWin)
else
w := nil;
if (w = nil) and (QApplication_mouseButtons() > 0) then
w := QApplication_focusWidget()
else
if w <> QWidget_mouseGrabber then
w := QWidget_mouseGrabber;
{$ELSE}
w := QWidget_mouseGrabber();
{$ENDIF}
if w <> nil then
begin
// Capture widget can be child of complex control. In any case we should return TQtWidget as result.
// So we will look for parent while not found apropriate LCL handle.
Widget := GetFirstQtObjectFromWidgetH(w);
Result := HWND(Widget);
end
else
Result := 0;
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI GetCapture] Capture = ', Result);
{$endif}
end;
function TQtWidgetSet.GetCaretPos(var lpPoint: TPoint): Boolean;
begin
Result := QtCaret.GetCaretPos(lpPoint);
end;
function TQtWidgetSet.GetCaretRespondToFocus(handle: HWND; var ShowHideOnFocus: boolean): Boolean;
begin
ShowHideOnFocus := QtCaret.GetQtCaretRespondToFocus;
Result := True;
end;*)
{------------------------------------------------------------------------------
Function: GetClientBounds
Params: handle:
Result:
Returns: true on success
Returns the client bounds of a control. The client bounds is the rectangle of
the inner area of a control, where the child controls are visible. The
coordinates are relative to the control's left and top.
------------------------------------------------------------------------------}
function TCDWidgetSet.GetClientBounds(handle : HWND; var ARect : TRect) : Boolean;
var
lObject: TObject;
begin
{$ifdef VerboseCDWinAPI}
DebugLn(Format(':>[WinAPI GetClientBounds] Handle=%x', [Handle]));
{$endif}
// ToDO check if the window is native or not and process accordingly
// For now just assume it is native
Result := False;
if Handle=0 then Exit;
lObject := TObject(Handle);
if lObject is TCDForm then
begin
// Initial size guessed
if TCDForm(lObject).Image <> nil then
ARect := Bounds(0, 0, TCDForm(lObject).Image.Width, TCDForm(lObject).Image.Height)
else ARect := Bounds(0, 0, 0, 0);
// Now ask for the real size
Result := BackendGetClientBounds(Handle, ARect)
end
else
begin
// If we return WinControl.BoundsRect then the controls get a x2 factor
// when Align=alClient, strange. Region.GetBoundingRect() works fine.
// ARect := TCDWinControl(lObject).WinControl.BoundsRect; <<-- don't do this
ARect := TCDWinControl(lObject).Region.GetBoundingRect();
end;
{$ifdef VerboseCDWinAPI}
DebugLn(Format(':<[WinAPI GetClientBounds] ARect.Left=%d ARect.Top=%d'
+ ' ARect.Right=%d ARect.Bottom=%d',
[ARect.Left, ARect.Top, ARect.Right, ARect.Bottom]));
{$endif}
end;
{------------------------------------------------------------------------------
Function: GetClientRect
Params: handle:
Result:
Returns: true on success
Returns the client bounds of a control. The client bounds is the rectangle of
the inner area of a control, where the child controls are visible. The
coordinates are relative to the control's left and top.
Left and Top are always 0,0
------------------------------------------------------------------------------}
function TCDWidgetSet.GetClientRect(handle : HWND; var ARect : TRect) : Boolean;
begin
{$ifdef VerboseCDWinAPI}
DebugLn(Format('[WinAPI GetClientRect] Handle=%x', [Handle]));
{$endif}
GetClientBounds(Handle, ARect);
OffsetRect(ARect, -ARect.Left, -ARect.Top);
Result := True;
end;
{------------------------------------------------------------------------------
Function: GetClipBox
Params: dc, lprect
Returns: Integer
Returns the smallest rectangle which includes the entire current
Clipping Region, or if no Clipping Region is set, the current
dimensions of the Drawable.
The result can be one of the following constants
Error
NullRegion
SimpleRegion
ComplexRegion
------------------------------------------------------------------------------}
function TCDWidgetSet.GetClipBox(DC: hDC; lpRect: PRect): Longint;
var
LazDC: TLazCanvas;
lClipRegion: TFPCustomRegion;
begin
{$ifdef VerboseCDWinAPI}
DebugLn('[WinAPI GetClipBox] DC ' + dbghex(DC));
{$endif}
Result := NULLREGION;
if lpRect <> nil then
lpRect^ := Types.Rect(0,0,0,0);
if DC = 0 then DC := HDC(ScreenDC);
if not IsValidDC(DC) then
Result := ERROR;
if Result = ERROR then Exit;
LazDC := TLazCanvas(DC);
if (lpRect<>nil) then
begin
lClipRegion := LazDC.ClipRegion;
if lClipRegion = nil then
begin
Result := NULLREGION;
lpRect^ := Types.Bounds(0, 0, LazDC.Width, LazDC.Height);
end
else
begin
Result := SIMPLEREGION;
lpRect^ := lClipRegion.GetBoundingRect();
end;
end;
end;
{------------------------------------------------------------------------------
Function: GetClipRGN
Params: dc, rgn
Returns: Integer
This routine assumes that RGN has been created previously
and it copies the current Clipping Region to RGN
The result can be one of the following constants
0 = no clipping set
1 = ok
-1 = error
------------------------------------------------------------------------------}
function TCDWidgetSet.GetClipRGN(DC : hDC; RGN : hRGN): Longint;
var
LazDC: TLazCanvas absolute DC;
lDestRegion: TLazRegion absolute RGN;
lDCRegion: TLazRegion;
begin
{$ifdef VerboseCDWinAPI}
DebugLn('[WinAPI GetClipRGN] DC ' + dbghex(DC));
{$endif}
Result := -1;
if not IsValidDC(DC) then exit;
if Rgn = 0 then Exit;
lDCRegion := TLazRegion(LazDC.ClipRegion);
if lDCRegion = nil then
Result := 0
else
begin
lDestRegion.Assign(lDCRegion);
Result := 1;
end;
end;
{------------------------------------------------------------------------------
Method: GetCurrentObject
Params:
DC - A handle to the DC
uObjectType - The object type to be queried
Returns: If the function succeeds, the return value is a handle to the specified object.
If the function fails, the return value is NULL.
------------------------------------------------------------------------------}
function TCDWidgetSet.GetCurrentObject(DC: HDC; uObjectType: UINT): HGDIOBJ;
var
LazDC: TLazCanvas;
begin
{$ifdef VerboseCDWinAPI}
DebugLn(Format('[TCDWidgetSet.GetCurrentObject uObjectType=%d', [uObjectType]));
{$endif}
Result := 0;
if not IsValidDC(DC) then exit;
LazDC := TLazCanvas(DC);
case uObjectType of
OBJ_BITMAP: Result := HGDIOBJ(LazDC.SelectedBitmap);
OBJ_BRUSH: Result := HGDIOBJ(LazDC.AssignedBrush);
OBJ_FONT: Result := HGDIOBJ(LazDC.AssignedFont);
OBJ_PEN: Result := HGDIOBJ(LazDC.AssignedPen);
end;
end;
(*{------------------------------------------------------------------------------
Function: GetCursorPos
Params: lpPoint: The cursorposition
Returns: True if succesful
------------------------------------------------------------------------------}
function TQtWidgetSet.GetCursorPos(var lpPoint: TPoint ): Boolean;
var
vPoint: TQtPoint;
begin
QCursor_pos(@vPoint);
lpPoint.x := vPoint.x;
lpPoint.y := vPoint.y;
Result := True;
end;*)
{------------------------------------------------------------------------------
Function: GetDC
Params: hWnd is any widget.
Returns: Nothing
This function is Called:
- Once on app startup with hWnd = 0
- Twice for every TLabel on the TCustomLabel.CalcSize function
------------------------------------------------------------------------------}
function TCDWidgetSet.GetDC(hWnd: HWND): HDC;
var
lObject: TObject;
lWinControl: TWinControl;
lFormHandle: TCDForm;
begin
{$ifdef VerboseCDDrawing}
DebugLn(':>[WinAPI GetDC] hWnd: ', dbghex(hWnd));
{$endif}
Result := 0;
// Screen DC
if HWnd = 0 then Result := HDC(CDWidgetset.ScreenDC);
// Invalid DC
if not IsValidDC(HWnd) then Exit;
lObject := TObject(HWnd);
// Control DC -> Search for the corresponding form
if lObject is TCDWinControl then
begin
lWinControl := TCDWinControl(lObject).WinControl;
lWinControl := Forms.GetParentForm(lWinControl);
lFormHandle := TCDForm(lWinControl.Handle);
end
// Form DC
else if lObject is TCDForm then
lFormHandle := TCDForm(hWnd)
else
raise Exception.Create('Invalid handle for GetDC');
// Now get Form DC
Result := HDC(lFormHandle.Canvas);
// If the Form DC doesn't yet exist, just give the ScreenDC
// Anyone asking for a DC outside the Paint event can't expect
// to receive something which can be drawn to anyway
if Result = 0 then Result := HDC(CDWidgetset.ScreenDC);
{$ifdef VerboseCDDrawing}
DebugLn(':<[WinAPI GetDC] Result: ', dbghex(Result));
{$endif}
end;
(*function TQtWidgetSet.GetDCOriginRelativeToWindow(PaintDC: HDC;
WindowHandle: HWND; var OriginDiff: TPoint): boolean;
var
QtDC: TQtDeviceContext absolute PaintDC;
Matrix: QTransformH;
P: TPoint;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI GetDCOriginRelativeToWindow] PaintDC ' + dbghex(PaintDC));
{$endif}
Result := IsValidDC(PaintDC);
if not Result then
exit;
Matrix := QPainter_transform(QtDC.Widget);
OriginDiff := Point(0, 0);
P := Point(0, 0);
if WindowHandle <> 0 then
P := TQtWidget(WindowHandle).getClientOffset;
if Matrix <> nil then
begin
OriginDiff.X := Round(QTransform_Dx(Matrix)) - P.X;
OriginDiff.Y := Round(QTransform_Dy(Matrix)) - P.Y;
end;
end;
{------------------------------------------------------------------------------
Function: GetDeviceCaps
Params: DC: HDC; Index: Integer
Returns: Integer
------------------------------------------------------------------------------}
function TQtWidgetSet.GetDeviceCaps(DC: HDC; Index: Integer): Integer;
var
QtDC: TQtDeviceContext;
PaintDevice: QPaintDeviceH;
PaintEngine: QPaintEngineH;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI GetDeviceCaps] DC ' + dbghex(DC));
{$endif}
Result := 0;
if DC = 0 then
DC := HDC(QtScreenContext);
if not IsValidDC(DC) then exit;
QtDC := TQtDeviceContext(DC);
PaintEngine := QtDC.PaintEngine;
if PaintEngine = nil then
exit;
PaintDevice := QPaintEngine_paintDevice(PaintEngine);
case Index of
HORZSIZE:
Result := QPaintDevice_widthMM(PaintDevice);
VERTSIZE:
Result := QPaintDevice_heightMM(PaintDevice);
HORZRES:
Result := QPaintDevice_width(PaintDevice);
BITSPIXEL:
Result := QPaintDevice_depth(PaintDevice);
PLANES:
Result := 1;
SIZEPALETTE:
Result := QPaintDevice_numColors(PaintDevice);
LOGPIXELSX:
Result := QPaintDevice_logicalDpiX(PaintDevice);
LOGPIXELSY:
Result := QPaintDevice_logicalDpiY(PaintDevice);
VERTRES:
Result := QPaintDevice_height(PaintDevice);
NUMRESERVED:
Result := 0;
else
Result := 0;
end;
end;*)
function TCDWidgetSet.GetDeviceSize(DC: HDC; var P: TPoint): Boolean;
Var
ScrSize: TPoint;
LazDC: TLazCanvas;
begin
Result:= False;
// Screen size
if IsScreenDC(DC) or (DC = 0) then
begin
P.X:= GetSystemMetrics(SM_CXSCREEN);
P.Y:= GetSystemMetrics(SM_CYSCREEN);
Exit(True);
end;
if not IsValidDC(DC) then exit;
LazDC := TLazCanvas(DC);
P.X := LazDC.Width;
P.Y := LazDC.Height;
Result := True;
end;
(*function TQtWidgetSet.GetDIBits(DC: HDC; Bitmap: HBitmap; StartScan, NumScans: UINT; Bits: Pointer; var BitInfo: BitmapInfo; Usage: UINT): Integer;
begin
Result := 0;
{$ifdef VerboseQtWinAPI_MISSING_IMPLEMENTATION}
WriteLn('***** [WinAPI TQtWidgetSet.GetDIBits] missing implementation ');
{$endif}
end;
{------------------------------------------------------------------------------
Function: GetDoubleClickTime
Params: none
Returns:
------------------------------------------------------------------------------}
function TQtWidgetSet.GetDoubleClickTime: UINT;
begin
Result := QApplication_doubleClickInterval;
end;*)
{------------------------------------------------------------------------------
Function: GetFocus
Params: None
Returns: Nothing
------------------------------------------------------------------------------}
function TCDWidgetSet.GetFocus: HWND;
begin
Result := 0;
// Don't return the intfcontrol, we try to pretend it doesn't exist
{if FocusedIntfControl <> nil then Result := FocusedIntfControl.Handle
else}
if FocusedControl <> nil then Result := FocusedControl.Handle;
end;
(*function TQtWidgetSet.GetKeyState(nVirtKey: Integer): Smallint;
const
StateDown = SmallInt($FF80);
{StateToggled = SmallInt($0001);}
begin
Result := 0;
case nVirtKey of
VK_LSHIFT: nVirtKey := VK_SHIFT;
VK_LCONTROL: nVirtKey := VK_CONTROL;
VK_LMENU: nVirtKey := VK_MENU;
end;
// where to track toggle state?
case nVirtKey of
VK_LBUTTON:
if (QApplication_mouseButtons and QtLeftButton) > 0 then
Result := Result or StateDown;
VK_RBUTTON:
if (QApplication_mouseButtons and QtRightButton) > 0 then
Result := Result or StateDown;
VK_MBUTTON:
if (QApplication_mouseButtons and QtMidButton) > 0 then
Result := Result or StateDown;
VK_XBUTTON1:
if (QApplication_mouseButtons and QtXButton1) > 0 then
Result := Result or StateDown;
VK_XBUTTON2:
if (QApplication_mouseButtons and QtXButton2) > 0 then
Result := Result or StateDown;
VK_MENU:
if (QApplication_keyboardModifiers and QtAltModifier) > 0 then
Result := Result or StateDown;
VK_SHIFT:
if (QApplication_keyboardModifiers and QtShiftModifier) > 0 then
Result := Result or StateDown;
VK_CONTROL:
if (QApplication_keyboardModifiers and QtControlModifier) > 0 then
Result := Result or StateDown;
VK_LWIN, VK_RWIN:
if (QApplication_keyboardModifiers and QtMetaModifier) > 0 then
Result := Result or StateDown;
{$ifdef VerboseQtWinAPI}
else
DebugLn('TQtWidgetSet.GetKeyState TODO ', DbgSVKCode(Word(nVirtkey)));
{$endif}
end;
end;
function TQtWidgetSet.GetMapMode(DC: HDC): Integer;
begin
if IsValidDC(DC) then
Result := TQtDeviceContext(DC).vMapMode
else
Result := 0;
end;
*)
{$ifndef CD_UseNativeMonitors}
function TCDWidgetSet.GetMonitorInfo(Monitor: HMONITOR; lpmi: PMonitorInfo): Boolean;
begin
Result := (lpmi <> nil) and (lpmi^.cbSize >= SizeOf(TMonitorInfo)) and (Monitor = 1);
if not Result then Exit;
lpmi^.rcMonitor:=Types.Rect(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
lpmi^.rcWork:=lpmi^.rcMonitor;
lpmi^.dwFlags := MONITORINFOF_PRIMARY
end;
{$endif}
(*
{------------------------------------------------------------------------------
Method: TQtWidgetSet.GetDeviceSize
Params: none
Returns: True if successful
Return the size of a device
------------------------------------------------------------------------------}
function TQtWidgetSet.GetDeviceSize(DC: HDC; var P: TPoint): Boolean;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI GetDeviceSize]');
{$endif}
Result := False;
P.X := 0;
P.Y := 0;
if not IsValidDC(DC) then Exit;
if (TObject(DC) is TQtDeviceContext) then
P := TQtDeviceContext(DC).getDeviceSize;
Result := True;
end;
{------------------------------------------------------------------------------
Method: TQtWidgetSet.GetObject
Params: none
Returns: The size written to the buffer
Necessary for TBitmap support
------------------------------------------------------------------------------}
function TQtWidgetSet.GetObject(GDIObj: HGDIOBJ; BufSize: Integer; Buf: Pointer): Integer;
const
QtPenStyleToWinStyleMap: array[QtPenStyle] of UINT =
(
{ QtNoPen } PS_NULL,
{ QtSolidLine } PS_SOLID,
{ QtDashLine } PS_DASH,
{ QtDotLine } PS_DOT,
{ QtDashDotLine } PS_DASHDOT,
{ QtDashDotDotLine } PS_DASHDOTDOT,
{ QtCustomDashLine } PS_USERSTYLE
);
var
aObject: TObject;
AFont: TQtFont absolute aObject;
APen: TQtPen absolute aObject;
ABrush: TQtBrush absolute aObject;
BitmapSection : TDIBSECTION;
ALogFont: PLogFont absolute Buf;
ALogPen: PLogPen absolute Buf;
AExtLogPen: PExtLogPen absolute Buf;
ALogBrush: PLogBrush absolute Buf;
Dashes: TQRealArray;
i: integer;
{$ifdef VerboseQtWinAPI}
ObjType: string;
{$endif}
begin
{$ifdef VerboseQtWinAPI}
WriteLn('Trace:> [WinAPI GetObject] GDIObj: ' + dbghex(GDIObj));
ObjType := '';
{$endif}
Result := 0;
if not IsValidGDIObject(GDIObj) then
begin
{$ifdef VerboseQtWinAPI}
WriteLn('Trace:< [WinAPI GetObject] Invalid GDI Object');
{$endif}
Exit;
end;
aObject := TObject(GDIObj);
{------------------------------------------------------------------------------
Font
------------------------------------------------------------------------------}
if aObject is TQtFont then
begin
if Buf = nil then
Result := SizeOf(TLogFont)
else
if BufSize >= SizeOf(TLogFont) then
begin
Result := SizeOf(TLogFont);
FillChar(ALogFont^, SizeOf(ALogFont^), 0);
ALogFont^.lfHeight := AFont.getPixelSize;
ALogFont^.lfEscapement := AFont.Angle;
case AFont.getWeight of
10: ALogFont^.lfWeight := FW_THIN;
15: ALogFont^.lfWeight := FW_EXTRALIGHT;
25: ALogFont^.lfWeight := FW_LIGHT;
50: ALogFont^.lfWeight := FW_NORMAL;
55: ALogFont^.lfWeight := FW_MEDIUM;
63: ALogFont^.lfWeight := FW_SEMIBOLD;
75: ALogFont^.lfWeight := FW_BOLD;
80: ALogFont^.lfWeight := FW_EXTRABOLD;
87: ALogFont^.lfWeight := FW_HEAVY;
end;
ALogFont^.lfItalic := Ord(AFont.getItalic) * High(Byte);
ALogFont^.lfUnderline := Ord(AFont.getUnderline) * High(Byte);
ALogFont^.lfStrikeOut := Ord(AFont.getStrikeOut) * High(Byte);
ALogFont^.lfCharSet := DEFAULT_CHARSET;
case AFont.getStyleStategy of
QFontPreferMatch: ALogFont^.lfQuality := DRAFT_QUALITY;
QFontPreferQuality: ALogFont^.lfQuality := PROOF_QUALITY;
QFontNoAntialias: ALogFont^.lfQuality := NONANTIALIASED_QUALITY;
QFontPreferAntialias: ALogFont^.lfQuality := ANTIALIASED_QUALITY;
else
ALogFont^.lfQuality := DEFAULT_QUALITY;
end;
ALogFont^.lfFaceName := UTF16ToUTF8(AFont.getFamily);
end;
end
{------------------------------------------------------------------------------
Pen
------------------------------------------------------------------------------}
else
if aObject is TQtPen then
begin
if not APen.IsExtPen then
begin
if Buf = nil then
Result := SizeOf(TLogPen)
else
if BufSize >= SizeOf(TLogPen) then
begin
Result := SizeOf(TLogPen);
TQColorToColorRef(APen.getColor, ALogPen^.lopnColor);
if APen.getCosmetic then
ALogPen^.lopnWidth := Point(1, 0)
else
ALogPen^.lopnWidth := Point(APen.getWidth, 0);
ALogPen^.lopnStyle := QtPenStyleToWinStyleMap[APen.getStyle];
end;
end
else
begin
i := SizeOf(TExtLogPen);
if APen.getStyle = QtCustomDashLine then
begin
Dashes := APen.getDashPattern;
inc(i, (Length(Dashes) - 1) * SizeOf(DWord));
end
else
Dashes := nil;
if Buf = nil then
Result := i
else
if BufSize >= i then
begin
Result := i;
AExtLogPen^.elpPenStyle := QtPenStyleToWinStyleMap[APen.getStyle];
if not APen.getCosmetic then
begin
AExtLogPen^.elpPenStyle := AExtLogPen^.elpPenStyle or PS_GEOMETRIC;
case APen.getJoinStyle of
QtMiterJoin: AExtLogPen^.elpPenStyle := AExtLogPen^.elpPenStyle or PS_JOIN_MITER;
QtBevelJoin: AExtLogPen^.elpPenStyle := AExtLogPen^.elpPenStyle or PS_JOIN_BEVEL;
QtRoundJoin: AExtLogPen^.elpPenStyle := AExtLogPen^.elpPenStyle or PS_JOIN_ROUND;
end;
case APen.getCapStyle of
QtFlatCap: AExtLogPen^.elpPenStyle := AExtLogPen^.elpPenStyle or PS_ENDCAP_FLAT;
QtSquareCap: AExtLogPen^.elpPenStyle := AExtLogPen^.elpPenStyle or PS_ENDCAP_SQUARE;
QtRoundCap: AExtLogPen^.elpPenStyle := AExtLogPen^.elpPenStyle or PS_ENDCAP_ROUND;
end;
AExtLogPen^.elpWidth := APen.getWidth;
end
else
AExtLogPen^.elpWidth := 1;
AExtLogPen^.elpBrushStyle := BS_SOLID;
TQColorToColorRef(APen.getColor, AExtLogPen^.elpColor);
AExtLogPen^.elpHatch := 0;
AExtLogPen^.elpNumEntries := Length(Dashes);
if AExtLogPen^.elpNumEntries > 0 then
begin
for i := 0 to AExtLogPen^.elpNumEntries - 1 do
PDword(@AExtLogPen^.elpStyleEntry)[i] := Trunc(Dashes[i]);
end
else
AExtLogPen^.elpStyleEntry[0] := 0;
end;
end;
end
{------------------------------------------------------------------------------
Region
------------------------------------------------------------------------------}
else
if aObject is TQtRegion then
begin
{TODO: implement Region}
{$ifdef VerboseQtWinAPI}
ObjType := 'Region';
{$endif}
end else
{------------------------------------------------------------------------------
Brush
------------------------------------------------------------------------------}
if aObject is TQtBrush then
begin
if Buf = nil then
Result := SizeOf(TLogBrush)
else
if BufSize >= SizeOf(TLogBrush) then
begin
Result := SizeOf(TLogBrush);
TQColorToColorRef(ABrush.getColor^, ALogBrush^.lbColor);
ABrush.GetLbStyle(ALogBrush^.lbStyle, ALogBrush^.lbHatch);
end;
end
{------------------------------------------------------------------------------
Image
------------------------------------------------------------------------------}
else
if aObject is TQtImage then
begin
{$ifdef VerboseQtWinAPI}
ObjType := 'Image';
{$endif}
if Buf = nil then
Result := SizeOf(TDIBSECTION)
else
begin
BitmapSection.dsOffset := 0;
FillChar(BitmapSection, SizeOf(TDIBSECTION), 0);
with TQtImage(aObject) do
begin
{dsBM - BITMAP}
BitmapSection.dsBm.bmType := $4D42;
BitmapSection.dsBm.bmWidth := width;
BitmapSection.dsBm.bmHeight := height;
BitmapSection.dsBm.bmWidthBytes := bytesPerLine;
BitmapSection.dsBm.bmPlanes := 1;//Does Bitmap Format support more?
BitmapSection.dsBm.bmBitsPixel := depth;
BitmapSection.dsBm.bmBits := bits;
{dsBmih - BITMAPINFOHEADER}
BitmapSection.dsBmih.biSize := 40;
BitmapSection.dsBmih.biWidth := BitmapSection.dsBm.bmWidth;
BitmapSection.dsBmih.biHeight := BitmapSection.dsBm.bmHeight;
BitmapSection.dsBmih.biPlanes := BitmapSection.dsBm.bmPlanes;
BitmapSection.dsBmih.biBitCount := BitmapSection.dsBm.bmBitsPixel;
BitmapSection.dsBmih.biCompression := 0;
BitmapSection.dsBmih.biSizeImage := numBytes;
BitmapSection.dsBmih.biXPelsPerMeter := dotsPerMeterX;
BitmapSection.dsBmih.biYPelsPerMeter := dotsPerMeterY;
BitmapSection.dsBmih.biClrUsed := 0;
BitmapSection.dsBmih.biClrImportant := 0;
end;
if BufSize >= SizeOf(BitmapSection) then
begin
PDIBSECTION(Buf)^ := BitmapSection;
Result := SizeOf(TDIBSECTION);
end
else if BufSize > 0 then
begin
Move(BitmapSection, Buf^, BufSize);
Result := BufSize;
end;
end;
end;
{$ifdef VerboseQtWinAPI}
WriteLn('Trace:< [WinAPI GetObject] Result=', dbgs(Result), ' ObjectType=', ObjType);
{$endif}
end;*)
function TCDWidgetSet.GetParent(Handle : HWND): HWND;
var
lHandle: TCDWinControl absolute Handle;
lWinControl: TWinControl;
begin
{$ifdef VerboseCDDrawing}
DebugLn(Format('[TCDWidgetSet.GetParent] Handle: ', [Handle]));
{$endif}
Result := 0;
// Invalid DC
if Handle = 0 then Exit;
if not IsValidDC(Handle) then Exit;
lWinControl := lHandle.GetWinControl();
if lWinControl = nil then Exit;
lWinControl := lWinControl.Parent;
if lWinControl = nil then Exit;
Result := lWinControl.Handle;
end;
function TCDWidgetSet.GetProp(Handle: hwnd; Str: PChar): Pointer;
begin
if Handle<>0 then
result := TCDWinControl(Handle).Props[str]
else
result := nil;
end;
function TCDWidgetSet.GetRgnBox(RGN : HRGN; lpRect : PRect) : Longint;
var
lLazRegion: TLazRegion absolute RGN;
begin
if RGN = 0 then
begin
Result := ERROR;
if lpRect <> nil then lpRect^ := Types.Rect(0,0,0,0);
Exit();
end;
//Result := lLazRegion.IsSimpleRectRegion(); TQtRegion(RGN).GetRegionType;
Result := SIMPLEREGION;
if lpRect <> nil then lpRect^ := lLazRegion.GetBoundingRect();
{$ifdef VerboseCDWinAPI}
Debugln('Trace:> [WinAPI GetRgnBox] Handle: ' + dbghex(RGN));
{$endif}
end;
(*function TQtWidgetSet.GetROP2(DC: HDC): Integer;
var
QtDC: TQtDeviceContext absolute DC;
begin
{$ifdef VerboseQtWinAPI}
writeln('> TQtWidgetSet.GetROP2() DC ',dbghex(DC));
{$endif}
Result := R2_COPYPEN;
if not IsValidDC(DC) then
exit;
Result := QtDC.Rop2;
{$ifdef VerboseQtWinAPI}
writeln('< TQtWidgetSet.GetROP2() DC ',dbghex(DC),' Result ',Result);
{$endif}
end;
function TQtWidgetSet.GetScrollBarSize(Handle: HWND; BarKind: Integer): integer;
var
w: TQtWidget;
ScrollBar: TQtScrollBar;
begin
{$ifdef VerboseQtWinAPI}
writeln('Trace:> [WinAPI GetScrollBarSize] Handle: ' + dbghex(Handle),' BarKind: ',BarKind);
{$endif}
Result := 0;
if Handle = 0 then exit;
w := TQtWidget(Handle);
{TODO: find out what to do with TCustomForm descendants }
if w is TQtAbstractScrollArea then
begin
if BarKind in [SM_CXVSCROLL, SM_CYVSCROLL] then
ScrollBar := TQtAbstractScrollArea(w).verticalScrollBar
else
ScrollBar := TQtAbstractScrollArea(w).horizontalScrollBar;
end else
if w is TQtScrollBar then
ScrollBar := TQtScrollBar(w)
else
ScrollBar := nil;
if ScrollBar <> nil then
begin
if BarKind in [SM_CXHSCROLL, SM_CYVSCROLL] then
Result := ScrollBar.getWidth
else
Result := ScrollBar.getHeight;
end;
end;
function TQtWidgetSet.GetScrollbarVisible(Handle: HWND; SBStyle: Integer): boolean;
var
w: TQtWidget;
ScrollBar: TQtScrollBar;
begin
{$ifdef VerboseQtWinAPI}
writeln('Trace:> [WinAPI GetScrollBarVisible] Handle: ' + dbghex(Handle),' SBStyle: ',SBStyle);
{$endif}
Result := False;
if Handle = 0 then exit;
w := TQtWidget(Handle);
{TODO: find out what to do with TCustomForm descendants }
if w is TQtAbstractScrollArea then
begin
if SBStyle = SB_VERT then
ScrollBar := TQtAbstractScrollArea(w).verticalScrollBar
else
ScrollBar := TQtAbstractScrollArea(w).horizontalScrollBar;
end else
if w is TQtScrollBar then
ScrollBar := TQtScrollBar(w)
else
ScrollBar := nil;
if ScrollBar <> nil then
Result := ScrollBar.getVisible;
end;
{------------------------------------------------------------------------------
Function: GetScrollInfo
Params: BarFlag
SB_CTL Retrieves the parameters for a scroll bar control. The hwnd
parameter must be the handle to the scroll bar control.
SB_HORZ Retrieves the parameters for the window's standard horizontal
scroll bar.
SB_VERT Retrieves the parameters for the window's standard vertical
scroll bar.
ScrollInfo returns TScrollInfo structure.
Returns: boolean
------------------------------------------------------------------------------}
function TQtWidgetSet.GetScrollInfo(Handle: HWND; BarFlag: Integer; Var ScrollInfo: TScrollInfo): Boolean;
var
QtScrollBar: TQtScrollBar;
begin
Result := False;
if Handle = 0 then exit;
if (csDestroying in TQtWidget(Handle).LCLObject.ComponentState) or
(csFreeNotification in TQtWidget(Handle).LCLObject.ComponentState) then
exit;
QtScrollBar := nil;
if not TQtWidget(Handle).LCLObject.InheritsFrom(TCustomScrollBar) then
begin
if (TQtWidget(Handle) is TQtAbstractScrollArea) then
begin
case BarFlag of
SB_HORZ: QtScrollBar := TQtAbstractScrollArea(Handle).horizontalScrollBar;
SB_VERT: QtScrollBar := TQtAbstractScrollArea(Handle).verticalScrollBar;
end;
end else
Result := False;
end
else
QtScrollBar := TQtScrollBar(TScrollBar(TQtWidget(Handle).LCLObject).Handle);
if Assigned(QtScrollBar) then
begin
// POS
if (ScrollInfo.fMask and SIF_POS) <> 0 then
begin
if QtScrollBar.ChildOfComplexWidget = ccwAbstractScrollArea then
ScrollInfo.nPos := QtScrollBar.getSliderPosition
else
ScrollInfo.nPos := QtScrollBar.getValue;
end;
// RANGE
if (ScrollInfo.fMask and SIF_RANGE) <> 0 then
begin
ScrollInfo.nMin:= QtScrollBar.getMin;
ScrollInfo.nMax:= QtScrollBar.getMax + QtScrollBar.getPageStep;
end;
// PAGE
if (ScrollInfo.fMask and SIF_PAGE) <> 0 then
ScrollInfo.nPage := QtScrollBar.getPageStep;
// TRACKPOS
if (ScrollInfo.fMask and SIF_TRACKPOS) <> 0 then
ScrollInfo.nTrackPos := QtScrollBar.getSliderPosition;
Result := True;
end;
end;*)
function TCDWidgetSet.GetStockObject(Value: Integer): TLCLHandle;
begin
{$ifdef VerboseCDWinAPI}
DebugLn(Format('Trace:> [WinAPI GetStockObject] Value: %d', [Value]));
{$endif}
Result := 0;
case Value of
BLACK_BRUSH: // Black brush.
Result := TLCLHandle(FStockBlackBrush);
DKGRAY_BRUSH: // Dark gray brush.
Result := TLCLHandle(FStockDKGrayBrush);
GRAY_BRUSH: // Gray brush.
Result := TLCLHandle(FStockGrayBrush);
LTGRAY_BRUSH: // Light gray brush.
Result := TLCLHandle(FStockLtGrayBrush);
NULL_BRUSH: // Null brush (equivalent to HOLLOW_BRUSH).
Result := TLCLHandle(FStockNullBrush);
WHITE_BRUSH: // White brush.
Result := TLCLHandle(FStockWhiteBrush);
BLACK_PEN: // Black pen.
Result := TLCLHandle(FStockBlackPen);
NULL_PEN: // Null pen.
Result := TLCLHandle(FStockNullPen);
WHITE_PEN: // White pen.
Result := TLCLHandle(FStockWhitePen);
{System font. By default, Windows uses the system font to draw menus,
dialog box controls, and text. In Windows versions 3.0 and later,
the system font is a proportionally spaced font; earlier versions of
Windows used a monospace system font.}
DEFAULT_GUI_FONT, SYSTEM_FONT:
Result := TLCLHandle(FDefaultGUIFont);
{$ifdef VerboseCDWinAPI}
else
DebugLn(Format('[WinAPI GetStockObject] UNHANDLED Value: %d', [Value]));
{$endif}
end;
end;
{------------------------------------------------------------------------------
Function: TCDWidgetSet.GetSysColor
Params: index to the syscolors array
Returns: RGB value
------------------------------------------------------------------------------}
function TCDWidgetSet.GetSysColor(nIndex: Integer): DWORD;
begin
if (nIndex < 0) or (nIndex > MAX_SYS_COLORS) then
begin
DebugLn('[TCDWidgetSet.GetSysColor] Unknown lcl system color: ');
Result := 0;
Exit;
end;
case nIndex of
COLOR_SCROLLBAR : Result:=GetDefaultDrawer().FallbackPalette.ScrollBar;
COLOR_BACKGROUND : Result:=GetDefaultDrawer().FallbackPalette.Background;
COLOR_ACTIVECAPTION : Result:=GetDefaultDrawer().FallbackPalette.ActiveCaption;
COLOR_INACTIVECAPTION : Result:=GetDefaultDrawer().FallbackPalette.InactiveCaption;
COLOR_MENU : Result:=GetDefaultDrawer().FallbackPalette.Menu;
COLOR_WINDOW : Result:=GetDefaultDrawer().FallbackPalette.Window;
COLOR_WINDOWFRAME : Result:=GetDefaultDrawer().FallbackPalette.WindowFrame;
COLOR_MENUTEXT : Result:=GetDefaultDrawer().FallbackPalette.MenuText;
COLOR_WINDOWTEXT : Result:=GetDefaultDrawer().FallbackPalette.WindowText;
COLOR_CAPTIONTEXT : Result:=GetDefaultDrawer().FallbackPalette.CaptionText;
COLOR_ACTIVEBORDER : Result:=GetDefaultDrawer().FallbackPalette.ActiveBorder;
COLOR_INACTIVEBORDER : Result:=GetDefaultDrawer().FallbackPalette.InactiveBorder;
COLOR_APPWORKSPACE : Result:=GetDefaultDrawer().FallbackPalette.AppWorkspace;
COLOR_HIGHLIGHT : Result:=GetDefaultDrawer().FallbackPalette.Highlight;
COLOR_HIGHLIGHTTEXT : Result:=GetDefaultDrawer().FallbackPalette.HighlightText;
COLOR_BTNFACE : Result:=GetDefaultDrawer().FallbackPalette.BtnFace;
COLOR_BTNSHADOW : Result:=GetDefaultDrawer().FallbackPalette.BtnShadow;
COLOR_GRAYTEXT : Result:=GetDefaultDrawer().FallbackPalette.GrayText;
COLOR_BTNTEXT : Result:=GetDefaultDrawer().FallbackPalette.BtnText;
COLOR_INACTIVECAPTIONTEXT : Result:=GetDefaultDrawer().FallbackPalette.InactiveCaptionText;
COLOR_BTNHIGHLIGHT : Result:=GetDefaultDrawer().FallbackPalette.BtnHighlight;
COLOR_3DDKSHADOW : Result:=GetDefaultDrawer().FallbackPalette.color3DDkShadow;
COLOR_3DLIGHT : Result:=GetDefaultDrawer().FallbackPalette.color3DLight;
COLOR_INFOTEXT : Result:=GetDefaultDrawer().FallbackPalette.InfoText;
COLOR_INFOBK : Result:=GetDefaultDrawer().FallbackPalette.InfoBk;
//
COLOR_HOTLIGHT : Result:=GetDefaultDrawer().FallbackPalette.HotLight;
COLOR_GRADIENTACTIVECAPTION : Result:=GetDefaultDrawer().FallbackPalette.GradientActiveCaption;
COLOR_GRADIENTINACTIVECAPTION : Result:=GetDefaultDrawer().FallbackPalette.GradientInactiveCaption;
COLOR_MENUHILIGHT : Result:=GetDefaultDrawer().FallbackPalette.MenuHighlight;
COLOR_MENUBAR : Result:=GetDefaultDrawer().FallbackPalette.MenuBar;
//
COLOR_FORM : Result:=GetDefaultDrawer().FallbackPalette.Form;
else
Result:=0;
end;
end;
(*function TQtWidgetSet.GetSysColorBrush(nIndex: Integer): HBrush;
function GetBrush(Group: QPaletteColorGroup; Role: QPaletteColorRole; ClassName: PAnsiChar = nil): HBrush;
var
Handle: QPaletteH;
begin
Handle := QPalette_create;
if ClassName = nil then
QApplication_palette(Handle)
else
QApplication_palette(Handle, ClassName);
if FSysColorBrushes[nIndex] = 0 then
Result := HBrush(TQtBrush.Create(False))
else
Result := FSysColorBrushes[nIndex];
TQtBrush(Result).FHandle := QBrush_create(QPalette_brush(Handle, Group, Role));
TQtBrush(Result).FShared := True;
QPalette_destroy(Handle);
end;
function GetSolidBrush(AColor: TColor): HBrush;
var
Color: TQColor;
begin
if FSysColorBrushes[nIndex] = 0 then
Result := HBrush(TQtBrush.Create(True))
else
Result := FSysColorBrushes[nIndex];
Color := QBrush_Color(TQtBrush(Result).FHandle)^;
ColorRefToTQColor(ColorToRGB(AColor), Color);
QBrush_setColor(TQtBrush(Result).FHandle, @Color);
TQtBrush(Result).FShared := True;
end;
begin
if (nIndex < 0) or (nIndex > MAX_SYS_COLORS) then
begin
Result := 0;
Exit;
end;
if (FSysColorBrushes[nIndex] = 0) or
(
(FSysColorBrushes[nIndex] <> 0) and
(TQtBrush(FSysColorBrushes[nIndex]).FHandle = nil)
) then
begin
case nIndex of
COLOR_SCROLLBAR : Result:=GetBrush(QPaletteActive, QPaletteButton);
COLOR_BACKGROUND : Result:=GetBrush(QPaletteActive, QPaletteWindow);
COLOR_WINDOW : Result:=GetBrush(QPaletteInActive, QPaletteBase);
COLOR_WINDOWFRAME : Result:=GetBrush(QPaletteActive, QPaletteShadow);
COLOR_WINDOWTEXT : Result:=GetBrush(QPaletteActive, QPaletteWindowText);
COLOR_ACTIVEBORDER : Result:=GetBrush(QPaletteActive, QPaletteWindow);
COLOR_INACTIVEBORDER : Result:=GetBrush(QPaletteInactive, QPaletteWindow);
COLOR_APPWORKSPACE : Result:=GetBrush(QPaletteActive, QPaletteWindow);
COLOR_HIGHLIGHT : Result:=GetBrush(QPaletteActive, QPaletteHighlight);
COLOR_HIGHLIGHTTEXT : Result:=GetBrush(QPaletteActive, QPaletteHighlightedText);
COLOR_BTNFACE : Result:=GetBrush(QPaletteActive, QPaletteButton);
COLOR_BTNSHADOW : Result:=GetBrush(QPaletteActive, QPaletteDark);
COLOR_GRAYTEXT : Result:=GetBrush(QPaletteActive, QPaletteText);
COLOR_BTNTEXT : Result:=GetBrush(QPaletteActive, QPaletteButtonText);
COLOR_BTNHIGHLIGHT : Result:=GetBrush(QPaletteActive, QPaletteLight);
COLOR_3DDKSHADOW : Result:=GetBrush(QPaletteActive, QPaletteShadow);
COLOR_3DLIGHT : Result:=GetBrush(QPaletteActive, QPaletteMidlight);
COLOR_INFOTEXT : Result:=GetBrush(QPaletteInActive, QPaletteToolTipText);
COLOR_INFOBK : Result:=GetBrush(QPaletteInActive, QPaletteToolTipBase);
COLOR_HOTLIGHT : Result:=GetBrush(QPaletteActive, QPaletteLight);
// qt does not provide any methods to retrieve titlebar colors
{$IFNDEF MSWINDOWS}
COLOR_ACTIVECAPTION : Result:=GetBrush(QPaletteActive, QPaletteHighlight);
COLOR_INACTIVECAPTION : Result:=GetBrush(QPaletteInActive, QPaletteHighlight);
COLOR_CAPTIONTEXT : Result:=GetBrush(QPaletteActive, QPaletteHighlightedText);
COLOR_INACTIVECAPTIONTEXT : Result:=GetBrush(QPaletteInactive, QPaletteHighlightedText);
COLOR_GRADIENTACTIVECAPTION : Result:=GetBrush(QPaletteActive, QPaletteBase);
COLOR_GRADIENTINACTIVECAPTION : Result:=GetBrush(QPaletteInactive, QPaletteBase);
{$ELSE}
COLOR_ACTIVECAPTION : Result:=GetSolidBrush(Windows.GetSysColor(COLOR_ACTIVECAPTION));
COLOR_INACTIVECAPTION : Result:=GetSolidBrush(Windows.GetSysColor(COLOR_INACTIVECAPTION));
COLOR_CAPTIONTEXT : Result:=GetSolidBrush(Windows.GetSysColor(COLOR_CAPTIONTEXT));
COLOR_INACTIVECAPTIONTEXT : Result:=GetSolidBrush(Windows.GetSysColor(COLOR_INACTIVECAPTIONTEXT));
COLOR_GRADIENTACTIVECAPTION : Result:=GetSolidBrush(Windows.GetSysColor(COLOR_GRADIENTACTIVECAPTION));
COLOR_GRADIENTINACTIVECAPTION : Result:=GetSolidBrush(Windows.GetSysColor(COLOR_GRADIENTINACTIVECAPTION));
{$ENDIF}
COLOR_MENU : Result:=GetBrush(QPaletteActive, QPaletteButton, 'QMenu');
COLOR_MENUTEXT : Result:=GetBrush(QPaletteActive, QPaletteButtonText, 'QMenu');
COLOR_MENUHILIGHT : Result:=GetBrush(QPaletteDisabled, QPaletteHighlight, 'QMenu');
COLOR_MENUBAR : Result:=GetBrush(QPaletteActive, QPaletteButton, 'QMenu');
COLOR_FORM : Result:=GetBrush(QPaletteActive, QPaletteWindow);
else
Result:=0;
end;
FSysColorBrushes[nIndex] := Result;
end
else
Result := FSysColorBrushes[nIndex];
end;
{------------------------------------------------------------------------------
Function: GetSystemMetrics
Params:
Returns: Nothing
------------------------------------------------------------------------------}
function TQtWidgetSet.GetSystemMetrics(nIndex: Integer): Integer;
var
R: TRect;
begin
{$ifdef VerboseQtWinAPI}
WriteLn(Format('Trace:> [TQtWidgetSet.GetSystemMetrics] %d', [nIndex]));
{$endif}
Result := 0;
case nIndex of
SM_ARRANGE:
begin
{$ifdef VerboseQtWinAPI}
WriteLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_ARRANGE ');
{$endif}
end;
SM_CLEANBOOT:
begin
{$ifdef VerboseQtWinAPI}
WriteLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CLEANBOOT ');
{$endif}
end;
SM_CMONITORS:
Result := QDesktopWidget_numScreens(QApplication_desktop());
SM_CMOUSEBUTTONS:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CMOUSEBUTTONS ');
end;
SM_CXBORDER, SM_CYBORDER:
begin
// size of frame around controls
Result := QStyle_pixelMetric(QApplication_style(),
QStylePM_DefaultFrameWidth, nil, nil);
end;
SM_CXCURSOR:
begin
Result := 32; // recomended in docs
end;
SM_CYCURSOR:
begin
Result := 32; // recomended in docs
end;
SM_CXDOUBLECLK:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CXDOUBLECLK ');
end;
SM_CYDOUBLECLK:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYDOUBLECLK ');
end;
SM_CXDRAG:
begin
Result := 2;
end;
SM_CYDRAG:
begin
Result := 2;
end;
SM_CXEDGE:
begin
Result := 2;
end;
SM_CYEDGE:
begin
Result := 2;
end;
SM_CXFIXEDFRAME:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CXFIXEDFRAME ');
end;
SM_CYFIXEDFRAME:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYFIXEDFRAME ');
end;
SM_CXFULLSCREEN:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CXFULLSCREEN ');
end;
SM_CYFULLSCREEN:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYFULLSCREEN ');
end;
SM_CXHTHUMB:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CXHTHUMB ');
end;
SM_CXICON,
SM_CYICON:
begin
Result := 32;
end;
SM_CXICONSPACING:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CXICONSPACING ');
end;
SM_CYICONSPACING:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYICONSPACING ');
end;
SM_CXMAXIMIZED:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CXMAXIMIZED ');
end;
SM_CYMAXIMIZED:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYMAXIMIZED ');
end;
SM_CXMAXTRACK:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CXMAXTRACK ');
end;
SM_CYMAXTRACK:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYMAXTRACK ');
end;
SM_CXMENUCHECK:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CXMENUCHECK ');
end;
SM_CYMENUCHECK:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYMENUCHECK ');
end;
SM_CXMENUSIZE:
begin
Result := QStyle_pixelMetric(QApplication_style(), QStylePM_IndicatorWidth, nil, nil);
end;
SM_CYMENUSIZE:
begin
Result := QStyle_pixelMetric(QApplication_style(), QStylePM_IndicatorHeight, nil, nil);
end;
SM_CXMIN:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CXMIN ');
end;
SM_CYMIN:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYMIN ');
end;
SM_CXMINIMIZED:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CXMINIMIZED ');
end;
SM_CYMINIMIZED:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYMINIMIZED ');
end;
SM_CXMINSPACING:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CXMINSPACING ');
end;
SM_CYMINSPACING:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYMINSPACING ');
end;
SM_CXMINTRACK:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CXMINTRACK ');
end;
SM_CYMINTRACK:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYMINTRACK ');
end;
SM_CXSCREEN:
begin
QDesktopWidget_screenGeometry(QApplication_desktop(), @R, QDesktopWidget_primaryScreen(QApplication_desktop()));
Result := R.Right - R.Left;
end;
SM_CYSCREEN:
begin
QDesktopWidget_screenGeometry(QApplication_desktop(), @R, QDesktopWidget_primaryScreen(QApplication_desktop()));
Result := R.Bottom - R.Top;
end;
SM_CXSIZE:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CXSIZE ');
end;
SM_CYSIZE:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYSIZE ');
end;
SM_CXSIZEFRAME,
SM_CYSIZEFRAME:
begin
Result := QStyle_pixelMetric(QApplication_style(), QStylePM_MDIFrameWidth, nil, nil);
end;
SM_CXSMICON,
SM_CYSMICON:
begin
Result := 16
end;
SM_CXSMSIZE:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CXSMSIZE ');
end;
SM_CYSMSIZE:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYSMSIZE ');
end;
SM_CXVIRTUALSCREEN:
begin
Result := QWidget_width(QApplication_desktop);
end;
SM_CYVIRTUALSCREEN:
begin
Result := QWidget_height(QApplication_desktop);
end;
SM_CXVSCROLL,
SM_CYVSCROLL,
SM_CXHSCROLL,
SM_CYHSCROLL:
begin
Result := QStyle_pixelMetric(QApplication_Style, QStylePM_ScrollBarExtent, nil, nil);
end;
SM_CYCAPTION:
begin
Result := QStyle_pixelMetric(QApplication_Style, QStylePM_TitleBarHeight, nil, nil);
end;
SM_CYKANJIWINDOW:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYKANJIWINDOW ');
end;
SM_CYMENU:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYMENU ');
end;
SM_CYSMCAPTION:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYSMCAPTION ');
end;
SM_CYVTHUMB:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_CYVTHUMB ');
end;
SM_DBCSENABLED:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_DBCSENABLED ');
end;
SM_DEBUG:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_DEBUG ');
end;
SM_MENUDROPALIGNMENT:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_MENUDROPALIGNMENT');
end;
SM_MIDEASTENABLED:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_MIDEASTENABLED ');
end;
SM_MOUSEPRESENT:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_MOUSEPRESENT ');
end;
SM_MOUSEWHEELPRESENT:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_MOUSEWHEELPRESENT');
end;
SM_NETWORK:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_NETWORK ');
end;
SM_PENWINDOWS:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_PENWINDOWS ');
end;
SM_SECURE:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_SECURE ');
end;
SM_SHOWSOUNDS:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_SHOWSOUNDS ');
end;
SM_SLOWMACHINE:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_SLOWMACHINE ');
end;
SM_SWAPBUTTON:
begin
//DebugLn('Trace:TODO: [TQtWidgetSet.GetSystemMetrics] --> SM_SWAPBUTTON ');
end;
end;
end; *)
{------------------------------------------------------------------------------
Function: GetTextColor
Params: DC - A device context
Returns: TColorRef
Gets the Font Color currently assigned to the Device Context
------------------------------------------------------------------------------}
function TCDWidgetSet.GetTextColor(DC: HDC) : TColorRef;
var
LazDC: TLazCanvas;
begin
{$ifdef VerboseCDDrawing}
DebugLn(Format('[TCDWidgetSet.SetTextColor] DC: %x', [DC]));
{$endif}
Result := 0;
if not IsValidDC(DC) then Exit;
LazDC := TLazCanvas(DC);
if LazDC.Font <> nil then
Result := FPColorToTColor(LazDC.Font.FPColor);
end;
{$ifndef CD_UseNativeText}
{------------------------------------------------------------------------------
Function: GetTextExtentExPoint
Params: http://msdn.microsoft.com/en-us/library/dd144935%28VS.85%29.aspx
Returns: True on success
------------------------------------------------------------------------------}
function TCDWidgetSet.GetTextExtentExPoint(DC: HDC; Str: PChar; Count,
MaxWidth: Integer; MaxCount, PartialWidths: PInteger; var Size: Types.TSize
): Boolean;
{var
i: Integer;
w: Integer;
AStr: WideString;
Accu: Integer; }
begin
// Result := False;
Result := inherited GetTextExtentExPoint(DC, Str, Count, MaxWidth,
MaxCount, PartialWidths, Size);
{if not IsValidDC(DC) then Exit;
with TQtDeviceContext(DC) do
begin
AStr := GetUtf8String(Str);
Size.cx := 0;
Size.cY := Font.Metrics.Height;
if PartialWidths = nil then
begin
if MaxCount <> nil then
begin
Size.cx := Font.Metrics.width(@AStr);
Accu := 0;
if MaxWidth <= 0 then
MaxCount^ := 0
else
for i := 0 to Count - 1 do
begin
W := QFontMetrics_charWidth(Font.Metrics.FHandle, @AStr, i);
Accu := Accu + W;
if Accu <= MaxWidth then
MaxCount^ := i + 1
else
break;
end;
end;
end else
begin
if MaxCount <> nil then
MaxCount^ := 0;
for i := 0 to Count - 1 do
begin
w := QFontMetrics_charWidth(Font.Metrics.FHandle, @AStr, i);
Inc(Size.cx, w);
if MaxCount <> nil then
begin
if Size.cx <= MaxWidth then
begin
inc(MaxCount^);
PartialWidths[i] := Size.cx;
end else
begin
Dec(Size.cx, w);
break;
end;
end else
PartialWidths[i] := Size.cx;
end;
end;
end;
Result := True;}
end;
{------------------------------------------------------------------------------
Function: GetTextExtentPoint
Params: none
Returns: Nothing
------------------------------------------------------------------------------}
function TCDWidgetSet.GetTextExtentPoint(DC: HDC; Str: PChar; Count: Integer; var Size: Types.TSize): Boolean;
var
LazDC: TLazCanvas absolute DC;
ftFont: TFreeTypeFont;
begin
{$ifdef VerboseCDWinAPI}
DebugLn('[WinAPI GetTextExtentPoint]');
{$endif}
Result := False;
if not IsValidDC(DC) then Exit;
ftFont := TFreeTypeFont(LazDC.ExtraFontData);
if ftFont = nil then
begin
DebugLn('[TCDWidgetSet.GetTextExtentPoint] Error: ExtraFontData not yet created');
Exit;
end;
Size.cx := Round(ftFont.TextWidth(Str));
Size.cy := Round(ftFont.TextHeight(Str));
if Size.cy = 0 then Size.cy := LazDC.AssignedFont.Size; // crude aproximation
if Size.cy = 0 then Size.cy := DefaultFontSize;
Result := True;
end;
{------------------------------------------------------------------------------
Function: GetTextMetrics
Params: DC - A device context with a font selected
TM - The structure to receive the font information
Returns: If successfull
------------------------------------------------------------------------------}
function TCDWidgetSet.GetTextMetrics(DC: HDC; var TM: TTextMetric): Boolean;
var
LazDC: TLazCanvas absolute DC;
lTestText: string;
lTestSize: Types.TSize;
lFont: TFPCustomFont;
lFTFont: TFreeTypeFont;
FreeFTFont: Boolean = False;
begin
{$ifdef VerboseCDWinAPI}
DebugLn('[WinAPI GetTextMetrics]');
{$endif}
Result := False;
if not IsValidDC(DC) then Exit;
FillChar(TM, SizeOf(TM), 0);
lFont := LazDC.Font;
lFTFont := TFreeTypeFont(LazDC.ExtraFontData);
if lFTFont = nil then
begin
DebugLn('[TCDWidgetSet.GetTextMetrics] Error: ExtraFontData not yet created');
Exit;
end;
//QtFontMetrics := QtDC.Metrics;
TM.tmHeight := Round(lFTFont.TextHeight('ŹÇ'));
TM.tmAscent := Round(lFTFont.Ascent);
TM.tmDescent := Round(lFTFont.Descent);
TM.tmInternalLeading := 0;
TM.tmExternalLeading := 0;// ToDo
TM.tmAveCharWidth := Round(lFTFont.TextWidth('x'));
TM.tmMaxCharWidth := Round(lFTFont.TextWidth('M'));
if lFont.Bold then TM.tmWeight := FW_BOLD
else TM.tmWeight := FW_NORMAL;
TM.tmOverhang := 0;
TM.tmDigitizedAspectX := 0;
TM.tmDigitizedAspectY := 0;
TM.tmFirstChar := 'a';
TM.tmLastChar := 'z';
TM.tmDefaultChar := 'x';
TM.tmBreakChar := '?';
TM.tmItalic := Ord(lFont.Italic);
TM.tmUnderlined := Ord(lFont.Underline);
TM.tmStruckOut := Ord(lFont.StrikeThrough);
{ Defaults to a TrueType font.
Note that the meaning of the FIXED_PITCH constant is the opposite of
the name implies, according to MSDN docs. Just a small inconsistency
on Windows API that we have to mimic. }
{ if QtDC.font.fixedPitch then
TM.tmPitchAndFamily := TRUETYPE_FONTTYPE
else}
TM.tmPitchAndFamily := FIXED_PITCH or TRUETYPE_FONTTYPE;
TM.tmCharSet := DEFAULT_CHARSET;
Result := True;
if FreeFTFont then lFTFont.Free;
end;
{$endif}
(*function TQtWidgetSet.GetViewPortExtEx(DC: HDC; Size: PSize): Integer;
var
R: TRect;
begin
if IsValidDC(DC) and (Size <> nil) then
begin
QPainter_ViewPort(TQtDeviceContext(DC).Widget, @R);
Size^.cx := R.Right - R.Left;
Size^.cy := R.Bottom - R.Top;
Result := Integer(True);
end else
Result := Integer(False);
end;
function TQtWidgetSet.GetViewPortOrgEx(DC: HDC; P: PPoint): Integer;
var
R: TRect;
begin
if IsValidDC(DC) and (P <> nil) then
begin
QPainter_ViewPort(TQtDeviceContext(DC).Widget, @R);
P^ := R.TopLeft;
Result := Integer(True);
end else
Result := Integer(False);
end;
function TQtWidgetSet.GetWindowExtEx(DC: HDC; Size: PSize): Integer;
var
R: TRect;
begin
if IsValidDC(DC) and (Size <> nil) then
begin
QPainter_Window(TQtDeviceContext(DC).Widget, @R);
Size^.cx := R.Right - R.Left;
Size^.cy := R.Bottom - R.Top;
Result := Integer(True);
end else
Result := Integer(False);
end;
function TQtWidgetSet.GetWindowLong(Handle : hwnd; int: Integer): PtrInt;
begin
Result := 0;
{$ifdef VerboseQtWinAPI_MISSING_IMPLEMENTATION}
WriteLn('***** [WinAPI TQtWidgetSet.GetWindowLong] missing implementation ');
{$endif}
end;*)
{------------------------------------------------------------------------------
Method: GetWindowOrgEx
Params: DC -
Returns:
------------------------------------------------------------------------------}
function TCDWidgetSet.GetWindowOrgEx(dc: hdc; P: PPoint): Integer;
var
LazDC: TLazCanvas absolute DC;
begin
{$ifdef VerboseCDDrawing}
DebugLn(Format(':>[WinAPI GetWindowOrgEx] DC=%s', [dbghex(DC)]));
{$endif}
Result := 0;
if not IsValidDC(DC) then Exit;
if P = nil then Exit;
P^.X := LazDC.WindowOrg.X - LazDC.BaseWindowOrg.X;
P^.Y := LazDC.WindowOrg.Y - LazDC.BaseWindowOrg.Y;
Result := 1; // any non-zero will do according to MSDN
{$ifdef VerboseCDDrawing}
DebugLn(':<[WinAPI GetWindowOrgEx] Result='+dbgs(p^));
{$endif}
end;
(*{------------------------------------------------------------------------------
Method: GetWindowRect
Params: Handle - handle of window
Rect - record for window coordinates
Returns: if the function succeeds, the return value is nonzero; if the
function fails, the return value is zero
Retrieves the dimensions of the bounding rectangle of the specified window.
------------------------------------------------------------------------------}
function TCDWidgetSet.GetWindowRect(Handle: HWND; var ARect: TRect): Integer;
var
APos: TQtPoint;
R: TRect;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI GetWindowRect]');
{$endif}
Result := 0;
if not IsValidHandle(Handle) then
exit;
APos := QtPoint(0,0);
QWidget_mapToGlobal(TQtWidget(Handle).Widget, @APos, @APos);
R := TQtWidget(Handle).getFrameGeometry;
ARect := Bounds(APos.X,APos.Y,R.Right-R.Left,R.Bottom-R.Top);
Result := -1;
end;*)
{------------------------------------------------------------------------------
Function: GetWindowRelativePosition
Params: Handle : HWND;
Returns: true on success
returns the current widget Left, Top, relative to the client origin of its
parent
------------------------------------------------------------------------------}
function TCDWidgetSet.GetWindowRelativePosition(Handle: HWND; var Left, Top: integer): boolean;
var
lObject: TObject;
begin
{$ifdef VerboseCDWinAPI}
DebugLn('[WinAPI GetWindowRelativePosition]');
{$endif}
if Handle = 0 then Exit(False);
lObject := TObject(Handle);
if lObject is TCDForm then
begin
Result := BackendGetWindowRelativePosition(Handle, Left, Top);
Exit;
end
else
Result := inherited GetWindowRelativePosition(Handle, Left, Top);
end;
{------------------------------------------------------------------------------
Function: GetWindowSize
Params: Handle : hwnd;
Returns: true on success
Returns the current widget Width and Height
------------------------------------------------------------------------------}
function TCDWidgetSet.GetWindowSize(Handle: hwnd; var Width, Height: integer): boolean;
var
lObject: TObject;
lCDWinControl: TCDWinControl;
begin
{$ifdef VerboseCDWinAPI}
DebugLn(':>[WinAPI GetWindowSize]');
{$endif}
if Handle = 0 then Exit(False);
lObject := TObject(Handle);
if lObject is TCDForm then
begin
// Initial size guessed
if TCDForm(lObject).Image <> nil then
begin
Width := TCDForm(lObject).Image.Width;
Height := TCDForm(lObject).Image.Height;
end
else
begin
Width := 0;
Height := 0;
end;
// Now ask the backend
Result := BackendGetWindowSize(Handle, Width, Height);
end
else if lObject is TCDWinControl then
begin
lCDWinControl := lObject as TCDWinControl;
Width := lCDWinControl.WinControl.Width;
Height := lCDWinControl.WinControl.Height;
Result := True;
{$ifdef VerboseCDWinAPI}
DebugLn(Format(':[WinAPI GetWindowSize] WinControl %s:%s',
[lCDWinControl.WinControl.Name, lCDWinControl.WinControl.ClassName]));
{$endif}
end
else
Result := False;
{$ifdef VerboseCDWinAPI}
DebugLn(Format(':<[WinAPI GetWindowSize] Result=%d Width=%d Height=%d',
[PtrInt(Result), Width, Height]));
{$endif}
end;
(*{------------------------------------------------------------------------------
Function: GradientFill
Params: DC - DeviceContext to perform on
Vertices - array of Points W/Color & Alpha
NumVertices - Number of Vertices
Meshes - array of Triangle or Rectangle Meshes,
each mesh representing one Gradient Fill
NumMeshes - Number of Meshes
Mode - Gradient Type, either Triangle,
Vertical Rect, Horizontal Rect
Returns: true on success
Performs multiple Gradient Fills, either a Three way Triangle Gradient,
or a two way Rectangle Gradient, each Vertex point also supports optional
Alpha/Transparency for more advanced Gradients.
------------------------------------------------------------------------------}
function TQtWidgetSet.GradientFill(DC: HDC; Vertices: PTriVertex;
NumVertices : Longint;
Meshes: Pointer; NumMeshes : Longint; Mode : Longint): boolean;
function DoFillTriangle: Boolean; inline;
begin
Result := (Mode and GRADIENT_FILL_TRIANGLE) = GRADIENT_FILL_TRIANGLE;
end;
function DoFillVRect: Boolean; inline;
begin
Result := (Mode and GRADIENT_FILL_RECT_V) = GRADIENT_FILL_RECT_V;
end;
function VertexToColor(AVertex: tagTRIVERTEX): TQColor;
var
TheAlpha: Byte;
begin
TheAlpha := AVertex.Alpha shr 8;
if TheAlpha = 0 then
TheAlpha := 255;
with AVertex do
QColor_fromRgb(@Result, Red shr 8, Green shr 8, Blue shr 8, TheAlpha);
end;
function FillTriMesh(Mesh: tagGradientTriangle) : Boolean;
var
V1, V2, V3: tagTRIVERTEX;
C1, C2, C3: TQColor;
Grad: QConicalGradientH;
Brush: QBrushH;
Triangle: QPolygonH;
R: TRect;
Painter: QPainterH;
Rgn: QRegionH;
begin
with Mesh do
begin
Result :=
(Vertex1 < Cardinal(NumVertices)) and (Vertex2 >= 0) and
(Vertex2 < Cardinal(NumVertices)) and (Vertex2 >= 0) and
(Vertex3 < Cardinal(NumVertices)) and (Vertex3 >= 0);
if (Vertex1 = Vertex2) or
(Vertex1 = Vertex3) or
(Vertex2 = Vertex3) or not Result then
Exit;
V1 := Vertices[Vertex1];
V2 := Vertices[Vertex2];
V3 := Vertices[Vertex3];
Painter := TQtDeviceContext(DC).Widget;
QPainter_save(Painter);
Triangle := QPolygon_create(3);
QPolygon_setPoint(Triangle, 0, V1.X, V1.Y);
QPolygon_setPoint(Triangle, 1, V2.X, V2.Y);
QPolygon_setPoint(Triangle, 2, V3.X, V3.Y);
QPolygon_boundingRect(Triangle, @R);
Dec(R.Bottom);
Dec(R.Right);
Rgn := QRegion_create(@R);
// make our poly clip region , so gradient center is at real center
QPainter_setClipRegion(Painter, Rgn, QtIntersectClip);
Grad := QConicalGradient_create(R.Right div 2, R.Bottom div 2, 90);
C1 := VertexToColor(V1);
C2 := VertexToColor(V2);
C3 := VertexToColor(V3);
QGradient_setColorAt(Grad, 0.0, @C1); // open
QGradient_setColorAt(Grad, 0.33, @C2); // left corner
QGradient_setColorAt(Grad, 0.66, @C3); // right corner
QGradient_setColorAt(Grad, 1.0, @C1); // close
Brush := QBrush_create(Grad);
QPainter_setPen(Painter, QtNoPen);
QPainter_setBrush(Painter, Brush);
// move center point down, so we remove reflections of C2 and C3
// TODO: C1 reflection is still visible
QPainter_setBrushOrigin(Painter, 0, R.Bottom div 5);
QPainter_drawPolygon(Painter, Triangle);
//TODO: now me must make it look "softer" because reflection look of
// first color is ugly.
QBrush_destroy(Brush);
QPolygon_destroy(Triangle);
QGradient_destroy(Grad);
QRegion_destroy(Rgn);
QPainter_restore(Painter);
end;
end;
function FillRectMesh(Mesh: tagGradientRect) : boolean;
var
TL,BR: tagTRIVERTEX;
StartColor, EndColor, SwapColor: TQColor;
Swap: Longint;
SwapColors: Boolean;
Grad: QGradientH;
Brush: QBrushH;
begin
with Mesh do
begin
Result :=
(UpperLeft < Cardinal(NumVertices)) and (UpperLeft >= 0) and
(LowerRight < Cardinal(NumVertices)) and (LowerRight >= 0);
if (LowerRight = UpperLeft) or not Result then
Exit;
TL := Vertices[UpperLeft];
BR := Vertices[LowerRight];
SwapColors := (BR.Y < TL.Y) and (BR.X < TL.X);
if BR.X < TL.X then
begin
Swap := BR.X;
BR.X := TL.X;
TL.X := Swap;
end;
if BR.Y < TL.Y then
begin
Swap := BR.Y;
BR.Y := TL.Y;
TL.Y := Swap;
end;
StartColor := VertexToColor(TL);
EndColor := VertexToColor(BR);
if SwapColors then
begin
SwapColor := StartColor;
StartColor := EndColor;
EndColor := SwapColor;
end;
if DoFillVRect then
Grad := QLinearGradient_create(TL.X, TL.Y, TL.X, BR.Y)
else
Grad := QLinearGradient_create(TL.X, TL.Y, BR.X, TL.Y);
QGradient_setColorAt(Grad, 0, @StartColor);
QGradient_setColorAt(Grad, 1, @EndColor);
Brush := QBrush_create(Grad);
TQtDeviceContext(DC).fillRect(TL.X, TL.Y, BR.X - TL.X, BR.Y - TL.Y, Brush);
QGradient_destroy(Grad);
QBrush_destroy(Brush);
end;
end;
const
MeshSize: Array[Boolean] of Integer = (
SizeOf(tagGradientRect), SizeOf(tagGradientTriangle));
var
i : Integer;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('***** [WinAPI TQtWidgetSet.GradientFill] ');
{$endif}
//Currently Alpha blending is ignored... Ideas anyone?
Result := (Meshes <> nil) and (NumMeshes >= 1) and (NumVertices >= 2)
and (Vertices <> nil);
if Result and DoFillTriangle then
Result := NumVertices >= 3;
if Result then
begin
Result := False;
//Sanity Checks For Vertices Size vs. Count
if MemSizeLessThan(MemSize(Vertices), PtrUInt(SizeOf(tagTRIVERTEX)*NumVertices)) then
exit;
//Sanity Checks For Meshes Size vs. Count
if MemSizeLessThan(MemSize(Meshes), PtrUInt(MeshSize[DoFillTriangle]*NumMeshes)) then
exit;
for I := 0 to NumMeshes - 1 do
begin
if DoFillTriangle then
begin
if not FillTriMesh(PGradientTriangle(Meshes)[I]) then
exit;
end
else
begin
if not FillRectMesh(PGradientRect(Meshes)[I]) then
exit;
end;
end;
Result := True;
end;
end;
function TQtWidgetSet.HideCaret(hWnd: HWND): Boolean;
begin
Result := (hWnd <> 0) and QtCaret.HideCaret(TQtWidget(hWnd));
end;*)
{------------------------------------------------------------------------------
Procedure: InitializeCriticalSection
Params: var CritSection: TCriticalSection
Returns:
------------------------------------------------------------------------------}
procedure TCDWidgetSet.InitializeCriticalSection(var CritSection: TCriticalSection);
var
ACritSec: System.PRTLCriticalSection;
begin
New(ACritSec);
System.InitCriticalSection(ACritSec^);
CritSection:=TCriticalSection(ACritSec);
end;
(*function TQtWidgetSet.IntersectClipRect(dc: hdc; Left, Top, Right, Bottom: Integer): Integer;
var
QtDC: TQtDeviceContext absolute dc;
IntersectRgn, Rgn: QRegionH;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI TQtWidgetSet.IntersectClipRect] L ',Left,' T ',Top,' R ',Right,' B ',Bottom);
{$endif}
Result := ERROR;
if not IsValidDC(DC) then exit;
IntersectRgn := QRegion_create(Left, Top, Right - Left, Bottom - Top);
try
if QtDC.getClipping then
begin
Rgn := QRegion_create;
try
QPainter_clipRegion(QtDC.Widget, Rgn);
if QRegion_isEmpty(Rgn) then
QtDC.setClipRegion(IntersectRgn)
else
QtDC.setClipRegion(IntersectRgn, QtIntersectClip);
QtDC.setClipping(True);
// recreate Rgn
QRegion_destroy(Rgn);
Rgn := QRegion_create;
QPainter_clipRegion(QtDC.Widget, Rgn);
Result := QtDC.GetRegionType(Rgn);
finally
QRegion_destroy(Rgn);
end;
end else
begin
QtDC.setClipRegion(InterSectRgn);
QtDC.setClipping(True);
Result := QtDC.GetRegionType(InterSectRgn);
end;
finally
QRegion_destroy(IntersectRgn);
end;
end;*)
(*function TCDWidgetSet.IsIconic(Handle: HWND): boolean;
begin
Result := TCDForm(Handle).LCLForm.FormState = fsMinimized;
end;*)
function TCDWidgetSet.IsWindow(handle: HWND): boolean;
begin
Result := TObject(Handle) is TCDForm;
end;
function TCDWidgetSet.IsWindowEnabled(Handle: HWND): boolean;
begin
Result := TCDForm(Handle).LCLForm.Enabled;
end;
function TCDWidgetSet.IsWindowVisible(Handle: HWND): boolean;
begin
Result := TCDForm(Handle).LCLForm.Visible;
end;
(*function TQtWidgetSet.IsZoomed(Handle: HWND): boolean;
begin
Result := TQtWidget(Handle).isMaximized;
end;*)
{------------------------------------------------------------------------------
Function: InvalidateRect
Params: aHandle:
Rect:
bErase:
Returns:
------------------------------------------------------------------------------}
function TCDWidgetSet.InvalidateRect(aHandle: HWND; Rect: pRect; bErase: Boolean): Boolean;
var
lHandle: TObject;
lControlHandle: TCDWinControl;
lControl: TWinControl;
begin
{$ifdef VerboseCDDrawing}
DebugLn('[WinAPI InvalidateRect]');
{$endif}
if AHandle = 0 then exit(False);
lHandle := TObject(AHandle);
// Invalidate on a child control
if lHandle is TCDWinControl then
begin
lControlHandle := TCDWinControl(lHandle);
lControlHandle.IncInvalidateCount();
if lControlHandle.CDControlInjected and (lControlHandle.CDControl <> nil) then
TCDWinControl(lControlHandle.CDControl.Handle).IncInvalidateCount();
lControl := lControlHandle.WinControl;
lControl := Forms.GetParentForm(lControl);
// Don't use Rect in BackendInvalidateRect unless we really make the full
// conversion of coordinates to window coordinates. Better invalidate everything
// then too few. And anyway on each draw we send everything.
// This fixes changing the selection in TCustomGrid
Result := BackendInvalidateRect(lControl.Handle, nil, BErase);
end
// Invalidate on a form
else
begin
Result := BackendInvalidateRect(AHandle, Rect, BErase);
end;
Result := True;
end;
{------------------------------------------------------------------------------
Function: InvalidateRgn
Params: aHandle:
Rect:
bErase:
Returns: True if invalidate is successfull.
Invalidates region of widget.
Felipe: Invalidating a non-rectangular region is unusual and complicated,
so for now lets just get the bounding rect and invalidate that instead.
------------------------------------------------------------------------------}
function TCDWidgetSet.InvalidateRgn(aHandle: HWND; Rgn: HRGN; Erase: Boolean): Boolean;
var
lLazRegion: TLazRegion absolute Rgn;
localRect: TRect;
begin
{$ifdef VerboseCDWinAPI}
DebugLn('[WinAPI InvalidateRgn]');
{$endif}
if aHandle = 0 then Exit(False);
if Rgn <> 0 then
begin
localRect := lLazRegion.GetBoundingRect();
Result := InvalidateRect(aHandle, @localRect, Erase);
end
else
Result := InvalidateRect(aHandle, nil, Erase);
end;
{------------------------------------------------------------------------------
Procedure: LeaveCriticalSection
Params: var CritSection: TCriticalSection
Returns: Nothing
------------------------------------------------------------------------------}
procedure TCDWidgetSet.LeaveCriticalSection(var CritSection: TCriticalSection);
var
ACritSec: System.PRTLCriticalSection;
begin
ACritSec:=System.PRTLCriticalSection(CritSection);
System.LeaveCriticalsection(ACritSec^);
end;
{------------------------------------------------------------------------------
Function: LineTo
Params: none
Returns: Nothing
------------------------------------------------------------------------------}
function TCDWidgetSet.LineTo(DC: HDC; X, Y: Integer): Boolean;
var
PenPos, LastPos: TPoint;
LazDC: TLazCanvas absolute DC;
begin
{$ifdef VerboseCDDrawing}
DebugLn(Format('[TCDWidgetSet.LineTo] DC=%x X=%d Y=%d', [DC, X, Y]));
{$endif}
Result := False;
if not IsValidDC(DC) then
begin
DebugLn('[TCDWidgetSet.LineTo] Invalid DC');
Exit;
end;
(* TQtDeviceContext(DC).getPenPos(@PenPos);
LastPos := Point(X, Y);
if TQtDeviceContext(DC).pen.getCosmetic then
LastPos := TQtDeviceContext(DC).GetLineLastPixelPos(PenPos, LastPos);
TQtDeviceContext(DC).drawLine(PenPos.X, PenPos.Y, LastPos.X, LastPos.Y);
MoveToEx(DC, X, Y, nil);*)
LazDC.LineTo(X, Y);
Result := True;
end;
(*
function TQtWidgetSet.LPtoDP(DC: HDC; var Points; Count: Integer): BOOL;
var
P: PPoint;
QtPoint: TQtPoint;
Matrix: QTransformH;
QtDC: TQtDeviceContext;
begin
Result := False;
if not IsValidDC(DC) then
Exit;
QtDC := TQtDeviceContext(DC);
Matrix := QPainter_transform(QtDC.Widget);
P := @Points;
while Count > 0 do
begin
Dec(Count);
QtPoint.X := P^.X;
QtPoint.Y := P^.Y;
QTransform_map(Matrix, PQtPoint(@QtPoint), PQtPoint(@QtPoint));
P^.X := QtPoint.X;
P^.Y := QtPoint.Y;
Inc(P);
end;
Result := True;
end;*)
{------------------------------------------------------------------------------
Function: MoveToEx
Params: none
Returns: Nothing
------------------------------------------------------------------------------}
function TCDWidgetSet.MoveToEx(DC: HDC; X, Y: Integer; OldPoint: PPoint): Boolean;
var
LazDC: TLazCanvas absolute DC;
begin
{$ifdef VerboseCDDrawing}
DebugLn('[WinAPI MoveToEx]',
' DC:', dbghex(DC),
' X:', dbgs(X),
' Y:', dbgs(Y));
{$endif}
Result := False;
if not IsValidDC(DC) then Exit;
if (OldPoint <> nil) then OldPoint^ := LazDC.PenPos;
LazDC.PenPos := Types.Point(X, Y);
Result := True;
end;
(*function TQtWidgetSet.OffsetRgn(RGN: HRGN; nXOffset, nYOffset: Integer): Integer;
var
QtRgn: QRegionH;
begin
Result := ERROR;
if not IsValidGDIObject(RGN) then
Exit
else
QtRgn := TQtRegion(RGN).FHandle;
QRegion_translate(QtRgn, nXOffset, nYOffset);
if QRegion_isEmpty(QtRgn) then
Result := NULLREGION
else
begin
if TQtRegion(RGN).IsPolyRegion or (TQtRegion(RGN).numRects > 0) then
Result := COMPLEXREGION
else
Result := SIMPLEREGION;
end;
end;
function TQtWidgetSet.PeekMessage(var lpMsg : TMsg; Handle : HWND; wMsgFilterMin, wMsgFilterMax,wRemoveMsg : UINT): Boolean;
begin
Result := False;
{$ifdef VerboseQtWinAPI_MISSING_IMPLEMENTATION}
WriteLn('***** [WinAPI TQtWidgetSet.PeekMessage] missing implementation ');
{$endif}
end;*)
{------------------------------------------------------------------------------
Function: PolyBezier
Params: DC: HDC; Points: PPoint; NumPts: Integer; Filled: Boolean;
Continuous: Boolean
Returns: Nothing
------------------------------------------------------------------------------}
function TCDWidgetSet.PolyBezier(DC: HDC; Points: PPoint; NumPts: Integer;
Filled, Continuous: Boolean): Boolean;
begin
{$ifdef VerboseCDDrawing}
WriteLn('[WinAPI PolyBezier] DC: ', dbghex(DC));
{$endif}
Result := inherited PolyBezier(DC, Points, NumPts, Filled, Continuous);
end;
{------------------------------------------------------------------------------
Function: Polygon
Params: DC: HDC; Points: PPoint; NumPts: Integer; Winding: Boolean
Returns: Nothing
------------------------------------------------------------------------------}
function TCDWidgetSet.Polygon(DC: HDC; Points: PPoint; NumPts: Integer;
Winding: Boolean): boolean;
var
LazDC: TLazCanvas absolute DC;
lPoints: array of TPoint;
i: Integer;
begin
{$ifdef VerboseCDDrawing}
DebugLn(Format(':>[WinAPI Polygon] DC=%s', [dbghex(DC)]));
{$endif}
if not IsValidDC(DC) then Exit(False);
SetLength(lPoints, NumPts);
for i := 0 to NumPts-1 do
begin
{$ifdef VerboseCDDrawing}
LCLProc.DbgOut(Format(' P=%d,%d', [Points[i].X, Points[i].Y]));
{$endif}
lPoints[i] := Points[i];
end;
LazDC.Polygon(lPoints);
Result := True;
{$ifdef VerboseCDDrawing}
DebugLn('');
{$endif}
end;
{------------------------------------------------------------------------------
Function: Polyline
Params: DC: HDC; Points: PPoint; NumPts: Integer
Returns: Nothing
------------------------------------------------------------------------------}
function TCDWidgetSet.Polyline(DC: HDC; Points: PPoint; NumPts: Integer): boolean;
var
LazDC: TLazCanvas absolute DC;
lPoints: array of TPoint;
i: Integer;
begin
{$ifdef VerboseCDDrawing}
DebugLn(Format(':>[WinAPI Polygon] DC=%s', [dbghex(DC)]));
{$endif}
if not IsValidDC(DC) then Exit(False);
SetLength(lPoints, NumPts);
for i := 0 to NumPts-1 do
lPoints[i] := Points[i];
LazDC.Polyline(lPoints);
Result := True;
end;
(*function TQtWidgetSet.PostMessage(Handle: HWND; Msg: Cardinal; wParam: WParam; lParam: LParam): Boolean;
var
Widget: TQtWidget absolute Handle;
Event: QLCLMessageEventH;
begin
Result := False;
if Handle <> 0 then
begin
Event := QLCLMessageEvent_create(QEventLCLMessage, Msg, wParam, lParam, 0);
QCoreApplication_postEvent(Widget.Widget, Event, 1 {high priority});
Result := True;
end;
end;*)
function TCDWidgetSet.PtInRegion(RGN: HRGN; X, Y: Integer): Boolean;
var
lRegion: TLazRegion absolute RGN;
begin
Result := False;
if not IsValidGDIObject(RGN) then Exit;
Result := lRegion.IsPointInRegion(X, Y);
end;
{------------------------------------------------------------------------------
Function: Rectangle
Params: DC: HDC; X1, Y1, X2, Y2: Integer
Returns: Nothing
The Rectangle function draws a rectangle. The rectangle is outlined by using
the current pen and filled by using the current brush.
------------------------------------------------------------------------------}
function TCDWidgetSet.Rectangle(DC: HDC; X1, Y1, X2, Y2: Integer): Boolean;
var
LazDC: TLazCanvas absolute DC;
begin
{$ifdef VerboseCDDrawing}
DebugLn(Format(':>[WinAPI Rectangle] DC=%s', [dbghex(DC)]));
{$endif}
if not IsValidDC(DC) then
begin
{$ifdef VerboseCDDrawing}
DebugLn(':<[WinAPI Rectangle] Invalid DC!');
{$endif}
Exit(False);
end;
// ToDo: We can normalize the rectangle, but this is not necessary as
// TLazCanvas ignores invalid coordinates
{ R := NormalizeRect(Rect(X1, Y1, X2, Y2));
if IsRectEmpty(R) then Exit(True);}
LazDC.Rectangle(X1, Y1, X2, Y2);
Result := True;
end;
function TCDWidgetSet.RectVisible(dc : hdc; const ARect: TRect) : Boolean;
var
LazDC: TLazCanvas;
begin
{$ifdef VerboseCDDrawing}
Debugln('[WinAPI RectVisible]');
{$endif}
Result := True;
if not IsValidDC(DC) then Exit;
LazDC := TLazCanvas(DC);
// as MSDN says only clipping region can play here
{ if QtDC.getClipping then
Result := QtDC.getClipRegion.containsRect(ARect);}
end;
(*{------------------------------------------------------------------------------
Function: RedrawWindow
Params: Wnd:
lprcUpdate:
hrgnUpdate:
flags:
Returns:
------------------------------------------------------------------------------}
function TQtWidgetSet.RedrawWindow(Wnd: HWND; lprcUpdate: PRECT; hrgnUpdate: HRGN; flags: UINT): Boolean;
var
QtWidget: TQtWidget;
Region: TQtRegion;
begin
if not IsValidHandle(Wnd) then
Exit(False);
QtWidget := TQtWidget(Wnd);
if IsValidGDIObject(hrgnUpdate) then
Region := TQtRegion(hrgnUpdate)
else
Region := nil;
if (lprcUpdate = nil) and (hrgnUpdate = 0) then
begin
QtWidget.Update(nil);
Exit(True);
end;
if Region = nil then
Result := InvalidateRect(Wnd, lprcUpdate, False)
else
QtWidget.UpdateRegion(Region.FHandle);
Result := True;
end;
function TQtWidgetSet.ReleaseCapture: Boolean;
var
w: TQtWidget;
begin
w := TQtWidget(GetCapture);
Result := w <> nil;
if Result then
begin
{$IFDEF MSWINDOWS}
if w is TQtMainWindow then
w.releaseMouse()
else
windows.ReleaseCapture;
{$ELSE}
w.releaseMouse();
{$ENDIF}
end;
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI ReleaseCapture] Capture = ', TLCLHandle(w));
{$endif}
end;
{------------------------------------------------------------------------------
Function: ReleaseDC
Params: hWnd: Handle to the window whose DC is to be released.
hDC: Handle to the DC to be released.
Returns:
------------------------------------------------------------------------------}
function TQtWidgetSet.ReleaseDC(hWnd: HWND; DC: HDC): Integer;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI ReleaseDC]',
' hWnd: ', dbghex(hWnd),
' DC: ', dbghex(DC));
{$endif}
Result := 0;
if IsValidDC(DC) then Exit;
Result := 1;
end;*)
{------------------------------------------------------------------------------
Function: RestoreDC: Restore a previously saved DC state
Params:
DC: Handle to a DeviceContext
SavedDC: Index of saved state that needs to be restored
Returns: True if state was successfuly restored.
-------------------------------------------------------------------------------}
function TCDWidgetSet.RestoreDC(DC: HDC; SavedDC: Integer): Boolean;
var
LazDC: TLazCanvas absolute DC;
begin
{$ifdef VerboseQTWinAPI}
WriteLn('Trace:> [WinAPI RestoreDC] DC=', dbghex(DC),' SavedDC=',SavedDC);
{$Endif}
if (SavedDC=0) or (not IsValidDC(DC)) then Exit(False);
if SavedDC>0 then
LazDC.RestoreState(SavedDC-1)
else
LazDC.RestoreState(SavedDC);
Result := True;
{$ifdef VerboseQTWinAPI}
WriteLn('Trace:< [WinAPI RestoreDC]');
{$Endif}
end;
(*function TQtWidgetSet.RoundRect(DC: hDC; X1, Y1, X2, Y2: Integer; RX,RY : Integer): Boolean;
begin
Result := False;
if not IsValidDC(DC) then
begin
{$ifdef VerboseQTWinAPI}
WriteLn('Trace:< [WinAPI RoundRect] DC Invalid, result=', result);
{$Endif}
Exit;
end;
Result := inherited RoundRect(DC, X1, Y1, X2, Y2, RX, RY);
end;*)
{------------------------------------------------------------------------------
Function: SaveDC: save DC state information to a stack
Params: DC
Returns: The index assigned to the or 0 if DC is not valid
-------------------------------------------------------------------------------}
function TCDWidgetSet.SaveDC(DC: HDC): Integer;
var
LazDC: TLazCanvas absolute DC;
begin
{$ifdef VerboseQTWinAPI}
WriteLn('Trace:> [WinAPI SaveDC] DC=', dbghex(DC));
{$Endif}
result:=0;
if not IsValidDC(DC) then
begin
{$ifdef VerboseQTWinAPI}
WriteLn('Trace:< [WinAPI SaveDC] DC Invalid, result=', result);
{$Endif}
exit;
end;
Result := LazDC.SaveState()+1;
{$ifdef VerboseQTWinAPI}
WriteLn('Trace:< [WinAPI SaveDC] result=', Result);
{$Endif}
end;
(*{------------------------------------------------------------------------------
Function: ScreenToClient
Params: Handle: HWND; var P: TPoint
Returns:
-------------------------------------------------------------------------------}
function TQtWidgetSet.ScreenToClient(Handle : HWND; var P : TPoint) : Integer;
var
APoint: TQtPoint;
begin
Result := 0;
if IsValidHandle(Handle) then
begin
APoint := QtPoint(P.X, P.Y);
QWidget_mapFromGlobal(TQtWidget(Handle).GetContainerWidget, @APoint, @APoint);
P := Point(APoint.x, APoint.y);
Result := 1;
end;
end;
{------------------------------------------------------------------------------
Method: ScrollWindowEx
Params: HWnd - handle of window to scroll
DX - horizontal amount to scroll
DY - vertical amount to scroll
PRcScroll - pointer to scroll rectangle
PRcClip - pointer to clip rectangle
HRgnUpdate - handle of update region
PRcUpdate - pointer to update rectangle
Flags - scrolling flags
Returns: True if succesfull
The ScrollWindowEx function scrolls the content of the specified window's
client area
------------------------------------------------------------------------------}
function TQtWidgetSet.ScrollWindowEx(HWnd: HWND; DX, DY: Integer; PRcScroll,
PRcClip: PRect; HRgnUpdate: HRGN; PRcUpdate: PRect; Flags: UINT): Boolean;
var
R: TRect;
W: TQtWidget;
begin
Result := False;
if (HWND = 0) then exit;
W := TQtWidget(HWND);
if ((Flags and SW_SCROLLCHILDREN) <> 0) then
W.scroll(dx, dy, nil)
else
if (PrcScroll = nil) then
begin
R := W.getClientBounds;
W.scroll(dx, dy, @R);
end
else
W.scroll(dx, dy, PRcScroll);
if ((Flags and SW_INVALIDATE) <> 0) then
begin
if IsValidGDIObject(HRgnUpdate) then
begin
R := TQtRegion(HRgnUpdate).getBoundingRect;
PRcUpdate := @R;
W.Update(@R);
end else
if PRcClip <> nil then
begin
PRcUpdate := PRcClip;
W.Update(PrcClip);
end;
end;
Result := True;
end;*)
{------------------------------------------------------------------------------
Function: SelectClipRGN
Params: DC, RGN
Returns: longint
Sets the DeviceContext's ClipRegion. The Return value
is the new clip regions type, or ERROR.
The result can be one of the following constants
Error
NullRegion
SimpleRegion
ComplexRegion
------------------------------------------------------------------------------}
function TCDWidgetSet.SelectClipRGN(DC: hDC; RGN: HRGN): Longint;
begin
Result := ExtSelectClipRgn(DC, RGN, RGN_COPY);
end;
{------------------------------------------------------------------------------
Function: SelectObject
Params: none
Returns: The GDI object of the same type previously associated with the DC
Changes one of the GDI objects (Font, Brush, etc) of a Device Context;
------------------------------------------------------------------------------}
function TCDWidgetSet.SelectObject(DC: HDC; GDIObj: HGDIOBJ): HGDIOBJ;
var
aObject: TObject;
lFont: TFPCustomFont absolute AObject;
lPen: TFPCustomPen absolute AObject;
lBrush: TFPCustomBrush absolute AObject;
lOrigBrush: TFPCustomBrush;
{$ifdef VerboseCDDrawing}
ObjType: string;
{$endif}
begin
{$ifdef VerboseCDDrawing}
DebugLn(Format(':>[TCDWidgetSet.SelectObject] DC=%s GDIObj=%s',
[dbghex(DC), dbghex(GDIObj)]));
{$endif}
Result := 0;
if not IsValidDC(DC) then
begin
{$ifdef VerboseCDDrawing}
DebugLn(':<[TCDWidgetSet.SelectObject] Invalid DC');
{$endif}
Exit;
end;
if not IsValidGDIObject(GDIObj) then
begin
{$ifdef VerboseCDDrawing}
DebugLn(':<[TCDWidgetSet.SelectObject] Invalid GDI Object');
{$endif}
Exit;
end;
aObject := TObject(GDIObj);
if aObject is TFPCustomFont then
begin
{$ifdef VerboseCDDrawing}ObjType := 'Font';{$endif}
Result := HGDIOBJ(TLazCanvas(DC).AssignedFont);
TLazCanvas(DC).AssignFontData(lFont); // := doesn't work and Assign() raises exceptions
TLazCanvas(DC).AssignedFont := lFont;
{$ifndef CD_UseNativeText}
TLazCanvas(DC).ExtraFontData := TLazCDCustomFont(lFont).FTFont;
{$endif}
end
else if aObject is TFPCustomPen then
begin
{$ifdef VerboseCDDrawing}ObjType := 'Pen';{$endif}
Result := HGDIOBJ(TLazCanvas(DC).AssignedPen);
TLazCanvas(DC).AssignPenData(lPen); // := doesn't work and Assign() raises exceptions
TLazCanvas(DC).AssignedPen := lPen;
end
else if aObject is TFPCustomBrush then
begin
{$ifdef VerboseCDDrawing}ObjType := 'Brush';{$endif}
Result := HGDIOBJ(TLazCanvas(DC).AssignedBrush);
TLazCanvas(DC).AssignBrushData(lBrush); // := doesn't work and Assign() raises exceptions
TLazCanvas(DC).AssignedBrush := lBrush;
end
else if aObject is TCDBitmap then
begin
{$ifdef VerboseCDDrawing}ObjType := 'Bitmap';{$endif}
Result := HGDIOBJ(TLazCanvas(DC).Image);
TLazCanvas(DC).Image := TCDBitmap(aObject).Image;
TLazCanvas(DC).SelectedBitmap := aObject;
end; (*else
if AObject is TQtRegion then
begin
Result := HGDIOBJ(TQtDeviceContext(DC).getClipRegion);
SelectClipRGN(DC, HRGN(GDIObj));
end*);
{$ifdef VerboseCDDrawing}
DebugLn(':<[TCDWidgetSet.SelectObject] Result=', dbghex(Result), ' ObjectType=', ObjType);
{$endif}
end;
(*function TQtWidgetSet.SendMessage(HandleWnd: HWND; Msg: Cardinal;
WParam: WParam; LParam: LParam): LResult;
var
Widget: TQtWidget absolute HandleWnd;
Event: QLCLMessageEventH;
begin
Result := 0;
if (HandleWnd <> 0) and (Widget.Widget <> nil) then
begin
Event := QLCLMessageEvent_create(QEventLCLMessage, Msg, wParam, lParam, 0);
try
QCoreApplication_sendEvent(Widget.Widget, Event);
Result := QLCLMessageEvent_getMsgResult(Event);
finally
QLCLMessageEvent_destroy(Event);
end;
end;
end;
function TQtWidgetSet.SetActiveWindow(Handle: HWND): HWND;
begin
Result := GetActiveWindow;
if Handle <> 0 then
TQtWidget(Handle).Activate
else
Result := 0; // error
end;
{------------------------------------------------------------------------------
Function: SetBKColor
Params: X:
Y:
Returns:
------------------------------------------------------------------------------}
function TQtWidgetSet.SetBKColor(DC: HDC; Color: TColorRef): TColorRef;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('Trace:> [WinAPI SetBkColor]',
' DC: ', dbghex(DC),
' Color: ', dbgs(Color));
{$endif}
Result := 0;
if not IsValidDC(DC) then
begin
{$ifdef VerboseQtWinAPI}
WriteLn('Trace:< [WinAPI SetBkColor] Invalid DC');
{$endif}
Exit;
end;
Result := TQtDeviceContext(DC).SetBkColor(TColorRef(Color));
end;
{------------------------------------------------------------------------------
Method: SetBkMode
Params: DC -
Returns:
------------------------------------------------------------------------------}
function TQtWidgetSet.SetBkMode(DC: HDC; bkMode: Integer): Integer;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('Trace:> [WinAPI SetBkMode] DC=', dbghex(DC), ' BkMode=', dbgs(bkMode));
{$endif}
Result := 0;
if not IsValidDC(DC) then
begin
{$ifdef VerboseQtWinAPI}
WriteLn('Trace:< [WinAPI SetBkMode] Invalid DC');
{$endif}
Exit;
end;
Result := TQtDeviceContext(DC).SetBkMode(bkMode);
end;
function TQtWidgetSet.SetCapture(AHandle: HWND): HWND;
var
Message: TLMessage;
begin
Result := GetCapture;
if Result <> AHandle then
begin
if Result <> 0 then
ReleaseCapture;
if AHandle <> 0 then
{$IFDEF MSWINDOWS}
Windows.SetCapture(AHandle);
{$ELSE}
TQtWidget(AHandle).grabMouse();
{$ENDIF}
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI SetCapture] Capture = ', Result, ' New capture = ', AHandle);
{$endif}
if Result <> 0 then
begin
Message.Msg := 0;
FillChar(Message, SizeOf(Message), 0);
Message.msg := LM_CAPTURECHANGED;
Message.wParam := 0;
Message.lParam := Result;
LCLMessageGlue.DeliverMessage(TQtWidget(AHandle).LCLObject, Message);
end;
end;
end;
function TQtWidgetSet.SetCaretPos(X, Y: Integer): Boolean;
begin
Result := QtCaret.SetCaretPos(X, Y);
end;
function TQtWidgetSet.SetCaretPosEx(Handle: HWnd; X, Y: Integer): Boolean;
begin
Result := QtCaret.SetCaretPos(X, Y);
end;
function TQtWidgetSet.SetCaretRespondToFocus(handle: HWND;
ShowHideOnFocus: boolean): Boolean;
begin
Result := True;
QtCaret.SetQtCaretRespondToFocus(ShowHideOnFocus);
end;
{------------------------------------------------------------------------------
Function: SetCursor
Params: ACursor - HCursor (TQtCursor)
Returns:
previous global cursor
------------------------------------------------------------------------------}
function TQtWidgetSet.SetCursor(ACursor: HCURSOR): HCURSOR;
begin
Result := HCURSOR(OverrideCursor);
if Result = ACursor then
Exit;
if Screen.Cursors[crDefault] = ACursor then
OverrideCursor := nil
else
OverrideCursor := TQtCursor(ACursor);
end;
{------------------------------------------------------------------------------
Function: SetCursorPos
Params: X:
Y:
Returns:
------------------------------------------------------------------------------}
function TQtWidgetSet.SetCursorPos(X, Y: Integer): Boolean;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI SetCursorPos]');
{$endif}
QCursor_setPos(X, Y);
Result := True;
end;*)
{------------------------------------------------------------------------------
Function: SetFocus
Params: hWnd - Window handle to be focused
Returns:
------------------------------------------------------------------------------}
function TCDWidgetSet.SetFocus(hWnd: HWND): HWND;
var
lObject, lOldObject: TCDBaseControl;
lOldControl: TWinControl;
lHandle: TCDWinControl;
begin
{$ifdef VerboseCDFocus}
DebugLn(Format('[TCDWidgetSet.SetFocus] Handle=%x', [hWnd]));
{$endif}
Result := 0;
// Strangly this breaks the Android Virtual Keyboard =(
// Remove the ifdef only when we can guarantee that this doesn't break Android Virtual Keyboard
{$ifndef CD_Android}
if hwnd = 0 then
begin
Result := GetFocus();
Exit;
end;
lObject := TCDBaseControl(hWnd);
// SetFocus on a child control
if lObject is TCDWinControl then
begin
lHandle := TCDWinControl(lObject);
// Set focus in the parent window
//Result := BackendSetFocus(hWnd);
if lHandle.WinControl = nil then Exit;
CDSetFocusToControl(lHandle.WinControl, lHandle.CDControl);
{$ifdef VerboseCDFocus}
DebugLn(Format(':[TCDWidgetSet.SetFocus] NewFocusedControl=%s NewFocusedIntfControl=%x', [FocusedControl.Name, PtrUInt(FocusedIntfControl)]));
{$endif}
end
// SetFocus on a form
else
begin
Result := BackendSetFocus(hWnd);
end;
{$endif}
end;
(*function TQtWidgetSet.GetForegroundWindow: HWND;
var
W: QWidgetH;
begin
{$IFDEF HASX11}
if WindowManagerName = 'metacity' then
W := X11GetActivewindow
else
W := QApplication_activeWindow();
{$ELSE}
W := QApplication_activeWindow();
{$ENDIF}
Result := HwndFromWidgetH(W);
end;
function TQtWidgetSet.SetForegroundWindow(HWnd: HWND): boolean;
begin
Result := False;
if HWND <> 0 then
begin
Result := TQtWidget(HWND).IsActiveWindow;
TQtWidget(HWnd).Activate;
end;
end;
function TQtWidgetSet.SetMenu(AWindowHandle: HWND; AMenuHandle: HMENU): Boolean;
var
AWidget, AMenuWidget: TQtWidget;
QtMainWindow: TQtMainWindow absolute AWidget;
QtMenuBar: TQtMenuBar absolute AMenuWidget;
R, R1: TRect;
begin
AWidget := TQtWidget(AWindowHandle);
Result := AWidget is TQtMainWindow;
if Result then
begin
AMenuWidget := TQtWidget(AMenuHandle);
if AMenuWidget is TQtMenuBar then
begin
R := AWidget.LCLObject.ClientRect;
R1 := QtMainWindow.MenuBar.getGeometry;
R1.Right := R.Right;
QtMenuBar.setGeometry(R1);
QtMainWindow.setMenuBar(QMenuBarH(QtMenuBar.Widget));
end
else
QtMainWindow.setMenuBar(QMenuBarH(QtMainWindow.MenuBar.Widget));
end;
end;
function TQtWidgetSet.SetParent(hWndChild: HWND; hWndParent: HWND): HWND;
var
OldVisible: Boolean;
Flags: QtWindowFlags;
W: TQtWidget;
begin
{$ifdef VerboseQtWinAPI}
writeln('[WinApi SetParent] child: ',dbgHex(PtrUInt(hwndChild)),
' parent: ',dbgHex(PtrUInt(hWndParent)));
{$endif}
Result := 0;
if not IsValidHandle(hwndChild) then
exit;
Result := GetParent(hWndChild);
if (Result = hwndParent) then
exit;
W := TQtWidget(hWndChild);
OldVisible := W.getVisible;
Flags := W.windowFlags;
if IsValidHandle(hWndParent) then
W.setParent(TQtWidget(hWndParent).GetContainerWidget)
else
begin
W.setParent(nil);
W.setWindowFlags(Flags);
end;
W.setVisible(OldVisible);
end;
function TQtWidgetSet.SetMapMode(DC: HDC; fnMapMode : Integer): Integer;
var
AWindowExt: TPoint;
R: TRect;
begin
if IsValidDC(DC) then
begin
if fnMapMode <> TQtDeviceContext(DC).vMapMode then
begin
case fnMapMode of
MM_ANISOTROPIC:; // user's choice
MM_ISOTROPIC:; // adjusted after each SetViewPortExtEx call (see MSDN for details)
MM_HIENGLISH: AWindowExt := Point(1000, -1000);
MM_HIMETRIC: AWindowExt := Point(2540, -2540);
MM_LOENGLISH: AWindowExt := Point(100, -100);
MM_LOMETRIC: AWindowExt := Point(254, -254);
MM_TWIPS: AWindowExt := Point(1440, -1440);
else
fnMapMode := MM_TEXT;
end;
TQtDeviceContext(DC).vMapMode := fnMapMode;
QPainter_setViewTransformEnabled(TQtDeviceContext(DC).Widget, fnMapMode <> MM_TEXT);
if not (fnMapMode in [MM_TEXT, MM_ANISOTROPIC, MM_ISOTROPIC]) then
begin
QPainter_Window(TQtDeviceContext(DC).Widget, @R);
R.BottomRight := AWindowExt;
QPainter_setWindow(TQtDeviceContext(DC).Widget, @R);
QPainter_ViewPort(TQtDeviceContext(DC).Widget, @R);
R.Right := QtWidgetSet.GetDeviceCaps(DC, LOGPIXELSX);
R.Bottom := QtWidgetSet.GetDeviceCaps(DC, LOGPIXELSX);
QPainter_setViewPort(TQtDeviceContext(DC).Widget, @R);
end;
end;
Result := Integer(True);
end else
Result := Integer(False);
end;
function TQtWidgetSet.ShowCaret(hWnd: HWND): Boolean;
begin
Result := (hWnd <> 0) and (QtCaret.ShowCaret(TQtWidget(hWnd)));
end;*)
{------------------------------------------------------------------------------
Method: SetProp
Params: Handle -
Returns:
------------------------------------------------------------------------------}
function TCDWidgetSet.SetProp(Handle: hwnd; Str: PChar; Data: Pointer): Boolean;
begin
if Handle<>0 then
begin
TCDBaseControl(Handle).Props[str] := Data;
Result := (TCDBaseControl(Handle).Props[str]=Data);
{$ifdef VerboseCDWinApi}
DebugLn('[WinAPI SetProp win=%s str=%s data=%x',[dbgsname(TCDWinControl(Handle)), str, ptrint(data)]);
{$endif}
end else
Result := False;
end;
(*{------------------------------------------------------------------------------
Function: SetROP2
Params: HDC, Raster OP mode
Returns: Old Raster OP mode
Please note that the bitwise raster operation modes, denoted with a
RasterOp prefix, are only natively supported in the X11 and
raster paint engines.
This means that the only way to utilize these modes on the Mac is
via a QImage.
The RasterOp denoted blend modes are not supported for pens and brushes
with alpha components. Also, turning on the QPainter::Antialiasing render
hint will effectively disable the RasterOp modes.
------------------------------------------------------------------------------}
function TQtWidgetSet.SetROP2(DC: HDC; Mode: Integer): Integer;
var
QtDC: TQtDeviceContext absolute DC;
begin
{$ifdef VerboseQtWinAPI}
writeln('TQtWidgetSet.SetROP2() DC ',dbghex(DC),' Mode ',Mode);
{$endif}
Result := R2_COPYPEN;
if not IsValidDC(DC) then
exit;
Result := QtDC.Rop2;
QtDC.Rop2 := Mode;
end;
{------------------------------------------------------------------------------
Function: SetScrollInfo
Params: none
Returns: The new position value
------------------------------------------------------------------------------}
function TQtWidgetSet.SetScrollInfo(Handle : HWND; SBStyle : Integer;
ScrollInfo: TScrollInfo; bRedraw : Boolean): Integer;
var
Control: TWinControl;
ScrollBar: TQtScrollBar;
function UpdateScrollInfo: Integer;
var
iReCountMax: Integer;
SBUpdatesCount: Integer;
i: Integer;
WheelLines: Integer;
begin
Result := 0;
SBUpdatesCount := 0;
if (ScrollInfo.FMask and SIF_RANGE) <> 0 then
begin
inc(SBUpdatesCount);
ScrollBar.setMinimum(ScrollInfo.nMin);
// we must recount ScrollBar.Max since invalid value raises AV
iRecountMax := ScrollInfo.nMax - ScrollInfo.nPage;
if iRecountMax < ScrollInfo.nMin then
iRecountMax := ScrollInfo.nMin;
ScrollBar.setMaximum(iRecountMax);
end;
if (ScrollInfo.FMask and SIF_PAGE) <> 0 then
begin
// segfaults if we don't check Enabled property
if ScrollBar.getEnabled then
begin
inc(SBUpdatesCount);
ScrollBar.setPageStep(ScrollInfo.nPage);
WheelLines := QApplication_wheelScrollLines();
with Scrollbar do
begin
i := Max(1, floor((GetPageStep / WheelLines) / 6));
setSingleStep(i);
end;
end;
end;
if (ScrollInfo.FMask and SIF_UPDATEPOLICY) <> 0 then
ScrollBar.setTracking(ScrollInfo.nTrackPos <> SB_POLICY_DISCONTINUOUS);
if (ScrollInfo.FMask and SIF_POS) <> 0 then
begin
inc(SBUpdatesCount);
if SBUpdatesCount = 1 then
ScrollBar.BeginUpdate;
try
if not (ScrollBar.getTracking and ScrollBar.getSliderDown) then
begin
{do not setValue() if values are equal, since it calls
signalValueChanged() which sends unneeded LM_SCROLL msgs }
if (ScrollBar.getValue = ScrollInfo.nPos) then
SBUpdatesCount := 0;
if (ScrollInfo.nPos < ScrollBar.getMin) then
ScrollInfo.nPos := ScrollBar.getMin
else
if (ScrollInfo.nPos > ScrollBar.getMax) then
ScrollInfo.nPos := ScrollBar.getMax;
if (SBUpdatesCount > 0) then
ScrollBar.setValue(ScrollInfo.nPos);
end;
finally
if ScrollBar.InUpdate then
ScrollBar.EndUpdate;
end;
end;
if (ScrollInfo.FMask and SIF_TRACKPOS) <> 0 then
begin
ScrollBar.TrackPos := ScrollInfo.nTrackPos;
// from MSDN: the SetScrollInfo function ignores this member
// ScrollBar.setSliderPosition(ScrollInfo.nTrackPos);
end;
Result := ScrollBar.getValue;
end;
begin
// bRedraw is useles with qt
Result := 0;
if (Handle = 0) then exit;
ScrollBar := nil;
case SBStyle of
SB_BOTH:
begin
{TODO: SB_BOTH fixme }
//writeln('TODO: ############## SB_BOTH CALLED HERE .... #################');
end; {SB_BOTH}
SB_CTL:
begin
{HWND is always TScrollBar, but seem that Create ScrollBar should be called here }
if (csReading in TQtWidget(Handle).LCLObject.ComponentState) or
(csDestroying in TQtWidget(Handle).LCLObject.ComponentState) then exit;
ScrollBar := TQtScrollBar(Handle);
if not Assigned(ScrollBar) then exit;
end; {SB_CTL}
SB_HORZ:
begin
if (csReading in TQtWidget(Handle).LCLObject.ComponentState) or
(csDestroying in TQtWidget(Handle).LCLObject.ComponentState) then
exit;
if TQtWidget(Handle) is TQtAbstractScrollArea then
begin
ScrollBar := TQtAbstractScrollArea(Handle).horizontalScrollBar;
end else
begin
{do not localize !}
Control := TWinControl(TQtWidget(Handle).LCLObject.FindChildControl(TQtWidget(Handle).LCLObject.Name+'_HSCROLLBAR'));
if (Control <> nil) and (Control.HandleAllocated) then
ScrollBar := TQtScrollBar(Control.Handle)
end;
end; {SB_HORZ}
SB_VERT:
begin
if (csReading in TQtWidget(Handle).LCLObject.ComponentState) or
(csDestroying in TQtWidget(Handle).LCLObject.ComponentState) then
exit;
if TQtWidget(Handle) is TQtAbstractScrollArea then
begin
ScrollBar := TQtAbstractScrollArea(Handle).verticalScrollBar;
end else
begin
{do not localize !}
Control := TWinControl(TQtWidget(Handle).LCLObject.FindChildControl(TQtWidget(Handle).LCLObject.Name+'_VSCROLLBAR'));
if (Control <> nil) and (Control.HandleAllocated) then
ScrollBar := TQtScrollBar(Control.Handle)
end;
end; {SB_VERT}
end;
if Assigned(ScrollBar) then
Result := UpdateScrollInfo;
end;*)
{------------------------------------------------------------------------------
Method: SetTextColor
Params: DC - Identifies the device context.
Color - Specifies the color of the text.
Returns: The previous color if succesful, CLR_INVALID otherwise
------------------------------------------------------------------------------}
function TCDWidgetSet.SetTextColor(DC: HDC; Color: TColorRef): TColorRef;
var
LazDC: TLazCanvas absolute DC;
begin
{$ifdef VerboseCDDrawing}
DebugLn(Format('[TCDWidgetSet.SetTextColor] DC: %x Color: %8x', [DC, Color]));
{$endif}
Result := CLR_INVALID;
if not IsValidDC(DC) then exit;
if LazDC.Font <> nil then
begin
Result := FPColorToTColorRef(LazDC.Font.FPColor);
LazDC.Font.FPColor := TColorToFPColor(Color);
end;
end;
(*{------------------------------------------------------------------------------
function ShowScrollBar(Handle: HWND; wBar: Integer; bShow: Boolean): Boolean;
Params Handle: HWND; wBar: Integer; bShow: Boolean
Result
------------------------------------------------------------------------------}
function TQtWidgetSet.ShowScrollBar(Handle: HWND; wBar: Integer; bShow: Boolean): Boolean;
var
w: TQtWidget;
ScrollArea: TQtAbstractScrollArea;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI ShowScrollBar] Handle: ', dbghex(Handle),' wBar: ',wBar);
{$endif}
Result := (Handle <> 0);
if not Result then exit;
w := TQtWidget(Handle);
if w is TQtAbstractScrollArea then
begin
ScrollArea := TQtAbstractScrollArea(w);
case wBar of
SB_BOTH:
begin
if bShow then
ScrollArea.setScrollStyle(ssBoth)
else
ScrollArea.setScrollStyle(ssNone);
end;
SB_HORZ:
begin
if bShow then
ScrollArea.setScrollStyle(ssHorizontal)
else
ScrollArea.ScrollBarPolicy[False] := QtScrollBarAlwaysOff;
end;
SB_VERT:
begin
if bShow then
ScrollArea.setScrollStyle(ssVertical)
else
ScrollArea.ScrollBarPolicy[True] := QtScrollBarAlwaysOff;
end;
SB_CTL:
begin
if bShow then
ScrollArea.Show
else
ScrollArea.Hide;
end;
end;
end else
Result := False;
end;
function TQtWidgetSet.SetViewPortExtEx(DC: HDC; XExtent, YExtent : Integer; OldSize: PSize): Boolean;
var
R, RW: TRect;
Ratio: Single;
begin
Result := False;
if IsValidDC(DC) then
begin
QPainter_ViewPort(TQtDeviceContext(DC).Widget, @R);
if OldSize <> nil then
begin
OldSize^.cx := R.Right - R.Left;
OldSize^.cy := R.Bottom - R.Top;
end;
if (XExtent <> R.Right) or (YExtent <> R.Bottom) then
begin
case TQtDeviceContext(DC).vMapMode of
MM_ANISOTROPIC, MM_ISOTROPIC:
begin
if TQtDeviceContext(DC).vMapMode = MM_ISOTROPIC then
begin
// TK: Is here also an adjustment on Windows if DPIX and DPIY are different?
QPainter_Window(TQtDeviceContext(DC).Widget, @RW);
Ratio := RW.Right / RW.Bottom; // no check, programmer cannot put nonsense
if YExtent * Ratio > XExtent then
YExtent := RoundToInt(XExtent / Ratio)
else if YExtent * Ratio < XExtent then
XExtent := RoundToInt(YExtent * Ratio)
end;
QPainter_setViewPort(TQtDeviceContext(DC).Widget, R.Left, R.Top, XExtent, YExtent);
Result := True;
end;
end;
end;
end;
end;
function TQtWidgetSet.SetViewPortOrgEx(DC: HDC; NewX, NewY: Integer; OldPoint: PPoint): Boolean;
var
R: TRect;
begin
Result := False;
if IsValidDC(DC) then
begin
QPainter_ViewPort(TQtDeviceContext(DC).Widget, @R);
if OldPoint <> nil then
OldPoint^ := R.TopLeft;
if (TQtDeviceContext(DC).vMapMode <> MM_TEXT) and (NewX <> R.Left) or (NewY <> R.Top) then
begin
QPainter_setViewPort(TQtDeviceContext(DC).Widget, NewX, NewY, R.Right - R.Left, R.Bottom - R.Top);
Result := True;
end;
end;
end;
function TQtWidgetSet.SetWindowExtEx(DC: HDC; XExtent, YExtent: Integer; OldSize: PSize): Boolean;
var
R: TRect;
begin
Result := False;
if IsValidDC(DC) then
begin
QPainter_Window(TQtDeviceContext(DC).Widget, @R);
if OldSize <> nil then
begin
OldSize^.cx := R.Right - R.Left;
OldSize^.cy := R.Bottom - R.Top;
end;
if (XExtent <> R.Right) or (YExtent <> R.Bottom) then
begin
case TQtDeviceContext(DC).vMapMode of
MM_ANISOTROPIC, MM_ISOTROPIC:
begin
QPainter_setWindow(TQtDeviceContext(DC).Widget, R.Left, R.Top, XExtent, YExtent);
Result := True;
end;
end;
end;
end;
end;*)
{------------------------------------------------------------------------------
Method: SetWindowOrgEx
Params: DC - handle of device context
NewX - new x-coordinate of window origin
NewY - new y-coordinate of window origin
Point - record receiving original origin
Returns: Whether the call was successful
Sets the window origin of the device context by using the specified coordinates.
------------------------------------------------------------------------------}
function TCDWidgetSet.SetWindowOrgEx(DC : HDC; NewX, NewY : Integer; OldPoint: PPoint) : Boolean;
var
P: TPoint;
LazDC: TLazCanvas absolute DC;
begin
{$ifdef VerboseCDDrawing}
DebugLn(Format('[WinAPI SetWindowOrgEx] DC=%x NewX=%d NewY=%d',
[DC, NewX, NewY]));
{$endif}
Result := False;
if not IsValidDC(DC) then Exit;
GetWindowOrgEx(DC, @P);
if OldPoint <> nil then OldPoint^ := P;
LazDC.WindowOrg := Types.Point(-NewX, -NewY);
Result := True;
end;
(*{------------------------------------------------------------------------------
Method: SetWindowPos
Params: HWnd - handle of window
HWndInsertAfter - placement-order handle
X - horizontal position
Y - vertical position
CX - width
CY - height
UFlags - window-positioning flags
Returns: If the function succeeds
Changes the size, position, and Z order of a child, pop-up, or top-level
window.
------------------------------------------------------------------------------}
function TQtWidgetSet.SetWindowPos(hWnd: HWND; hWndInsertAfter: HWND; X, Y, cx,
cy: Integer; uFlags: UINT): Boolean;
var
DisableUpdates: boolean;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI SetWindowPos] Handle: ', dbghex(hWnd),
' hWndInsertAfter: ',dbghex(hWnd));
{$endif}
Result := hWnd <> 0;
if not Result then
exit;
DisableUpdates := (SWP_NOREDRAW and uFlags) <> 0;
if DisableUpdates then
TQtWidget(Hwnd).setUpdatesEnabled(False);
try
if (SWP_NOMOVE and uFlags) = 0 then
TQtWidget(Hwnd).move(X, Y);
if (SWP_NOSIZE and uFlags) = 0 then
TQtWidget(Hwnd).resize(CX, CY);
if (SWP_NOZORDER and uFlags) = 0 then
begin
case hWndInsertAfter of
HWND_TOP:
begin
TQtWidget(hWnd).raiseWidget;
if (SWP_NOACTIVATE and uFlags) = 0 then
TQtWidget(hWnd).Activate;
end;
HWND_BOTTOM: TQtWidget(hWnd).lowerWidget;
{TODO: HWND_TOPMOST ,HWND_NOTOPMOST}
end;
end;
finally
if DisableUpdates then
TQtWidget(Hwnd).setUpdatesEnabled(True);
end;
end;
{------------------------------------------------------------------------------
Method: SetWindowRgn
Params: hWnd - handle of the widget
hRgn - handle of the region
bRedraw - ?
Returns: 0 if the call failed, any other value if it was successful
Makes the region specifyed in hRgn be the only part of the window which is
visible.
------------------------------------------------------------------------------}
function TQtWidgetSet.SetWindowRgn(hWnd: HWND;
hRgn: HRGN; bRedraw: Boolean):longint;
var
w: TQtWidget;
r: TQtRegion;
begin
Result := 0;
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI SetWindowRgn] Handle: ', dbghex(hWnd));
{$endif}
// Basic checks
if (hWnd = 0) or (hRgn = 0) then Exit;
w := TQtWidget(hWnd);
r := TQtRegion(hRgn);
// Now set the mask in the widget
w.setMask(r.FHandle);
Result := 1;
end;
{------------------------------------------------------------------------------
function ShowWindow(hWnd: HWND; nCmdShow: Integer): Boolean;
nCmdShow:
SW_SHOWNORMAL, SW_MINIMIZE, SW_SHOWMAXIMIZED
------------------------------------------------------------------------------}
function TQtWidgetSet.ShowWindow(hWnd: HWND; nCmdShow: Integer): Boolean;
var
Widget: TQtWidget;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI ShowWindow] hwnd ',dbgHex(PtrUInt(hWnd)),' nCmdShow ',nCmdShow);
{$endif}
Result := False;
Widget := TQtWidget(hWnd);
if Widget <> nil then
begin
case nCmdShow of
SW_SHOW: Widget.setVisible(True);
SW_SHOWNORMAL: Widget.ShowNormal;
SW_MINIMIZE: Widget.setWindowState(QtWindowMinimized);
SW_SHOWMINIMIZED: Widget.ShowMinimized;
SW_SHOWMAXIMIZED: Widget.ShowMaximized;
SW_SHOWFULLSCREEN: Widget.ShowFullScreen;
SW_HIDE: Widget.setVisible(False);
end;
Result := True;
end;
end;*)
{------------------------------------------------------------------------------
Function: StretchBlt
Params: DestDC: The destination devicecontext
X, Y: The left/top corner of the destination rectangle
Width, Height: The size of the destination rectangle
SrcDC: The source devicecontext
XSrc, YSrc: The left/top corner of the source rectangle
SrcWidth, SrcHeight: The size of the source rectangle
ROp: The raster operation to be performed
Returns: True if succesful
The StretchBlt function copies a bitmap from a source rectangle into a
destination rectangle using the specified raster operation. If needed it
resizes the bitmap to fit the dimensions of the destination rectangle.
Sizing is done according to the stretching mode currently set in the
destination device context.
If SrcDC contains a mask the pixmap will be copied with this transparency.
------------------------------------------------------------------------------}
function TCDWidgetSet.StretchBlt(DestDC: HDC; X, Y, Width, Height: Integer;
SrcDC: HDC; XSrc, YSrc, SrcWidth, SrcHeight: Integer; ROp: Cardinal): Boolean;
begin
Result := StretchMaskBlt(DestDC,X,Y,Width,Height,
SrcDC,XSrc,YSrc,SrcWidth,SrcHeight,
0,0,0,
ROp);
end;
{------------------------------------------------------------------------------
Function: StretchMaskBlt
Params: DestDC: The destination devicecontext
X, Y: The left/top corner of the destination rectangle
Width, Height: The size of the destination rectangle
SrcDC: The source devicecontext
XSrc, YSrc: The left/top corner of the source rectangle
SrcWidth, SrcHeight: The size of the source rectangle
Mask: The handle of a monochrome bitmap
XMask, YMask: The left/top corner of the mask rectangle
ROp: The raster operation to be performed
Returns: True if succesful
The StretchMaskBlt function copies a bitmap from a source rectangle into a
destination rectangle using the specified mask and raster operation. If needed
it resizes the bitmap to fit the dimensions of the destination rectangle.
Sizing is done according to the stretching mode currently set in the
destination device context.
------------------------------------------------------------------------------}
function TCDWidgetSet.StretchMaskBlt(DestDC: HDC; X, Y, Width, Height: Integer;
SrcDC: HDC; XSrc, YSrc, SrcWidth, SrcHeight: Integer; Mask: HBITMAP;
XMask, YMask: Integer; Rop: DWORD): Boolean;
var
SrcLazDC: TLazCanvas absolute SrcDC;
DstLazDC: TLazCanvas absolute DestDC;
BufferImage: TLazIntfImage = nil;
BufferDC: TLazCanvas = nil;
FreeBuffer: Boolean;
SrcRect, DstRect, MaskRect: TRect;
begin
{$ifdef VerboseCDDrawing}
DebugLn('[WinAPI StretchMaskBlt]' +
' DestDC:' + dbghex(DestDC) +
' SrcDC:' + dbghex(SrcDC) +
' X:' + dbgs(X) + ' Y:' + dbgs(Y) +
' W:' + dbgs(Width) + ' H:', dbgs(Height) +
' XSrc:' + dbgs(XSrc) + ' YSrc:' + dbgs(YSrc) +
' WSrc:' + dbgs(SrcWidth) + ' HSrc:' + dbgs(SrcHeight));
{$endif}
Result := False;
// Optimization if no stretch is desired
if (SrcWidth = Width) and (SrcHeight = Height) then
begin
DstLazDC.CanvasCopyRect(SrcLazDC, X, Y, XSrc, YSrc, SrcWidth, SrcHeight);
Exit;
end;
// Otherwise do the real stretch
// Get an interpolation acording to the anti-aliasing option
{if DstLazDC. .AntiAliasing then
DstLazDC.Interpolation := TMitchelInterpolation.Create
else}
DstLazDC.Interpolation := TFPSharpInterpolation.Create;
// Copy the source rectangle to a temporary buffer if it is not the entire source
if (XSrc = 0) and (YSrc = 0) and (SrcWidth = SrcLazDC.Width) and (SrcHeight = SrcLazDC.Height) then
begin
BufferDC := SrcLazDC;
BufferImage := TLazIntfImage(SrcLazDC.Image);
FreeBuffer := False;
end
else
begin
UpdateControlLazImageAndCanvas(BufferImage, BufferDC,
SrcWidth, SrcHeight, clfARGB32);
BufferDC.CanvasCopyRect(SrcLazDC, 0, 0, XSrc, YSrc, SrcWidth, SrcHeight);
FreeBuffer := True;
end;
// Execute the stretch
DstLazDC.StretchDraw(X, Y, Width, Height, BufferImage);
// Free the interpolation
DstLazDC.Interpolation.Free;
DstLazDC.Interpolation := nil;
// Free the buffer
if FreeBuffer then
begin
BufferDC.Free;
BufferImage.Free;
end;
Result := True;
end;
(*{------------------------------------------------------------------------------
Function: SystemParametersInfo
Params: uiAction: System-wide parameter to be retrieved or set
uiParam: Depends on the system parameter being queried or set
pvParam: Depends on the system parameter being queried or set
fWinIni:
Returns: True if the function succeeds
retrieves or sets the value of one of the system-wide parameters
------------------------------------------------------------------------------}
function TQtWidgetSet.SystemParametersInfo(uiAction: DWord; uiParam: DWord; pvParam: Pointer; fWinIni: DWord): LongBool;
begin
case uiAction of
SPI_GETWHEELSCROLLLINES: PDword(pvPAram)^ := QApplication_wheelScrollLines;
SPI_GETWORKAREA: begin
TRect(pvParam^):=Bounds(GetSystemMetrics(SM_XVIRTUALSCREEN),
GetSystemMetrics(SM_YVIRTUALSCREEN),
GetSystemMetrics(SM_CXVIRTUALSCREEN),
GetSystemMetrics(SM_CYVIRTUALSCREEN));
Result:=True;
end;
else
Result := False;
end
end;*)
{------------------------------------------------------------------------------
Function: TextOut
Params: DC:
X:
Y:
Str:
Count:
Returns:
------------------------------------------------------------------------------}
function TCDWidgetSet.TextOut(DC: HDC; X,Y : Integer; Str : Pchar; Count: Integer) : Boolean;
begin
Result:=ExtTextOut(DC, X, Y, 0, nil, Str, Count, nil);
end;
(*{------------------------------------------------------------------------------
Method: UpdateWindow
Params: Handle
Returns:
------------------------------------------------------------------------------}
function TQtWidgetSet.UpdateWindow(Handle: HWND): Boolean;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI UpdateWindow]');
{$endif}
Result := False;
if Handle <> 0 then
begin
TQtWidget(Handle).Update;
Result := True;
end;
end;
{------------------------------------------------------------------------------
Method: WindowFromPoint
Params: TPoint
Returns: The return value is a handle to the window that contains the param
point.
If no window exists at the given point, the return value is 0.
If the point is over a static text control,
the return value is a handle to the window under the static text control.
------------------------------------------------------------------------------}
function TQtWidgetSet.WindowFromPoint(APoint: TPoint): HWND;
var
Widget: QWidgetH;
begin
// we use cachedresults instead of calling very expensive widgetAt
if (FLastWFPResult <> 0) then
begin
if not IsValidWidgetAtCachePointer then
FLastWFPResult := 0
else
if (APoint.X = FLastWFPMousePos.X) and (APoint.Y = FLastWFPMousePos.Y) and
TQtWidget(FLastWFPResult).getVisible and
TQtWidget(FLastWFPResult).getEnabled then
begin
// return from cache
exit(FLastWFPResult);
end;
end;
Result := 0;
Widget := QApplication_widgetAt(APoint.x, APoint.y);
if (Widget = nil) then
begin
if (APoint.X = FLastWFPMousePos.X) and (APoint.Y = FLastWFPMousePos.Y) then
begin
FLastWFPMousePos := Point(MaxInt, MaxInt);
FLastWFPResult := 0;
end;
exit;
end;
// according to MSDN disabled widget shouldn't be in result
// but win32 returns first enabled and visible parent !
if not QWidget_isEnabled(Widget) or not QWidget_isVisible(Widget) then
begin
while Widget <> nil do
begin
Widget := QWidget_parentWidget(Widget);
if (Widget <> nil) and QWidget_IsVisible(Widget) and
QWidget_isEnabled(Widget) then
break;
end;
if Widget = nil then
exit;
end;
Result := HwndFromWidgetH(Widget);
// return from cache if we are same TQtWidget, just update point
if IsValidWidgetAtCachePointer and (Result = FLastWFPResult) then
begin
FLastWFPMousePos := APoint;
exit(FLastWFPResult);
end;
// maybe we are viewport of native QAbstractScrollArea (eg. QTextEdit).
if (Result = 0) then
begin
if QWidget_parentWidget(Widget) <> nil then
begin
while (Widget <> nil) do
begin
Widget := QWidget_parentWidget(Widget);
if Widget <> nil then
Result := HwndFromWidgetH(Widget);
if Result <> 0 then
break;
end;
end;
end;
if (Result <> 0) and
not (TQtWidget(Result) is TQtMainWindow) then
begin
if TQtWidget(Result).getOwner <> nil then
Result := HWND(TQtWidget(Result).getOwner);
end else
begin
Widget := QApplication_topLevelAt(APoint.x, APoint.y);
if (Widget <> nil) and QWidget_isEnabled(Widget) then
Result := HwndFromWidgetH(Widget)
else
Result := 0;
end;
// add to cache
FLastWFPResult := Result;
FLastWFPMousePos := APoint;
end;*)
//##apiwiz##eps## // Do not remove, no wizard declaration after this line