mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-23 12:46:34 -04:00
Finish porting WinGLNative to C.
This commit is contained in:
parent
44ec23c931
commit
d6a8b7d35c
@ -339,11 +339,7 @@ namespace OpenTK.Platform.Windows
|
||||
if (Closing != null)
|
||||
Closing(this, e);
|
||||
|
||||
if (!e.Cancel)
|
||||
{
|
||||
if (Unload != null)
|
||||
Unload(this, EventArgs.Empty);
|
||||
|
||||
if (!e.Cancel) {
|
||||
DestroyWindow();
|
||||
break;
|
||||
}
|
||||
@ -403,7 +399,7 @@ namespace OpenTK.Platform.Windows
|
||||
wc.Icon = Icon != null ? Icon.Handle : IntPtr.Zero;
|
||||
#warning "This seems to resize one of the 'large' icons, rather than using a small icon directly (multi-icon files). Investigate!"
|
||||
wc.IconSm = Icon != null ? new Icon(Icon, 16, 16).Handle : IntPtr.Zero;
|
||||
wc.Cursor = API.LoadCursor(IntPtr.Zero, (IntPtr)32512); // CursorName.Arrow
|
||||
//wc.Cursor = API.LoadCursor(IntPtr.Zero, (IntPtr)32512); // CursorName.Arrow
|
||||
ushort atom = API.RegisterClassEx(ref wc);
|
||||
|
||||
if (atom == 0)
|
||||
@ -701,8 +697,6 @@ namespace OpenTK.Platform.Windows
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public event EventHandler<EventArgs> Load;
|
||||
public event EventHandler<EventArgs> Unload;
|
||||
public event EventHandler<EventArgs> Move;
|
||||
public event EventHandler<EventArgs> Resize;
|
||||
public event EventHandler<System.ComponentModel.CancelEventArgs> Closing;
|
||||
|
@ -10,10 +10,22 @@ bool Rectangle2D_Contains(Rectangle2D a, Int32 x, Int32 y) {
|
||||
return x >= a.X && y >= a.Y && x < (a.X + a.Width) && y < (a.Y + a.Height);
|
||||
}
|
||||
|
||||
bool Rectangle2D_Equals(Rectangle2D a, Rectangle2D b) {
|
||||
return a.X == b.X && a.Y == b.Y && a.Width == b.Width && a.Height == b.Height;
|
||||
}
|
||||
|
||||
Size2D Size2D_Make(Int32 width, Int32 height) {
|
||||
Size2D s; s.Width = width; s.Height = height; return s;
|
||||
}
|
||||
|
||||
bool Size2D_Equals(Size2D a, Size2D b) {
|
||||
return a.Width == b.Width && a.Height == b.Height;
|
||||
}
|
||||
|
||||
Point2D Point2D_Make(Int32 x, Int32 y) {
|
||||
Point2D p; p.X = x; p.Y = y; return p;
|
||||
}
|
||||
|
||||
bool Point2D_Equals(Point2D a, Point2D b) {
|
||||
return a.X == b.X && a.Y == b.Y;
|
||||
}
|
@ -13,6 +13,9 @@ typedef struct Rectangle2D_ {
|
||||
Int32 Width, Height;
|
||||
} Rectangle2D;
|
||||
|
||||
/* Empty 2D rectangle. */
|
||||
Rectangle2D Rectangle2D_Empty;
|
||||
|
||||
/* Stores a coordinate in 2D space.*/
|
||||
typedef struct Point2D_ {
|
||||
Int32 X, Y;
|
||||
@ -30,9 +33,18 @@ Rectangle2D Rectangle2D_Make(Int32 x, Int32 y, Int32 width, Int32 height);
|
||||
/* Returns whether the given rectangle contains the given point. */
|
||||
bool Rectangle2D_Contains(Rectangle2D a, Int32 x, Int32 y);
|
||||
|
||||
/* Returns whether the two rectangles are equal. */
|
||||
bool Rectangle2D_Equals(Rectangle2D a, Rectangle2D b);
|
||||
|
||||
/* Creates a new size. */
|
||||
Size2D Size2D_Make(Int32 width, Int32 height);
|
||||
|
||||
/* Returns whether the two sizes are equal. */
|
||||
bool Size2D_Equals(Size2D a, Size2D b);
|
||||
|
||||
/* Creates a new point. */
|
||||
Point2D Point2D_Make(Int32 x, Int32 y);
|
||||
|
||||
/* Returns whether the two points are equal. */
|
||||
bool Point2D_Equals(Point2D a, Point2D b);
|
||||
#endif
|
@ -1,9 +1,17 @@
|
||||
#include "Typedefs.h"
|
||||
#include "ErrorHandler.h"
|
||||
#include "Platform.h"
|
||||
#include "Window.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
ErrorHandler_Init();
|
||||
Platform_Init();
|
||||
|
||||
Window_Create(0, 0, 320, 320, "TEST", NULL);
|
||||
Window_SetVisible(true);
|
||||
while (true) {
|
||||
Window_ProcessEvents();
|
||||
Platform_ThreadSleep(100);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -14,6 +14,7 @@
|
||||
|
||||
HINSTANCE win_Instance;
|
||||
HWND win_Handle;
|
||||
HDC win_DC;
|
||||
WindowState win_State = WindowState_Normal;
|
||||
bool win_Exists, win_Focused;
|
||||
bool mouse_outside_window = true;
|
||||
@ -24,41 +25,157 @@ Rectangle2D win_Bounds;
|
||||
Rectangle2D win_ClientRect;
|
||||
Rectangle2D previous_bounds; // Used to restore previous size when leaving fullscreen mode.
|
||||
|
||||
void Window_Create(Int32 x, Int32 y, Int32 width, Int32 height, STRING_TRANSIENT String* title, DisplayDevice* device) {
|
||||
win_Instance = GetModuleHandleA(NULL);
|
||||
/* TODO: UngroupFromTaskbar(); */
|
||||
|
||||
/* Find out the final window rectangle, after the WM has added its chrome (titlebar, sidebars etc). */
|
||||
RECT rect; rect.left = x; rect.top = y; rect.right = x + width; rect.bottom = y + height;
|
||||
AdjustWindowRectEx(&rect, win_Style, false, win_StyleEx);
|
||||
|
||||
WNDCLASSEXA wc;
|
||||
Platform_MemSet(&wc, 0, sizeof(WNDCLASSEXA));
|
||||
wc.cbSize = sizeof(WNDCLASSEXA);
|
||||
wc.style = CS_OWNDC;
|
||||
wc.hInstance = win_Instance;
|
||||
wc.lpfnWndProc = Window_Procedure;
|
||||
wc.lpszClassName = win_ClassName;
|
||||
/* TODO: Set window icons here */
|
||||
wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
|
||||
|
||||
ATOM atom = RegisterClassExA(&wc);
|
||||
if (atom == 0) {
|
||||
ErrorHandler_FailWithCode(GetLastError(), "Failed to register window class");
|
||||
}
|
||||
|
||||
win_Handle = CreateWindowExA(
|
||||
win_StyleEx, win_ClassName, title->buffer, win_Style,
|
||||
rect.left, rect.top, RECT_WIDTH(rect), RECT_HEIGHT(rect),
|
||||
NULL, NULL, win_Instance, NULL);
|
||||
|
||||
if (win_Handle == NULL) {
|
||||
ErrorHandler_FailWithCode(GetLastError(), "Failed to create window");
|
||||
}
|
||||
win_Exists = true;
|
||||
Rectangle2D Window_FromRect(RECT rect) {
|
||||
Rectangle2D r;
|
||||
r.X = rect.left; r.Y = rect.top;
|
||||
r.Width = RECT_WIDTH(rect);
|
||||
r.Height = RECT_HEIGHT(rect);
|
||||
return r;
|
||||
}
|
||||
|
||||
WNDPROC Window_Procedure(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
|
||||
void Window_Destroy(void) {
|
||||
if (!win_Exists) return;
|
||||
|
||||
DestroyWindow(win_Handle);
|
||||
win_Exists = false;
|
||||
}
|
||||
|
||||
void Window_ResetWindowState(void) {
|
||||
suppress_resize++;
|
||||
Window_SetWindowState(WindowState_Normal);
|
||||
Window_ProcessEvents();
|
||||
suppress_resize--;
|
||||
}
|
||||
|
||||
bool win_hiddenBorder;
|
||||
void Window_DoSetHiddenBorder(bool value) {
|
||||
if (win_hiddenBorder == value) return;
|
||||
|
||||
/* We wish to avoid making an invisible window visible just to change the border.
|
||||
However, it's a good idea to make a visible window invisible temporarily, to
|
||||
avoid garbage caused by the border change. */
|
||||
bool was_visible = Window_GetVisible();
|
||||
|
||||
/* To ensure maximized/minimized windows work correctly, reset state to normal,
|
||||
change the border, then go back to maximized/minimized. */
|
||||
WindowState state = win_State;
|
||||
Window_ResetWindowState();
|
||||
DWORD style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
||||
style |= (value ? WS_POPUP : WS_OVERLAPPEDWINDOW);
|
||||
|
||||
/* Make sure client size doesn't change when changing the border style.*/
|
||||
RECT rect;
|
||||
rect.left = win_Bounds.X; rect.top = win_Bounds.Y;
|
||||
rect.right = rect.left + win_Bounds.Width;
|
||||
rect.bottom = rect.top + win_Bounds.Height;
|
||||
AdjustWindowRectEx(&rect, style, false, win_StyleEx);
|
||||
|
||||
/* This avoids leaving garbage on the background window. */
|
||||
if (was_visible) Window_SetVisible(false);
|
||||
|
||||
SetWindowLongA(win_Handle, GWL_STYLE, style);
|
||||
SetWindowPos(win_Handle, NULL, 0, 0, RECT_WIDTH(rect), RECT_HEIGHT(rect),
|
||||
SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
|
||||
/* Force window to redraw update its borders, but only if it's
|
||||
already visible (invisible windows will change borders when
|
||||
they become visible, so no need to make them visiable prematurely).*/
|
||||
if (was_visible) Window_SetVisible(true);
|
||||
|
||||
Window_SetWindowState(state);
|
||||
}
|
||||
|
||||
void Window_SetHiddenBorder(bool hidden) {
|
||||
suppress_resize++;
|
||||
Window_DoSetHiddenBorder(hidden);
|
||||
Window_ProcessEvents();
|
||||
suppress_resize--;
|
||||
}
|
||||
|
||||
void Window_EnableMouseTracking(void) {
|
||||
TRACKMOUSEEVENT me;
|
||||
Platform_MemSet(&me, 0, sizeof(TRACKMOUSEEVENT));
|
||||
me.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||
me.hwndTrack = win_Handle;
|
||||
me.dwFlags = TME_LEAVE;
|
||||
|
||||
if (!TrackMouseEvent(&me)) {
|
||||
ErrorHandler_FailWithCode(GetLastError(), "Enabling mouse tracking");
|
||||
}
|
||||
}
|
||||
|
||||
Key Window_MapKey(WPARAM key) {
|
||||
if (key >= VK_F1 && key <= VK_F24) {
|
||||
return Key_F1 + (key - VK_F1);
|
||||
}
|
||||
if (key >= '0' && key <= '9') {
|
||||
return Key_Number0 + (key - '0');
|
||||
}
|
||||
if (key >= 'A' && key <= 'Z') {
|
||||
return Key_A + (key - 'A');
|
||||
}
|
||||
if (key >= VK_NUMPAD0 && key <= VK_NUMPAD9) {
|
||||
return Key_Keypad0 + (key - VK_NUMPAD0);
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case VK_ESCAPE: return Key_Escape;
|
||||
case VK_TAB: return Key_Tab;
|
||||
case VK_CAPITAL: return Key_CapsLock;
|
||||
case VK_LCONTROL: return Key_ControlLeft;
|
||||
case VK_LSHIFT: return Key_ShiftLeft;
|
||||
case VK_LWIN: return Key_WinLeft;
|
||||
case VK_LMENU: return Key_AltLeft;
|
||||
case VK_SPACE: return Key_Space;
|
||||
case VK_RMENU: return Key_AltRight;
|
||||
case VK_RWIN: return Key_WinRight;
|
||||
case VK_APPS: return Key_Menu;
|
||||
case VK_RCONTROL: return Key_ControlRight;
|
||||
case VK_RSHIFT: return Key_ShiftRight;
|
||||
case VK_RETURN: return Key_Enter;
|
||||
case VK_BACK: return Key_BackSpace;
|
||||
|
||||
case VK_OEM_1: return Key_Semicolon; /* Varies by keyboard: return ;: on Win2K/US */
|
||||
case VK_OEM_2: return Key_Slash; /* Varies by keyboard: return /? on Win2K/US */
|
||||
case VK_OEM_3: return Key_Tilde; /* Varies by keyboard: return `~ on Win2K/US */
|
||||
case VK_OEM_4: return Key_BracketLeft; /* Varies by keyboard: return [{ on Win2K/US */
|
||||
case VK_OEM_5: return Key_BackSlash; /* Varies by keyboard: return \| on Win2K/US */
|
||||
case VK_OEM_6: return Key_BracketRight; /* Varies by keyboard: return ]} on Win2K/US */
|
||||
case VK_OEM_7: return Key_Quote; /* Varies by keyboard: return '" on Win2K/US */
|
||||
case VK_OEM_PLUS: return Key_Plus; /* Invariant: + */
|
||||
case VK_OEM_COMMA: return Key_Comma; /* Invariant: : return */
|
||||
case VK_OEM_MINUS: return Key_Minus; /* Invariant: - */
|
||||
case VK_OEM_PERIOD: return Key_Period; /* Invariant: . */
|
||||
|
||||
case VK_HOME: return Key_Home;
|
||||
case VK_END: return Key_End;
|
||||
case VK_DELETE: return Key_Delete;
|
||||
case VK_PRIOR: return Key_PageUp;
|
||||
case VK_NEXT: return Key_PageDown;
|
||||
case VK_PRINT: return Key_PrintScreen;
|
||||
case VK_PAUSE: return Key_Pause;
|
||||
case VK_NUMLOCK: return Key_NumLock;
|
||||
|
||||
case VK_SCROLL: return Key_ScrollLock;
|
||||
case VK_SNAPSHOT: return Key_PrintScreen;
|
||||
case VK_INSERT: return Key_Insert;
|
||||
|
||||
case VK_DECIMAL: return Key_KeypadDecimal;
|
||||
case VK_ADD: return Key_KeypadAdd;
|
||||
case VK_SUBTRACT: return Key_KeypadSubtract;
|
||||
case VK_DIVIDE: return Key_KeypadDivide;
|
||||
case VK_MULTIPLY: return Key_KeypadMultiply;
|
||||
|
||||
case VK_UP: return Key_Up;
|
||||
case VK_DOWN: return Key_Down;
|
||||
case VK_LEFT: return Key_Left;
|
||||
case VK_RIGHT: return Key_Right;
|
||||
}
|
||||
return Key_Unknown;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
bool new_focused_state;
|
||||
Real32 wheel_delta;
|
||||
WORD mouse_x, mouse_y;
|
||||
@ -73,7 +190,7 @@ WNDPROC Window_Procedure(HWND handle, UINT message, WPARAM wParam, LPARAM lParam
|
||||
switch (message) {
|
||||
|
||||
case WM_ACTIVATE:
|
||||
new_focused_state = LOWORD(wParam);
|
||||
new_focused_state = LOWORD(wParam) != 0;
|
||||
if (new_focused_state != win_Focused) {
|
||||
win_Focused = new_focused_state;
|
||||
Event_RaiseVoid(&WindowEvents_OnFocusedChanged);
|
||||
@ -93,18 +210,18 @@ WNDPROC Window_Procedure(HWND handle, UINT message, WPARAM wParam, LPARAM lParam
|
||||
pos = (WINDOWPOS*)lParam;
|
||||
if (pos->hwnd == win_Handle) {
|
||||
Point2D new_location = Point2D_Make(pos->x, pos->y);
|
||||
if (Location != new_location) {
|
||||
if (!Point2D_Equals(Window_GetLocation(), new_location)) {
|
||||
win_Bounds.X = pos->x; win_Bounds.Y = pos->y;
|
||||
Event_RaiseVoid(&WindowEvents_OnMove);
|
||||
}
|
||||
|
||||
Size2D new_size = Size2D_Make(pos->cx, pos->cy);
|
||||
if (Size != new_size) {
|
||||
if (!Size2D_Equals(Window_GetSize(), new_size)) {
|
||||
win_Bounds.Width = pos->cx; win_Bounds.Height = pos->cy;
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(handle, &rect);
|
||||
client_rectangle = rect.ToRectangle();
|
||||
win_ClientRect = Window_FromRect(rect);
|
||||
|
||||
SetWindowPos(win_Handle, NULL,
|
||||
win_Bounds.X, win_Bounds.Y, win_Bounds.Width, win_Bounds.Height,
|
||||
@ -156,7 +273,7 @@ WNDPROC Window_Procedure(HWND handle, UINT message, WPARAM wParam, LPARAM lParam
|
||||
if (mouse_outside_window) {
|
||||
/* Once we receive a mouse move event, it means that the mouse has re-entered the window. */
|
||||
mouse_outside_window = false;
|
||||
EnableMouseTracking();
|
||||
Window_EnableMouseTracking();
|
||||
Event_RaiseVoid(&WindowEvents_OnMouseEnter);
|
||||
}
|
||||
break;
|
||||
@ -280,59 +397,59 @@ WNDPROC Window_Procedure(HWND handle, UINT message, WPARAM wParam, LPARAM lParam
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(handle, &rect);
|
||||
win_ClientRect = rect.ToRectangle();
|
||||
win_ClientRect = Window_FromRect(rect);
|
||||
invisible_since_creation = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
Event_RaiseVoid(&WindowEvents_OnClosing);
|
||||
if (Unload != null)
|
||||
Unload(this, EventArgs.Empty);
|
||||
DestroyWindow();
|
||||
Window_Destroy();
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
win_Exists = false;
|
||||
UnregisterClassA(win_ClassName, win_Instance);
|
||||
window.Dispose();
|
||||
if (win_DC != NULL) ReleaseDC(win_Handle, win_DC);
|
||||
Event_RaiseVoid(&WindowEvents_OnClosed);
|
||||
break;
|
||||
}
|
||||
return DefWindowProcA(handle, message, wParam, lParam);
|
||||
}
|
||||
|
||||
void Window_EnableMouseTracking(void) {
|
||||
TRACKMOUSEEVENT me;
|
||||
Platform_MemSet(&me, 0, sizeof(TRACKMOUSEEVENT));
|
||||
me.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||
me.hwndTrack = win_Handle;
|
||||
me.dwFlags = TME_LEAVE;
|
||||
|
||||
if (!TrackMouseEvent(&me)) {
|
||||
ErrorHandler_FailWithCode(GetLastError(), "Enabling mouse tracking");
|
||||
void Window_Create(Int32 x, Int32 y, Int32 width, Int32 height, STRING_TRANSIENT String* title, DisplayDevice* device) {
|
||||
win_Instance = GetModuleHandleA(NULL);
|
||||
/* TODO: UngroupFromTaskbar(); */
|
||||
|
||||
/* Find out the final window rectangle, after the WM has added its chrome (titlebar, sidebars etc). */
|
||||
RECT rect; rect.left = x; rect.top = y; rect.right = x + width; rect.bottom = y + height;
|
||||
AdjustWindowRectEx(&rect, win_Style, false, win_StyleEx);
|
||||
|
||||
WNDCLASSEXA wc;
|
||||
Platform_MemSet(&wc, 0, sizeof(WNDCLASSEXA));
|
||||
wc.cbSize = sizeof(WNDCLASSEXA);
|
||||
wc.style = CS_OWNDC;
|
||||
wc.hInstance = win_Instance;
|
||||
wc.lpfnWndProc = Window_Procedure;
|
||||
wc.lpszClassName = win_ClassName;
|
||||
/* TODO: Set window icons here */
|
||||
wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
|
||||
|
||||
ATOM atom = RegisterClassExA(&wc);
|
||||
if (atom == 0) {
|
||||
ErrorHandler_FailWithCode(GetLastError(), "Failed to register window class");
|
||||
}
|
||||
}
|
||||
|
||||
void Window_Destroy(void) {
|
||||
if (!win_Exists) return;
|
||||
|
||||
DestroyWindow(win_Handle);
|
||||
win_Exists = false;
|
||||
}
|
||||
win_Handle = CreateWindowExA(
|
||||
win_StyleEx, win_ClassName, title->buffer, win_Style,
|
||||
rect.left, rect.top, RECT_WIDTH(rect), RECT_HEIGHT(rect),
|
||||
NULL, NULL, win_Instance, NULL);
|
||||
|
||||
void Window_SetHiddenBorder(bool hidden) {
|
||||
suppress_resize++;
|
||||
Window_DoSetHiddenBorder(hidden);
|
||||
Window_ProcessEvents();
|
||||
suppress_resize--;
|
||||
}
|
||||
|
||||
void Window_ResetWindowState(void) {
|
||||
suppress_resize++;
|
||||
Window_SetWindowState(WindowState_Normal);
|
||||
Window_ProcessEvents();
|
||||
suppress_resize--;
|
||||
if (win_Handle == NULL) {
|
||||
ErrorHandler_FailWithCode(GetLastError(), "Failed to create window");
|
||||
}
|
||||
win_Exists = true;
|
||||
}
|
||||
|
||||
void Window_GetClipboardText(STRING_TRANSIENT String* value) {
|
||||
@ -360,7 +477,7 @@ void Window_GetClipboardText(STRING_TRANSIENT String* value) {
|
||||
String_Append(value, Convert_UnicodeToCP437(*text)); text++;
|
||||
}
|
||||
} else {
|
||||
UInt8* text = (UInt16*)src;
|
||||
UInt8* text = (UInt8*)src;
|
||||
while (*text != 0) {
|
||||
String_Append(value, *text); text++;
|
||||
}
|
||||
@ -400,6 +517,7 @@ void Window_SetClipboardText(STRING_TRANSIENT String* value) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle2D Window_GetBounds(void) { return win_Bounds; }
|
||||
void Window_SetBounds(Rectangle2D rect) {
|
||||
/* Note: the bounds variable is updated when the resize/move message arrives.*/
|
||||
@ -422,35 +540,36 @@ void Window_SetClientRectangle(Rectangle2D rect) {
|
||||
Window_SetClientSize(size);
|
||||
}
|
||||
|
||||
Size2D Window_GetClientSize(void) {
|
||||
Size2D Window_GetClientSize(void) {
|
||||
return Size2D_Make(win_ClientRect.Width, win_ClientRect.Height);
|
||||
}
|
||||
void Window_SetClientSize(Size2D size) {
|
||||
DWORD style = GetWindowLongA(win_Handle, GWL_STYLE);
|
||||
RECT rect;
|
||||
rect.left = 0; rect.top = 0;
|
||||
RECT rect;
|
||||
rect.left = 0; rect.top = 0;
|
||||
rect.right = size.Width; rect.bottom = size.Height;
|
||||
|
||||
|
||||
AdjustWindowRect(&rect, style, false);
|
||||
Window_SetSize(Size2D_Make(RECT_WIDTH(rect), RECT_HEIGHT(rect)));
|
||||
}
|
||||
|
||||
/* TODO: Set window icon
|
||||
public Icon Icon{
|
||||
get{ return icon; }
|
||||
set{
|
||||
icon = value;
|
||||
get{ return icon; }
|
||||
set{
|
||||
icon = value;
|
||||
if (window.handle != IntPtr.Zero)
|
||||
{
|
||||
//Icon small = new Icon( value, 16, 16 );
|
||||
//GC.KeepAlive( small );
|
||||
API.SendMessage(window.handle, WM_SETICON, (IntPtr)0, icon == null ? IntPtr.Zero : value.Handle);
|
||||
API.SendMessage(window.handle, WM_SETICON, (IntPtr)1, icon == null ? IntPtr.Zero : value.Handle);
|
||||
//Icon small = new Icon( value, 16, 16 );
|
||||
//GC.KeepAlive( small );
|
||||
API.SendMessage(window.handle, WM_SETICON, (IntPtr)0, icon == null ? IntPtr.Zero : value.Handle);
|
||||
API.SendMessage(window.handle, WM_SETICON, (IntPtr)1, icon == null ? IntPtr.Zero : value.Handle);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
bool Window_GetFocused(void) { return win_Focused; }
|
||||
bool Window_GetExists(void) { return win_Exists; }
|
||||
|
||||
bool Window_GetVisible(void) { return IsWindowVisible(win_Handle); }
|
||||
void Window_SetVisible(bool visible) {
|
||||
@ -460,19 +579,19 @@ void Window_SetVisible(bool visible) {
|
||||
BringWindowToTop(win_Handle);
|
||||
SetForegroundWindow(win_Handle);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ShowWindow(win_Handle, SW_HIDE);
|
||||
}
|
||||
}
|
||||
|
||||
bool Window_GetExists(void) { return win_Exists; }
|
||||
|
||||
void Window_Close(void) {
|
||||
PostMessageA(win_Handle, WM_CLOSE, NULL, NULL);
|
||||
}
|
||||
|
||||
WindowState Window_GetState(void) { return win_State; }
|
||||
void Window_SetState(WindowState value) {
|
||||
WindowState Window_GetWindowState(void) { return win_State; }
|
||||
void Window_SetWindowState(WindowState value) {
|
||||
if (win_State == value) return;
|
||||
|
||||
DWORD command = 0;
|
||||
@ -489,7 +608,7 @@ void Window_SetState(WindowState value) {
|
||||
|
||||
case WindowState_Maximized:
|
||||
/* Reset state to avoid strange interactions with fullscreen/minimized windows. */
|
||||
ResetWindowState();
|
||||
Window_ResetWindowState();
|
||||
command = SW_MAXIMIZE;
|
||||
break;
|
||||
|
||||
@ -499,13 +618,13 @@ void Window_SetState(WindowState value) {
|
||||
|
||||
case WindowState_Fullscreen:
|
||||
/* We achieve fullscreen by hiding the window border and sending the MAXIMIZE command.
|
||||
We cannot use the WindowState.Maximized directly, as that will not send the MAXIMIZE
|
||||
command for windows with hidden borders. */
|
||||
We cannot use the WindowState.Maximized directly, as that will not send the MAXIMIZE
|
||||
command for windows with hidden borders. */
|
||||
|
||||
/* Reset state to avoid strange side-effects from maximized/minimized windows. */
|
||||
ResetWindowState();
|
||||
previous_bounds = Bounds;
|
||||
SetHiddenBorder(true);
|
||||
Window_ResetWindowState();
|
||||
previous_bounds = win_Bounds;
|
||||
Window_SetHiddenBorder(true);
|
||||
|
||||
command = SW_MAXIMIZE;
|
||||
SetForegroundWindow(win_Handle);
|
||||
@ -515,64 +634,27 @@ void Window_SetState(WindowState value) {
|
||||
if (command != 0) ShowWindow(win_Handle, command);
|
||||
|
||||
/* Restore previous window border or apply pending border change when leaving fullscreen mode. */
|
||||
if (exiting_fullscreen) SetHiddenBorder(false);
|
||||
if (exiting_fullscreen) Window_SetHiddenBorder(false);
|
||||
|
||||
/* Restore previous window size/location if necessary */
|
||||
if (command == SW_RESTORE && previous_bounds != Rectangle.Empty) {
|
||||
Bounds = previous_bounds;
|
||||
previous_bounds = Rectangle.Empty;
|
||||
if (command == SW_RESTORE && !Rectangle2D_Equals(previous_bounds, Rectangle2D_Empty)) {
|
||||
Window_SetBounds(previous_bounds);
|
||||
previous_bounds = Rectangle2D_Empty;
|
||||
}
|
||||
}
|
||||
|
||||
bool win_hiddenBorder;
|
||||
void Window_DoSetHiddenBorder(bool value) {
|
||||
if (win_hiddenBorder == value) return;
|
||||
|
||||
/* We wish to avoid making an invisible window visible just to change the border.
|
||||
However, it's a good idea to make a visible window invisible temporarily, to
|
||||
avoid garbage caused by the border change. */
|
||||
bool was_visible = Window_GetVisible();
|
||||
|
||||
/* To ensure maximized/minimized windows work correctly, reset state to normal,
|
||||
change the border, then go back to maximized/minimized. */
|
||||
WindowState state = win_State;
|
||||
Window_ResetWindowState();
|
||||
DWORD style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
||||
style |= (value ? WS_POPUP : WS_OVERLAPPEDWINDOW);
|
||||
|
||||
/* Make sure client size doesn't change when changing the border style.*/
|
||||
Win32Rectangle rect = Win32Rectangle.From(bounds);
|
||||
AdjustWindowRectEx(&rect, style, false, win_StyleEx);
|
||||
|
||||
/* This avoids leaving garbage on the background window. */
|
||||
if (was_visible) Window_SetVisible(false);
|
||||
|
||||
SetWindowLongA(win_Handle, GWL_STYLE, style);
|
||||
SetWindowPos(win_Handle, NULL, 0, 0, rect.Width, rect.Height,
|
||||
SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
|
||||
/* Force window to redraw update its borders, but only if it's
|
||||
already visible (invisible windows will change borders when
|
||||
they become visible, so no need to make them visiable prematurely).*/
|
||||
if (was_visible) Window_SetVisible(true);
|
||||
|
||||
Window_SetWindowState(state);
|
||||
}
|
||||
|
||||
Point2D Window_PointToClient(Point2D point) {
|
||||
if (!ScreenToClient(win_Handle, ref point)) {
|
||||
POINT p; p.x = point.X; p.y = point.Y;
|
||||
if (!ScreenToClient(win_Handle, &p)) {
|
||||
ErrorHandler_FailWithCode(GetLastError(), "Converting point from client to screen coordinates");
|
||||
}
|
||||
return point;
|
||||
return Point2D_Make(p.x, p.y);
|
||||
}
|
||||
|
||||
Point2D Window_PointToScreen(Point2D p) {
|
||||
ErrorHandler_Fail("PointToScreen NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
public event EventHandler<EventArgs> Load;
|
||||
public event EventHandler<EventArgs> Unload;
|
||||
|
||||
MSG msg;
|
||||
void Window_ProcessEvents() {
|
||||
while (PeekMessageA(&msg, NULL, 0, 0, 1)) {
|
||||
@ -599,74 +681,4 @@ bool Window_GetCursorVisible(void) { return win_cursorVisible; }
|
||||
void Window_SetCursorVisible(bool visible) {
|
||||
win_cursorVisible = visible;
|
||||
ShowCursor(visible ? 1 : 0);
|
||||
}
|
||||
|
||||
Key Window_MapKey(WPARAM key) {
|
||||
if (key >= VK_F1 && key <= VK_F24) {
|
||||
return Key_F1 + (key - VK_F1);
|
||||
}
|
||||
if (key >= '0' && key <= '9') {
|
||||
return Key_Number0 + (key - '0');
|
||||
}
|
||||
if (key >= 'A' && key <= 'Z') {
|
||||
return Key_A + (key - 'A');
|
||||
}
|
||||
if (key >= VK_NUMPAD0 && key <= VK_NUMPAD9) {
|
||||
return Key_Keypad0 + (key - VK_NUMPAD0);
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case VK_ESCAPE: return Key_Escape;
|
||||
case VK_TAB: return Key_Tab;
|
||||
case VK_CAPITAL: return Key_CapsLock;
|
||||
case VK_LCONTROL: return Key_ControlLeft;
|
||||
case VK_LSHIFT: return Key_ShiftLeft;
|
||||
case VK_LWIN: return Key_WinLeft;
|
||||
case VK_LMENU: return Key_AltLeft;
|
||||
case VK_SPACE: return Key_Space;
|
||||
case VK_RMENU: return Key_AltRight;
|
||||
case VK_RWIN: return Key_WinRight;
|
||||
case VK_APPS: return Key_Menu;
|
||||
case VK_RCONTROL: return Key_ControlRight;
|
||||
case VK_RSHIFT: return Key_ShiftRight;
|
||||
case VK_RETURN: return Key_Enter;
|
||||
case VK_BACK: return Key_BackSpace;
|
||||
|
||||
case VK_OEM_1: return Key_Semicolon; /* Varies by keyboard: return ;: on Win2K/US */
|
||||
case VK_OEM_2: return Key_Slash; /* Varies by keyboard: return /? on Win2K/US */
|
||||
case VK_OEM_3: return Key_Tilde; /* Varies by keyboard: return `~ on Win2K/US */
|
||||
case VK_OEM_4: return Key_BracketLeft; /* Varies by keyboard: return [{ on Win2K/US */
|
||||
case VK_OEM_5: return Key_BackSlash; /* Varies by keyboard: return \| on Win2K/US */
|
||||
case VK_OEM_6: return Key_BracketRight; /* Varies by keyboard: return ]} on Win2K/US */
|
||||
case VK_OEM_7: return Key_Quote; /* Varies by keyboard: return '" on Win2K/US */
|
||||
case VK_OEM_PLUS: return Key_Plus; /* Invariant: + */
|
||||
case VK_OEM_COMMA: return Key_Comma; /* Invariant: : return */
|
||||
case VK_OEM_MINUS: return Key_Minus; /* Invariant: - */
|
||||
case VK_OEM_PERIOD: return Key_Period; /* Invariant: . */
|
||||
|
||||
case VK_HOME: return Key_Home;
|
||||
case VK_END: return Key_End;
|
||||
case VK_DELETE: return Key_Delete;
|
||||
case VK_PRIOR: return Key_PageUp;
|
||||
case VK_NEXT: return Key_PageDown;
|
||||
case VK_PRINT: return Key_PrintScreen;
|
||||
case VK_PAUSE: return Key_Pause;
|
||||
case VK_NUMLOCK: return Key_NumLock;
|
||||
|
||||
case VK_SCROLL: return Key_ScrollLock;
|
||||
case VK_SNAPSHOT: return Key_PrintScreen;
|
||||
case VK_INSERT: return Key_Insert;
|
||||
|
||||
case VK_DECIMAL: return Key_KeypadDecimal;
|
||||
case VK_ADD: return Key_KeypadAdd;
|
||||
case VK_SUBTRACT: return Key_KeypadSubtract;
|
||||
case VK_DIVIDE: return Key_KeypadDivide;
|
||||
case VK_MULTIPLY: return Key_KeypadMultiply;
|
||||
|
||||
case VK_UP: return Key_Up;
|
||||
case VK_DOWN: return Key_Down;
|
||||
case VK_LEFT: return Key_Left;
|
||||
case VK_RIGHT: return Key_Right;
|
||||
}
|
||||
return Key_Unknown;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user