X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e7c652bc7aecc963aeb85022deeb810970d0dbcd..25b34b267ec6878c04add03e874986673fa0f19f:/src/msw/window.cpp diff --git a/src/msw/window.cpp b/src/msw/window.cpp index a4e435e411..32facca384 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -46,6 +46,8 @@ #include "wx/sizer.h" #include "wx/intl.h" #include "wx/log.h" + #include "wx/textctrl.h" + #include "wx/menuitem.h" #endif #if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__) @@ -54,6 +56,7 @@ #include "wx/evtloop.h" #include "wx/module.h" +#include "wx/power.h" #include "wx/sysopt.h" #if wxUSE_DRAG_AND_DROP @@ -72,8 +75,6 @@ #endif #endif -#include "wx/menuitem.h" - #include "wx/msw/private.h" #if wxUSE_TOOLTIPS @@ -88,7 +89,6 @@ #include "wx/spinctrl.h" #endif // wxUSE_SPINCTRL -#include "wx/textctrl.h" #include "wx/notebook.h" #include "wx/listctrl.h" @@ -103,7 +103,12 @@ #include #endif -#include +// include "properly" +#include "wx/msw/wrapcctl.h" + +#ifndef __WXWINCE__ + #include +#endif #include "wx/msw/missing.h" @@ -1141,6 +1146,25 @@ void wxWindowMSW::SetWindowStyleFlag(long flags) // update the internal variable wxWindowBase::SetWindowStyleFlag(flags); + // and the real window flags + MSWUpdateStyle(flagsOld, GetExtraStyle()); +} + +void wxWindowMSW::SetExtraStyle(long exflags) +{ + long exflagsOld = GetExtraStyle(); + if ( exflags == exflagsOld ) + return; + + // update the internal variable + wxWindowBase::SetExtraStyle(exflags); + + // and the real window flags + MSWUpdateStyle(GetWindowStyleFlag(), exflagsOld); +} + +void wxWindowMSW::MSWUpdateStyle(long flagsOld, long exflagsOld) +{ // now update the Windows style as well if needed - and if the window had // been already created if ( !GetHwnd() ) @@ -1149,9 +1173,21 @@ void wxWindowMSW::SetWindowStyleFlag(long flags) // we may need to call SetWindowPos() when we change some styles bool callSWP = false; - WXDWORD exstyle, exstyleOld; - long style = MSWGetStyle(flags, &exstyle), - styleOld = MSWGetStyle(flagsOld, &exstyleOld); + WXDWORD exstyle; + long style = MSWGetStyle(GetWindowStyleFlag(), &exstyle); + + // this is quite a horrible hack but we need it because MSWGetStyle() + // doesn't take exflags as parameter but uses GetExtraStyle() internally + // and so we have to modify the window exflags temporarily to get the + // correct exstyleOld + long exflagsNew = GetExtraStyle(); + wxWindowBase::SetExtraStyle(exflagsOld); + + WXDWORD exstyleOld; + long styleOld = MSWGetStyle(flagsOld, &exstyleOld); + + wxWindowBase::SetExtraStyle(exflagsNew); + if ( style != styleOld ) { @@ -1165,14 +1201,8 @@ void wxWindowMSW::SetWindowStyleFlag(long flags) ::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal); - // If any of the style changes changed any of the frame styles: - // MSDN: SetWindowLong: - // Certain window data is cached, so changes you make using - // SetWindowLong will not take effect until you call the - // SetWindowPos function. Specifically, if you change any of - // the frame styles, you must call SetWindowPos with the - // SWP_FRAMECHANGED flag for the cache to be updated properly. - + // we need to call SetWindowPos() if any of the styles affecting the + // frame appearance have changed callSWP = ((styleOld ^ style ) & (WS_BORDER | WS_THICKFRAME | WS_CAPTION | @@ -1537,6 +1567,7 @@ bool wxWindowMSW::IsSizeDeferred() const // Get total size void wxWindowMSW::DoGetSize(int *x, int *y) const { +#if USE_DEFERRED_SIZING // if SetSize() had been called at wx level but not realized at Windows // level yet (i.e. EndDeferWindowPos() not called), we still should return // the new and not the old position to the other wx code @@ -1548,6 +1579,7 @@ void wxWindowMSW::DoGetSize(int *x, int *y) const *y = m_pendingSize.y; } else // use current size +#endif // USE_DEFERRED_SIZING { RECT rect = wxGetWindowRect(GetHwnd()); @@ -1562,21 +1594,9 @@ void wxWindowMSW::DoGetSize(int *x, int *y) const void wxWindowMSW::DoGetClientSize(int *x, int *y) const { #if USE_DEFERRED_SIZING - if ( IsTopLevel() || m_pendingSize == wxDefaultSize ) -#endif - { // top level windows resizing is never deferred, so we can safely use - // the current size here - RECT rect = wxGetClientRect(GetHwnd()); - - if ( x ) - *x = rect.right; - if ( y ) - *y = rect.bottom; - } -#if USE_DEFERRED_SIZING - else // non top level and using deferred sizing + if ( m_pendingSize != wxDefaultSize ) { - // we need to calculate the *pending* client size here + // we need to calculate the client size corresponding to pending size RECT rect; rect.left = m_pendingPosition.x; rect.top = m_pendingPosition.y; @@ -1590,7 +1610,16 @@ void wxWindowMSW::DoGetClientSize(int *x, int *y) const if ( y ) *y = rect.bottom - rect.top; } -#endif + else +#endif // USE_DEFERRED_SIZING + { + RECT rect = wxGetClientRect(GetHwnd()); + + if ( x ) + *x = rect.right; + if ( y ) + *y = rect.bottom; + } } void wxWindowMSW::DoGetPosition(int *x, int *y) const @@ -2027,18 +2056,14 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // WM_GETDLGCODE: ask the control if it wants the key for itself, // don't process it if it's the case (except for Ctrl-Tab/Enter // combinations which are always processed) - LONG lDlgCode = 0; - if ( !bCtrlDown ) - { - lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0); + LONG lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0); - // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the - // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically, - // it, of course, implies them - if ( lDlgCode & DLGC_WANTALLKEYS ) - { - lDlgCode |= DLGC_WANTTAB | DLGC_WANTARROWS; - } + // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the + // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically, + // it, of course, implies them + if ( lDlgCode & DLGC_WANTALLKEYS ) + { + lDlgCode |= DLGC_WANTTAB | DLGC_WANTARROWS; } bool bForward = true, @@ -2075,6 +2100,20 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) bProcess = false; break; + case VK_PRIOR: + bForward = false; + // fall through + + case VK_NEXT: + // we treat PageUp/Dn as arrows because chances are that + // a control which needs arrows also needs them for + // navigation (e.g. wxTextCtrl, wxListCtrl, ...) + if ( (lDlgCode & DLGC_WANTARROWS) || !bCtrlDown ) + bProcess = false; + else + bWindowChange = true; + break; + case VK_RETURN: { if ( (lDlgCode & DLGC_WANTMESSAGE) && !bCtrlDown ) @@ -2267,7 +2306,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // relay mouse move events to the tooltip control MSG *msg = (MSG *)pMsg; if ( msg->message == WM_MOUSEMOVE ) - m_tooltip->RelayEvent(pMsg); + wxToolTip::RelayEvent(pMsg); } #endif // wxUSE_TOOLTIPS @@ -2994,50 +3033,48 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l #if defined(WM_HELP) case WM_HELP: { - // HELPINFO doesn't seem to be supported on WinCE. + // by default, WM_HELP is propagated by DefWindowProc() upwards + // to the window parent but as we do it ourselves already + // (wxHelpEvent is derived from wxCommandEvent), we don't want + // to get the other events if we process this message at all + processed = true; + + // WM_HELP doesn't use lParam under CE #ifndef __WXWINCE__ HELPINFO* info = (HELPINFO*) lParam; - // Don't yet process menu help events, just windows - if (info->iContextType == HELPINFO_WINDOW) + if ( info->iContextType == HELPINFO_WINDOW ) { -#endif - wxWindowMSW* subjectOfHelp = this; - bool eventProcessed = false; - while (subjectOfHelp && !eventProcessed) - { - wxHelpEvent helpEvent(wxEVT_HELP, - subjectOfHelp->GetId(), +#endif // !__WXWINCE__ + wxHelpEvent helpEvent + ( + wxEVT_HELP, + GetId(), #ifdef __WXWINCE__ - wxPoint(0,0) + wxGetMousePosition() // what else? #else - wxPoint(info->MousePos.x, info->MousePos.y) + wxPoint(info->MousePos.x, info->MousePos.y) #endif - ); - - helpEvent.SetEventObject(this); - eventProcessed = - GetEventHandler()->ProcessEvent(helpEvent); + ); - // Go up the window hierarchy until the event is - // handled (or not) - subjectOfHelp = subjectOfHelp->GetParent(); - } - - processed = eventProcessed; + helpEvent.SetEventObject(this); + GetEventHandler()->ProcessEvent(helpEvent); #ifndef __WXWINCE__ } - else if (info->iContextType == HELPINFO_MENUITEM) + else if ( info->iContextType == HELPINFO_MENUITEM ) { wxHelpEvent helpEvent(wxEVT_HELP, info->iCtrlId); helpEvent.SetEventObject(this); - processed = GetEventHandler()->ProcessEvent(helpEvent); + GetEventHandler()->ProcessEvent(helpEvent); } - //else: processed is already false -#endif + else // unknown help event? + { + processed = false; + } +#endif // !__WXWINCE__ } break; -#endif +#endif // WM_HELP #if !defined(__WXWINCE__) case WM_CONTEXTMENU: @@ -3078,6 +3115,16 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l } } break; + +#ifndef __WXWINCE__ + case WM_POWERBROADCAST: + { + bool vetoed; + processed = HandlePower(wParam, lParam, &vetoed); + rc.result = processed && vetoed ? BROADCAST_QUERY_DENY : TRUE; + } + break; +#endif // __WXWINCE__ } if ( !processed ) @@ -3377,7 +3424,7 @@ bool wxWindowMSW::HandleTooltipNotify(WXUINT code, // Truncate tooltip length if needed as otherwise we might not have // enough space for it in the buffer and MultiByteToWideChar() would // return an error - size_t tipLength = wxMin(ttip.Len(), WXSIZEOF(buf) - 1); + size_t tipLength = wxMin(ttip.length(), WXSIZEOF(buf) - 1); // Convert to WideChar without adding the NULL character. The NULL // character is added afterwards (this is more efficient). @@ -3785,6 +3832,69 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd), return false; } +bool wxWindowMSW::HandlePower(WXWPARAM WXUNUSED_IN_WINCE(wParam), + WXLPARAM WXUNUSED(lParam), + bool *WXUNUSED_IN_WINCE(vetoed)) +{ +#ifdef __WXWINCE__ + // FIXME + return false; +#else + wxEventType evtType; + switch ( wParam ) + { + case PBT_APMQUERYSUSPEND: + evtType = wxEVT_POWER_SUSPENDING; + break; + + case PBT_APMQUERYSUSPENDFAILED: + evtType = wxEVT_POWER_SUSPEND_CANCEL; + break; + + case PBT_APMSUSPEND: + evtType = wxEVT_POWER_SUSPENDED; + break; + + case PBT_APMRESUMESUSPEND: +#ifdef PBT_APMRESUMEAUTOMATIC + case PBT_APMRESUMEAUTOMATIC: +#endif + evtType = wxEVT_POWER_RESUME; + break; + + default: + wxLogDebug(_T("Unknown WM_POWERBROADCAST(%d) event"), wParam); + // fall through + + // these messages are currently not mapped to wx events + case PBT_APMQUERYSTANDBY: + case PBT_APMQUERYSTANDBYFAILED: + case PBT_APMSTANDBY: + case PBT_APMRESUMESTANDBY: + case PBT_APMBATTERYLOW: + case PBT_APMPOWERSTATUSCHANGE: + case PBT_APMOEMEVENT: + case PBT_APMRESUMECRITICAL: + evtType = wxEVT_NULL; + break; + } + + // don't handle unknown messages + if ( evtType == wxEVT_NULL ) + return false; + + // TODO: notify about PBTF_APMRESUMEFROMFAILURE in case of resume events? + + wxPowerEvent event(evtType); + if ( !GetEventHandler()->ProcessEvent(event) ) + return false; + + *vetoed = event.IsVetoed(); + + return true; +#endif +} + // --------------------------------------------------------------------------- // owner drawn stuff // --------------------------------------------------------------------------- @@ -4299,37 +4409,11 @@ WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC, WXHWND hWndToPaint) return 0; } -bool wxWindowMSW::HandlePrintClient(WXHDC hDC) +bool wxWindowMSW::HandlePrintClient(WXHDC WXUNUSED(hDC)) { - // we receive this message when DrawThemeParentBackground() is - // called from def window proc of several controls under XP and we - // must draw properly themed background here - // - // note that naively I'd expect filling the client rect with the - // brush returned by MSWGetBgBrush() work -- but for some reason it - // doesn't and we have to call parents MSWPrintChild() which is - // supposed to call DrawThemeBackground() with appropriate params - // - // also note that in this case lParam == PRF_CLIENT but we're - // clearly expected to paint the background and nothing else! - - if ( IsTopLevel() || InheritsBackgroundColour() ) - return false; - - // sometimes we don't want the parent to handle it at all, instead - // return whatever value this window wants - if ( !MSWShouldPropagatePrintChild() ) - return MSWPrintChild(hDC, (wxWindow *)this); - - for ( wxWindow *win = GetParent(); win; win = win->GetParent() ) - { - if ( win->MSWPrintChild(hDC, (wxWindow *)this) ) - return true; - - if ( win->IsTopLevel() || win->InheritsBackgroundColour() ) - break; - } - + // TODO: handle wxBG_STYLE_CUSTOM and/or wxBG_STYLE_COLOUR here so when + // DrawParentThemeBackground() from uxtheme.dll is called we don't get + // the default background e.g. the border when custom drawing buttons return false; } @@ -4921,35 +5005,14 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) int id; if ( isASCII ) { - // If 1 -> 26, translate to either special keycode or just set - // ctrlDown. IOW, Ctrl-C should result in keycode == 3 and - // ControlDown() == true. 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; - break; - } - } } else // we're called from WM_KEYDOWN { - id = wxCharCodeMSWToWX(wParam, lParam); + // don't pass lParam to wxCharCodeMSWToWX() here because we don't want + // to get numpad key codes: CHAR events should use the logical keys + // such as WXK_HOME instead of WXK_NUMPAD_HOME which is for KEY events + id = wxCharCodeMSWToWX(wParam); if ( id == 0 ) { // it's ASCII and will be processed here only when called from @@ -4986,16 +5049,8 @@ bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam) id = wParam; } - if ( id != -1 ) // VZ: does this ever happen (FIXME)? - { - wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam)); - if ( GetEventHandler()->ProcessEvent(event) ) - { - return true; - } - } - - return false; + wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam)); + return GetEventHandler()->ProcessEvent(event); } bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam) @@ -5008,14 +5063,8 @@ bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam) id = wParam; } - if ( id != -1 ) // VZ: does this ever happen (FIXME)? - { - wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam)); - if ( GetEventHandler()->ProcessEvent(event) ) - return true; - } - - return false; + wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam)); + return GetEventHandler()->ProcessEvent(event); } int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel), @@ -5088,6 +5137,18 @@ int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel), return wxNOT_FOUND; } +bool wxWindowMSW::HandleClipboardEvent( WXUINT nMsg ) +{ + const wxEventType type = ( nMsg == WM_CUT ) ? wxEVT_COMMAND_TEXT_CUT : + ( nMsg == WM_COPY ) ? wxEVT_COMMAND_TEXT_COPY : + /*( nMsg == WM_PASTE ) ? */ wxEVT_COMMAND_TEXT_PASTE; + wxClipboardTextEvent evt(type, GetId()); + + evt.SetEventObject(this); + + return GetEventHandler()->ProcessEvent(evt); +} + // --------------------------------------------------------------------------- // joystick // --------------------------------------------------------------------------- @@ -5303,244 +5364,277 @@ int ChooseNormalOrExtended(int lParam, int keyNormal, int keyExtended) return !lParam || (lParam & (1 << 24)) ? keyExtended : keyNormal; } +// this array contains the Windows virtual key codes which map one to one to +// WXK_xxx constants and is used in wxCharCodeMSWToWX/WXToMSW() below +// +// note that keys having a normal and numpad version (e.g. WXK_HOME and +// WXK_NUMPAD_HOME) are not included in this table as the mapping is not 1-to-1 +static const struct wxKeyMapping +{ + int vk; + wxKeyCode wxk; +} gs_specialKeys[] = +{ + { VK_CANCEL, WXK_CANCEL }, + { VK_BACK, WXK_BACK }, + { VK_TAB, WXK_TAB }, + { VK_CLEAR, WXK_CLEAR }, + { VK_SHIFT, WXK_SHIFT }, + { VK_CONTROL, WXK_CONTROL }, + { VK_MENU , WXK_ALT }, + { VK_PAUSE, WXK_PAUSE }, + { VK_CAPITAL, WXK_CAPITAL }, + { VK_SPACE, WXK_SPACE }, + { VK_ESCAPE, WXK_ESCAPE }, + { VK_SELECT, WXK_SELECT }, + { VK_PRINT, WXK_PRINT }, + { VK_EXECUTE, WXK_EXECUTE }, + { VK_SNAPSHOT, WXK_SNAPSHOT }, + { VK_HELP, WXK_HELP }, + + { VK_NUMPAD0, WXK_NUMPAD0 }, + { VK_NUMPAD1, WXK_NUMPAD1 }, + { VK_NUMPAD2, WXK_NUMPAD2 }, + { VK_NUMPAD3, WXK_NUMPAD3 }, + { VK_NUMPAD4, WXK_NUMPAD4 }, + { VK_NUMPAD5, WXK_NUMPAD5 }, + { VK_NUMPAD6, WXK_NUMPAD6 }, + { VK_NUMPAD7, WXK_NUMPAD7 }, + { VK_NUMPAD8, WXK_NUMPAD8 }, + { VK_NUMPAD9, WXK_NUMPAD9 }, + { VK_MULTIPLY, WXK_NUMPAD_MULTIPLY }, + { VK_ADD, WXK_NUMPAD_ADD }, + { VK_SUBTRACT, WXK_NUMPAD_SUBTRACT }, + { VK_DECIMAL, WXK_NUMPAD_DECIMAL }, + { VK_DIVIDE, WXK_NUMPAD_DIVIDE }, + + { VK_F1, WXK_F1 }, + { VK_F2, WXK_F2 }, + { VK_F3, WXK_F3 }, + { VK_F4, WXK_F4 }, + { VK_F5, WXK_F5 }, + { VK_F6, WXK_F6 }, + { VK_F7, WXK_F7 }, + { VK_F8, WXK_F8 }, + { VK_F9, WXK_F9 }, + { VK_F10, WXK_F10 }, + { VK_F11, WXK_F11 }, + { VK_F12, WXK_F12 }, + { VK_F13, WXK_F13 }, + { VK_F14, WXK_F14 }, + { VK_F15, WXK_F15 }, + { VK_F16, WXK_F16 }, + { VK_F17, WXK_F17 }, + { VK_F18, WXK_F18 }, + { VK_F19, WXK_F19 }, + { VK_F20, WXK_F20 }, + { VK_F21, WXK_F21 }, + { VK_F22, WXK_F22 }, + { VK_F23, WXK_F23 }, + { VK_F24, WXK_F24 }, + + { VK_NUMLOCK, WXK_NUMLOCK }, + { VK_SCROLL, WXK_SCROLL }, + +#ifdef VK_APPS + { VK_LWIN, WXK_WINDOWS_LEFT }, + { VK_RWIN, WXK_WINDOWS_RIGHT }, + { VK_APPS, WXK_WINDOWS_MENU }, +#endif // VK_APPS defined +}; + // 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, WXLPARAM lParam) +int wxCharCodeMSWToWX(int vk, WXLPARAM lParam) { - int id; - 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_SHIFT: id = WXK_SHIFT; break; - case VK_CONTROL: id = WXK_CONTROL; break; - case VK_MENU : id = WXK_ALT; break; - case VK_PAUSE: id = WXK_PAUSE; break; - case VK_CAPITAL: id = WXK_CAPITAL; break; - case VK_SPACE: id = WXK_SPACE; break; - case VK_ESCAPE: id = WXK_ESCAPE; break; - case VK_SELECT: id = WXK_SELECT; break; - case VK_PRINT: id = WXK_PRINT; break; - case VK_EXECUTE: id = WXK_EXECUTE; 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_NUMPAD_MULTIPLY; break; - case VK_ADD: id = WXK_NUMPAD_ADD; break; - case VK_SUBTRACT: id = WXK_NUMPAD_SUBTRACT; break; - case VK_DECIMAL: id = WXK_NUMPAD_DECIMAL; break; - case VK_DIVIDE: id = WXK_NUMPAD_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; + // check the table first + for ( size_t n = 0; n < WXSIZEOF(gs_specialKeys); n++ ) + { + if ( gs_specialKeys[n].vk == vk ) + return gs_specialKeys[n].wxk; + } + // keys requiring special handling + int wxk; + switch ( vk ) + { // the mapping for these keys may be incorrect on non-US keyboards so // maybe we shouldn't map them to ASCII values at all - case VK_OEM_1: id = ';'; break; - case VK_OEM_PLUS: id = '+'; break; - case VK_OEM_COMMA: id = ','; break; - case VK_OEM_MINUS: id = '-'; break; - case VK_OEM_PERIOD: id = '.'; break; - case VK_OEM_2: id = '/'; break; - case VK_OEM_3: id = '~'; break; - case VK_OEM_4: id = '['; break; - case VK_OEM_5: id = '\\'; break; - case VK_OEM_6: id = ']'; break; - case VK_OEM_7: id = '\''; break; - -#ifdef VK_APPS - case VK_LWIN: id = WXK_WINDOWS_LEFT; break; - case VK_RWIN: id = WXK_WINDOWS_RIGHT; break; - case VK_APPS: id = WXK_WINDOWS_MENU; break; -#endif // VK_APPS defined + case VK_OEM_1: wxk = ';'; break; + case VK_OEM_PLUS: wxk = '+'; break; + case VK_OEM_COMMA: wxk = ','; break; + case VK_OEM_MINUS: wxk = '-'; break; + case VK_OEM_PERIOD: wxk = '.'; break; + case VK_OEM_2: wxk = '/'; break; + case VK_OEM_3: wxk = '~'; break; + case VK_OEM_4: wxk = '['; break; + case VK_OEM_5: wxk = '\\'; break; + case VK_OEM_6: wxk = ']'; break; + case VK_OEM_7: wxk = '\''; break; // handle extended keys case VK_PRIOR: - id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEUP, WXK_PAGEUP); + wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEUP, WXK_PAGEUP); break; + case VK_NEXT: - id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEDOWN, WXK_PAGEDOWN); + wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEDOWN, WXK_PAGEDOWN); break; + case VK_END: - id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_END, WXK_END); + wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_END, WXK_END); break; + case VK_HOME: - id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_HOME, WXK_HOME); + wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_HOME, WXK_HOME); break; + case VK_LEFT: - id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_LEFT, WXK_LEFT); + wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_LEFT, WXK_LEFT); break; + case VK_UP: - id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_UP, WXK_UP); + wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_UP, WXK_UP); break; + case VK_RIGHT: - id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_RIGHT, WXK_RIGHT); + wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_RIGHT, WXK_RIGHT); break; + case VK_DOWN: - id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DOWN, WXK_DOWN); + wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DOWN, WXK_DOWN); break; + case VK_INSERT: - id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_INSERT, WXK_INSERT); + wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_INSERT, WXK_INSERT); break; + case VK_DELETE: - id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DELETE, WXK_DELETE); + wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DELETE, WXK_DELETE); break; + case VK_RETURN: // don't use ChooseNormalOrExtended() here as the keys are reversed // here: numpad enter is the extended one - id = lParam && (lParam & (1 << 24)) ? WXK_NUMPAD_ENTER : WXK_RETURN; + wxk = lParam && (lParam & (1 << 24)) ? WXK_NUMPAD_ENTER : WXK_RETURN; break; default: - id = 0; - } - - return id; -} - -WXWORD wxCharCodeWXToMSW(int id, bool *isVirtual) -{ - *isVirtual = true; - WXWORD keySym; - 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_ALT: keySym = VK_MENU; break; - case WXK_PAUSE: keySym = VK_PAUSE; break; - case WXK_CAPITAL: keySym = VK_CAPITAL; break; - case WXK_PAGEUP: keySym = VK_PRIOR; break; - case WXK_PAGEDOWN: 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_NUMPAD_MULTIPLY: keySym = VK_MULTIPLY; break; - case WXK_NUMPAD_ADD: keySym = VK_ADD; break; - case WXK_NUMPAD_SUBTRACT: keySym = VK_SUBTRACT; break; - case WXK_NUMPAD_DECIMAL: keySym = VK_DECIMAL; break; - case WXK_NUMPAD_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: - { - *isVirtual = false; - keySym = (WORD)id; + wxk = 0; + } + + return wxk; +} + +WXWORD wxCharCodeWXToMSW(int wxk, bool *isVirtual) +{ + if ( isVirtual ) + *isVirtual = true; + + // check the table first + for ( size_t n = 0; n < WXSIZEOF(gs_specialKeys); n++ ) + { + if ( gs_specialKeys[n].wxk == wxk ) + return gs_specialKeys[n].vk; + } + + // and then check for special keys not included in the table + WXWORD vk; + switch ( wxk ) + { + case WXK_PAGEUP: + case WXK_NUMPAD_PAGEUP: + vk = VK_PRIOR; + break; + + case WXK_PAGEDOWN: + case WXK_NUMPAD_PAGEDOWN: + vk = VK_NEXT; + break; + + case WXK_END: + case WXK_NUMPAD_END: + vk = VK_END; + break; + + case WXK_HOME: + case WXK_NUMPAD_HOME: + vk = VK_HOME; + break; + + case WXK_LEFT: + case WXK_NUMPAD_LEFT: + vk = VK_LEFT; + break; + + case WXK_UP: + case WXK_NUMPAD_UP: + vk = VK_UP; + break; + + case WXK_RIGHT: + case WXK_NUMPAD_RIGHT: + vk = VK_RIGHT; + break; + + case WXK_DOWN: + case WXK_NUMPAD_DOWN: + vk = VK_DOWN; + break; + + case WXK_INSERT: + case WXK_NUMPAD_INSERT: + vk = VK_INSERT; + break; + + case WXK_DELETE: + case WXK_NUMPAD_DELETE: + vk = VK_DELETE; + break; + + default: + if ( isVirtual ) + *isVirtual = false; + vk = (WXWORD)wxk; break; - } } - return keySym; + + return vk; +} + +// small helper for wxGetKeyState() and wxGetMouseState() +static inline bool wxIsKeyDown(WXWORD vk) +{ + // the low order bit indicates whether the key was pressed since the last + // call and the high order one indicates whether it is down right now and + // we only want that one + return (::GetAsyncKeyState(vk) & (1<<15)) != 0; } bool wxGetKeyState(wxKeyCode key) { - bool bVirtual; + // although this does work under Windows, it is not supported under other + // platforms so don't allow it, you must use wxGetMouseState() instead + wxASSERT_MSG( key != VK_LBUTTON && + key != VK_RBUTTON && + key != VK_MBUTTON, + wxT("can't use wxGetKeyState() for mouse buttons") ); - wxASSERT_MSG(key != WXK_LBUTTON && key != WXK_RBUTTON && key != - WXK_MBUTTON, wxT("can't use wxGetKeyState() for mouse buttons")); + const WXWORD vk = wxCharCodeWXToMSW(key); -//High order with GetAsyncKeyState only available on WIN32 -#ifdef __WIN32__ - //If the requested key is a LED key, return - //true if the led is pressed - if (key == WXK_NUMLOCK || - key == WXK_CAPITAL || - key == WXK_SCROLL) + // if the requested key is a LED key, return true if the led is pressed + if ( key == WXK_NUMLOCK || key == WXK_CAPITAL || key == WXK_SCROLL ) { -#endif - //low order bit means LED is highlighted, - //high order means key is down - //Here, for compat with other ports we want both - return GetKeyState( wxCharCodeWXToMSW(key, &bVirtual) ) != 0; + // low order bit means LED is highlighted and high order one means the + // key is down; for compatibility with the other ports return true if + // either one is set + return ::GetKeyState(vk) != 0; -#ifdef __WIN32__ } - else + else // normal key { - //normal key - //low order bit means key pressed since last call - //high order means key is down - //We want only the high order bit - the key may not be down if only low order - return ( GetAsyncKeyState( wxCharCodeWXToMSW(key, &bVirtual) ) & (1<<15) ) != 0; + return wxIsKeyDown(vk); } -#endif } @@ -5552,13 +5646,13 @@ wxMouseState wxGetMouseState() ms.SetX(pt.x); ms.SetY(pt.y); - ms.SetLeftDown( (GetAsyncKeyState(VK_LBUTTON) & (1<<15)) != 0 ); - ms.SetMiddleDown( (GetAsyncKeyState(VK_MBUTTON) & (1<<15)) != 0 ); - ms.SetRightDown( (GetAsyncKeyState(VK_RBUTTON) & (1<<15)) != 0 ); + ms.SetLeftDown(wxIsKeyDown(VK_LBUTTON)); + ms.SetMiddleDown(wxIsKeyDown(VK_MBUTTON)); + ms.SetRightDown(wxIsKeyDown(VK_RBUTTON)); - ms.SetControlDown( (GetAsyncKeyState(VK_CONTROL) & (1<<15)) != 0 ); - ms.SetShiftDown( (GetAsyncKeyState(VK_SHIFT) & (1<<15)) != 0 ); - ms.SetAltDown( (GetAsyncKeyState(VK_MENU) & (1<<15)) != 0 ); + ms.SetControlDown(wxIsKeyDown(VK_CONTROL)); + ms.SetShiftDown(wxIsKeyDown(VK_SHIFT)); + ms.SetAltDown(wxIsKeyDown(VK_MENU)); // ms.SetMetaDown(); return ms; @@ -6164,18 +6258,10 @@ wxWindow* wxFindWindowAtPoint(const wxPoint& pt) POINT pt2; pt2.x = pt.x; pt2.y = pt.y; - HWND hWndHit = ::WindowFromPoint(pt2); - wxWindow* win = wxFindWinFromHandle((WXHWND) hWndHit) ; - HWND hWnd = hWndHit; + HWND hWnd = ::WindowFromPoint(pt2); - // Try to find a window with a wxWindow associated with it - while (!win && (hWnd != 0)) - { - hWnd = ::GetParent(hWnd); - win = wxFindWinFromHandle((WXHWND) hWnd) ; - } - return win; + return wxGetWindowFromHWND((WXHWND)hWnd); } // Get the current mouse position.