Модуль еще не совсем завершен.
Отметки:
Теоретически готоввый код
//
Не готовый код, нв таком виде, как он есть, его можно использовать, но дописать все равно нужно
//-
Код, который нужно обязательно дописать, прежде чем использовать
//--
код, в котором я абсолютно не уверен
//Need Testing!
Описание:
В проекте не должно быть обращений к специфичным функциям ОС. Все обращения только через функции с префиксом OSAL_.
OSAL_GlCreateWindow - создание GL окна. Либо через wgl(Windows), либо через glx(linux)
CALLBACK_MESSAGE - процедура, которая вызывается для обработки сообщений. Пока обрабатывает только Resize окна.
Эту процедуру нужно инициализировать в самом начале. Иначе проект упадет при первом же обращении к ней.
У меня это выглядит так:
- Код: Выделить всё
Procedure ProcessMessage(Msg:integer; wParam: integer; lParam: integer); extdecl;
begin
case Msg of
OSAL_MESSAGE_RESIZE: begin
glResizeWnd(wParam,lParam);
end;
end;
end;
begin
CALLBACK_MESSAGES:=ProcessMessage;
end.
OSAL_UpdateWNDMessages - вызов обработки сообщений. Это примерно тоже самое что Application.ProcessMessages в Delphi/Lazarus. Крутится пока не обработает все сообщения, потом выход. Это НЕ циклическая обработка.
У меня выглядит примерно так:
- Код: Выделить всё
while not finished do begin
OSAL_UpdateWNDMessages;
//Расчет кадра
end;
glKillWindow - грохает окно.
Модуль Data, который требуется для работы модуля - содержит следующий код:
- Код: Выделить всё
{$ifdef windows}
h_DC:HDC;
h_RC:HGLRC;
h_Wnd:HWND;
{$else}
hXDisplay: PDisplay;
hglXContext: GLXContext;
hXWindow: TWindow;
hXVisualInfo: PXVisualInfo;
{$endif}
finished:boolean = false;
Вот собственно код модуля. Просьба сильно не пиннать, делается все в очень сжатые сроки, рефакторить буду, когда все работать будет.
- Код: Выделить всё
{$MACRO ON}
{$IFDEF Windows}
{$DEFINE extdecl := stdcall}
{$ELSE}
{$DEFINE extdecl := cdecl}
{$ENDIF}
unit uOSAL;
interface
uses
{$ifdef win32}
windows, ShellAPI,
{$else}
libc,
glx,unix,x,xlib,xutil,
{$endif}
{$ifdef FPC}
gl,
{$else}
OpenGL,
{$endif}
Types
;
{$ifdef win32}
type HDC = windows.HDC;
type HGLRC = windows.HGLRC;
type HWND = windows.HWND;
{$else}
type HDC = integer;
type HGLRC = integer;
type HWND = integer;
{$endif}
{ type TRect = record
Left,Right,Top,Bottom:integer;
end;
type TPoint = record
X,Y:integer;
end; }
const
VK_LBUTTON = 1;
VK_RBUTTON = 2;
VK_TAB = 9;
VK_BACK = 19; //!!!BACKSPACE!!!
VK_ESCAPE = 27;
VK_SPACE = 32;
VK_RETURN = 13;
Function OSAL_GetScreenWidth:integer;
Function OSAL_GetScreenHeight:integer;
Procedure OSAL_CopyMemory(Dst,Src:Pointer; Length:integer);
Procedure OSAL_ZeroMemory(Dst:Pointer; Length:integer);
Function OSAL_isKeyBoardLayoutRussian:boolean;
Function OSAL_GetKeyState(Key:byte):boolean;
Procedure OSAL_ShowMouse(Show:boolean);
Procedure OSAL_SetWorldMousePos(X,Y:integer);
Function OSAL_GetWorldMousePos:TPoint;
Function OSAL_GetWindowMousePos:TPoint;
Procedure OSAL_SetFocus();
Procedure OSAL_SetForeground();
Function OSAL_isOnFocus:boolean;
Function OSAL_GetTextSize(const Text:string):TPoint;
procedure OSAL_SwapBuffers;
procedure OSAL_ExecuteWebPage(const URL:String);
procedure OSAL_ExecuteFile(const FileName:String);
procedure OSAL_ExecuteExe(const FileName,Param:String);
Function OSAL_GetWindowPos:TPoint;
Function OSAL_GetWindowClientSize:TPoint;
Procedure OSAL_SetWindowPos(X,Y, Width, Height: integer);
Procedure OSAL_SetWindowText(const Text:String);
function OSAL_glCreateWnd(Width, Height : Integer; Fullscreen : Boolean; PixelDepth : Integer; const Title:string) : Boolean;
procedure OSAL_glKillWnd(Fullscreen : Boolean);
procedure OSAL_UpdateWNDMessages;
Procedure OSAL_Sleep(TimeForSleep:integer);
Procedure OSAL_InitCounter;
Function OSAL_GetCounterValue:int64;
const
OSAL_MESSAGE_RESIZE = 0; //wParam - Width, lParam - Height
var
CALLBACK_MESSAGES: procedure(Msg:integer; wParam: integer; lParam: integer); extdecl;
implementation
uses Data;
var
Keys:array[0..255] of boolean; //Key States array for X System
MousePos:TPoint;
WndX,WndY,WndWidth,WndHeight:integer;
function OSAL_GetScreenWidth: integer; //
begin
{$ifdef win32}
Result:=GetSystemMetrics(SM_CXSCREEN);
{$else}
Result:=XDisplayWidth(hXDisplay,0);
{$endif}
end;
function OSAL_GetScreenHeight: integer; //
begin
{$ifdef win32}
Result:=GetSystemMetrics(SM_CYSCREEN);
{$else}
Result:=XDisplayHeight(hXDisplay,0);
{$endif}
end;
Function OSAL_isKeyBoardLayoutRussian:boolean; //-
begin
{$ifdef win32}
Result:=($000000FF and (GetKeyboardLayout(0))) = LANG_RUSSIAN;
{$else}
Result:=false;
{$endif}
end;
Function OSAL_GetKeyState(Key:byte):boolean; //
begin
{$ifdef win32}
Result:=GetAsyncKeyState(Key) And $8000<>0;
{$else}
Result:=Keys[Key];
{$endif}
end;
procedure OSAL_ShowMouse(Show: boolean); //--
begin
{$ifdef win32}
ShowCursor(Show);
{$else}
{$endif}
end;
Procedure OSAL_SetWorldMousePos(X,Y:integer); // //Need Testing!
begin
{$ifdef win32}
SetCursorPos(X,Y);
{$else}
XWarpPointer(hXDisplay,0, hXWindow,0,0,0,0,X-WndX,Y-WndY);
{$endif}
end;
Function OSAL_GetWorldMousePos:TPoint; //
begin
{$ifdef win32}
GetCursorPos(Result);
{$else}
Result.X:=MousePos.X+WndX;
Result.Y:=MousePos.Y+WndY;
{$endif}
end;
Function OSAL_GetWindowMousePos:TPoint; //
begin
{$ifdef win32}
GetCursorPos(Result);
ScreenToClient(h_Wnd,Result);
{$else}
Result:=MousePos;
{$endif}
end;
procedure OSAL_SetFocus(); //-
begin
{$ifdef win32}
SetFocus(h_Wnd);
{$else}
{$endif}
end;
procedure OSAL_SetForeground(); //-
begin
{$ifdef win32}
SetForegroundWindow(h_Wnd);
{$else}
{$endif}
end;
function OSAL_isOnFocus: boolean; //-
begin
{$ifdef win32}
Result:= GetFocus = h_Wnd;
{$else}
Result:=true;
{$endif}
end;
Function OSAL_GetTextSize(const Text:string):TPoint; //--
{$ifdef win32}
var
Size:TSize;
begin
GetTextExtentPoint32(h_Dc,PChar(Text),Length(Text),Size);
Result.x:=Size.cx;
Result.y:=Size.cy;
end;
{$else}
begin
Result.x:=0;
Result.y:=0;
end;
{$endif}
procedure OSAL_SwapBuffers; //
begin
{$ifdef win32}
SwapBuffers(h_DC);
{$else}
glXSwapBuffers(hXDisplay, hXWindow);
{$endif}
end;
procedure OSAL_ExecuteWebPage(const URL:String); //-
begin
{$ifdef win32}
ShellExecute(0,Pchar('open'),PChar(URL),nil,nil,SW_NORMAL);
{$else}
{$endif}
end;
procedure OSAL_ExecuteFile(const FileName: String); //-
begin
{$ifdef win32}
ShellExecute(0,'open',PChar(FileName),'','',SW_SHOW);
{$else}
{$endif}
end;
procedure OSAL_ExecuteExe(const FileName, Param: String); //-
begin
{$ifdef win32}
ShellExecute(0,'open',PChar(FileName),PChar(Param),'',SW_NORMAL);
{$else}
{$endif}
end;
function OSAL_GetWindowPos: TPoint; //-
{$ifdef win32}
var
WndPlace:TWindowPlacement;
begin
GetWindowPlacement(h_Wnd,@WndPlace);
Result:=WndPlace.rcNormalPosition;
end;
{$else}
begin
Result.X:=WndX;
Result.Y:=WndY;
end;
{$endif}
{$ifdef win32}
procedure OSAL_glKillWnd(Fullscreen : Boolean); //-
begin
if Fullscreen then
begin
ChangeDisplaySettings(devmode(nil^), 0);
ShowCursor(True);
end;
if (not wglMakeCurrent(h_DC, 0)) then
begin
MessageBox(0, 'Release of DC and RC failed!', 'Error', MB_OK or MB_ICONERROR);
end;
if (not wglDeleteContext(h_RC)) then
begin
MessageBox(0, 'Release of rendering context failed!', 'Error', MB_OK or MB_ICONERROR);
h_RC := 0;
end;
if ((h_DC > 0) and (ReleaseDC(h_Wnd, h_DC) = 0)) then
begin
MessageBox(0, 'Release of device context failed!', 'Error', MB_OK or MB_ICONERROR);
h_DC := 0;
end;
if ((h_Wnd <> 0) and (not DestroyWindow(h_Wnd))) then
begin
MessageBox(0, 'Unable to destroy window!', 'Error', MB_OK or MB_ICONERROR);
h_Wnd := 0;
end;
if (not Windows.UnRegisterClass('OpenGL', hInstance)) then
begin
MessageBox(0, 'Unable to unregister window class!', 'Error', MB_OK or MB_ICONERROR);
//hInstance := 0;
end;
end;
{$else}
procedure OSAL_glKillWnd(Fullscreen : Boolean);
begin
glXDestroyContext(hXDisplay, hglXContext);
XDestroyWindow(hXDisplay, hXWindow);
XCloseDisplay(hXDisplay);
end;
{$endif}
procedure OSAL_UpdateWNDMessages; //
{$ifdef win32}
var
Msg:TMessage;
begin
while (PeekMessage(msg, 0, 0, 0, PM_REMOVE)) do begin
if (msg.message = WM_QUIT) then
finished := True
else
begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
end;
end;
{$else}
var
Event:TXEvent;
begin
while XPending(hXDisplay)>0 do begin
XNextEvent(hXDisplay, @Event);
case Event._type of
KeyPress: begin
Keys[XLookupKeysym(@event, 0)]:=true; //Need Testing!
end;
KeyRelease: begin
Keys[XLookupKeysym(@event, 0)]:=false; //Need Testing!
end;
ButtonPress: begin
case event.xbutton.button of //Need Testing!
0:Keys[1]:=true;
1:Keys[2]:=true;
2:Keys[3]:=true;
end;
end;
ButtonRelease:begin
case event.xbutton.button of //Need Testing!
0:Keys[1]:=false;
1:Keys[2]:=false;
2:Keys[3]:=false;
end;
end;
MotionNotify: begin
MousePos.X:=Event.xmotion.x;
MousePos.Y:=Event.xmotion.y;
end;
ConfigureNotify:begin
CALLBACK_MESSAGES(OSAL_MESSAGE_RESIZE,Event.xconfigure.width,Event.xconfigure.height);
WndX:=Event.xconfigure.x;
WndY:=Event.xconfigure.y;
WndWidth:=Event.xconfigure.width;
WndHeight:=Event.xconfigure.height;
end;
end;
end;
end;
procedure OSAL_Sleep(TimeForSleep: integer); //
begin
{$ifdef win32}
Sleep(TimeForSleep);
{$else}
usleep(TimeForSleep);
{$endif}
end;
var
TimerFreq:int64;
Procedure OSAL_InitCounter; //
begin
{$ifdef win32}
QueryPerformanceFrequency(TimerFreq);
TimerFreq:=TimerFreq div 1000;
{$else}
{$endif}
end;
function OSAL_GetCounterValue: int64; //
{$ifdef win32}
begin
QueryPerformanceCounter(Result);
Result:=Result div TimerFreq;
end;
{$else}
var
tp:Ttimeval;
tpz:Ttimezone;
begin
gettimeofday(@tp,@tpz);
Result:=tp.tv_usec;
end;
{$endif}
Procedure OSAL_CopyMemory(Dst,Src:Pointer; Length:integer); //
begin
{$ifdef win32}
CopyMemory(Dst,Src,Length);
{$else}
memcpy(Dst,Src,Length);
{$endif}
end;
procedure OSAL_ZeroMemory(Dst: Pointer; Length: integer); //
begin
{$ifdef win32}
ZeroMemory(Dst,Length);
{$else}
memset(Dst,0,Length);
{$endif}
end;
{$endif}
Procedure OSAL_SetWindowText(const Text:String); //
{$ifdef win32}
begin
SetWindowText(h_Wnd,PChar(Text));
end;
{$else}
var
window_title_property: TXTextProperty;
begin
XStringListToTextProperty(@Text,1,@window_title_property);
XSetWMName(hXDisplay,hXWindow,@window_title_property);
end;
{$endif}
{$ifdef win32}
function WndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
case (Msg) of
WM_CLOSE:
begin
PostQuitMessage(0);
Result := 1;
end;
{ WM_ACCEPT:
begin
if LanServer<>nil then
Result:=LanServer.WMSERVER(hWnd,Msg,WParam, LParam)
else
Result := 0;
end;
WM_SERVER:
begin
if LanServer<>nil then
Result:=LanServer.WMSCLIENT(hWnd,Msg,WParam, LParam)
else
Result := 0;
end;
WM_CLIENT:
begin
if LanClient<>nil then
Result:=LanClient.WMCLIENT(hWnd,Msg,WParam, LParam)
else
Result := 0;
end; }
WM_SIZE:
begin
CALLBACK_MESSAGES(OSAL_MESSAGE_RESIZE,LOWORD(lParam),HIWORD(lParam));
Result := 0;
end;
else
Result := DefWindowProc(hWnd, Msg, wParam, lParam);
end;
end;
function glCreateWnd(Width, Height : Integer; Fullscreen : Boolean; PixelDepth : Integer; const Title:string) : Boolean;
var
wndClass : TWndClass; // Window class
dwStyle : DWORD; // Window styles
dwExStyle : DWORD; // Extended window styles
dmScreenSettings : DEVMODE; // Screen settings (fullscreen, etc...)
PixelFormat : GLuint; // Settings for the OpenGL rendering
h_Instance : HINST; // Current instance
pfd : TPIXELFORMATDESCRIPTOR; // Settings for the OpenGL window
begin
h_Instance := GetModuleHandle(nil); //Grab An Instance For Our Window
ZeroMemory(@wndClass, SizeOf(wndClass)); // Clear the window class structure
with wndClass do // Set up the window class
begin
style := CS_HREDRAW or // Redraws entire window if length changes
CS_VREDRAW or // Redraws entire window if height changes
CS_OWNDC; // Unique device context for the window
lpfnWndProc := @WndProc; // Set the window procedure to our func WndProc
hInstance := h_Instance;
hCursor := LoadCursor(0, IDC_ARROW);
hIcon := LoadIcon(h_Instance,'MAINICON');
lpszClassName := 'OpenGL';
end;
if (Windows.RegisterClass(wndClass) = 0) then // Attemp to register the window class
begin
MessageBox(0, 'Failed to register the window class!', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit
end;
if Fullscreen then
begin
ZeroMemory(@dmScreenSettings, SizeOf(dmScreenSettings));
with dmScreenSettings do begin // Set parameters for the screen setting
dmSize := SizeOf(dmScreenSettings);
dmPelsWidth := Width; // Window width
dmPelsHeight := Height; // Window height
dmBitsPerPel := PixelDepth; // Window color depth
dmFields := DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL;
end;
if (ChangeDisplaySettings(dmScreenSettings, CDS_FULLSCREEN) = DISP_CHANGE_FAILED) then
begin
MessageBox(0, 'Unable to switch to fullscreen!', 'Error', MB_OK or MB_ICONERROR);
Fullscreen := False;
end;
end;
if (Fullscreen) then
begin
dwStyle := WS_POPUP or // Creates a popup window
WS_CLIPCHILDREN // Doesn't draw within child windows
or WS_CLIPSIBLINGS; // Doesn't draw within sibling windows
dwExStyle := WS_EX_APPWINDOW or WS_EX_TOPMOST; // Top level window
end
else
begin
dwStyle := // Creates an overlapping window
WS_CLIPCHILDREN or // Doesn't draw within child windows
WS_CLIPSIBLINGS or WS_SYSMENU or WS_MINIMIZEBOX{ or // Doesn't draw within sibling windows
WS_POPUP};
dwExStyle := WS_EX_APPWINDOW;{ or // Top level window
WS_EX_WINDOWEDGE; // Border with a raised edge}
end;
h_Wnd := CreateWindowEx(dwExStyle, // Extended window styles
'OpenGL', // Class name
PChar(Title), // Window title (caption)
dwStyle, // Window styles
0, 0, // Window position
Width, Height, // Size of window
0, // No parent window
0, // No menu
h_Instance, // Instance
nil); // Pass nothing to WM_CREATE
if h_Wnd = 0 then
begin
glKillWnd(Fullscreen); // Undo all the settings we've changed
MessageBox(0, 'Unable to create window!', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;
h_DC := GetDC(h_Wnd);
if (h_DC = 0) then
begin
glKillWnd(Fullscreen);
MessageBox(0, 'Unable to get a device context!', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;
with pfd do
begin
nSize := SizeOf(TPIXELFORMATDESCRIPTOR); // Size Of This Pixel Format Descriptor
nVersion := 1; // The version of this data structure
dwFlags := PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER or PFD_GENERIC_ACCELERATED; // Supports double buffering
iPixelType := PFD_TYPE_RGBA; // RGBA color format
cColorBits := PixelDepth; // OpenGL color depth
cRedBits := 0; // Number of red bitplanes
cRedShift := 0; // Shift count for red bitplanes
cGreenBits := 0; // Number of green bitplanes
cGreenShift := 0; // Shift count for green bitplanes
cBlueBits := 0; // Number of blue bitplanes
cBlueShift := 0; // Shift count for blue bitplanes
cAlphaBits := 0; // Not supported
cAlphaShift := 0; // Not supported
cAccumBits := 0; // No accumulation buffer
cAccumRedBits := 0; // Number of red bits in a-buffer
cAccumGreenBits := 0; // Number of green bits in a-buffer
cAccumBlueBits := 0; // Number of blue bits in a-buffer
cAccumAlphaBits := 0; // Number of alpha bits in a-buffer
cDepthBits := 8; // Specifies the depth of the depth buffer
cStencilBits := 32; // Turn off stencil buffer
cAuxBuffers := 0; // Not supported
iLayerType := PFD_MAIN_PLANE; // Ignored
bReserved := 0; // Number of overlay and underlay planes
dwLayerMask := 0; // Ignored
dwVisibleMask := 0; // Transparent color of underlay plane
dwDamageMask := 0; // Ignored
end;
PixelFormat := ChoosePixelFormat(h_DC, @pfd);
if (PixelFormat = 0) then
begin
glKillWnd(Fullscreen);
MessageBox(0, 'Unable to find a suitable pixel format', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;
if (not SetPixelFormat(h_DC, PixelFormat, @pfd)) then
begin
glKillWnd(Fullscreen);
MessageBox(0, 'Unable to set the pixel format', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;
h_RC := wglCreateContext(h_DC);
if (h_RC = 0) then
begin
glKillWnd(Fullscreen);
MessageBox(0, 'Unable to create an OpenGL rendering context', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;
if (not wglMakeCurrent(h_DC, h_RC)) then
begin
glKillWnd(Fullscreen);
MessageBox(0, 'Unable to activate OpenGL rendering context', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;
//SetTimer(h_Wnd, FPS_TIMER, FPS_INTERVAL, nil);
ShowWindow(h_Wnd, SW_SHOW);
SetForegroundWindow(h_Wnd);
SetFocus(h_Wnd);
glResizeWnd(Width, Height);
Result := True;
end;
{$else}
function OSAL_glCreateWnd(Width, Height : Integer; Fullscreen : Boolean; PixelDepth : Integer; const Title:string) : Boolean;
var
errorBase,eventBase: integer;
Attr: Array[0..8] of integer = (GLX_RGBA,GLX_RED_SIZE,1,GLX_GREEN_SIZE,1,GLX_BLUE_SIZE,1,GLX_DOUBLEBUFFER,no
ne);
cm: TColormap;
winAttr: TXSetWindowAttributes;
window_title_property: TXTextProperty;
begin
initGlx();
hXDisplay := XOpenDisplay(nil);
if(hXDisplay = nil) then
writeLn('Error: Could not connect to X server');
if not (glXQueryExtension(hXDisplay,errorBase,eventBase)) then
writeLn('Error: GLX extension not supported');
hXVisualInfo := glXChooseVisual(hXDisplay,DefaultScreen(hXDisplay), Attr);
if(hXVisualInfo = nil) then
writeLn('Error: Could not find visual');
//Create a new colormap
cm := XCreateColormap(hXDisplay,RootWindow(hXDisplay,hXVisualInfo.screen),hXVisualInfo.visual,AllocNone);
winAttr.colormap := cm;
winAttr.border_pixel := 0;
winAttr.background_pixel := 0;
winAttr.event_mask := KeyPressMask or KeyReleaseMask or ButtonPressMask or ButtonReleaseMask or PointerMotionMask or StructureNotifyMask;
//Create a window
hXWindow := XCreateWindow(hXDisplay,RootWindow(hXDisplay,hXVisualInfo.screen),0,0,Width,Height,0,hXVisualInfo.depth,InputOutput,hXVisualInfo.visual,CWBor
derPixel or CWColormap or CWEventMask,@winAttr);
OSAL_SetWindowText(Title);
//Create an OpenGL rendering context
hglXContext := glXCreateContext(hXDisplay,hXVisualInfo,none,true);
if(hglXContext = nil) then
writeLn('Error: Could not create an OpenGL rendering context');
//Make it current
glXMakeCurrent(hXDisplay,hXWindow,hglXContext);
//Map the window on the display
XMapWindow(hXDisplay,hXWindow);
end;
{$endif}
{$ifdef win32}
type
TWindowInfo = packed record
cbSize: DWORD;
rcWindow: TRect;
rcClient: TRect;
dwStyle: DWORD;
dwExStyle: DWORD;
dwOtherStuff: DWORD;
cxWindowBorders: uInt;
cyWindowBorders: uInt;
atomWindowType: TAtom;
wCreatorVersion: WORD;
end;}
function GetWindowInfo(hwnd: HWND; var pwi: TWindowInfo): BOOL; stdcall; external 'user32.dll' name 'GetWindowInfo';
{$endif}
function OSAL_GetWindowClientSize: TPoint; //-
{$ifdef win32}
var
Info:TWindowInfo;
begin
GetWindowInfo(h_Wnd,Info);
Result.X:=Info.Info.rcClient.Right;
Result.Y:=Info.rcClient.Bottom-Info.rcClient.Top;
end;
{$else}
begin
Result.X:=ScreenWidth;
Result.Y:=ScreenHeight;
end;
{$endif}
procedure OSAL_SetWindowPos(X,Y, Width, Height: integer); //-
{$ifdef win32}
begin
SetWindowPos(h_Wnd,HWND_TOP,X,Y, Width, Height,SWP_NOZORDER);
end;
{$else}
var
wndAttr:TXWindowAttributes;
begin
wndAttr.x:=X;
wndAttr.y:=Y;
wndAttr.width:=Width;
wndAttr.height:=Height;
XChangeWindowAttributes(hXDisplay,hXWindow,CWX or CWY or CWWidth or CWHeight,@wndAttr);
end;
{$endif}
end.
- Код: Выделить всё