lazarus/lcl/interfaces/fpgui/fpguiwinapi.inc
mattias 0d38a13c22 fpgui: patch #18542
git-svn-id: trunk@29075 -
2011-01-17 20:17:19 +00:00

611 lines
17 KiB
PHP

{%MainUnit fpguiint.pp}
{******************************************************************************
All FPGUI Winapi implementations.
This are the implementations of the overrides of the FPGUI Interface for the
methods defined in the
lcl/include/winapi.inc
!! 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 copyright. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
*****************************************************************************
}
//##apiwiz##sps## // Do not remove, no wizard declaration before this line
{------------------------------------------------------------------------------
Function: BeginPaint
Params:
Returns:
This function is Called:
- Once on every OnPaint event
------------------------------------------------------------------------------}
function TFpGuiWidgetSet.BeginPaint(Handle: hWnd; Var PS : TPaintStruct): hdc;
var
PrivateWidget: TFPGUIPrivateWidget absolute Handle;
DC: TFpGuiDeviceContext;
begin
{$ifdef VerboseFPGUIWinAPI}
WriteLn('Trace:> [WinAPI BeginPaint] Handle=', dbghex(Handle));
{$endif}
{$WARNING TFpGuiWidgetSet.BeginPaint Temporary Fix to prevent Crashing}
try
if PrivateWidget <> nil then
DC := TFpGuiDeviceContext.Create(PrivateWidget)
else
DC := TFpGuiDeviceContext.Create(nil);
{$ifdef VerboseFPGUIWinAPI}
if PrivateWidget <> nil then
WriteLn(PrivateWidget.ClassName);
{$endif}
except
DC := TFpGuiDeviceContext.Create(nil);
end;
PS.hdc := HDC(DC);
Result := PS.hdc;
{$ifdef VerboseFPGUIWinAPI}
WriteLn('Trace:< [WinAPI BeginPaint] Result=', dbghex(Result));
{$endif}
end;
function TFpGuiWidgetSet.ClientToScreen(Handle: HWND; var P: TPoint): Boolean;
var
O: TFPGUIPrivateWidget;
begin
O:=GlobalMouseCursorPosWidget;
while O<>nil do begin
P.X:=P.X+O.Widget.Left;
P.Y:=P.Y+O.Widget.Top;
if O.LCLObject.Parent<>nil then begin
O:=TFPGUIPrivateWidget(O.LCLObject.Parent.Handle);
end else begin
O:=nil;
end;
end;
Result:=true;
end;
function TFpGuiWidgetSet.CombineRgn(Dest, Src1, Src2: HRGN;
fnCombineMode: Longint): Longint;
var
R1: TFPGUIBasicRegion absolute Src1;
R2: TFPGUIBasicRegion absolute Src2;
DR: TFPGUIBasicRegion absolute Dest;
Combine: TFPGUIRegionCombine;
begin
case fnCombineMode of
RGN_AND: Combine:=eRegionCombineAnd;
RGN_COPY: Combine:=eRegionCombineCopy;
RGN_DIFF: Combine:=eRegionCombineDiff;
RGN_OR: Combine:=eRegionCombineOr;
RGN_XOR: Combine:=eRegionCombineXor;
end;
if DR<>nil then DR.Free;
DR:=R1.CombineWithRegion(R2,Combine);
Case dr.RegionType of
eRegionNULL: Result:=NullRegion;
eRegionSimple: Result:=SimpleRegion ;
eRegionComplex: Result:=ComplexRegion;
eRegionNotCombinableOrError: Result:=Region_Error;
end;
end;
function TFpGuiWidgetSet.CreateBitmap(Width, Height: Integer; Planes,
BitCount: Longint; BitmapBits: Pointer): HBITMAP;
var
img: TFPGUIWinAPIBitmap;
begin
if BitCount>0 then begin
img:=TFPGUIWinAPIBitmap.Create(BitCount,Width,Height);
Result:=HBITMAP(img);
end else begin
Result:=0;
end;
end;
function TFpGuiWidgetSet.CreateBrushIndirect(const LogBrush: TLogBrush
): HBRUSH;
begin
Result:=HBRUSH(TFPGUIWinAPIBrush.Create(LogBrush));
end;
function TFpGuiWidgetSet.CreateCompatibleBitmap(DC: HDC; Width, Height: Integer
): HBITMAP;
var
img: TFPGUIWinAPIBitmap;
begin
img:=TFPGUIWinAPIBitmap.Create(32,Width,Height);
Result:=HBITMAP(img);
end;
function TFpGuiWidgetSet.CreateCompatibleDC(DC: HDC): HDC;
var
ADC: TFpGuiDeviceContext absolute DC;
begin
{$ifdef VerboseFPGUIWinAPI}
if DC=0 then begin
WriteLn(Self.ClassName,'.CreateCompatibleDC ','NULL');
end else begin
if ADC.FPrivateWidget<>nil then begin
WriteLn(Self.ClassName,'.CreateCompatibleDC ',ADC.FPrivateWidget.LCLObject.Name);
end else begin
WriteLn(Self.ClassName,'.CreateCompatibleDC ','Desktop');
end;
end;
{$endif}
if DC=0 then begin
//Create DC desktop compatible, or retrieve the destop one to avoid memory leask.
Result:=HDC(FPGUIGetDesktopDC());
end else begin
//Create DC widget compatible
Result:=HDC(TFpGuiDeviceContext.Create(ADC.FPrivateWidget));
end;
end;
function TFpGuiWidgetSet.CreateFontIndirect(const LogFont: TLogFont): HFONT;
begin
Result:=HFONT(TFPGUIWinAPIFont.Create(LogFont));
end;
function TFpGuiWidgetSet.CreateFontIndirectEx(const LogFont: TLogFont;
const LongFontName: string): HFONT;
begin
Result:=HFONT(TFPGUIWinAPIFont.Create(LogFont,LongFontName));
end;
function TFpGuiWidgetSet.CreatePenIndirect(const LogPen: TLogPen): HPEN;
begin
Result:=HPEN(TFPGUIWinAPIPen.Create(LogPen));
end;
function TFpGuiWidgetSet.CreateRectRgn(X1, Y1, X2, Y2: Integer): HRGN;
var
Reg: TFPGUIBasicRegion;
begin
Reg:=TFPGUIBasicRegion.Create(Rect(X1,Y1,X2,Y2));
Result:=HRGN(Reg);
end;
function TFpGuiWidgetSet.DeleteObject(GDIObject: HGDIOBJ): Boolean;
begin
if IsValidGDIObject(GDIObject) then begin
TObject(GDIObject).Free;
Result:=true;
end else begin
Result:=false;
end;
end;
function TFpGuiWidgetSet.DrawFocusRect(DC: HDC; const Rect: TRect): boolean;
var
ADC: TFpGuiDeviceContext absolute DC;
r: TfpgRect;
begin
ADC.fpgCanvas.DrawFocusRect(ADC.PrepareRectOffsets(Rect));
Result:=true;
end;
function TFpGuiWidgetSet.DrawText(DC: HDC; Str: PChar; Count: Integer;
var ARect: TRect; Flags: Cardinal): Integer;
var
ADC: TFpGuiDeviceContext absolute DC;
begin
Result:=inherited DrawText(DC, Str, Count, ARect, Flags);
if (Flags and DT_CALCRECT)=0 then begin
ADC.fpgCanvas.DrawText(ADC.PrepareRectOffsets(ARect),Str,[],0);
end;
Result:=ARect.Bottom-ARect.Top; //The height of the text.
end;
function TFpGuiWidgetSet.EnableWindow(hWnd: HWND; bEnable: Boolean): Boolean;
var
Widget: TFPGUIPrivateWidget absolute hWnd;
begin
Result:=true;
Widget.Enabled:=bEnable;
Result:=true;
end;
function TFpGuiWidgetSet.EndPaint(Handle: hwnd; var PS: TPaintStruct): Integer;
var
DC: TFpGuiDeviceContext;
begin
DC := TFpGuiDeviceContext(PS.hdc);
DC.Free;
Result:=1; //Any non zero value.
end;
function TFpGuiWidgetSet.ExtTextOut(DC: HDC; X, Y: Integer; Options: Longint;
Rect: PRect; Str: PChar; Count: Longint; Dx: PInteger): Boolean;
var
ADC: TFpGuiDeviceContext absolute DC;
AStr: string;
r: TfpgRect;
rClip,OldClip: TfpgRect;
RestoreClip: Boolean;
begin
SetLength(AStr,Count);
move(Str[0],AStr[1],Count);
r:=ADC.PrepareRectOffsets(classes.Rect(X,Y,0,0));
RestoreClip:=false;
if Rect<>nil then begin
rClip:=fpgRect(Rect^.Left,Rect^.Top,Rect^.Right-Rect^.Left,Rect^.Bottom-Rect^.Top);
if (ETO_CLIPPED or ETO_OPAQUE) and Options <> 0 then begin
OldClip:=ADC.fpgCanvas.GetClipRect;
ADC.fpgCanvas.SetClipRect(rClip);
RestoreClip:=true;
end;
if ETO_OPAQUE and Options = ETO_OPAQUE then begin
ADC.ClearRectangle(rClip);
end;
end;
ADC.fpgCanvas.DrawText(r.Left, r.Top, AStr);
if RestoreClip then begin
ADC.fpgCanvas.SetClipRect(OldClip);
end;
Result:=true;
end;
function TFpGuiWidgetSet.FillRect(DC: HDC; const Rect: TRect; Brush: HBRUSH
): Boolean;
var
ADC: TFpGuiDeviceContext absolute DC;
NewBrush: TFPGUIWinAPIBrush absolute Brush;
OldColor: TfpgColor;
TheRect: TfpgRect;
begin
OldColor:=ADC.fpgCanvas.Color;
ADC.fpgCanvas.Color:=NewBrush.Color;
TRectTofpgRect(Rect,TheRect);
AdjustRectToOrg(TheRect,ADC.FOrg);
ADC.fpgCanvas.FillRectangle(TheRect);
ADC.fpgCanvas.Color:=OldColor;
Result:=true;
end;
function TFpGuiWidgetSet.GetClientRect(handle: HWND; var ARect: TRect
): Boolean;
var
fpguiPrivate: TFPGUIPrivateWidget absolute handle;
begin
fpguiPrivate.GetClientRect(ARect);
Result:=true;
end;
function TFpGuiWidgetSet.GetClipRGN(DC: hDC; RGN: hRGN): Longint;
var
ADC: TFpGuiDeviceContext absolute DC;
Clip: TfpgRect;
Region: TFPGUIBasicRegion absolute RGN;
begin
ADC.fpgCanvas.GetWinRect(Clip); { TODO : Should be a clip region, but use this by now }
if Region<>nil Then FreeAndNil(Region);
Region:=TFPGUIBasicRegion.Create(Rect(Clip.Left,Clip.Top,Clip.Right,Clip.Bottom));
RGN:=HRGN(Region);
if Region.RegionType=eRegionNULL then begin
Result:=0;
end else if Region.RegionType=eRegionNotCombinableOrError then begin
Result:=-1;
end else begin
Result:=1;
end;
end;
function TFpGuiWidgetSet.GetCursorPos(var lpPoint: TPoint): Boolean;
var
O: TFPGUIPrivateWidget;
begin
O:=GlobalMouseCursorPosWidget;
lpPoint:=GlobalMouseCursorPos;
while O<>nil do begin
lpPoint.X:=lpPoint.X+O.Widget.Left;
lpPoint.Y:=lpPoint.Y+O.Widget.Top;
if O.LCLObject.Parent<>nil then begin
O:=TFPGUIPrivateWidget(O.LCLObject.Parent.Handle);
end else begin
O:=nil;
end;
end;
Result:=true;
end;
function TFpGuiWidgetSet.GetDC(hWnd: HWND): HDC;
var
PrivateWidget: TFPGUIPrivateWidget absolute hWnd;
begin
//Create a new DC
if Assigned(PrivateWidget) then begin
if PrivateWidget.DC<>0 then begin
Result:=PrivateWidget.DC;
end else begin
Result:=HDC(TFpGuiDeviceContext.Create(PrivateWidget));
end;
end else Result:=HDC(FPGUIGetDesktopDC());
end;
function TFpGuiWidgetSet.GetDeviceCaps(DC: HDC; Index: Integer): Integer;
var
ADC: TFpGuiDeviceContext absolute DC;
begin
if ADC.FPrivateWidget=nil then begin
//Desktop device caps
{ TODO : Create real data for GetDeviceCaps }
Case Index of
LOGPIXELSX: Result:=96; //Hardcoded by now
BITSPIXEL : Result:=32; //Hardcoded by now
else begin
{$ifdef VerboseFPGUIWinAPI}
WriteLn(Self.ClassName,'.GetDeviceCaps Index ',Index,' Desktop');
{$endif}
end;
end;
end else begin
//other
{$ifdef VerboseFPGUIWinAPI}
WriteLn(Self.ClassName,'.GetDeviceCaps Index ',Index,ADC.FPrivateWidget.LCLObject.Name);
{$endif}
end;
end;
function TFpGuiWidgetSet.GetProp(Handle: hwnd; Str: PChar): Pointer;
var
PrivateWidget: TFPGUIPrivateWidget absolute Handle;
begin
if Str='WinControl' then begin
Result:=PrivateWidget.LCLObject;
end else begin
{$ifdef VerboseFPGUIWinAPI}
WriteLn('Trace:Unknown Window property: ',Str);
{$endif}
Result:=nil;
end;
end;
function TFpGuiWidgetSet.GetSysColor(nIndex: Integer): DWORD;
begin
if (nIndex < 0) or (nIndex > MAX_SYS_COLORS) then
begin
{$ifdef VerboseFPGUIWinAPI}
WriteLn('Trace:Unknown lcl system color: [TFpGuiWidgetSet.GetSysColor]');
{$endif}
Result:=clRed;
exit;
end;
Result:=GetSysColorRGB(nIndex);
end;
function TFpGuiWidgetSet.GetSystemMetrics(nIndex: Integer): Integer;
begin
case nIndex of
//Current screen size
SM_CXSCREEN: Result:=1400; //Hardcoded by now
SM_CYSCREEN: Result:=400;
//Desktop size
SM_CXVIRTUALSCREEN: Result:=1400;
SM_CYVIRTUALSCREEN: Result:=400;
end;
end;
function TFpGuiWidgetSet.GetTextExtentPoint(DC: HDC; Str: PChar;
Count: Integer; var Size: TSize): Boolean;
var
ADC: TFpGuiDeviceContext absolute DC;
begin
Size.cx:=ADC.fpgCanvas.Font.TextWidth(Str);
Size.cy:=ADC.fpgCanvas.Font.Height;
Result:=true;
end;
function TFpGuiWidgetSet.GetTextMetrics(DC: HDC; var TM: TTextMetric): Boolean;
var
ADC: TFpGuiDeviceContext absolute DC;
begin
FillByte(TM,sizeof(TM),0);
TM.tmAscent:=ADC.FFont.fpguiFont.Ascent;
TM.tmDescent:=ADC.FFont.fpguiFont.Descent;
//Defined usually in MSDN as the average of 'x' char.
TM.tmAveCharWidth:=ADC.FFont.fpguiFont.TextWidth('x');
TM.tmHeight:=ADC.FFont.Height;
Result:=true;
end;
function TFpGuiWidgetSet.GetWindowOrgEx(dc: hdc; P: PPoint): Integer;
var
ADC: TFpGuiDeviceContext absolute DC;
begin
P^:=ADC.FOrg;
Result:=1;
end;
function TFpGuiWidgetSet.GetWindowRect(Handle: hwnd; var ARect: TRect
): Integer;
var
PrivateWidget: TFPGUIPrivateBin absolute Handle;
begin
ARect:=fpgRectToRect(PrivateWidget.Widget.GetBoundsRect);
Result:=1;
end;
function TFpGuiWidgetSet.GetWindowSize(Handle: hwnd; var Width, Height: Integer
): boolean;
var
PrivateWidget: TFPGUIPrivateBin absolute Handle;
begin
Width:=PrivateWidget.Widget.Width;
Height:=PrivateWidget.Widget.Height;
Result:=true;
end;
function TFpGuiWidgetSet.InvalidateRect(aHandle: HWND; Rect: pRect;
bErase: Boolean): Boolean;
var
PrivateWidget: TFPGUIPrivateWidget absolute aHandle;
begin
PrivateWidget.Widget.Canvas.BeginDraw(false);
PrivateWidget.Paint;
PrivateWidget.Widget.Canvas.EndDraw;
Result:=true;
end;
function TFpGuiWidgetSet.Rectangle(DC: HDC; X1, Y1, X2, Y2: Integer): Boolean;
var
ADC: TFpGuiDeviceContext absolute DC;
r: TfpgRect;
begin
r:=ADC.PrepareRectOffsets(Rect(X1,Y1,X2,Y2));
ADC.fpgCanvas.BeginDraw(true);
ADC.ClearRectangle(r);
ADC.fpgCanvas.DrawRectangle(r);
ADC.fpgCanvas.EndDraw;
Result:=true;
end;
function TFpGuiWidgetSet.ReleaseDC(hWnd: HWND; DC: HDC): Integer;
var
MyDC: TFpGuiDeviceContext absolute DC;
begin
if MyDC<>FPGUIGetDesktopDC then begin //DesktopDC can not be freed
MyDC.Free;
end;
Result:=1;
end;
function TFpGuiWidgetSet.RestoreDC(DC: HDC; SavedDC: Integer): Boolean;
var
ADC: TFPGUIDeviceContext absolute DC;
begin
Result:=ADC.RestoreDC(SavedDC);
end;
function TFpGuiWidgetSet.SaveDC(DC: HDC): Integer;
var
ADC: TFPGUIDeviceContext absolute DC;
begin
Result:=ADC.SaveDC;
end;
function TFpGuiWidgetSet.SelectClipRGN(DC: hDC; RGN: HRGN): Longint;
var
ADC: TFPGUIDeviceContext absolute DC;
Reg: TFPGUIBasicRegion absolute RGN;
begin
if Reg.RegionType=eRegionSimple then begin
ADC.SelectObject(HGDIObj(Reg));
Result:=SimpleRegion;
end else begin
Result:=NullRegion;
end;
end;
function TFpGuiWidgetSet.SelectObject(DC: HDC; GDIObj: HGDIOBJ): HGDIOBJ;
var
MyDC: TFpGuiDeviceContext absolute DC;
begin
Result:=MyDC.SelectObject(GDIObj);
end;
function TFpGuiWidgetSet.SetFocus(hWnd: HWND): HWND;
var
Widget: TFPGUIPrivateWidget absolute hWnd;
begin
Result:=LCLType.HWND(Widget.Widget.ActiveWidget);
Widget.SetFocus;
end;
function TFpGuiWidgetSet.SetParent(hWndChild: HWND; hWndParent: HWND): HWND;
var
PrivateWidgetParent: TFPGUIPrivateWidget absolute hWndParent;
PrivateWidgetChild: TFPGUIPrivateWidget absolute hWndChild;
begin
PrivateWidgetChild.Widget.Parent:=PrivateWidgetParent.Widget;
Result:=0; //???
end;
function TFpGuiWidgetSet.SetTextColor(DC: HDC; Color: TColorRef): TColorRef;
var
ADC: TFpGuiDeviceContext absolute DC;
begin
Result:=ADC.SetTextColor(Color);
end;
function TFpGuiWidgetSet.SetWindowOrgEx(DC: HDC; NewX, NewY: Integer;
OldPoint: PPoint): Boolean;
var
ADC: TFpGuiDeviceContext absolute DC;
begin
ADC.SetOrigin(NewX,NewY);
Result:=true;
end;
function TFpGuiWidgetSet.ShowWindow(hWnd: HWND; nCmdShow: Integer): Boolean;
var
Widget: TFPGUIPrivateWidget absolute hWnd;
begin
Result:=Widget.Visible;
Widget.Visible:=true;{ TODO -oJose Mejuto : Process showwindow mode }
end;
function TFpGuiWidgetSet.StretchBlt(DestDC: HDC; X, Y, Width, Height: Integer;
SrcDC: HDC; XSrc, YSrc, SrcWidth, SrcHeight: Integer; ROp: Cardinal
): Boolean;
var
SDC: TFPGUIDeviceContext absolute SrcDC;
TDC: TFPGUIDeviceContext absolute DestDC;
begin
Result:=false;
end;
function TFpGuiWidgetSet.StretchMaskBlt(DestDC: HDC; X, Y, Width,
Height: Integer; SrcDC: HDC; XSrc, YSrc, SrcWidth, SrcHeight: Integer;
Mask: HBITMAP; XMask, YMask: Integer; Rop: DWORD): Boolean;
var
SDC: TFPGUIDeviceContext;
TDC: TFPGUIDeviceContext;
R: TRect;
ClientRect: TfpgRect;
P: TPoint;
begin
SDC:=TFPGUIDeviceContext(SrcDC);
TDC:=TFPGUIDeviceContext(DestDC);
r.Left:=X; r.Right:=Width; R.Top:=Y; r.Bottom:=Height;
AdjustRectToOrg(r,TDC.FOrg);
ClientRect:=TDC.FPrivateWidget.Widget.GetClientRect;
P.x:=-ClientRect.Left;
P.y:=-ClientRect.Top;
AdjustRectToOrg(r,P);
TDC.ClearDC;
TDC.fpgCanvas.DrawImage(r.Left,r.Top,SDC.FBitmap.Image);
Result:=true;
end;
function TFpGuiWidgetSet.WindowFromPoint(Point: TPoint): HWND;
begin
{ TODO : Temporal hack while not real WindowFromPoint implementation }
Result:=HWND(GlobalMouseCursorPosWidget);
end;
//##apiwiz##eps## // Do not remove, no wizard declaration after this line