405 lines
9.5 KiB
PHP
405 lines
9.5 KiB
PHP
|
|
{
|
|
Qt Interface
|
|
|
|
Initial implementation by Zeljan Rikalo
|
|
|
|
SetTimer/KillTimer implementation by Luiz Americo
|
|
}
|
|
|
|
function CF_UNICODETEXT: TClipboardFormat;
|
|
begin
|
|
//todo
|
|
Result := TClipboardFormat(0);
|
|
end;
|
|
|
|
{$define HAS_GETBKCOLOR}
|
|
{$define HAS_GETCURRENTOBJECT}
|
|
{$define HAS_INVERTRECT}
|
|
{$define HAS_GETTEXTEXTENTEXPOINT}
|
|
{$define HAS_GETDOUBLECLICKTIME}
|
|
{$define HAS_GETTEXTALIGN}
|
|
{$define HAS_GETWINDOWDC}
|
|
{$define HAS_OFFSETRGN}
|
|
{$define HAS_REDRAWWINDOW}
|
|
{$define HAS_SCROLLWINDOW}
|
|
{$define HAS_SETBRUSHORGEX}
|
|
|
|
|
|
{$i ../generic/stubs.inc}
|
|
{$i ../generic/independentfunctions.inc}
|
|
{$i ../generic/unicodefunctions.inc}
|
|
|
|
function GetBkColor(DC:HDC):COLORREF;
|
|
var
|
|
Color: PQColor;
|
|
begin
|
|
if QtWidgetSet.IsValidDC(DC) then
|
|
begin
|
|
Color := TQtDeviceContext(DC).BackgroundBrush.getColor;
|
|
TQColorToColorRef(Color^, Result);
|
|
end else
|
|
Result := CLR_INVALID;
|
|
end;
|
|
|
|
function BitBlt(DestDC: HDC; X, Y, Width, Height: Integer; SrcDC: HDC; XSrc,
|
|
YSrc: Integer; Rop: DWORD): Boolean;
|
|
begin
|
|
Result := StretchBlt(DestDC, X, Y, Width, Height, SrcDC, XSrc, YSrc, Width,
|
|
Height, ROP);
|
|
end;
|
|
|
|
function GetCurrentObject(hdc: HDC; uObjectType: UINT): HGDIOBJ;
|
|
begin
|
|
Result := 0;
|
|
if QtWidgetSet.IsValidDC(hdc) then
|
|
with TQtDeviceContext(hdc) do
|
|
begin {TODO: FIXME}
|
|
case uObjectType of
|
|
OBJ_BITMAP: Result := HGDIOBJ(vImage);
|
|
OBJ_BRUSH: Result := HGDIOBJ(vBrush);
|
|
OBJ_FONT: Result := HGDIOBJ(vFont);
|
|
OBJ_PEN: Result := HGDIOBJ(vPen);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function GetDoubleClickTime: UINT;
|
|
begin
|
|
Result := QApplication_doubleClickInterval;
|
|
end;
|
|
|
|
function GetTextExtentExPoint(DC: HDC; Str: PChar;
|
|
Count, MaxWidth: Integer; MaxCount, PartialWidths: PInteger;
|
|
var Size: TSize): BOOL;
|
|
begin
|
|
Result := QtWidgetSet.GetTextExtentExPoint(DC, Str, Count, MaxWidth, MaxCount, PartialWidths, Size);
|
|
end;
|
|
|
|
function GetTextAlign(hDC:HDC): LongWord;
|
|
var
|
|
QtDC: TQtDeviceContext;
|
|
QtFontMetrics: QFontMetricsH;
|
|
QtFont: QFontH;
|
|
begin
|
|
Result := 0;
|
|
if not QtWidgetSet.IsValidDC(hdC) then
|
|
Exit;
|
|
QtDC := TQtDeviceContext(hDC);
|
|
QtFont := QtDC.vFont.FHandle;
|
|
QtFontMetrics := QFontMetrics_create(QtFont);
|
|
try
|
|
{TODO: FIXME we should save somehow text flags into QtDC
|
|
cause we don't have any function which returns current flags !}
|
|
finally
|
|
QFontMetrics_destroy(QtFontMetrics);
|
|
end;
|
|
end;
|
|
|
|
function GetWindowDC(hWnd:THandle): HDC;
|
|
begin
|
|
Result := LCLIntf.GetDC(hWnd);
|
|
end;
|
|
|
|
function InvertRect(DC: HDC; const lprc: TRect): Boolean;
|
|
var
|
|
DCOrigin: TQtPoint;
|
|
begin
|
|
//todo: see the windows result when rect is invalid
|
|
Result := QtWidgetSet.IsValidDC(DC) and (lprc.Bottom > lprc.Top)
|
|
and (lprc.Right > lprc.Left);
|
|
if Result then
|
|
begin
|
|
with lprc do
|
|
Result := BitBlt(DC, Left, Top, Right - Left, Bottom-Top,
|
|
DC, Left, Top, LongWord(QPainterCompositionMode_DestinationOver));
|
|
{TODO: FIXME !}
|
|
end;
|
|
end;
|
|
|
|
function OffsetRgn(hrgn:HRGN; nxOffset, nYOffset:longint):longint;
|
|
var
|
|
Region: TQtRegion;
|
|
begin
|
|
Region := TQtRegion(hrgn);
|
|
QRegion_translate(Region.FHandle, nxOffset, nYOffset);
|
|
Result := Region.GetRegionType;
|
|
end;
|
|
|
|
function RedrawWindow(hWnd:THandle; lprcUpdate:PRECT; hrgnUpdate:HRGN; flags:LongWord):BOOLEAN;
|
|
begin
|
|
Result := QtWidgetSet.RedrawWindow(hWnd, lprcUpdate, hrgnUpdate, flags);
|
|
end;
|
|
|
|
function ScrollWindow(hWnd:THandle; XAmount, YAmount:longint;lpRect:PRECT; lpClipRect:PRECT): Boolean;
|
|
begin
|
|
Result := False;
|
|
if hWnd = 0 then
|
|
Exit;
|
|
QWidget_scroll(TQtWidget(hWnd).Widget, XAmount, YAmount, lpRect);
|
|
Result := True;
|
|
end;
|
|
|
|
function SetBrushOrgEx(DC:HDC; nXOrg, nYOrg:longint; lppt:PPOINT):Boolean;
|
|
var
|
|
QtDC: TQtDeviceContext;
|
|
begin
|
|
Result := False;
|
|
if not QtWidgetSet.IsValidDC(DC) then
|
|
Exit;
|
|
QtDC := TQtDeviceContext(DC);
|
|
if lppt <> nil then
|
|
QtDC.getBrushOrigin(lppt);
|
|
QtDC.setBrushOrigin(nXorg, nYOrg);
|
|
Result := True;
|
|
end;
|
|
|
|
|
|
type
|
|
|
|
TTimerID = record
|
|
hWnd: THandle;
|
|
nIDEvent: UINT_PTR;
|
|
end;
|
|
|
|
{ TQtTimerEx }
|
|
|
|
TQtTimerEx = class(TQtObject)
|
|
private
|
|
FTimerHook: QTimer_hookH;
|
|
FWidgetHook: QObject_hookH;
|
|
FCallbackFunc: TTimerNotify;
|
|
FID: UINT_PTR;
|
|
FHandle: THandle;
|
|
FControl: TWinControl;
|
|
public
|
|
constructor Create(hWnd: THandle; nIDEvent: UINT_PTR; TimerFunc: TTimerNotify);
|
|
destructor Destroy; override;
|
|
procedure AttachEvents; override;
|
|
procedure DetachEvents; override;
|
|
procedure signalWidgetDestroyed; cdecl;
|
|
procedure signalTimeout; cdecl;
|
|
public
|
|
function EventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl; override;
|
|
procedure Start(Interval: Integer);
|
|
procedure Stop;
|
|
end;
|
|
|
|
|
|
{ TTimerList }
|
|
|
|
TTimerList = class
|
|
private
|
|
FMap: TMap;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure Delete(hWnd: THandle; nIDEvent: UINT_PTR);
|
|
function Find(hWnd: THandle; nIDEvent: UINT_PTR): TQtTimerEx;
|
|
function Get(hWnd: THandle; nIDEvent: UINT_PTR; NotifyFunc: TTimerNotify): TQtTimerEx;
|
|
end;
|
|
|
|
TQtWidgetSetHack = Class(TWidgetSet)
|
|
private
|
|
App: QApplicationH;
|
|
end;
|
|
|
|
var
|
|
FTimerList: TTimerList;
|
|
|
|
{ TQtTimerEx }
|
|
|
|
constructor TQtTimerEx.Create(hWnd: THandle; nIDEvent: UINT_PTR; TimerFunc: TTimerNotify);
|
|
var
|
|
AName: WideString;
|
|
begin
|
|
inherited Create;
|
|
FDeleteLater := True;
|
|
FCallbackFunc := TimerFunc;
|
|
FID := nIDEvent;
|
|
FControl := FindControl(hWnd);
|
|
FHandle := hWnd;
|
|
if hWnd <> 0 then
|
|
begin
|
|
FWidgetHook := QObject_hook_create(TQtWidget(hWnd).TheObject);
|
|
QObject_hook_hook_destroyed(FWidgetHook, @signalWidgetDestroyed);
|
|
end;
|
|
//very big ultra extreme hack to get the app from QtWidgetset
|
|
TheObject := QTimer_create(TQtWidgetSetHack(QtWidgetSet).App);
|
|
AName := 'tqttimerex';
|
|
QObject_setObjectName(TheObject, @AName);
|
|
|
|
AttachEvents;
|
|
end;
|
|
|
|
destructor TQtTimerEx.Destroy;
|
|
begin
|
|
if FWidgetHook <> nil then
|
|
QObject_hook_destroy(FWidgetHook);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TQtTimerEx.AttachEvents;
|
|
begin
|
|
FTimerHook := QTimer_hook_create(QTimerH(TheObject));
|
|
QTimer_hook_hook_timeout(FTimerHook, @signalTimeout);
|
|
inherited AttachEvents;
|
|
end;
|
|
|
|
procedure TQtTimerEx.DetachEvents;
|
|
begin
|
|
QTimer_stop(QTimerH(TheObject));
|
|
if FTimerHook <> nil then
|
|
QTimer_hook_destroy(FTimerHook);
|
|
inherited DetachEvents;
|
|
end;
|
|
|
|
procedure TQtTimerEx.signalWidgetDestroyed; cdecl;
|
|
begin
|
|
Stop;
|
|
FTimerList.Delete(FHandle, FID);
|
|
Destroy;
|
|
end;
|
|
|
|
procedure TQtTimerEx.signalTimeout; cdecl;
|
|
begin
|
|
if Assigned(FCallbackFunc) then
|
|
FCallbackFunc(FID)
|
|
else if Assigned(FControl) then
|
|
begin
|
|
if ([csLoading, csDestroying] * FControl.ComponentState = []) and not
|
|
(csDestroyingHandle in FControl.ControlState) then
|
|
begin
|
|
LCLSendTimerMsg(FControl, FID, 0);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
//orphan timer. Stop.
|
|
//todo: better to remove from the list?
|
|
Stop;
|
|
end;
|
|
end;
|
|
|
|
function TQtTimerEx.EventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl;
|
|
begin
|
|
Result := False;
|
|
QEvent_accept(Event);
|
|
end;
|
|
|
|
procedure TQtTimerEx.Start(Interval: Integer);
|
|
begin
|
|
QTimer_start(QTimerH(TheObject), Interval);
|
|
end;
|
|
|
|
procedure TQtTimerEx.Stop;
|
|
begin
|
|
QTimer_stop(QTimerH(TheObject));
|
|
end;
|
|
|
|
function KillTimer(hWnd: THandle; nIDEvent: UINT_PTR): Boolean;
|
|
var
|
|
TimerObject: TQtTimerEx;
|
|
begin
|
|
Result := True;
|
|
TimerObject := FTimerList.Find(hWnd, nIDEvent);
|
|
if TimerObject <> nil then
|
|
begin
|
|
// DebugLn('KillTimer HWnd: %d ID: %d TimerObject: %d',[hWnd, nIDEvent, PtrInt(TimerObject)]);
|
|
TimerObject.Stop;
|
|
end;
|
|
end;
|
|
|
|
function SetTimer(hWnd: THandle; nIDEvent: UINT_PTR; uElapse: LongWord; lpTimerFunc: TTimerNotify): UINT_PTR;
|
|
var
|
|
TimerObject: TQtTimerEx;
|
|
begin
|
|
TimerObject := FTimerList.Get(hWnd, nIDEvent, lpTimerFunc);
|
|
try
|
|
TimerObject.Start(uElapse);
|
|
if hWnd = 0 then
|
|
Result := PtrInt(TimerObject)
|
|
else
|
|
Result := nIdEvent;
|
|
except
|
|
Result := 0;
|
|
end;
|
|
//DebugLn('SetTimer HWnd: %d ID: %d TimerObject: %d',[hWnd, nIDEvent, PtrInt(TimerObject)]);
|
|
end;
|
|
|
|
function TTimerList.Get(hWnd: THandle; nIDEvent: UINT_PTR; NotifyFunc: TTimerNotify): TQtTimerEx;
|
|
var
|
|
AID: TTimerID;
|
|
begin
|
|
AID.hWnd := hWnd;
|
|
AID.nIDEvent := nIDEvent;
|
|
with FMap do
|
|
begin
|
|
if HasId(AID) then
|
|
begin
|
|
// DebugLn('Reset timer for HWnd: %d ID: %d AID: %d', [hWnd, ID, AID]);
|
|
GetData(AID, Result);
|
|
Result.FCallbackFunc := NotifyFunc;
|
|
end
|
|
else
|
|
begin
|
|
// DebugLn('Create timer for HWnd: %d ID: %d AID: %d', [hWnd, ID, AID]);
|
|
Result := TQtTimerEx.Create(hWnd, nIDEvent, NotifyFunc);
|
|
if hWnd = 0 then
|
|
begin
|
|
AID.nIDEvent := PtrUInt(Result);
|
|
Result.FID := PtrUInt(Result);
|
|
end;
|
|
Add(AID, Result);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
constructor TTimerList.Create;
|
|
begin
|
|
FMap := TMap.Create({$ifdef CPU64}itu16{$else}itu8{$endif}, SizeOf(TQtTimerEx));
|
|
end;
|
|
|
|
destructor TTimerList.Destroy;
|
|
var
|
|
Iterator: TMapIterator;
|
|
TimerObject: TQtTimerEx;
|
|
begin
|
|
Iterator := TMapIterator.Create(FMap);
|
|
with Iterator do
|
|
begin
|
|
while not EOM do
|
|
begin
|
|
GetData(TimerObject);
|
|
TimerObject.Free;
|
|
Next;
|
|
end;
|
|
Destroy;
|
|
end;
|
|
FMap.Destroy;
|
|
end;
|
|
|
|
procedure TTimerList.Delete(hWnd: THandle; nIDEvent: UINT_PTR);
|
|
var
|
|
TimerID: TTimerID;
|
|
begin
|
|
TimerID.hWnd := hWnd;
|
|
TimerID.nIDEvent := nIDEvent;
|
|
FMap.Delete(TimerID);
|
|
end;
|
|
|
|
function TTimerList.Find(hWnd: THandle; nIDEvent: UINT_PTR): TQtTimerEx;
|
|
var
|
|
DataPtr: ^TQtTimerEx;
|
|
TimerID: TTimerID;
|
|
begin
|
|
Result := nil;
|
|
TimerID.hWnd := hWnd;
|
|
TimerID.nIDEvent := nIDEvent;
|
|
// DebugLn('GetTimerObject for HWnd: %d ID: %d AID: %d', [hWnd, nIDEvent, TimerID]);
|
|
DataPtr := FMap.GetDataPtr(TimerID);
|
|
if DataPtr <> nil then
|
|
Result := DataPtr^;
|
|
end;
|
|
|