+ case SC_MAXIMIZE:
+ return HandleMaximize();
+
+ case SC_MINIMIZE:
+ return HandleMinimize();
+ }
+
+ return FALSE;
+}
+
+// ---------------------------------------------------------------------------
+// mouse events
+// ---------------------------------------------------------------------------
+
+void wxWindow::InitMouseEvent(wxMouseEvent& event, int x, int y, WXUINT flags)
+{
+ event.m_x = x;
+ event.m_y = y;
+ event.m_shiftDown = ((flags & MK_SHIFT) != 0);
+ event.m_controlDown = ((flags & MK_CONTROL) != 0);
+ event.m_leftDown = ((flags & MK_LBUTTON) != 0);
+ event.m_middleDown = ((flags & MK_MBUTTON) != 0);
+ event.m_rightDown = ((flags & MK_RBUTTON) != 0);
+ event.SetTimestamp(s_currentMsg.time);
+ event.m_eventObject = this;
+
+#if wxUSE_MOUSEEVENT_HACK
+ m_lastMouseX = x;
+ m_lastMouseY = y;
+ m_lastMouseEvent = event.GetEventType();
+#endif // wxUSE_MOUSEEVENT_HACK
+
+}
+
+bool wxWindow::HandleMouseEvent(WXUINT msg, int x, int y, WXUINT flags)
+{
+ // the mouse events take consecutive IDs from WM_MOUSEFIRST to
+ // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
+ // from the message id and take the value in the table to get wxWin event
+ // id
+ static const wxEventType eventsMouse[] =
+ {
+ wxEVT_MOTION,
+ wxEVT_LEFT_DOWN,
+ wxEVT_LEFT_UP,
+ wxEVT_LEFT_DCLICK,
+ wxEVT_RIGHT_DOWN,
+ wxEVT_RIGHT_UP,
+ wxEVT_RIGHT_DCLICK,
+ wxEVT_MIDDLE_DOWN,
+ wxEVT_MIDDLE_UP,
+ wxEVT_MIDDLE_DCLICK
+ };
+
+ wxMouseEvent event(eventsMouse[msg - WM_MOUSEMOVE]);
+ InitMouseEvent(event, x, y, flags);
+
+ return GetEventHandler()->ProcessEvent(event);
+}
+
+bool wxWindow::HandleMouseMove(int x, int y, WXUINT flags)
+{
+ if ( !m_mouseInWindow )
+ {
+ // Generate an ENTER event
+ m_mouseInWindow = TRUE;
+
+ wxMouseEvent event(wxEVT_ENTER_WINDOW);
+ InitMouseEvent(event, x, y, flags);
+
+ (void)GetEventHandler()->ProcessEvent(event);
+ }
+
+#if wxUSE_MOUSEEVENT_HACK
+ // Window gets a click down message followed by a mouse move message even
+ // if position isn't changed! We want to discard the trailing move event
+ // if x and y are the same.
+ if ( (m_lastMouseEvent == wxEVT_RIGHT_DOWN ||
+ m_lastMouseEvent == wxEVT_LEFT_DOWN ||
+ m_lastMouseEvent == wxEVT_MIDDLE_DOWN) &&
+ (m_lastMouseX == event.m_x && m_lastMouseY == event.m_y) )
+ {
+ m_lastMouseEvent = wxEVT_MOTION;
+
+ return FALSE;
+ }
+#endif // wxUSE_MOUSEEVENT_HACK
+
+ return HandleMouseEvent(WM_MOUSEMOVE, x, y, flags);
+}
+
+// ---------------------------------------------------------------------------
+// keyboard handling
+// ---------------------------------------------------------------------------
+
+// create the key event of the given type for the given key - used by
+// HandleChar and HandleKeyDown/Up
+wxKeyEvent wxWindow::CreateKeyEvent(wxEventType evType,
+ int id,
+ WXLPARAM lParam) const
+{
+ wxKeyEvent event(evType);
+ event.SetId(GetId());
+ event.m_shiftDown = IsShiftDown();
+ event.m_controlDown = IsCtrlDown();
+ event.m_altDown = (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN;
+
+ event.m_eventObject = (wxWindow *)this; // const_cast
+ event.m_keyCode = id;
+ event.SetTimestamp(s_currentMsg.time);
+
+ // translate the position to client coords
+ POINT pt;
+ GetCursorPos(&pt);
+ RECT rect;
+ GetWindowRect(GetHwnd(),&rect);
+ pt.x -= rect.left;
+ pt.y -= rect.top;
+
+ event.m_x = pt.x;
+ event.m_y = pt.y;
+
+ return event;
+}
+
+// isASCII is TRUE only when we're called from WM_CHAR handler and not from
+// WM_KEYDOWN one
+bool wxWindow::HandleChar(WXWORD wParam, WXLPARAM lParam, bool isASCII)
+{
+ bool ctrlDown = FALSE;
+
+ int id;
+ if ( isASCII )
+ {
+ // If 1 -> 26, translate to CTRL plus a letter.
+ id = wParam;
+ if ( (id > 0) && (id < 27) )
+ {
+ switch (id)
+ {
+ case 13:
+ id = WXK_RETURN;
+ break;
+
+ case 8:
+ id = WXK_BACK;
+ break;
+
+ case 9:
+ id = WXK_TAB;
+ break;
+
+ default:
+ ctrlDown = TRUE;
+ id = id + 96;
+ }
+ }
+ }
+ else if ( (id = wxCharCodeMSWToWX(wParam)) == 0 )
+ {
+ // it's ASCII and will be processed here only when called from
+ // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
+ id = -1;
+ }
+
+ if ( id != -1 )
+ {
+ wxKeyEvent event(CreateKeyEvent(wxEVT_CHAR, id, lParam));
+ if ( ctrlDown )
+ {
+ event.m_controlDown = TRUE;
+ }
+
+ if ( GetEventHandler()->ProcessEvent(event) )
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+bool wxWindow::HandleKeyDown(WXWORD wParam, WXLPARAM lParam)
+{
+ int id = wxCharCodeMSWToWX(wParam);
+
+ if ( !id )
+ {
+ // normal ASCII char
+ id = wParam;
+ }
+
+ if ( id != -1 ) // VZ: does this ever happen (FIXME)?
+ {
+ wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam));
+ if ( GetEventHandler()->ProcessEvent(event) )
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+bool wxWindow::HandleKeyUp(WXWORD wParam, WXLPARAM lParam)
+{
+ int id = wxCharCodeMSWToWX(wParam);
+
+ if ( !id )
+ {
+ // normal ASCII char
+ id = wParam;
+ }
+
+ if ( id != -1 ) // VZ: does this ever happen (FIXME)?
+ {
+ wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam));
+ if ( GetEventHandler()->ProcessEvent(event) )
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// ---------------------------------------------------------------------------
+// joystick
+// ---------------------------------------------------------------------------
+
+bool wxWindow::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags)
+{
+ int change = 0;
+ if ( flags & JOY_BUTTON1CHG )
+ change = wxJOY_BUTTON1;
+ if ( flags & JOY_BUTTON2CHG )
+ change = wxJOY_BUTTON2;
+ if ( flags & JOY_BUTTON3CHG )
+ change = wxJOY_BUTTON3;
+ if ( flags & JOY_BUTTON4CHG )
+ change = wxJOY_BUTTON4;
+
+ int buttons = 0;
+ if ( flags & JOY_BUTTON1 )
+ buttons |= wxJOY_BUTTON1;
+ if ( flags & JOY_BUTTON2 )
+ buttons |= wxJOY_BUTTON2;
+ if ( flags & JOY_BUTTON3 )
+ buttons |= wxJOY_BUTTON3;
+ if ( flags & JOY_BUTTON4 )
+ buttons |= wxJOY_BUTTON4;
+
+ // the event ids aren't consecutive so we can't use table based lookup
+ int joystick;
+ wxEventType eventType;
+ switch ( msg )
+ {
+ case MM_JOY1MOVE:
+ joystick = 1;
+ eventType = wxEVT_JOY_MOVE;
+ break;
+
+ case MM_JOY2MOVE:
+ joystick = 2;
+ eventType = wxEVT_JOY_MOVE;
+ break;
+
+ case MM_JOY1ZMOVE:
+ joystick = 1;
+ eventType = wxEVT_JOY_ZMOVE;
+ break;
+
+ case MM_JOY2ZMOVE:
+ joystick = 2;
+ eventType = wxEVT_JOY_ZMOVE;
+ break;
+
+ case MM_JOY1BUTTONDOWN:
+ joystick = 1;
+ eventType = wxEVT_JOY_BUTTON_DOWN;
+ break;
+
+ case MM_JOY2BUTTONDOWN:
+ joystick = 2;
+ eventType = wxEVT_JOY_BUTTON_DOWN;
+ break;
+
+ case MM_JOY1BUTTONUP:
+ joystick = 1;
+ eventType = wxEVT_JOY_BUTTON_UP;
+ break;
+
+ case MM_JOY2BUTTONUP:
+ joystick = 2;
+ eventType = wxEVT_JOY_BUTTON_UP;
+ break;
+
+ default:
+ wxFAIL_MSG(wxT("no such joystick event"));
+
+ return FALSE;
+ }
+
+ wxJoystickEvent event(eventType, buttons, joystick, change);
+ event.SetPosition(wxPoint(x, y));
+ event.SetEventObject(this);
+
+ return GetEventHandler()->ProcessEvent(event);
+}
+
+// ---------------------------------------------------------------------------
+// scrolling
+// ---------------------------------------------------------------------------
+
+bool wxWindow::MSWOnScroll(int orientation, WXWORD wParam,
+ WXWORD pos, WXHWND control)
+{
+ if ( control )
+ {
+ wxWindow *child = wxFindWinFromHandle(control);
+ if ( child )
+ return child->MSWOnScroll(orientation, wParam, pos, control);
+ }
+
+ wxScrollWinEvent event;
+ event.SetPosition(pos);
+ event.SetOrientation(orientation);
+ event.m_eventObject = this;
+
+ switch ( wParam )
+ {
+ case SB_TOP:
+ event.m_eventType = wxEVT_SCROLLWIN_TOP;
+ break;
+
+ case SB_BOTTOM:
+ event.m_eventType = wxEVT_SCROLLWIN_BOTTOM;
+ break;
+
+ case SB_LINEUP:
+ event.m_eventType = wxEVT_SCROLLWIN_LINEUP;
+ break;
+
+ case SB_LINEDOWN:
+ event.m_eventType = wxEVT_SCROLLWIN_LINEDOWN;
+ break;
+
+ case SB_PAGEUP:
+ event.m_eventType = wxEVT_SCROLLWIN_PAGEUP;
+ break;
+
+ case SB_PAGEDOWN:
+ event.m_eventType = wxEVT_SCROLLWIN_PAGEDOWN;
+ break;
+
+ case SB_THUMBPOSITION:
+ event.m_eventType = wxEVT_SCROLLWIN_THUMBRELEASE;
+ break;
+
+ case SB_THUMBTRACK:
+ event.m_eventType = wxEVT_SCROLLWIN_THUMBTRACK;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ return GetEventHandler()->ProcessEvent(event);
+}
+
+// ===========================================================================
+// global functions
+// ===========================================================================
+
+void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont *the_font)
+{
+ TEXTMETRIC tm;
+ HDC dc = ::GetDC((HWND) wnd);
+ HFONT fnt =0;
+ HFONT was = 0;
+ if ( the_font )
+ {
+ // the_font->UseResource();
+ // the_font->RealizeResource();
+ fnt = (HFONT)((wxFont *)the_font)->GetResourceHandle(); // const_cast
+ if ( fnt )
+ was = (HFONT) SelectObject(dc,fnt);
+ }
+ GetTextMetrics(dc, &tm);
+ if ( the_font && fnt && was )
+ {
+ SelectObject(dc,was);
+ }
+ ReleaseDC((HWND)wnd, dc);
+
+ if ( x )
+ *x = tm.tmAveCharWidth;
+ if ( y )
+ *y = tm.tmHeight + tm.tmExternalLeading;
+
+ // if ( the_font )
+ // the_font->ReleaseResource();
+}
+
+// Returns 0 if was a normal ASCII value, not a special key. This indicates that
+// the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
+int wxCharCodeMSWToWX(int keySym)
+{
+ int id = 0;
+ switch (keySym)
+ {
+ case VK_CANCEL: id = WXK_CANCEL; break;
+ case VK_BACK: id = WXK_BACK; break;
+ case VK_TAB: id = WXK_TAB; break;
+ case VK_CLEAR: id = WXK_CLEAR; break;
+ case VK_RETURN: id = WXK_RETURN; break;
+ case VK_SHIFT: id = WXK_SHIFT; break;
+ case VK_CONTROL: id = WXK_CONTROL; break;
+ case VK_MENU : id = WXK_MENU; break;
+ case VK_PAUSE: id = WXK_PAUSE; break;
+ case VK_SPACE: id = WXK_SPACE; break;
+ case VK_ESCAPE: id = WXK_ESCAPE; break;
+ case VK_PRIOR: id = WXK_PRIOR; break;
+ case VK_NEXT : id = WXK_NEXT; break;
+ case VK_END: id = WXK_END; break;
+ case VK_HOME : id = WXK_HOME; break;
+ case VK_LEFT : id = WXK_LEFT; break;
+ case VK_UP: id = WXK_UP; break;
+ case VK_RIGHT: id = WXK_RIGHT; break;
+ case VK_DOWN : id = WXK_DOWN; break;
+ case VK_SELECT: id = WXK_SELECT; break;
+ case VK_PRINT: id = WXK_PRINT; break;
+ case VK_EXECUTE: id = WXK_EXECUTE; break;
+ case VK_INSERT: id = WXK_INSERT; break;
+ case VK_DELETE: id = WXK_DELETE; break;
+ case VK_HELP : id = WXK_HELP; break;
+ case VK_NUMPAD0: id = WXK_NUMPAD0; break;
+ case VK_NUMPAD1: id = WXK_NUMPAD1; break;
+ case VK_NUMPAD2: id = WXK_NUMPAD2; break;
+ case VK_NUMPAD3: id = WXK_NUMPAD3; break;
+ case VK_NUMPAD4: id = WXK_NUMPAD4; break;
+ case VK_NUMPAD5: id = WXK_NUMPAD5; break;
+ case VK_NUMPAD6: id = WXK_NUMPAD6; break;
+ case VK_NUMPAD7: id = WXK_NUMPAD7; break;
+ case VK_NUMPAD8: id = WXK_NUMPAD8; break;
+ case VK_NUMPAD9: id = WXK_NUMPAD9; break;
+ case VK_MULTIPLY: id = WXK_MULTIPLY; break;
+ case VK_ADD: id = WXK_ADD; break;
+ case VK_SUBTRACT: id = WXK_SUBTRACT; break;
+ case VK_DECIMAL: id = WXK_DECIMAL; break;
+ case VK_DIVIDE: id = WXK_DIVIDE; break;
+ case VK_F1: id = WXK_F1; break;
+ case VK_F2: id = WXK_F2; break;
+ case VK_F3: id = WXK_F3; break;
+ case VK_F4: id = WXK_F4; break;
+ case VK_F5: id = WXK_F5; break;
+ case VK_F6: id = WXK_F6; break;
+ case VK_F7: id = WXK_F7; break;
+ case VK_F8: id = WXK_F8; break;
+ case VK_F9: id = WXK_F9; break;
+ case VK_F10: id = WXK_F10; break;
+ case VK_F11: id = WXK_F11; break;
+ case VK_F12: id = WXK_F12; break;
+ case VK_F13: id = WXK_F13; break;
+ case VK_F14: id = WXK_F14; break;
+ case VK_F15: id = WXK_F15; break;
+ case VK_F16: id = WXK_F16; break;
+ case VK_F17: id = WXK_F17; break;
+ case VK_F18: id = WXK_F18; break;
+ case VK_F19: id = WXK_F19; break;
+ case VK_F20: id = WXK_F20; break;
+ case VK_F21: id = WXK_F21; break;
+ case VK_F22: id = WXK_F22; break;
+ case VK_F23: id = WXK_F23; break;
+ case VK_F24: id = WXK_F24; break;
+ case VK_NUMLOCK: id = WXK_NUMLOCK; break;
+ case VK_SCROLL: id = WXK_SCROLL; break;
+ default:
+ {
+ return 0;
+ }
+ }
+ return id;
+}
+
+int wxCharCodeWXToMSW(int id, bool *isVirtual)
+{
+ *isVirtual = TRUE;
+ int keySym = 0;
+ switch (id)
+ {
+ case WXK_CANCEL: keySym = VK_CANCEL; break;
+ case WXK_CLEAR: keySym = VK_CLEAR; break;
+ case WXK_SHIFT: keySym = VK_SHIFT; break;
+ case WXK_CONTROL: keySym = VK_CONTROL; break;
+ case WXK_MENU : keySym = VK_MENU; break;
+ case WXK_PAUSE: keySym = VK_PAUSE; break;
+ case WXK_PRIOR: keySym = VK_PRIOR; break;
+ case WXK_NEXT : keySym = VK_NEXT; break;
+ case WXK_END: keySym = VK_END; break;
+ case WXK_HOME : keySym = VK_HOME; break;
+ case WXK_LEFT : keySym = VK_LEFT; break;
+ case WXK_UP: keySym = VK_UP; break;
+ case WXK_RIGHT: keySym = VK_RIGHT; break;
+ case WXK_DOWN : keySym = VK_DOWN; break;
+ case WXK_SELECT: keySym = VK_SELECT; break;
+ case WXK_PRINT: keySym = VK_PRINT; break;
+ case WXK_EXECUTE: keySym = VK_EXECUTE; break;
+ case WXK_INSERT: keySym = VK_INSERT; break;
+ case WXK_DELETE: keySym = VK_DELETE; break;
+ case WXK_HELP : keySym = VK_HELP; break;
+ case WXK_NUMPAD0: keySym = VK_NUMPAD0; break;
+ case WXK_NUMPAD1: keySym = VK_NUMPAD1; break;
+ case WXK_NUMPAD2: keySym = VK_NUMPAD2; break;
+ case WXK_NUMPAD3: keySym = VK_NUMPAD3; break;
+ case WXK_NUMPAD4: keySym = VK_NUMPAD4; break;
+ case WXK_NUMPAD5: keySym = VK_NUMPAD5; break;
+ case WXK_NUMPAD6: keySym = VK_NUMPAD6; break;
+ case WXK_NUMPAD7: keySym = VK_NUMPAD7; break;
+ case WXK_NUMPAD8: keySym = VK_NUMPAD8; break;
+ case WXK_NUMPAD9: keySym = VK_NUMPAD9; break;
+ case WXK_MULTIPLY: keySym = VK_MULTIPLY; break;
+ case WXK_ADD: keySym = VK_ADD; break;
+ case WXK_SUBTRACT: keySym = VK_SUBTRACT; break;
+ case WXK_DECIMAL: keySym = VK_DECIMAL; break;
+ case WXK_DIVIDE: keySym = VK_DIVIDE; break;
+ case WXK_F1: keySym = VK_F1; break;
+ case WXK_F2: keySym = VK_F2; break;
+ case WXK_F3: keySym = VK_F3; break;
+ case WXK_F4: keySym = VK_F4; break;
+ case WXK_F5: keySym = VK_F5; break;
+ case WXK_F6: keySym = VK_F6; break;
+ case WXK_F7: keySym = VK_F7; break;
+ case WXK_F8: keySym = VK_F8; break;
+ case WXK_F9: keySym = VK_F9; break;
+ case WXK_F10: keySym = VK_F10; break;
+ case WXK_F11: keySym = VK_F11; break;
+ case WXK_F12: keySym = VK_F12; break;
+ case WXK_F13: keySym = VK_F13; break;
+ case WXK_F14: keySym = VK_F14; break;
+ case WXK_F15: keySym = VK_F15; break;
+ case WXK_F16: keySym = VK_F16; break;
+ case WXK_F17: keySym = VK_F17; break;
+ case WXK_F18: keySym = VK_F18; break;
+ case WXK_F19: keySym = VK_F19; break;
+ case WXK_F20: keySym = VK_F20; break;
+ case WXK_F21: keySym = VK_F21; break;
+ case WXK_F22: keySym = VK_F22; break;
+ case WXK_F23: keySym = VK_F23; break;
+ case WXK_F24: keySym = VK_F24; break;
+ case WXK_NUMLOCK: keySym = VK_NUMLOCK; break;
+ case WXK_SCROLL: keySym = VK_SCROLL; break;
+ default: