1
0
mirror of https://github.com/moparisthebest/Simba synced 2024-11-22 01:02:17 -05:00

Fixed bug in getclientdimensions:

In conformance with conventions for the  RECT structure, the bottom-right coordinates of the returned rectangle are exclusive. In other words, the pixel at (right, bottom) lies immediately outside the rectangle.

git-svn-id: http://www.villavu.com/repositories/merlijn/mufasa@23 3f818213-9676-44b0-a9b4-5e4c4e03d09d
This commit is contained in:
Markus 2009-09-04 05:38:37 +00:00
parent 58995711ad
commit 71c7f9bf3d

View File

@ -1,443 +1,443 @@
unit Window; unit Window;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
interface interface
uses uses
Classes, SysUtils, mufasatypes, Classes, SysUtils, mufasatypes,
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
windows, // For windows API windows, // For windows API
{$ENDIF} {$ENDIF}
graphics, graphics,
LCLType, LCLType,
LCLIntf // for ReleaseDC and such LCLIntf // for ReleaseDC and such
{$IFDEF LINUX}, xlib, x, xutil, ctypes{$ENDIF}; {$IFDEF LINUX}, xlib, x, xutil, ctypes{$ENDIF};
type type
{ TMWindow } { TMWindow }
TMWindow = class(TObject) TMWindow = class(TObject)
function ReturnData(xs, ys, width, height: Integer): TRetData; function ReturnData(xs, ys, width, height: Integer): TRetData;
procedure FreeReturnData; procedure FreeReturnData;
procedure GetDimensions(var W, H: Integer); procedure GetDimensions(var W, H: Integer);
function CopyClientToBitmap(xs, ys, xe, ye: integer): TBitmap; function CopyClientToBitmap(xs, ys, xe, ye: integer): TBitmap;
procedure ActivateClient; procedure ActivateClient;
{$IFDEF LINUX} {$IFDEF LINUX}
function SetTarget(XWindow: x.TWindow): integer; overload; function SetTarget(XWindow: x.TWindow): integer; overload;
{$ENDIF} {$ENDIF}
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
function UpdateDrawBitmap:boolean; function UpdateDrawBitmap:boolean;
{$ENDIF} {$ENDIF}
function SetTarget(Window: THandle; NewType: TTargetWindowMode): integer; overload; function SetTarget(Window: THandle; NewType: TTargetWindowMode): integer; overload;
function SetTarget(ArrPtr: PRGB32; Size: TPoint): integer; overload; function SetTarget(ArrPtr: PRGB32; Size: TPoint): integer; overload;
constructor Create(Client: TObject); constructor Create(Client: TObject);
destructor Destroy; override; destructor Destroy; override;
public public
// Reference to client. // Reference to client.
Client: TObject; Client: TObject;
// Target Window Mode. // Target Window Mode.
TargetMode: TTargetWindowMode; TargetMode: TTargetWindowMode;
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
//Target handle; HWND //Target handle; HWND
TargetHandle : Hwnd; TargetHandle : Hwnd;
DrawBmpDataPtr : PRGB32; DrawBmpDataPtr : PRGB32;
//Works on linux as well, test it out //Works on linux as well, test it out
TargetDC : HDC; TargetDC : HDC;
DrawBitmap : TBitmap; DrawBitmap : TBitmap;
DrawBmpW,DrawBmpH : integer; DrawBmpW,DrawBmpH : integer;
{$ENDIF} {$ENDIF}
{$IFDEF LINUX} {$IFDEF LINUX}
// X Display // X Display
XDisplay: PDisplay; XDisplay: PDisplay;
// Connection Number // Connection Number
XConnectionNumber: Integer; XConnectionNumber: Integer;
// X Window // X Window
CurWindow: x.TWindow; CurWindow: x.TWindow;
// Desktop Window // Desktop Window
DesktopWindow: x.TWindow; DesktopWindow: x.TWindow;
// X Screen // X Screen
XScreen: PScreen; XScreen: PScreen;
// X Screen Number // X Screen Number
XScreenNum: Integer; XScreenNum: Integer;
// The X Image pointer. // The X Image pointer.
XWindowImage: PXImage; XWindowImage: PXImage;
{$IFDEF M_MEMORY_DEBUG} {$IFDEF M_MEMORY_DEBUG}
// XImageFreed should be True if there is currently no // XImageFreed should be True if there is currently no
// XImage loaded. If one is loaded, XImageFreed is true. // XImage loaded. If one is loaded, XImageFreed is true.
// If ReturnData is called while XImageFreed is false, // If ReturnData is called while XImageFreed is false,
// we throw an exception. // we throw an exception.
// Same for FreeReturnData with XImageFreed true. // Same for FreeReturnData with XImageFreed true.
XImageFreed: Boolean; XImageFreed: Boolean;
{$ENDIF} {$ENDIF}
{$ELSE} {$ELSE}
{$ENDIF} {$ENDIF}
ArrayPtr: PRGB32; ArrayPtr: PRGB32;
ArraySize: TPoint; ArraySize: TPoint;
end; end;
implementation implementation
uses uses
Client, // For the Client Class Client, // For the Client Class
windowutil, // For utilities such as XImageToRawImage windowutil, // For utilities such as XImageToRawImage
GraphType // For TRawImage GraphType // For TRawImage
; ;
constructor TMWindow.Create(Client: TObject); constructor TMWindow.Create(Client: TObject);
begin begin
inherited Create; inherited Create;
Self.Client := Client; Self.Client := Client;
Self.ArrayPtr := nil; Self.ArrayPtr := nil;
Self.ArraySize := Classes.Point(-1, -1); Self.ArraySize := Classes.Point(-1, -1);
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
Self.DrawBitmap := TBitmap.Create; Self.DrawBitmap := TBitmap.Create;
Self.DrawBitmap.PixelFormat:= pf32bit; Self.DrawBitmap.PixelFormat:= pf32bit;
Self.TargetMode:= w_Window; Self.TargetMode:= w_Window;
Self.TargetHandle:= windows.GetDesktopWindow; Self.TargetHandle:= windows.GetDesktopWindow;
Self.TargetDC:= GetWindowDC(Self.TargetHandle); Self.TargetDC:= GetWindowDC(Self.TargetHandle);
Self.UpdateDrawBitmap; Self.UpdateDrawBitmap;
{$ENDIF} {$ENDIF}
{$IFDEF LINUX} {$IFDEF LINUX}
Self.TargetMode := w_XWindow; Self.TargetMode := w_XWindow;
Self.XDisplay := XOpenDisplay(nil); Self.XDisplay := XOpenDisplay(nil);
if Self.XDisplay = nil then if Self.XDisplay = nil then
begin begin
// throw Exception // throw Exception
end; end;
Self.XConnectionNumber:= ConnectionNumber(Self.XDisplay); Self.XConnectionNumber:= ConnectionNumber(Self.XDisplay);
Self.XScreen := XDefaultScreenOfDisplay(Self.XDisplay); Self.XScreen := XDefaultScreenOfDisplay(Self.XDisplay);
Self.XScreenNum:= DefaultScreen(Self.XDisplay); Self.XScreenNum:= DefaultScreen(Self.XDisplay);
// The Root Window is the Desktop. :-) // The Root Window is the Desktop. :-)
Self.DesktopWindow:= RootWindow(Self.XDisplay, Self.XScreenNum); Self.DesktopWindow:= RootWindow(Self.XDisplay, Self.XScreenNum);
Self.CurWindow:= Self.DesktopWindow; Self.CurWindow:= Self.DesktopWindow;
{$ENDIF} {$ENDIF}
end; end;
destructor TMWindow.Destroy; destructor TMWindow.Destroy;
begin begin
{$IFDEF LINUX} {$IFDEF LINUX}
XCloseDisplay(Self.XDisplay); XCloseDisplay(Self.XDisplay);
{$ENDIF} {$ENDIF}
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
if TargetMode = w_Window then if TargetMode = w_Window then
ReleaseDC(TargetHandle,TargetDC); ReleaseDC(TargetHandle,TargetDC);
DrawBitmap.Free; DrawBitmap.Free;
{$ENDIF} {$ENDIF}
inherited; inherited;
end; end;
function TMWindow.ReturnData(xs, ys, width, height: Integer): TRetData; function TMWindow.ReturnData(xs, ys, width, height: Integer): TRetData;
var var
{$IFDEF LINUX} {$IFDEF LINUX}
Old_Handler: TXErrorHandler; Old_Handler: TXErrorHandler;
{$ENDIF} {$ENDIF}
TmpData: PRGB32; TmpData: PRGB32;
begin begin
case Self.TargetMode of case Self.TargetMode of
w_Window: w_Window:
begin begin
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
BitBlt(Self.DrawBitmap.Canvas.Handle,0,0, width, height, Self.TargetDC, xs,ys, SRCCOPY); BitBlt(Self.DrawBitmap.Canvas.Handle,0,0, width, height, Self.TargetDC, xs,ys, SRCCOPY);
Result.Ptr:= Self.DrawBmpDataPtr; Result.Ptr:= Self.DrawBmpDataPtr;
Result.IncPtrWith:= DrawBmpW - Width; Result.IncPtrWith:= DrawBmpW - Width;
{$ENDIF} {$ENDIF}
end; end;
w_XWindow: w_XWindow:
begin begin
{$IFDEF LINUX} {$IFDEF LINUX}
{ Should be this. } { Should be this. }
Old_Handler := XSetErrorHandler(@MufasaXErrorHandler); Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
Self.XWindowImage := XGetImage(Self.XDisplay, Self.curWindow, xs, ys, width, height, AllPlanes, ZPixmap); Self.XWindowImage := XGetImage(Self.XDisplay, Self.curWindow, xs, ys, width, height, AllPlanes, ZPixmap);
if QWord(Self.XWindowImage) = 0 then if QWord(Self.XWindowImage) = 0 then
begin begin
Writeln('ReturnData: XGetImage Error. Dumping data now:'); Writeln('ReturnData: XGetImage Error. Dumping data now:');
Writeln('xs, ys, width, height: ' + inttostr(xs) + ', ' + inttostr(ys) + Writeln('xs, ys, width, height: ' + inttostr(xs) + ', ' + inttostr(ys) +
', ' + inttostr(width) + ', ' + inttostr(height)); ', ' + inttostr(width) + ', ' + inttostr(height));
Result.Ptr := nil; Result.Ptr := nil;
Result.IncPtrWith := 0; Result.IncPtrWith := 0;
XSetErrorHandler(Old_Handler); XSetErrorHandler(Old_Handler);
Exit; Exit;
end; end;
WriteLn(IntToStr(Self.XWindowImage^.width) + ', ' + IntToStr(Self.XWindowImage^.height)); WriteLn(IntToStr(Self.XWindowImage^.width) + ', ' + IntToStr(Self.XWindowImage^.height));
Result.Ptr := PRGB32(Self.XWindowImage^.data); Result.Ptr := PRGB32(Self.XWindowImage^.data);
Result.IncPtrWith := 0; Result.IncPtrWith := 0;
XSetErrorHandler(Old_Handler); XSetErrorHandler(Old_Handler);
{$ELSE} {$ELSE}
WriteLn('Windows doesn''t support XImage'); WriteLn('Windows doesn''t support XImage');
{$ENDIF} {$ENDIF}
end; end;
w_ArrayPtr: w_ArrayPtr:
begin begin
TmpData := Self.ArrayPtr; TmpData := Self.ArrayPtr;
Inc(TmpData, ys * Height + xs); Inc(TmpData, ys * Height + xs);
Result.Ptr := TmpData; Result.Ptr := TmpData;
Result.IncPtrWith:= Self.ArraySize.x - width; Result.IncPtrWith:= Self.ArraySize.x - width;
end; end;
end; end;
end; end;
procedure TMWindow.FreeReturnData; procedure TMWindow.FreeReturnData;
begin begin
if Self.TargetMode <> w_XWindow then if Self.TargetMode <> w_XWindow then
begin begin
// throw exception. // throw exception.
exit; exit;
end; end;
{$IFDEF LINUX} {$IFDEF LINUX}
if(QWord(Self.XWindowImage) <> 0) then // 0, nil? if(QWord(Self.XWindowImage) <> 0) then // 0, nil?
begin begin
XDestroyImage(Self.XWindowImage); XDestroyImage(Self.XWindowImage);
end; end;
{$ENDIF} {$ENDIF}
end; end;
// Bugged. For params other than 0, 0, ClientWidth, ClientHeight // Bugged. For params other than 0, 0, ClientWidth, ClientHeight
// if other type than w_XImage // if other type than w_XImage
// Also thread bugged // Also thread bugged
function TMWindow.CopyClientToBitmap(xs, ys, xe, ye: integer): TBitmap; function TMWindow.CopyClientToBitmap(xs, ys, xe, ye: integer): TBitmap;
var var
w,h : Integer; w,h : Integer;
ww, hh: Integer; ww, hh: Integer;
Raw: TRawImage; Raw: TRawImage;
Bmp: TBitmap; Bmp: TBitmap;
{$IFDEF LINUX} {$IFDEF LINUX}
Old_Handler: TXErrorHandler; Old_Handler: TXErrorHandler;
Img: PXImage; Img: PXImage;
{$ENDIF} {$ENDIF}
begin begin
Self.GetDimensions(w, h); Self.GetDimensions(w, h);
writeln(inttostr(xs) + ', ' + inttostr(ys) + ' : ' + inttostr(xe) + ', ' + writeln(inttostr(xs) + ', ' + inttostr(ys) + ' : ' + inttostr(xe) + ', ' +
inttostr(ye)); inttostr(ye));
ww := xe-xs; ww := xe-xs;
hh := ye-ys; hh := ye-ys;
if(xs < 0) or (ys < 0) or (xe > W) or (ye > H) then if(xs < 0) or (ys < 0) or (xe > W) or (ye > H) then
begin begin
writeln('Faulty coordinates'); writeln('Faulty coordinates');
exit; exit;
end; end;
case Self.TargetMode Of case Self.TargetMode Of
w_Window: w_Window:
begin begin
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
Result := TBitmap.Create; Result := TBitmap.Create;
Result.SetSize(ww+1,hh+1); Result.SetSize(ww+1,hh+1);
BitBlt(result.canvas.handle,0,0,ww+1,hh+1, BitBlt(result.canvas.handle,0,0,ww+1,hh+1,
self.TargetDC,xs,ys, SRCCOPY); self.TargetDC,xs,ys, SRCCOPY);
{$ENDIF} {$ENDIF}
end; end;
w_XWindow: w_XWindow:
begin begin
{$IFDEF LINUX} {$IFDEF LINUX}
Old_Handler := XSetErrorHandler(@MufasaXErrorHandler); Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
Img := XGetImage(Self.XDisplay, Self.curWindow, xs, ys, ww, hh, AllPlanes, ZPixmap); Img := XGetImage(Self.XDisplay, Self.curWindow, xs, ys, ww, hh, AllPlanes, ZPixmap);
XImageToRawImage(Img, Raw); XImageToRawImage(Img, Raw);
Bmp := TBitmap.Create; Bmp := TBitmap.Create;
Bmp.LoadFromRawImage(Raw, False); Bmp.LoadFromRawImage(Raw, False);
Result := Bmp; Result := Bmp;
{ {
If you want to use some internal Bitmap system, BitBlt to it here. If you want to use some internal Bitmap system, BitBlt to it here.
Don't forget to free Bmp! Don't forget to free Bmp!
} }
//lclintf.BitBlt(Bmps[bitmap].Canvas.Handle, 0, 0, ww + 1, hh + 1, Bmp.Canvas.Handle, xs, ys, SRCCOPY); //lclintf.BitBlt(Bmps[bitmap].Canvas.Handle, 0, 0, ww + 1, hh + 1, Bmp.Canvas.Handle, xs, ys, SRCCOPY);
//Bmp.Free; //Bmp.Free;
XDestroyImage(Img); XDestroyImage(Img);
XSetErrorHandler(Old_Handler); XSetErrorHandler(Old_Handler);
{$ELSE} {$ELSE}
writeln('Windows and tXWindow'); writeln('Windows and tXWindow');
{$ENDIF} {$ENDIF}
end; end;
w_ArrayPtr: w_ArrayPtr:
begin begin
ArrDataToRawImage(Self.ArrayPtr, Self.ArraySize, Raw); ArrDataToRawImage(Self.ArrayPtr, Self.ArraySize, Raw);
Bmp := TBitmap.Create; Bmp := TBitmap.Create;
Bmp.LoadFromRawImage(Raw, False); Bmp.LoadFromRawImage(Raw, False);
Result := Bmp; Result := Bmp;
end; end;
end; end;
end; end;
procedure TMWindow.ActivateClient; procedure TMWindow.ActivateClient;
begin begin
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
if TargetMode = w_Window then if TargetMode = w_Window then
SetForegroundWindow(Self.TargetHandle); SetForegroundWindow(Self.TargetHandle);
{$ENDIF} {$ENDIF}
{$IFDEF LINUX} {$IFDEF LINUX}
if TargetMode = w_XWindow then if TargetMode = w_XWindow then
XSetInputFocus(Self.XDisplay,Self.CurWindow,RevertToParent,CurrentTime); XSetInputFocus(Self.XDisplay,Self.CurWindow,RevertToParent,CurrentTime);
{$ENDIF} {$ENDIF}
end; end;
{$IFDEF MSWINDOWS} //Probably need one for Linux as well {$IFDEF MSWINDOWS} //Probably need one for Linux as well
function TMWindow.UpdateDrawBitmap :boolean; function TMWindow.UpdateDrawBitmap :boolean;
var var
w,h : integer; w,h : integer;
BmpInfo : Windows.TBitmap; BmpInfo : Windows.TBitmap;
begin begin
GetDimensions(w,h); GetDimensions(w,h);
DrawBitmap.SetSize(w,h); DrawBitmap.SetSize(w,h);
// DrawBitmap.PixelFormat:= // DrawBitmap.PixelFormat:=
DrawBmpW := w; DrawBmpW := w;
DrawBmpH := h; DrawBmpH := h;
GetObject(DrawBitmap.Handle, SizeOf(BmpInfo), @BmpInfo); GetObject(DrawBitmap.Handle, SizeOf(BmpInfo), @BmpInfo);
DrawBmpDataPtr := BmpInfo.bmBits; DrawBmpDataPtr := BmpInfo.bmBits;
end; end;
{$ENDIF} {$ENDIF}
procedure TMWindow.GetDimensions(var W, H: Integer); procedure TMWindow.GetDimensions(var W, H: Integer);
{$IFDEF LINUX} {$IFDEF LINUX}
var var
Attrib: TXWindowAttributes; Attrib: TXWindowAttributes;
newx,newy : integer; newx,newy : integer;
childwindow : x.TWindow; childwindow : x.TWindow;
Old_Handler: TXErrorHandler; Old_Handler: TXErrorHandler;
{$ENDIF} {$ENDIF}
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
var var
Rect : TRect; Rect : TRect;
{$ENDIF} {$ENDIF}
begin begin
case TargetMode of case TargetMode of
w_Window: w_Window:
begin begin
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
GetWindowRect(Self.TargetHandle, Rect); GetWindowRect(Self.TargetHandle, Rect);
w:= Rect.Right - Rect.left + 1; w:= Rect.Right - Rect.left;
h:= Rect.Bottom - Rect.Top + 1; h:= Rect.Bottom - Rect.Top;
{$ENDIF} {$ENDIF}
end; end;
w_XWindow: w_XWindow:
begin begin
{$IFDEF LINUX} {$IFDEF LINUX}
Old_Handler := XSetErrorHandler(@MufasaXErrorHandler); Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
if XGetWindowAttributes(Self.XDisplay, Self.CurWindow, @Attrib) <> 0 Then if XGetWindowAttributes(Self.XDisplay, Self.CurWindow, @Attrib) <> 0 Then
begin begin
XTranslateCoordinates(Self.XDisplay, Self.CurWindow, Self.DesktopWindow, 0,0, @newx, @newy, @childwindow); XTranslateCoordinates(Self.XDisplay, Self.CurWindow, Self.DesktopWindow, 0,0, @newx, @newy, @childwindow);
W := Attrib.Width; W := Attrib.Width;
H := Attrib.Height; H := Attrib.Height;
end else end else
begin begin
W := -1; W := -1;
H := -1; H := -1;
end; end;
XSetErrorHandler(Old_Handler); XSetErrorHandler(Old_Handler);
{$ELSE} {$ELSE}
WriteLn('You dummy! How are you going to use w_XWindow on non Linux systems?'); WriteLn('You dummy! How are you going to use w_XWindow on non Linux systems?');
{$ENDIF} {$ENDIF}
end; end;
w_ArrayPtr: w_ArrayPtr:
begin begin
W := Self.ArraySize.X; W := Self.ArraySize.X;
H := Self.ArraySize.Y; H := Self.ArraySize.Y;
end; end;
end; end;
end; end;
{$IFDEF LINUX} {$IFDEF LINUX}
function TMWindow.SetTarget(XWindow: x.TWindow): integer; overload; function TMWindow.SetTarget(XWindow: x.TWindow): integer; overload;
var var
Old_Handler: TXErrorHandler; Old_Handler: TXErrorHandler;
begin begin
Old_Handler := XSetErrorHandler(@MufasaXErrorHandler); Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
Self.CurWindow := XWindow; Self.CurWindow := XWindow;
Self.TargetMode:= w_XWindow; Self.TargetMode:= w_XWindow;
XSetErrorHandler(Old_Handler); XSetErrorHandler(Old_Handler);
end; end;
{$ENDIF} {$ENDIF}
function TMWindow.SetTarget(Window: THandle; NewType: TTargetWindowMode): integer; overload; function TMWindow.SetTarget(Window: THandle; NewType: TTargetWindowMode): integer; overload;
begin begin
if NewType in [ w_XWindow, w_ArrayPtr ] then if NewType in [ w_XWindow, w_ArrayPtr ] then
begin begin
// throw exception // throw exception
Exit; Exit;
end; end;
case NewType of case NewType of
w_Window : w_Window :
begin; begin;
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
ReleaseDC(Self.TargetHandle,Self.TargetDC); ReleaseDC(Self.TargetHandle,Self.TargetDC);
Self.TargetHandle := Window; Self.TargetHandle := Window;
Self.TargetDC := GetWindowDC(Window); Self.TargetDC := GetWindowDC(Window);
{$ENDIF} {$ENDIF}
end; end;
end; end;
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
UpdateDrawBitmap; UpdateDrawBitmap;
{$ENDIF} {$ENDIF}
end; end;
{ {
This functionality is very BETA. This functionality is very BETA.
We have no way to send events to a window, so we should probably use the We have no way to send events to a window, so we should probably use the
desktop window? desktop window?
eg: In mouse/keys: if Self.TargetMode not in [w_Window, w_XWindow], send it eg: In mouse/keys: if Self.TargetMode not in [w_Window, w_XWindow], send it
to the desktop. to the desktop.
} }
function TMWindow.SetTarget(ArrPtr: PRGB32; Size: TPoint): integer; overload; function TMWindow.SetTarget(ArrPtr: PRGB32; Size: TPoint): integer; overload;
begin begin
Self.ArrayPtr := ArrPtr; Self.ArrayPtr := ArrPtr;
Self.ArraySize := Size; Self.ArraySize := Size;
Self.TargetMode:= w_ArrayPtr; Self.TargetMode:= w_ArrayPtr;
{$IFDEF LINUX} {$IFDEF LINUX}
Self.CurWindow := Self.DesktopWindow; Self.CurWindow := Self.DesktopWindow;
{$ENDIF} {$ENDIF}
{$IFDEF WINDOWS} {$IFDEF WINDOWS}
Self.TargetHandle:= windows.GetDesktopWindow; Self.TargetHandle:= windows.GetDesktopWindow;
{$ENDIF} {$ENDIF}
end; end;
end. end.