#pragma hdrstop
#endif
+#include "wx/window.h"
+
#ifndef WX_PRECOMP
#include "wx/msw/wrapwin.h"
- #include "wx/window.h"
#include "wx/accel.h"
#include "wx/menu.h"
#include "wx/dc.h"
#include "wx/settings.h"
#include "wx/statbox.h"
#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__)
#include "wx/evtloop.h"
#include "wx/module.h"
+#include "wx/power.h"
#include "wx/sysopt.h"
#if wxUSE_DRAG_AND_DROP
#endif
#endif
-#include "wx/menuitem.h"
-#include "wx/log.h"
-
#include "wx/msw/private.h"
#if wxUSE_TOOLTIPS
#include "wx/spinctrl.h"
#endif // wxUSE_SPINCTRL
-#include "wx/intl.h"
-#include "wx/log.h"
-
-#include "wx/textctrl.h"
#include "wx/notebook.h"
#include "wx/listctrl.h"
#include <windowsx.h>
#endif
-#include <commctrl.h>
+// include <commctrl.h> "properly"
+#include "wx/msw/wrapcctl.h"
+
+#ifndef __WXWINCE__
+ #include <pbt.h>
+#endif
#include "wx/msw/missing.h"
return false;
}
- if ( m_cursor.Ok() )
+ // don't "overwrite" busy cursor
+ if ( m_cursor.Ok() && !wxIsBusy() )
{
- HWND hWnd = GetHwnd();
-
- // Change the cursor NOW if we're within the correct window
- POINT point;
-#ifdef __WXWINCE__
- ::GetCursorPosWinCE(&point);
-#else
- ::GetCursorPos(&point);
-#endif
-
- RECT rect = wxGetWindowRect(hWnd);
-
- if ( ::PtInRect(&rect, point) && !wxIsBusy() )
- ::SetCursor(GetHcursorOf(m_cursor));
+ ::SetCursor(GetHcursorOf(m_cursor));
}
return true;
// simply check m_oldWndProc
m_oldWndProc = NULL;
}
+
+ // we're officially created now, send the event
+ wxWindowCreateEvent event((wxWindow *)this);
+ (void)GetEventHandler()->ProcessEvent(event);
}
void wxWindowMSW::UnsubclassWin()
// 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() )
return;
- WXDWORD exstyle, exstyleOld;
- long style = MSWGetStyle(flags, &exstyle),
- styleOld = MSWGetStyle(flagsOld, &exstyleOld);
+ // we may need to call SetWindowPos() when we change some styles
+ bool callSWP = false;
+
+ 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 )
{
styleReal |= style;
::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal);
+
+ // 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 |
+ WS_DLGFRAME |
+ WS_MAXIMIZEBOX |
+ WS_MINIMIZEBOX |
+ WS_SYSMENU) ) != 0;
}
// and the extended style
+ long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
+
if ( exstyle != exstyleOld )
{
- long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
exstyleReal &= ~exstyleOld;
exstyleReal |= exstyle;
::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal);
+ // ex style changes don't take effect without calling SetWindowPos
+ callSWP = true;
+ }
+
+ if ( callSWP )
+ {
// we must call SetWindowPos() to flush the cached extended style and
// also to make the change to wxSTAY_ON_TOP style take effect: just
// setting the style simply doesn't work
exstyleReal & WS_EX_TOPMOST ? HWND_TOPMOST
: HWND_NOTOPMOST,
0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE) )
+ SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED) )
{
wxLogLastError(_T("SetWindowPos"));
}
// 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
*y = m_pendingSize.y;
}
else // use current size
+#endif // USE_DEFERRED_SIZING
{
RECT rect = wxGetWindowRect(GetHwnd());
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;
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
#if defined(__WXWINCE__)
UINT flags = 0;
#else
- UINT flags = TPM_RIGHTBUTTON;
+ UINT flags = TPM_RIGHTBUTTON | TPM_RECURSE;
#endif
::TrackPopupMenu(hMenu, flags, point.x, point.y, 0, hWnd, NULL);
// 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,
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 )
// 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
if (IsContextMenuEnabled() && message == WM_LBUTTONDOWN)
{
SHRGINFO shrgi = {0};
-
+
shrgi.cbSize = sizeof(SHRGINFO);
shrgi.hwndClient = (HWND) GetHWND();
shrgi.ptDown.x = x;
shrgi.ptDown.y = y;
-
+
shrgi.dwFlags = SHRG_RETURNCMD;
// shrgi.dwFlags = SHRG_NOTIFYPARENT;
-
+
if (GN_CONTEXTMENU == ::SHRecognizeGesture(&shrgi))
{
wxPoint pt(x, y);
pt = ClientToScreen(pt);
-
+
wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
-
+
evtCtx.SetEventObject(this);
if (GetEventHandler()->ProcessEvent(evtCtx))
{
case VK_SUBTRACT:
case VK_MULTIPLY:
case VK_DIVIDE:
+ case VK_NUMPAD0:
+ case VK_NUMPAD1:
+ case VK_NUMPAD2:
+ case VK_NUMPAD3:
+ case VK_NUMPAD4:
+ case VK_NUMPAD5:
+ case VK_NUMPAD6:
+ case VK_NUMPAD7:
+ case VK_NUMPAD8:
+ case VK_NUMPAD9:
case VK_OEM_1:
case VK_OEM_2:
case VK_OEM_3:
#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:
}
}
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 )
// 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).
EnsureParentHasControlParentStyle(GetParent());
#endif // !__WXWINCE__
- // TODO: should generate this event from WM_NCCREATE
- wxWindowCreateEvent event((wxWindow *)this);
- (void)GetEventHandler()->ProcessEvent(event);
-
*mayCreate = true;
return true;
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
// ---------------------------------------------------------------------------
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;
}
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
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)
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),
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
// ---------------------------------------------------------------------------
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_PRIOR, WXK_PRIOR);
+ wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEUP, WXK_PAGEUP);
break;
+
case VK_NEXT:
- id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_NEXT, WXK_NEXT);
+ 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_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_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
}
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;
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.