summaryrefslogtreecommitdiff
path: root/utils/mxtk/mx.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/mxtk/mx.cpp
downloadarchived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz
archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip
Diffstat (limited to 'utils/mxtk/mx.cpp')
-rw-r--r--utils/mxtk/mx.cpp1152
1 files changed, 1152 insertions, 0 deletions
diff --git a/utils/mxtk/mx.cpp b/utils/mxtk/mx.cpp
new file mode 100644
index 0000000..8d5e35a
--- /dev/null
+++ b/utils/mxtk/mx.cpp
@@ -0,0 +1,1152 @@
+//
+// mxToolKit (c) 1999 by Mete Ciragan
+//
+// file: mx.cpp
+// implementation: Win32 API
+// last modified: Apr 18 1999, Mete Ciragan
+// copyright: The programs and associated files contained in this
+// distribution were developed by Mete Ciragan. The programs
+// are not in the public domain, but they are freely
+// distributable without licensing fees. These programs are
+// provided without guarantee or warrantee expressed or
+// implied.
+//
+#include "mxtk/mx.h"
+#include "mxtk/mxWindow.h"
+#include "mxtk/mxEvent.h"
+#include "mxtk/mxLinkedList.h"
+#include <windows.h>
+#include <commctrl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tier1/utlvector.h"
+
+
+#define WM_MOUSEWHEEL 0x020A
+
+//#include <ostream.h"
+
+
+
+void mxTab_resizeChild (HWND hwnd);
+
+
+
+mxWindow *g_mainWindow = 0;
+static mxLinkedList *g_widgetList = 0;
+static mxWindow *g_idleWindow = 0;
+
+static MSG msg;
+static HWND g_hwndToolTipControl = 0;
+static bool isClosing = false;
+static HACCEL g_hAcceleratorTable = NULL;
+
+void mx::createAccleratorTable( int numentries, Accel_t *entries )
+{
+ CUtlVector< ACCEL > accelentries;
+
+ for ( int i = 0; i < numentries; ++i )
+ {
+ const Accel_t& entry = entries[ i ];
+
+ ACCEL add;
+ add.key = entry.key;
+ add.cmd = entry.command;
+ add.fVirt = 0;
+ if ( entry.flags & ACCEL_ALT )
+ {
+ add.fVirt |= FALT;
+ }
+ if ( entry.flags & ACCEL_CONTROL )
+ {
+ add.fVirt |= FCONTROL;
+ }
+ if ( entry.flags & ACCEL_SHIFT )
+ {
+ add.fVirt |= FSHIFT;
+ }
+ if ( entry.flags & ACCEL_VIRTKEY )
+ {
+ add.fVirt |= FVIRTKEY;
+ }
+
+ accelentries.AddToTail( add );
+ }
+
+ g_hAcceleratorTable = ::CreateAcceleratorTable( accelentries.Base(), accelentries.Count() );
+}
+
+
+
+void
+mx_addWidget (mxWidget *widget)
+{
+ if (g_widgetList)
+ g_widgetList->add ((void *) widget);
+}
+
+
+
+void
+mx_removeWidget (mxWidget *widget)
+{
+ if (g_widgetList)
+ g_widgetList->remove ((void *) widget);
+}
+
+
+
+HWND
+mx_CreateToolTipControl ()
+{
+ if (!g_hwndToolTipControl)
+ {
+ if (g_mainWindow)
+ {
+ g_hwndToolTipControl = CreateWindowEx (0, TOOLTIPS_CLASS, "", WS_POPUP | WS_EX_TOPMOST,
+ 0, 0, 0, 0, (HWND) g_mainWindow->getHandle (),
+ (HMENU) NULL, (HINSTANCE) GetModuleHandle (NULL), NULL);
+ }
+ }
+
+ return g_hwndToolTipControl;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *window -
+// *event -
+// Output : static void
+//-----------------------------------------------------------------------------
+static void RecursiveHandleEvent( mxWindow *window, mxEvent *event )
+{
+ while ( window )
+ {
+ if ( window->handleEvent ( event ) )
+ break;
+
+ window = window->getParent();
+ }
+}
+
+char const *translatecode( int code )
+{
+ switch ( code )
+ {
+ case NM_CLICK:
+ return "NM_CLICK";
+ case NM_CUSTOMDRAW:
+ return "NM_CUSTOMDRAW";
+ case NM_DBLCLK:
+ return "NM_DBLCLK";
+ case NM_KILLFOCUS:
+ return "NM_KILLFOCUS";
+ case NM_RCLICK:
+ return "NM_RCLICK";
+ case NM_RETURN:
+ return "NM_RETURN";
+ case NM_SETCURSOR:
+ return "NM_SETCURSOR";
+ case NM_SETFOCUS:
+ return "NM_SETFOCUS";
+ case TVN_BEGINDRAG:
+ return "TVN_BEGINDRAG";
+ case TVN_BEGINLABELEDIT:
+ return "TVN_BEGINLABELEDIT";
+ case TVN_BEGINRDRAG:
+ return "TVN_BEGINRDRAG";
+ case TVN_DELETEITEM:
+ return "TVN_DELETEITEM";
+ case TVN_ENDLABELEDIT:
+ return "TVN_ENDLABELEDIT";
+ case TVN_GETDISPINFO:
+ return "TVN_GETDISPINFO";
+ case TVN_GETINFOTIP:
+ return "TVN_GETINFOTIP";
+ case TVN_ITEMEXPANDED:
+ return "TVN_ITEMEXPANDED";
+ case TVN_ITEMEXPANDING:
+ return "TVN_ITEMEXPANDING";
+ case TVN_KEYDOWN :
+ return "TVN_KEYDOWN";
+ case TVN_SELCHANGED :
+ return "TVN_SELCHANGED";
+ case TVN_SELCHANGING :
+ return "TVN_SELCHANGING";
+ case TVN_SETDISPINFO :
+ return "TVN_SETDISPINFO";
+ case TVN_SINGLEEXPAND:
+ return "TVN_SINGLEEXPAND";
+ }
+
+ return "Unknown!!!";
+}
+static LRESULT CALLBACK WndProc (HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
+{
+ static bool bDragging = FALSE;
+
+ switch (uMessage)
+ {
+ case WM_SETFOCUS:
+ case WM_KILLFOCUS:
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if ( window )
+ {
+ mxEvent event;
+ event.event = mxEvent::Focus;
+ event.widget = NULL;
+ event.action = (uMessage == WM_SETFOCUS);
+ RecursiveHandleEvent( window, &event );
+ return 0;
+ }
+ }
+ break;
+
+ case WM_ACTIVATE:
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if ( window )
+ {
+ mxEvent event;
+ event.event = mxEvent::Activate;
+ event.widget = NULL;
+ event.action = (LOWORD( wParam ) != WA_INACTIVE);
+ RecursiveHandleEvent( window, &event );
+ return 0;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (LOWORD (wParam) > 0 && window)
+ {
+ WORD wNotifyCode = (WORD) HIWORD (wParam);
+ HWND hwndCtrl = (HWND) lParam;
+ mxEvent event;
+
+ CHAR className[128];
+ GetClassName (hwndCtrl, className, 128);
+ if (!strcmpi (className, "edit"))
+ {
+ if (wNotifyCode != EN_CHANGE)
+ break;
+ }
+ else if (!strcmpi (className, "combobox"))
+ {
+ if (wNotifyCode != CBN_SELCHANGE)
+ break;
+ }
+ else if (!strcmpi (className, "listbox"))
+ {
+ if (wNotifyCode != LBN_SELCHANGE)
+ break;
+ }
+
+ event.event = mxEvent::Action;
+ event.widget = (mxWidget *) GetWindowLong ((HWND) lParam, GWL_USERDATA);
+ event.action = (int) LOWORD (wParam);
+ RecursiveHandleEvent( window, &event );
+ }
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ if (isClosing)
+ break;
+
+ NMHDR *nmhdr = (NMHDR *) lParam;
+ mxEvent event;
+
+#if 0
+ //if ( nmhdr->idFrom > 0 )
+ {
+ mxWidget *temp = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA);
+ if ( temp && temp->getType() == MX_TREEVIEW )
+ {
+ NMTREEVIEW *nmt = ( NMTREEVIEW * )nmhdr;
+
+ HTREEITEM hItem = TreeView_GetSelection (nmhdr->hwndFrom);
+
+ char sz[ 256 ];
+ sprintf( sz, "tree view receiving notify %i : %s action %i old %p new %p selection %p\n", nmhdr->code, translatecode( nmhdr->code ),
+ nmt->action, nmt->itemOld, nmt->itemNew, hItem );
+
+ OutputDebugString( sz );
+ }
+ }
+#endif
+
+ if (nmhdr->code == TVN_SELCHANGED)
+ {
+ if (nmhdr->idFrom > 0)
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ event.event = mxEvent::Action;
+ event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA);
+ event.action = (int) nmhdr->idFrom;
+
+ RECT rc;
+ HTREEITEM hItem = TreeView_GetSelection (nmhdr->hwndFrom);
+ TreeView_GetItemRect (nmhdr->hwndFrom, hItem, &rc, TRUE);
+ event.x = (int) rc.left;
+ event.y = (int) rc.bottom;
+ RecursiveHandleEvent( window, &event );
+
+ }
+ }
+ else if (nmhdr->code == LVN_ITEMCHANGED)
+ {
+ if (nmhdr->idFrom > 0)
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ event.event = mxEvent::Action;
+ event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA);
+ event.action = (int) nmhdr->idFrom;
+
+ RecursiveHandleEvent( window, &event );
+ }
+ }
+ else if (nmhdr->code == NM_RCLICK)
+ {
+ if (nmhdr->idFrom > 0)
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ event.event = mxEvent::Action;
+ event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA);
+ event.action = (int) nmhdr->idFrom;
+ event.flags = mxEvent::RightClicked;
+
+ if ( event.widget )
+ {
+ if ( event.widget->getType () == MX_TREEVIEW )
+ {
+ RECT rc;
+ HTREEITEM hItem = TreeView_GetSelection (nmhdr->hwndFrom);
+ TreeView_GetItemRect (nmhdr->hwndFrom, hItem, &rc, TRUE);
+ event.x = (int) rc.left;
+ event.y = (int) rc.bottom;
+ }
+ }
+ RecursiveHandleEvent( window, &event );
+ }
+ }
+ else if (nmhdr->code == NM_DBLCLK)
+ {
+ if (nmhdr->idFrom > 0)
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ event.event = mxEvent::Action;
+ event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA);
+ event.action = (int) nmhdr->idFrom;
+ event.flags = mxEvent::DoubleClicked;
+
+ if (event.widget )
+ {
+ if ( event.widget->getType () == MX_TREEVIEW )
+ {
+ RECT rc;
+ HTREEITEM hItem = TreeView_GetSelection (nmhdr->hwndFrom);
+ TreeView_GetItemRect (nmhdr->hwndFrom, hItem, &rc, TRUE);
+ event.x = (int) rc.left;
+ event.y = (int) rc.bottom;
+ }
+ }
+
+ RecursiveHandleEvent( window, &event );
+ return TRUE;
+ }
+ }
+ else if (nmhdr->code == TCN_SELCHANGING)
+ {
+ TC_ITEM ti;
+
+ int index = TabCtrl_GetCurSel (nmhdr->hwndFrom);
+ if (index >= 0)
+ {
+ ti.mask = TCIF_PARAM;
+ TabCtrl_GetItem (nmhdr->hwndFrom, index, &ti);
+ mxWindow *window = (mxWindow *) ti.lParam;
+ if (window)
+ window->setVisible (false);
+ }
+ }
+ else if (nmhdr->code == TCN_SELCHANGE)
+ {
+ mxTab_resizeChild (nmhdr->hwndFrom);
+ if (nmhdr->idFrom > 0)
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ event.event = mxEvent::Action;
+ event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA);
+ event.action = (int) nmhdr->idFrom;
+ RecursiveHandleEvent( window, &event );
+ }
+ }
+ }
+ break;
+
+ case WM_SIZE:
+ {
+ mxEvent event;
+
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ event.event = mxEvent::Size;
+ event.width = (int) LOWORD (lParam);
+ event.height = (int) HIWORD (lParam);
+ window->handleEvent (&event);
+ }
+ }
+ break;
+ case WM_WINDOWPOSCHANGED:
+ {
+ mxEvent event;
+
+
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ event.event = mxEvent::PosChanged;
+
+ WINDOWPOS *wp = ( WINDOWPOS * )lParam;
+
+ event.x = wp->x;
+ event.y = wp->y;
+ event.width = wp->cx;
+ event.height = wp->cy;
+
+ window->handleEvent (&event);
+ }
+ }
+ break;
+
+ case WM_ERASEBKGND:
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ if (window->getType () == MX_GLWINDOW)
+ return 0;
+ if (window->getType () == MX_MATSYSWINDOW)
+ return 0;
+
+ if ( !isClosing && !window->PaintBackground() )
+ {
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case WM_HSCROLL:
+ case WM_VSCROLL:
+ {
+ mxWidget *widget = (mxWidget *) GetWindowLong ((HWND) lParam, GWL_USERDATA);
+ if (!widget)
+ {
+ break;
+ }
+
+ if (widget->getType() != MX_SCROLLBAR && widget->getType() != MX_SLIDER)
+ {
+ break;
+ }
+
+
+ switch (LOWORD (wParam))
+ {
+ case TB_LINEUP: // SB_LINEUP SB_LINELEFT
+ break;
+ case TB_LINEDOWN: // SB_LINEDOWN SB_LINERIGHT
+ break;
+ case TB_PAGEUP: // SB_PAGEUP SB_PAGELEFT
+ break;
+ case TB_PAGEDOWN: // SB_PAGEDOWN SB_PAGERIGHT
+ break;
+ case TB_THUMBPOSITION: // SB_THUMBPOSITION
+ break;
+ case TB_THUMBTRACK: // SB_THUMBTRACK
+ break;
+ case TB_TOP: // SB_TOP SB_LEFT
+ break;
+ case TB_BOTTOM: // SB_BOTTOM SB_RIGHT
+ break;
+ case TB_ENDTRACK: // SB_ENDSCROLL
+ break;
+ default:
+ break;
+ }
+
+ switch (LOWORD (wParam))
+ {
+ case TB_LINEUP: // SB_LINEUP SB_LINELEFT
+ case TB_LINEDOWN: // SB_LINEDOWN SB_LINERIGHT
+ case TB_PAGEUP: // SB_PAGEUP SB_PAGELEFT
+ case TB_PAGEDOWN: // SB_PAGEDOWN SB_PAGERIGHT
+ case TB_THUMBPOSITION: // SB_THUMBPOSITION
+ case TB_THUMBTRACK: // SB_THUMBTRACK
+ case TB_TOP: // SB_TOP SB_LEFT
+ case TB_BOTTOM: // SB_BOTTOM SB_RIGHT
+ case TB_ENDTRACK: // SB_ENDSCROLL
+ {
+ mxEvent event;
+
+ event.event = mxEvent::Action;
+ event.widget = widget;
+ event.action = widget->getId ();
+ event.modifiers = LOWORD (wParam);
+ event.height = HIWORD( wParam );
+ mxWindow *window = widget->getParent ();
+
+ if ( event.action > 0 )
+ {
+ RecursiveHandleEvent( window, &event );
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case WM_PAINT:
+ {
+ if ( !isClosing )
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ window->redraw ();
+ }
+ }
+ }
+ break;
+
+ case WM_PARENTNOTIFY:
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ if ( wParam == WM_LBUTTONDOWN ||
+ wParam == WM_MBUTTONDOWN ||
+ wParam == WM_RBUTTONDOWN /*||
+ wParam & WM_XBUTTONDOWN*/ )
+ {
+ mxEvent event;
+ event.event = mxEvent::ParentNotify;
+ event.x = (short)LOWORD (lParam);
+ event.y = (short)HIWORD (lParam);
+ event.buttons = 0;
+ event.modifiers = 0;
+
+ if ( wParam == WM_LBUTTONDOWN )
+ event.buttons |= mxEvent::MouseLeftButton;
+
+ if ( wParam == WM_RBUTTONDOWN )
+ event.buttons |= mxEvent::MouseRightButton;
+
+ if ( wParam == WM_MBUTTONDOWN )
+ event.buttons |= mxEvent::MouseMiddleButton;
+
+ window->handleEvent (&event);
+ RecursiveHandleEvent( window, &event );
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ {
+ bDragging = TRUE;
+ SetCapture (hwnd);
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+
+ if (window)
+ {
+ mxEvent event;
+ event.event = mxEvent::MouseDown;
+ event.x = (short)LOWORD (lParam);
+ event.y = (short)HIWORD (lParam);
+ event.buttons = 0;
+ event.modifiers = 0;
+
+ if (uMessage == WM_MBUTTONDOWN)
+ event.buttons |= mxEvent::MouseMiddleButton;
+ else if (uMessage == WM_RBUTTONDOWN)
+ event.buttons |= mxEvent::MouseRightButton;
+ else
+ event.buttons |= mxEvent::MouseLeftButton;
+
+ if (wParam & MK_LBUTTON)
+ event.buttons |= mxEvent::MouseLeftButton;
+
+ if (wParam & MK_RBUTTON)
+ event.buttons |= mxEvent::MouseRightButton;
+
+ if (wParam & MK_MBUTTON)
+ event.buttons |= mxEvent::MouseMiddleButton;
+
+ if (wParam & MK_CONTROL)
+ event.modifiers |= mxEvent::KeyCtrl;
+
+ if (wParam & MK_SHIFT)
+ event.modifiers |= mxEvent::KeyShift;
+
+ window->handleEvent (&event);
+ }
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ case WM_MBUTTONUP:
+ case WM_RBUTTONUP:
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ mxEvent event;
+ event.event = mxEvent::MouseUp;
+ event.x = (short) LOWORD (lParam);
+ event.y = (short) HIWORD (lParam);
+ event.buttons = 0;
+ event.modifiers = 0;
+
+ if (uMessage == WM_MBUTTONUP)
+ event.buttons |= mxEvent::MouseMiddleButton;
+ else if (uMessage == WM_RBUTTONUP)
+ event.buttons |= mxEvent::MouseRightButton;
+ else
+ event.buttons |= mxEvent::MouseLeftButton;
+
+ if (wParam & MK_LBUTTON)
+ event.buttons |= mxEvent::MouseLeftButton;
+
+ if (wParam & MK_RBUTTON)
+ event.buttons |= mxEvent::MouseRightButton;
+
+ if (wParam & MK_MBUTTON)
+ event.buttons |= mxEvent::MouseMiddleButton;
+
+ if (wParam & MK_CONTROL)
+ event.modifiers |= mxEvent::KeyCtrl;
+
+ if (wParam & MK_SHIFT)
+ event.modifiers |= mxEvent::KeyShift;
+
+ window->handleEvent (&event);
+ }
+ bDragging = FALSE;
+ ReleaseCapture ();
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ mxEvent event;
+
+ if (bDragging)
+ event.event = mxEvent::MouseDrag;
+ else
+ event.event = mxEvent::MouseMove;
+
+ event.x = (short) LOWORD (lParam);
+ event.y = (short) HIWORD (lParam);
+ event.buttons = 0;
+ event.modifiers = 0;
+
+ if (wParam & MK_LBUTTON)
+ event.buttons |= mxEvent::MouseLeftButton;
+
+ if (wParam & MK_RBUTTON)
+ event.buttons |= mxEvent::MouseRightButton;
+
+ if (wParam & MK_MBUTTON)
+ event.buttons |= mxEvent::MouseMiddleButton;
+
+ if (wParam & MK_CONTROL)
+ event.modifiers |= mxEvent::KeyCtrl;
+
+ if (wParam & MK_SHIFT)
+ event.modifiers |= mxEvent::KeyShift;
+
+ window->handleEvent (&event);
+ }
+ }
+ break;
+ case WM_NCLBUTTONDOWN:
+ case WM_NCMBUTTONDOWN:
+ case WM_NCRBUTTONDOWN:
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+
+ if (window)
+ {
+ mxEvent event;
+ event.event = mxEvent::NCMouseDown;
+ event.x = (short) LOWORD (lParam);
+ event.y = (short) HIWORD (lParam);
+ event.buttons = 0;
+ event.modifiers = 0;
+
+ if (uMessage == WM_NCMBUTTONDOWN)
+ event.buttons |= mxEvent::MouseMiddleButton;
+ else if (uMessage == WM_NCRBUTTONDOWN)
+ event.buttons |= mxEvent::MouseRightButton;
+ else
+ event.buttons |= mxEvent::MouseLeftButton;
+
+ window->handleEvent (&event);
+ }
+ }
+ break;
+
+ case WM_NCLBUTTONUP:
+ case WM_NCMBUTTONUP:
+ case WM_NCRBUTTONUP:
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ mxEvent event;
+ event.event = mxEvent::NCMouseUp;
+ event.x = (short) LOWORD (lParam);
+ event.y = (short) HIWORD (lParam);
+ event.buttons = 0;
+ event.modifiers = 0;
+
+ if (uMessage == WM_NCMBUTTONUP)
+ event.buttons |= mxEvent::MouseMiddleButton;
+ else if (uMessage == WM_NCRBUTTONUP)
+ event.buttons |= mxEvent::MouseRightButton;
+ else
+ event.buttons |= mxEvent::MouseLeftButton;
+
+ window->handleEvent (&event);
+ }
+ }
+ break;
+
+ case WM_NCMOUSEMOVE:
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ mxEvent event;
+
+ event.event = mxEvent::NCMouseMove;
+
+ event.x = (short) LOWORD (lParam);
+ event.y = (short) HIWORD (lParam);
+ event.buttons = 0;
+ event.modifiers = 0;
+
+ window->handleEvent (&event);
+ }
+ }
+ break;
+
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ mxEvent event;
+ event.event = mxEvent::KeyDown;
+ event.key = (int) wParam;
+ if ( window->handleEvent (&event) )
+ return 0;
+ }
+ }
+ break;
+
+ case WM_CHAR:
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ mxEvent event;
+ event.event = mxEvent::Char;
+ event.key = (int) wParam;
+ if ( window->handleEvent (&event) )
+ return 0;
+ }
+ }
+ break;
+
+ case WM_SYSCHAR:
+ return 0;
+ break;
+
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ mxEvent event;
+ event.event = mxEvent::KeyUp;
+ event.key = (int) wParam;
+ if ( window->handleEvent (&event) )
+ return 0;
+ }
+ }
+ break;
+
+ case WM_MOUSEWHEEL:
+ {
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ mxEvent event;
+ memset( &event, 0, sizeof( event ) );
+ event.event = mxEvent::MouseWheeled;
+ event.x = (short) LOWORD (lParam);
+ event.y = (short) HIWORD (lParam);
+
+ if (wParam & MK_LBUTTON)
+ event.buttons |= mxEvent::MouseLeftButton;
+
+ if (wParam & MK_RBUTTON)
+ event.buttons |= mxEvent::MouseRightButton;
+
+ if (wParam & MK_MBUTTON)
+ event.buttons |= mxEvent::MouseMiddleButton;
+
+ if (wParam & MK_CONTROL)
+ event.modifiers |= mxEvent::KeyCtrl;
+
+ if (wParam & MK_SHIFT)
+ event.modifiers |= mxEvent::KeyShift;
+
+ event.height = (short)HIWORD( wParam );;
+ RecursiveHandleEvent( window, &event );
+ }
+ }
+ break;
+ case WM_TIMER:
+ {
+ if (isClosing)
+ break;
+
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ mxEvent event;
+ event.event = mxEvent::Timer;
+ window->handleEvent (&event);
+ }
+ }
+ break;
+
+ case WM_CLOSE:
+ if (g_mainWindow)
+ {
+ if ((void *) hwnd == g_mainWindow->getHandle ())
+ {
+ mx::quit ();
+ }
+ else
+ {
+ ShowWindow (hwnd, SW_HIDE);
+
+ mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
+ if (window)
+ {
+ mxEvent event;
+ event.event = mxEvent::Close;
+ window->handleEvent( &event );
+ }
+ }
+ }
+ //else // shouldn't happen
+ //DestroyWindow (hwnd);
+ return 0;
+/*
+ case WM_DESTROY:
+ if (g_mainWindow)
+ {
+ if ((void *) hwnd == g_mainWindow->getHandle ())
+ mx::quit ();
+ }
+ break;
+*/
+ }
+
+ return DefWindowProc (hwnd, uMessage, wParam, lParam);
+}
+
+
+
+int
+mx::init(int argc, char **argv)
+{
+ WNDCLASS wc;
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ wc.lpfnWndProc = WndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = (HINSTANCE) GetModuleHandle (NULL);
+ wc.hIcon = LoadIcon (wc.hInstance, "MX_ICON");
+ wc.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "mx_class";
+
+ if (!wc.hIcon)
+ wc.hIcon = LoadIcon (NULL, IDI_WINLOGO);
+
+ if (!RegisterClass (&wc))
+ return 0;
+
+ InitCommonControls ();
+
+ g_widgetList = new mxLinkedList ();
+
+ isClosing = false;
+
+ return 1;
+}
+
+
+
+int
+mx::run()
+{
+ int messagecount = 0;
+
+ while (1)
+ {
+ bool doframe = false;
+ if ( PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE) || !g_idleWindow )
+ {
+ if (!GetMessage (&msg, NULL, 0, 0))
+ {
+ doframe = false;
+ break;
+ }
+
+ if ( !g_hAcceleratorTable ||
+ !TranslateAccelerator( (HWND)g_mainWindow->getHandle (), g_hAcceleratorTable, &msg ))
+ {
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+ messagecount++;
+
+ if ( messagecount > 10 )
+ {
+ messagecount = 0;
+ doframe = true;
+ }
+ }
+ else if (g_idleWindow)
+ {
+ doframe = true;
+ messagecount = 0;
+ }
+
+ if ( doframe && g_idleWindow )
+ {
+ mxEvent event;
+ event.event = mxEvent::Idle;
+ g_idleWindow->handleEvent (&event);
+ }
+ }
+
+ return msg.wParam;
+}
+
+
+
+int
+mx::check ()
+{
+ if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
+ {
+ if (GetMessage (&msg, NULL, 0, 0))
+ {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+
+void
+mx::quit ()
+{
+ isClosing = true;
+
+ mxWindow *mainwnd = getMainWindow();
+ if ( mainwnd )
+ {
+ if ( !mainwnd->Closing() )
+ {
+ isClosing = false;
+ return;
+ }
+ }
+
+ if (g_widgetList)
+ {
+ // remove from back to front
+ mxListNode *node = g_widgetList->getLast ();
+
+ // Pass 1, see if anyone objects to closing
+ while (node)
+ {
+ mxWidget *widget = (mxWidget *) g_widgetList->getData (node);
+ node = g_widgetList->getPrev (node);
+
+ bool canclose = true;
+ if ( widget )
+ {
+ if ( !widget->CanClose() )
+ {
+ canclose = false;
+ }
+ }
+
+ if ( !canclose )
+ {
+ isClosing = false;
+ return;
+ }
+ }
+
+ node = g_widgetList->getLast ();
+
+ // Pass 2, call OnDelete to allow final cleanup
+ while (node)
+ {
+ mxWidget *widget = (mxWidget *) g_widgetList->getData (node);
+ node = g_widgetList->getPrev (node);
+
+ if ( widget )
+ {
+ widget->OnDelete();
+ }
+ }
+
+ node = g_widgetList->getLast ();
+
+ // Pass 3, delete stuff
+ while (node)
+ {
+ mxWidget *widget = (mxWidget *) g_widgetList->getData (node);
+ node = g_widgetList->getPrev (node);
+
+ // remove it!
+ if ( widget )
+ {
+ delete widget;
+ }
+ }
+
+ delete g_widgetList;
+ }
+
+ if (g_hwndToolTipControl)
+ DestroyWindow (g_hwndToolTipControl);
+
+ if ( g_hAcceleratorTable )
+ {
+ DestroyAcceleratorTable( g_hAcceleratorTable );
+ g_hAcceleratorTable = 0;
+ }
+
+ PostQuitMessage (0);
+ UnregisterClass ("mx_class", (HINSTANCE) GetModuleHandle (NULL));
+}
+
+
+
+int
+mx::setDisplayMode (int w, int h, int bpp)
+{
+ DEVMODE dm;
+
+ dm.dmSize = sizeof (DEVMODE);
+ dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+ dm.dmBitsPerPel = bpp;
+ dm.dmPelsWidth = w;
+ dm.dmPelsHeight = h;
+
+ if (w == 0 || h == 0 || bpp == 0)
+ ChangeDisplaySettings (0, 0);
+ else
+ ChangeDisplaySettings (&dm, CDS_FULLSCREEN);
+
+ return 0;
+}
+
+
+
+void
+mx::setIdleWindow (mxWindow *window)
+{
+ g_idleWindow = window;
+}
+
+
+
+int
+mx::getDisplayWidth ()
+{
+ return (int) GetSystemMetrics (SM_CXSCREEN);
+}
+
+
+
+int
+mx::getDisplayHeight ()
+{
+ return (int) GetSystemMetrics (SM_CYSCREEN);
+}
+
+
+
+mxWindow*
+mx::getMainWindow ()
+{
+ return g_mainWindow;
+}
+
+
+
+const char *
+mx::getApplicationPath ()
+{
+ static char path[256];
+ GetModuleFileName (0, path, 256);
+ char *ptr = strrchr (path, '\\');
+ if (ptr)
+ *ptr = '\0';
+
+ return path;
+}
+
+
+
+int
+mx::getTickCount ()
+{
+ return (int) GetTickCount ();
+}