#ifndef WX_PRECOMP
#include "wx/msw/wrapwin.h"
+ #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
+ #include "wx/msw/missing.h"
#include "wx/accel.h"
#include "wx/menu.h"
#include "wx/dc.h"
#include "wx/log.h"
#include "wx/textctrl.h"
#include "wx/menuitem.h"
+ #include "wx/module.h"
#endif
#if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
#include "wx/ownerdrw.h"
#endif
+#include "wx/hashmap.h"
#include "wx/evtloop.h"
-#include "wx/module.h"
#include "wx/power.h"
#include "wx/sysopt.h"
#endif
#include "wx/msw/private.h"
+#include "wx/msw/dcclient.h"
#if wxUSE_TOOLTIPS
#include "wx/tooltip.h"
#include "wx/notebook.h"
#include "wx/listctrl.h"
+#include "wx/dynlib.h"
#include <string.h>
#include <windowsx.h>
#endif
-// include <commctrl.h> "properly"
-#include "wx/msw/wrapcctl.h"
-
-#ifndef __WXWINCE__
+#if !defined __WXWINCE__ && !defined NEED_PBT_H
#include <pbt.h>
#endif
-#include "wx/msw/missing.h"
-
#if defined(__WXWINCE__)
#include "wx/msw/wince/missing.h"
#ifdef __POCKETPC__
#endif
#endif
-#if defined(TME_LEAVE) && defined(WM_MOUSELEAVE)
+#if wxUSE_UXTHEME
+ #include "wx/msw/uxtheme.h"
+ #define EP_EDITTEXT 1
+ #define ETS_NORMAL 1
+ #define ETS_HOT 2
+ #define ETS_SELECTED 3
+ #define ETS_DISABLED 4
+ #define ETS_FOCUSED 5
+ #define ETS_READONLY 6
+ #define ETS_ASSIST 7
+#endif
+
+// define the constants used by AnimateWindow() if our SDK doesn't have them
+#ifndef AW_CENTER
+ #define AW_HOR_POSITIVE 0x00000001
+ #define AW_HOR_NEGATIVE 0x00000002
+ #define AW_VER_POSITIVE 0x00000004
+ #define AW_VER_NEGATIVE 0x00000008
+ #define AW_CENTER 0x00000010
+ #define AW_HIDE 0x00010000
+ #define AW_ACTIVATE 0x00020000
+ #define AW_SLIDE 0x00040000
+ #define AW_BLEND 0x00080000
+#endif
+
+#if defined(TME_LEAVE) && defined(WM_MOUSELEAVE) && wxUSE_DYNLIB_CLASS
#define HAVE_TRACKMOUSEEVENT
#endif // everything needed for TrackMouseEvent()
#define wxUSE_MOUSEEVENT_HACK 1
#endif
+// not all compilers/platforms have X button related declarations (notably
+// Windows CE doesn't, and probably some old SDKs don't neither)
+#ifdef WM_XBUTTONDOWN
+ #define wxHAS_XBUTTON
+#endif
+
// ---------------------------------------------------------------------------
// global variables
// ---------------------------------------------------------------------------
#if wxUSE_MENUS_NATIVE
-wxMenu *wxCurrentPopupMenu = NULL;
-#endif // wxUSE_MENUS_NATIVE
+extern wxMenu *wxCurrentPopupMenu;
+#endif
#ifdef __WXWINCE__
extern wxChar *wxCanvasClassName;
} gs_lastMouseEvent;
#endif // wxUSE_MOUSEEVENT_HACK
+// hash containing the registered handlers for the custom messages
+WX_DECLARE_HASH_MAP(int, wxWindow::MSWMessageHandler,
+ wxIntegerHash, wxIntegerEqual,
+ MSWMessageHandlers);
+
+static MSWMessageHandlers gs_messageHandlers;
+
+// hash containing all our windows, it uses HWND keys and wxWindow* values
+WX_DECLARE_HASH_MAP(HWND, wxWindow *,
+ wxPointerHash, wxPointerEqual,
+ WindowHandles);
+
+static WindowHandles gs_windowHandles;
+
// ---------------------------------------------------------------------------
// private functions
// ---------------------------------------------------------------------------
void wxRemoveHandleAssociation(wxWindowMSW *win);
extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
-wxWindow *wxFindWinFromHandle(WXHWND hWnd);
// get the text metrics for the current font
static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win);
m_mouseInWindow = false;
m_lastKeydownProcessed = false;
- m_childrenDisabled = NULL;
- m_frozenness = 0;
-
m_hWnd = 0;
m_hDWP = 0;
wxRemoveHandleAssociation(this);
}
- delete m_childrenDisabled;
-
}
// real construction (Init() must have been called before!)
return NULL;
}
-bool wxWindowMSW::Enable(bool enable)
+void wxWindowMSW::DoEnable( bool enable )
{
- if ( !wxWindowBase::Enable(enable) )
- return false;
-
HWND hWnd = GetHwnd();
if ( hWnd )
::EnableWindow(hWnd, (BOOL)enable);
-
- // the logic below doesn't apply to the top level windows -- otherwise
- // showing a modal dialog would result in total greying out (and ungreying
- // out later) of everything which would be really ugly
- if ( IsTopLevel() )
- return true;
-
- // when the parent is disabled, all of its children should be disabled as
- // well but when it is enabled back, only those of the children which
- // hadn't been already disabled in the beginning should be enabled again,
- // so we have to keep the list of those children
- for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
- node;
- node = node->GetNext() )
- {
- wxWindow *child = node->GetData();
- if ( child->IsTopLevel() )
- {
- // the logic below doesn't apply to top level children
- continue;
- }
-
- if ( enable )
- {
- // re-enable the child unless it had been disabled before us
- if ( !m_childrenDisabled || !m_childrenDisabled->Find(child) )
- child->Enable();
- }
- else // we're being disabled
- {
- if ( child->IsEnabled() )
- {
- // disable it as children shouldn't stay enabled while the
- // parent is not
- child->Disable();
- }
- else // child already disabled, remember it
- {
- // have we created the list of disabled children already?
- if ( !m_childrenDisabled )
- m_childrenDisabled = new wxWindowList;
-
- m_childrenDisabled->Append(child);
- }
- }
- }
-
- if ( enable && m_childrenDisabled )
- {
- // we don't need this list any more, don't keep unused memory
- delete m_childrenDisabled;
- m_childrenDisabled = NULL;
- }
-
- return true;
}
bool wxWindowMSW::Show(bool show)
::ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
}
+ if ( IsFrozen() )
+ {
+ // DoFreeze/DoThaw don't do anything if the window is not shown, so
+ // we have to call them from here now
+ if ( show )
+ DoFreeze();
+ else
+ DoThaw();
+ }
+
+ return true;
+}
+
+bool
+wxWindowMSW::MSWShowWithEffect(bool show,
+ wxShowEffect effect,
+ unsigned timeout,
+ wxDirection dir)
+{
+ if ( !wxWindowBase::Show(show) )
+ return false;
+
+ typedef BOOL (WINAPI *AnimateWindow_t)(HWND, DWORD, DWORD);
+
+ static AnimateWindow_t s_pfnAnimateWindow = NULL;
+ static bool s_initDone = false;
+ if ( !s_initDone )
+ {
+ wxDynamicLibrary dllUser32(_T("user32.dll"), wxDL_VERBATIM | wxDL_QUIET);
+ wxDL_INIT_FUNC(s_pfn, AnimateWindow, dllUser32);
+
+ s_initDone = true;
+
+ // notice that it's ok to unload user32.dll here as it won't be really
+ // unloaded, being still in use because we link to it statically too
+ }
+
+ if ( !s_pfnAnimateWindow )
+ return Show(show);
+
+ // prepare to use AnimateWindow()
+
+ if ( !timeout )
+ timeout = 200; // this is the default animation timeout, per MSDN
+
+ DWORD dwFlags = show ? 0 : AW_HIDE;
+ bool needsDir = false;
+ switch ( effect )
+ {
+ case wxSHOW_EFFECT_ROLL:
+ needsDir = true;
+ break;
+
+ case wxSHOW_EFFECT_SLIDE:
+ needsDir = true;
+ dwFlags |= AW_SLIDE;
+ break;
+
+ case wxSHOW_EFFECT_BLEND:
+ dwFlags |= AW_BLEND;
+ break;
+
+ case wxSHOW_EFFECT_EXPAND:
+ dwFlags |= AW_CENTER;
+ break;
+
+
+ case wxSHOW_EFFECT_MAX:
+ wxFAIL_MSG( _T("invalid window show effect") );
+ return false;
+
+ default:
+ wxFAIL_MSG( _T("unknown window show effect") );
+ return false;
+ }
+
+ if ( needsDir )
+ {
+ switch ( dir )
+ {
+ case wxTOP:
+ dwFlags |= AW_VER_NEGATIVE;
+ break;
+
+ case wxBOTTOM:
+ dwFlags |= AW_VER_POSITIVE;
+ break;
+
+ case wxLEFT:
+ dwFlags |= AW_HOR_NEGATIVE;
+ break;
+
+ case wxRIGHT:
+ dwFlags |= AW_HOR_POSITIVE;
+ break;
+
+ default:
+ wxFAIL_MSG( _T("unknown window effect direction") );
+ return false;
+ }
+ }
+ else // animation effect which doesn't need the direction
+ {
+ wxASSERT_MSG( dir == wxBOTTOM,
+ _T("non-default direction used unnecessarily") );
+ }
+
+
+ if ( !(*s_pfnAnimateWindow)(GetHwnd(), timeout, dwFlags) )
+ {
+ wxLogLastError(_T("AnimateWindow"));
+
+ return false;
+ }
+
return true;
}
/* static */ wxWindow *wxWindowBase::GetCapture()
{
HWND hwnd = ::GetCapture();
- return hwnd ? wxFindWinFromHandle((WXHWND)hwnd) : (wxWindow *)NULL;
+ return hwnd ? wxFindWinFromHandle(hwnd) : NULL;
}
bool wxWindowMSW::SetFont(const wxFont& font)
// don't "overwrite" busy cursor
if ( m_cursor.Ok() && !wxIsBusy() )
{
- ::SetCursor(GetHcursorOf(m_cursor));
+ // normally we should change the cursor only if it's over this window
+ // but we should do it always if we capture the mouse currently
+ bool set = HasCapture();
+ if ( !set )
+ {
+ HWND hWnd = GetHwnd();
+
+ POINT point;
+#ifdef __WXWINCE__
+ ::GetCursorPosWinCE(&point);
+#else
+ ::GetCursorPos(&point);
+#endif
+
+ RECT rect = wxGetWindowRect(hWnd);
+
+ set = ::PtInRect(&rect, point) != 0;
+ }
+
+ if ( set )
+ {
+ ::SetCursor(GetHcursorOf(m_cursor));
+ }
+ //else: will be set later when the mouse enters this window
}
return true;
if ( s_needToUpdate == -1 )
{
int verMaj, verMin;
- s_needToUpdate = wxGetOsVersion(&verMaj, &verMin) == wxWINDOWS_NT &&
+ s_needToUpdate = wxGetOsVersion(&verMaj, &verMin) == wxOS_WINDOWS_NT &&
verMaj >= 5;
}
RECT *pr;
if ( prect )
{
- rect.left = prect->x;
- rect.top = prect->y;
- rect.right = prect->x + prect->width;
- rect.bottom = prect->y + prect->height;
+ wxCopyRectToRECT(*prect, rect);
pr = ▭
}
else
down ? pages : -pages);
}
+// ----------------------------------------------------------------------------
+// RTL support
+// ----------------------------------------------------------------------------
+
+void wxWindowMSW::SetLayoutDirection(wxLayoutDirection dir)
+{
+#ifdef __WXWINCE__
+ wxUnusedVar(dir);
+#else
+ const HWND hwnd = GetHwnd();
+ wxCHECK_RET( hwnd, _T("layout direction must be set after window creation") );
+
+ LONG styleOld = ::GetWindowLong(hwnd, GWL_EXSTYLE);
+
+ LONG styleNew = styleOld;
+ switch ( dir )
+ {
+ case wxLayout_LeftToRight:
+ styleNew &= ~WS_EX_LAYOUTRTL;
+ break;
+
+ case wxLayout_RightToLeft:
+ styleNew |= WS_EX_LAYOUTRTL;
+ break;
+
+ default:
+ wxFAIL_MSG(_T("unsupported layout direction"));
+ break;
+ }
+
+ if ( styleNew != styleOld )
+ {
+ ::SetWindowLong(hwnd, GWL_EXSTYLE, styleNew);
+ }
+#endif
+}
+
+wxLayoutDirection wxWindowMSW::GetLayoutDirection() const
+{
+#ifdef __WXWINCE__
+ return wxLayout_Default;
+#else
+ const HWND hwnd = GetHwnd();
+ wxCHECK_MSG( hwnd, wxLayout_Default, _T("invalid window") );
+
+ return ::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL
+ ? wxLayout_RightToLeft
+ : wxLayout_LeftToRight;
+#endif
+}
+
+wxCoord
+wxWindowMSW::AdjustForLayoutDirection(wxCoord x,
+ wxCoord WXUNUSED(width),
+ wxCoord WXUNUSED(widthTotal)) const
+{
+ // Win32 mirrors the coordinates of RTL windows automatically, so don't
+ // redo it ourselves
+ return x;
+}
+
// ---------------------------------------------------------------------------
// subclassing
// ---------------------------------------------------------------------------
HWND hwnd = (HWND)hWnd;
wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in SubclassWin") );
+ SetHWND(hWnd);
+
wxAssociateWinWithHandle(hwnd, this);
m_oldWndProc = (WXFARPROC)wxGetWindowProc((HWND)hWnd);
// we're officially created now, send the event
wxWindowCreateEvent event((wxWindow *)this);
- (void)GetEventHandler()->ProcessEvent(event);
+ (void)HandleWindowEvent(event);
}
void wxWindowMSW::UnsubclassWin()
WXHWND wxhwnd = (WXHWND)handle;
- SetHWND(wxhwnd);
+ // this also calls SetHWND(wxhwnd)
SubclassWin(wxhwnd);
}
}
}
+wxBorder wxWindowMSW::GetDefaultBorderForControl() const
+{
+ return wxBORDER_THEME;
+}
+
+wxBorder wxWindowMSW::GetDefaultBorder() const
+{
+ return wxWindowBase::GetDefaultBorder();
+}
+
+// Translate wxBORDER_THEME (and other border styles if necessary) to the value
+// that makes most sense for this Windows environment
+wxBorder wxWindowMSW::TranslateBorder(wxBorder border) const
+{
+#if defined(__POCKETPC__) || defined(__SMARTPHONE__)
+ if (border == wxBORDER_THEME || border == wxBORDER_SUNKEN || border == wxBORDER_SIMPLE)
+ return wxBORDER_SIMPLE;
+ else
+ return wxBORDER_NONE;
+#else
+#if wxUSE_UXTHEME
+ if (border == wxBORDER_THEME)
+ {
+ if (CanApplyThemeBorder())
+ {
+ wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive();
+ if (theme)
+ return wxBORDER_THEME;
+ }
+ return wxBORDER_SUNKEN;
+ }
+#endif
+ return border;
+#endif
+}
+
+
WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
{
// translate common wxWidgets styles to Windows ones
if ( flags & wxHSCROLL )
style |= WS_HSCROLL;
- const wxBorder border = GetBorder(flags);
+ const wxBorder border = TranslateBorder(GetBorder(flags));
+
+ // After translation, border is now optimized for the specific version of Windows
+ // and theme engine presence.
// WS_BORDER is only required for wxBORDER_SIMPLE
if ( border == wxBORDER_SIMPLE )
case wxBORDER_NONE:
case wxBORDER_SIMPLE:
+ case wxBORDER_THEME:
break;
case wxBORDER_STATIC:
style &= ~WS_BORDER;
break;
- case wxBORDER_DOUBLE:
- *exstyle |= WS_EX_DLGMODALFRAME;
- break;
+// case wxBORDER_DOUBLE:
+// *exstyle |= WS_EX_DLGMODALFRAME;
+// break;
}
// wxUniv doesn't use Windows dialog navigation functions at all
}
#endif // !HAVE_TRACKMOUSEEVENT
- if (wxUpdateUIEvent::CanUpdate(this))
+ if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
}
#endif
}
-void wxWindowMSW::Freeze()
+void wxWindowMSW::DoFreeze()
{
- if ( !m_frozenness++ )
- {
- if ( IsShown() )
- SendSetRedraw(GetHwnd(), false);
- }
+ if ( !IsShown() )
+ return; // no point in freezing hidden window
+
+ SendSetRedraw(GetHwnd(), false);
}
-void wxWindowMSW::Thaw()
+void wxWindowMSW::DoThaw()
{
- wxASSERT_MSG( m_frozenness > 0, _T("Thaw() without matching Freeze()") );
+ if ( !IsShown() )
+ return; // hidden windows aren't frozen by DoFreeze
- if ( --m_frozenness == 0 )
- {
- if ( IsShown() )
- {
- SendSetRedraw(GetHwnd(), true);
+ SendSetRedraw(GetHwnd(), true);
- // we need to refresh everything or otherwise the invalidated area
- // is not going to be repainted
- Refresh();
- }
- }
+ // we need to refresh everything or otherwise the invalidated area
+ // is not going to be repainted
+ Refresh();
}
void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
const RECT *pRect;
if ( rect )
{
- mswRect.left = rect->x;
- mswRect.top = rect->y;
- mswRect.right = rect->x + rect->width;
- mswRect.bottom = rect->y + rect->height;
-
+ wxCopyRectToRECT(*rect, mswRect);
pRect = &mswRect;
}
else
// drag and drop
// ---------------------------------------------------------------------------
+#if wxUSE_DRAG_AND_DROP || !defined(__WXWINCE__)
+
+#if wxUSE_STATBOX
+
// we need to lower the sibling static boxes so controls contained within can be
// a drop target
-static inline void AdjustStaticBoxZOrder(wxWindow *parent)
+static void AdjustStaticBoxZOrder(wxWindow *parent)
{
// no sibling static boxes if we have no parent (ie TLW)
if ( !parent )
}
}
+#else // !wxUSE_STATBOX
+
+static inline void AdjustStaticBoxZOrder(wxWindow * WXUNUSED(parent))
+{
+}
+
+#endif // wxUSE_STATBOX/!wxUSE_STATBOX
+
+#endif // drag and drop is used
+
#if wxUSE_DRAG_AND_DROP
void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
{
// 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
// children, not for the dialogs/frames
if ( !IsTopLevel() )
{
+ if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
+ {
+ // In RTL mode, we want the logical left x-coordinate,
+ // which would be the physical right x-coordinate.
+ point.x = rect.right;
+ }
+
// Since we now have the absolute screen coords, if there's a
// parent we must subtract its top left corner
if ( parent )
void wxWindowMSW::GetTextExtent(const wxString& string,
int *x, int *y,
int *descent, int *externalLeading,
- const wxFont *theFont) const
+ const wxFont *fontToUse) const
{
- wxASSERT_MSG( !theFont || theFont->Ok(),
+ wxASSERT_MSG( !fontToUse || fontToUse->Ok(),
_T("invalid font in GetTextExtent()") );
- wxFont fontToUse;
- if (theFont)
- fontToUse = *theFont;
+ HFONT hfontToUse;
+ if ( fontToUse )
+ hfontToUse = GetHfontOf(*fontToUse);
else
- fontToUse = GetFont();
+ hfontToUse = GetHfontOf(GetFont());
WindowHDC hdc(GetHwnd());
- SelectInHDC selectFont(hdc, GetHfontOf(fontToUse));
+ SelectInHDC selectFont(hdc, hfontToUse);
SIZE sizeRect;
TEXTMETRIC tm;
- ::GetTextExtentPoint32(hdc, string, string.length(), &sizeRect);
+ ::GetTextExtentPoint32(hdc, string.wx_str(), string.length(), &sizeRect);
GetTextMetrics(hdc, &tm);
if ( x )
point.x = x;
point.y = y;
::ClientToScreen(hWnd, &point);
- wxCurrentPopupMenu = menu;
#if defined(__WXWINCE__)
- UINT flags = 0;
-#else
- UINT flags = TPM_RIGHTBUTTON | TPM_RECURSE;
-#endif
+ static const UINT flags = 0;
+#else // !__WXWINCE__
+ UINT flags = TPM_RIGHTBUTTON;
+ // NT4 doesn't support TPM_RECURSE and simply doesn't show the menu at all
+ // when it's use, I'm not sure about Win95/98 but prefer to err on the safe
+ // side and not to use it there neither -- modify the test if it does work
+ // on these systems
+ if ( wxGetWinVersion() >= wxWinVersion_5 )
+ {
+ // using TPM_RECURSE allows us to show a popup menu while another menu
+ // is opened which can be useful and is supported by the other
+ // platforms, so allow it under Windows too
+ flags |= TPM_RECURSE;
+ }
+#endif // __WXWINCE__/!__WXWINCE__
+
::TrackPopupMenu(hMenu, flags, point.x, point.y, 0, hWnd, NULL);
// we need to do it right now as otherwise the events are never going to be
// for example) and so we do need to process the event immediately
wxYieldForCommandsOnly();
- wxCurrentPopupMenu = NULL;
-
menu->SetInvokingWindow(NULL);
return true;
// 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,
switch ( msg->wParam )
{
case VK_TAB:
- if ( lDlgCode & DLGC_WANTTAB ) {
+ if ( (lDlgCode & DLGC_WANTTAB) && !bCtrlDown )
+ {
+ // let the control have the TAB
bProcess = false;
}
- else {
+ else // use it for navigation
+ {
// Ctrl-Tab cycles thru notebook pages
bWindowChange = bCtrlDown;
bForward = !bShiftDown;
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 // OTOH Ctrl-PageUp/Dn works as [Shift-]Ctrl-Tab
+ bWindowChange = true;
+ break;
+
case VK_RETURN:
{
- if ( (lDlgCode & DLGC_WANTMESSAGE) && !bCtrlDown )
- {
- // control wants to process Enter itself, don't
- // call IsDialogMessage() which would interpret
- // it
- return false;
- }
-
+#if wxUSE_BUTTON
// currently active button should get enter press even
- // if there is a default button elsewhere
+ // if there is a default button elsewhere so check if
+ // this window is a button first
+ wxWindow *btn = NULL;
if ( lDlgCode & DLGC_DEFPUSHBUTTON )
{
// let IsDialogMessage() handle this for all
if ( (style & BS_OWNERDRAW) == BS_OWNERDRAW )
{
// emulate the button click
- wxWindow *
- btn = wxFindWinFromHandle((WXHWND)msg->hwnd);
- if ( btn )
- btn->MSWCommand(BN_CLICKED, 0 /* unused */);
+ btn = wxFindWinFromHandle(msg->hwnd);
}
bProcess = false;
}
- else // not a button itself
+ else // not a button itself, do we have default button?
{
-#if wxUSE_BUTTON
- wxButton *btn = wxDynamicCast(GetDefaultItem(),
- wxButton);
- if ( btn && btn->IsEnabled() )
+ // check if this window or any of its ancestors
+ // wants the message for itself (we always reserve
+ // Ctrl-Enter for dialog navigation though)
+ wxWindow *win = this;
+ if ( !bCtrlDown )
{
- // if we do have a default button, do press it
- btn->MSWCommand(BN_CLICKED, 0 /* unused */);
+ // this will contain the dialog code of this
+ // window and all of its parent windows in turn
+ LONG lDlgCode2 = lDlgCode;
- return true;
- }
- else // no default button
-#endif // wxUSE_BUTTON
- {
-#ifdef __WXWINCE__
- wxJoystickEvent event(wxEVT_JOY_BUTTON_DOWN);
- event.SetEventObject(this);
- if(GetEventHandler()->ProcessEvent(event))
- return true;
-#endif
- // this is a quick and dirty test for a text
- // control
- if ( !(lDlgCode & DLGC_HASSETSEL) )
+ while ( win )
{
- // don't process Enter, the control might
- // need it for itself and don't let
- // ::IsDialogMessage() have it as it can
- // eat the Enter events sometimes
- return false;
+ if ( lDlgCode2 & DLGC_WANTMESSAGE )
+ {
+ // as it wants to process Enter itself,
+ // don't call IsDialogMessage() which
+ // would consume it
+ return false;
+ }
+
+ // don't propagate keyboard messages beyond
+ // the first top level window parent
+ if ( win->IsTopLevel() )
+ break;
+
+ win = win->GetParent();
+
+ lDlgCode2 = ::SendMessage
+ (
+ GetHwndOf(win),
+ WM_GETDLGCODE,
+ 0,
+ 0
+ );
}
- else if (!IsTopLevel())
- {
- // if not a top level window, let parent
- // handle it
- return false;
- }
- //else: treat Enter as TAB: pass to the next
- // control as this is the best thing to do
- // if the text doesn't handle Enter itself
}
+ else // bCtrlDown
+ {
+ win = wxGetTopLevelParent(win);
+ }
+
+ wxTopLevelWindow * const
+ tlw = wxDynamicCast(win, wxTopLevelWindow);
+ if ( tlw )
+ {
+ btn = wxDynamicCast(tlw->GetDefaultItem(),
+ wxButton);
+ }
+ }
+
+ if ( btn && btn->IsEnabled() )
+ {
+ btn->MSWCommand(BN_CLICKED, 0 /* unused */);
+ return true;
}
+
+#endif // wxUSE_BUTTON
+
+#ifdef __WXWINCE__
+ // map Enter presses into button presses on PDAs
+ wxJoystickEvent event(wxEVT_JOY_BUTTON_DOWN);
+ event.SetEventObject(this);
+ if ( HandleWindowEvent(event) )
+ return true;
+#endif // __WXWINCE__
}
break;
event.SetFromTab(bFromTab);
event.SetEventObject(this);
- if ( GetEventHandler()->ProcessEvent(event) )
+ if ( HandleWindowEvent(event) )
{
// as we don't call IsDialogMessage(), which would take of
// this by default, we need to manually send this message
}
}
- // don't let IsDialogMessage() get VK_ESCAPE as it _always_ eats the
- // message even when there is no cancel button and when the message is
- // needed by the control itself: in particular, it prevents the tree in
- // place edit control from being closed with Escape in a dialog
- if ( msg->message != WM_KEYDOWN || msg->wParam != VK_ESCAPE )
+ if ( ::IsDialogMessage(GetHwnd(), msg) )
{
- // ::IsDialogMessage() is broken and may sometimes hang the
- // application by going into an infinite loop, so we try to detect
- // [some of] the situations when this may happen and not call it
- // then
-
- // assume we can call it by default
- bool canSafelyCallIsDlgMsg = true;
-
- HWND hwndFocus = ::GetFocus();
-
- // if the currently focused window itself has WS_EX_CONTROLPARENT style, ::IsDialogMessage() will also enter
- // an infinite loop, because it will recursively check the child
- // windows but not the window itself and so if none of the children
- // accepts focus it loops forever (as it only stops when it gets
- // back to the window it started from)
- //
- // while it is very unusual that a window with WS_EX_CONTROLPARENT
- // style has the focus, it can happen. One such possibility is if
- // all windows are either toplevel, wxDialog, wxPanel or static
- // controls and no window can actually accept keyboard input.
-#if !defined(__WXWINCE__)
- if ( ::GetWindowLong(hwndFocus, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
- {
- // pessimistic by default
- canSafelyCallIsDlgMsg = false;
- for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
- node;
- node = node->GetNext() )
- {
- wxWindow * const win = node->GetData();
- if ( win->AcceptsFocus() &&
- !(::GetWindowLong(GetHwndOf(win), GWL_EXSTYLE) &
- WS_EX_CONTROLPARENT) )
- {
- // it shouldn't hang...
- canSafelyCallIsDlgMsg = true;
-
- break;
- }
- }
- }
-#endif // !__WXWINCE__
-
- if ( canSafelyCallIsDlgMsg )
- {
- // ::IsDialogMessage() can enter in an infinite loop when the
- // currently focused window is disabled or hidden and its
- // parent has WS_EX_CONTROLPARENT style, so don't call it in
- // this case
- while ( hwndFocus )
- {
- if ( !::IsWindowEnabled(hwndFocus) ||
- !::IsWindowVisible(hwndFocus) )
- {
- // it would enter an infinite loop if we do this!
- canSafelyCallIsDlgMsg = false;
-
- break;
- }
-
- if ( !(::GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD) )
- {
- // it's a top level window, don't go further -- e.g. even
- // if the parent of a dialog is disabled, this doesn't
- // break navigation inside the dialog
- break;
- }
-
- hwndFocus = ::GetParent(hwndFocus);
- }
- }
-
- // let IsDialogMessage() have the message if it's safe to call it
- if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) )
- {
- // IsDialogMessage() did something...
- return true;
- }
+ // IsDialogMessage() did something...
+ return true;
}
}
#endif // __WXUNIVERSAL__
#endif // wxUSE_ACCEL
}
-bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG* WXUNUSED(pMsg))
-{
- // preprocess all messages by default
- return true;
+bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG* msg)
+{
+ // all tests below have to deal with various bugs/misfeatures of
+ // IsDialogMessage(): we have to prevent it from being called from our
+ // MSWProcessMessage() in some situations
+
+ // don't let IsDialogMessage() get VK_ESCAPE as it _always_ eats the
+ // message even when there is no cancel button and when the message is
+ // needed by the control itself: in particular, it prevents the tree in
+ // place edit control from being closed with Escape in a dialog
+ if ( msg->message == WM_KEYDOWN && msg->wParam == VK_ESCAPE )
+ {
+ return false;
+ }
+
+ // ::IsDialogMessage() is broken and may sometimes hang the application by
+ // going into an infinite loop when it tries to find the control to give
+ // focus to when Alt-<key> is pressed, so we try to detect [some of] the
+ // situations when this may happen and not call it then
+ if ( msg->message != WM_SYSCHAR )
+ return true;
+
+ // assume we can call it by default
+ bool canSafelyCallIsDlgMsg = true;
+
+ HWND hwndFocus = ::GetFocus();
+
+ // if the currently focused window itself has WS_EX_CONTROLPARENT style,
+ // ::IsDialogMessage() will also enter an infinite loop, because it will
+ // recursively check the child windows but not the window itself and so if
+ // none of the children accepts focus it loops forever (as it only stops
+ // when it gets back to the window it started from)
+ //
+ // while it is very unusual that a window with WS_EX_CONTROLPARENT
+ // style has the focus, it can happen. One such possibility is if
+ // all windows are either toplevel, wxDialog, wxPanel or static
+ // controls and no window can actually accept keyboard input.
+#if !defined(__WXWINCE__)
+ if ( ::GetWindowLong(hwndFocus, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
+ {
+ // pessimistic by default
+ canSafelyCallIsDlgMsg = false;
+ for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ wxWindow * const win = node->GetData();
+ if ( win->CanAcceptFocus() &&
+ !(::GetWindowLong(GetHwndOf(win), GWL_EXSTYLE) &
+ WS_EX_CONTROLPARENT) )
+ {
+ // it shouldn't hang...
+ canSafelyCallIsDlgMsg = true;
+
+ break;
+ }
+ }
+ }
+#endif // !__WXWINCE__
+
+ if ( canSafelyCallIsDlgMsg )
+ {
+ // ::IsDialogMessage() can enter in an infinite loop when the
+ // currently focused window is disabled or hidden and its
+ // parent has WS_EX_CONTROLPARENT style, so don't call it in
+ // this case
+ while ( hwndFocus )
+ {
+ if ( !::IsWindowEnabled(hwndFocus) ||
+ !::IsWindowVisible(hwndFocus) )
+ {
+ // it would enter an infinite loop if we do this!
+ canSafelyCallIsDlgMsg = false;
+
+ break;
+ }
+
+ if ( !(::GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD) )
+ {
+ // it's a top level window, don't go further -- e.g. even
+ // if the parent of a dialog is disabled, this doesn't
+ // break navigation inside the dialog
+ break;
+ }
+
+ hwndFocus = ::GetParent(hwndFocus);
+ }
+ }
+
+ return canSafelyCallIsDlgMsg;
}
// ---------------------------------------------------------------------------
// trace all messages - useful for the debugging
#ifdef __WXDEBUG__
wxLogTrace(wxTraceMessages,
- wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"),
- wxGetMessageName(message), (long)hWnd, (long)wParam, lParam);
+ wxT("Processing %s(hWnd=%p, wParam=%08lx, lParam=%08lx)"),
+ wxGetMessageName(message), hWnd, (long)wParam, lParam);
#endif // __WXDEBUG__
- wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd);
+ wxWindowMSW *wnd = wxFindWinFromHandle(hWnd);
// when we get the first message for the HWND we just created, we associate
// it with wxWindow stored in gs_winBeingCreated
LRESULT rc;
- if ( wnd && wxEventLoop::AllowProcessing(wnd) )
+ if ( wnd && wxGUIEventLoop::AllowProcessing(wnd) )
rc = wnd->MSWWindowProc(message, wParam, lParam);
else
rc = ::DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
+#if 0
+ case WM_ENTERSIZEMOVE:
+ {
+ processed = HandleEnterSizeMove();
+ }
+ break;
+ case WM_EXITSIZEMOVE:
+ {
+ processed = HandleExitSizeMove();
+ }
+ break;
+#endif
case WM_SIZING:
{
LPRECT pRect = (LPRECT)lParam;
break;
case WM_SETFOCUS:
- processed = HandleSetFocus((WXHWND)(HWND)wParam);
+ processed = HandleSetFocus((WXHWND)wParam);
break;
case WM_KILLFOCUS:
- processed = HandleKillFocus((WXHWND)(HWND)wParam);
+ processed = HandleKillFocus((WXHWND)wParam);
break;
case WM_PRINTCLIENT:
#ifdef HAVE_TRACKMOUSEEVENT
case WM_MOUSELEAVE:
- // filter out excess WM_MOUSELEAVE events sent after PopupMenu() (on XP at least)
+ // filter out excess WM_MOUSELEAVE events sent after PopupMenu()
+ // (on XP at least)
if ( m_mouseInWindow )
{
GenerateMouseLeave();
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MBUTTONDBLCLK:
+#ifdef wxHAS_XBUTTON
+ case WM_XBUTTONDOWN:
+ case WM_XBUTTONUP:
+ case WM_XBUTTONDBLCLK:
+#endif // wxHAS_XBUTTON
{
#ifdef __WXMICROWIN__
// MicroWindows seems to ignore the fact that a window is
wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
evtCtx.SetEventObject(this);
- if (GetEventHandler()->ProcessEvent(evtCtx))
+ if (HandleWindowEvent(evtCtx))
{
processed = true;
return true;
// problems, so don't do it for them (unnecessary anyhow)
if ( !win->IsOfStandardClass() )
{
- if ( message == WM_LBUTTONDOWN && win->AcceptsFocus() )
+ if ( message == WM_LBUTTONDOWN && win->IsFocusable() )
win->SetFocus();
}
}
// for these messages we must return true if process the message
#ifdef WM_DRAWITEM
case WM_DRAWITEM:
- case WM_MEASUREITEM:
- {
- int idCtrl = (UINT)wParam;
- if ( message == WM_DRAWITEM )
- {
- processed = MSWOnDrawItem(idCtrl,
- (WXDRAWITEMSTRUCT *)lParam);
- }
- else
- {
- processed = MSWOnMeasureItem(idCtrl,
- (WXMEASUREITEMSTRUCT *)lParam);
- }
+ processed = MSWOnDrawItem(wParam, (WXDRAWITEMSTRUCT *)lParam);
+ if ( processed )
+ rc.result = TRUE;
+ break;
- if ( processed )
- rc.result = TRUE;
- }
+ case WM_MEASUREITEM:
+ processed = MSWOnMeasureItem(wParam, (WXMEASUREITEMSTRUCT *)lParam);
+ if ( processed )
+ rc.result = TRUE;
break;
#endif // defined(WM_DRAWITEM)
case WM_GETDLGCODE:
- if ( !IsOfStandardClass() )
+ if ( !IsOfStandardClass() || HasFlag(wxWANTS_CHARS) )
{
// we always want to get the char events
rc.result = DLGC_WANTCHARS;
- if ( GetWindowStyleFlag() & wxWANTS_CHARS )
+ if ( HasFlag(wxWANTS_CHARS) )
{
// in fact, we want everything
rc.result |= DLGC_WANTARROWS |
break;
#endif // wxUSE_HOTKEY
+ case WM_CUT:
+ case WM_COPY:
+ case WM_PASTE:
+ processed = HandleClipboardEvent(message);
+ break;
+
case WM_HSCROLL:
case WM_VSCROLL:
{
#endif
case WM_PALETTECHANGED:
- processed = HandlePaletteChanged((WXHWND) (HWND) wParam);
+ processed = HandlePaletteChanged((WXHWND)wParam);
break;
case WM_CAPTURECHANGED:
- processed = HandleCaptureChanged((WXHWND) (HWND) lParam);
+ processed = HandleCaptureChanged((WXHWND)lParam);
break;
case WM_SETTINGCHANGE:
break;
case WM_ERASEBKGND:
- processed = HandleEraseBkgnd((WXHDC)(HDC)wParam);
+ processed = HandleEraseBkgnd((WXHDC)wParam);
if ( processed )
{
// we processed the message, i.e. erased the background
#endif
case WM_INITDIALOG:
- processed = HandleInitDialog((WXHWND)(HWND)wParam);
+ processed = HandleInitDialog((WXHWND)wParam);
if ( processed )
{
#endif
case WM_SETCURSOR:
- processed = HandleSetCursor((WXHWND)(HWND)wParam,
+ processed = HandleSetCursor((WXHWND)wParam,
LOWORD(lParam), // hit test
HIWORD(lParam)); // mouse msg
);
helpEvent.SetEventObject(this);
- GetEventHandler()->ProcessEvent(helpEvent);
+ HandleWindowEvent(helpEvent);
#ifndef __WXWINCE__
}
else if ( info->iContextType == HELPINFO_MENUITEM )
{
wxHelpEvent helpEvent(wxEVT_HELP, info->iCtrlId);
helpEvent.SetEventObject(this);
- GetEventHandler()->ProcessEvent(helpEvent);
+ HandleWindowEvent(helpEvent);
}
else // unknown help event?
// we could have got an event from our child, reflect it back
// to it if this is the case
wxWindowMSW *win = NULL;
- if ( (WXHWND)wParam != m_hWnd )
+ WXHWND hWnd = (WXHWND)wParam;
+ if ( hWnd != m_hWnd )
{
- win = FindItemByHWND((WXHWND)wParam);
+ win = FindItemByHWND(hWnd);
}
if ( !win )
win = this;
evtCtx.SetEventObject(win);
- processed = win->GetEventHandler()->ProcessEvent(evtCtx);
+ processed = win->HandleWindowEvent(evtCtx);
}
break;
#endif
+#if wxUSE_MENUS
case WM_MENUCHAR:
// we're only interested in our own menus, not MF_SYSMENU
if ( HIWORD(wParam) == MF_POPUP )
}
}
break;
+#endif // wxUSE_MENUS
#ifndef __WXWINCE__
case WM_POWERBROADCAST:
}
break;
#endif // __WXWINCE__
+
+#if wxUSE_UXTHEME
+ // If we want the default themed border then we need to draw it ourselves
+ case WM_NCCALCSIZE:
+ {
+ wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive();
+ const wxBorder border = TranslateBorder(GetBorder());
+ if (theme && border == wxBORDER_THEME)
+ {
+ // first ask the widget to calculate the border size
+ rc.result = MSWDefWindowProc(message, wParam, lParam);
+ processed = true;
+
+ // now alter the client size making room for drawing a themed border
+ NCCALCSIZE_PARAMS *csparam = NULL;
+ RECT *rect;
+ if ( wParam )
+ {
+ csparam = (NCCALCSIZE_PARAMS *)lParam;
+ rect = &csparam->rgrc[0];
+ }
+ else
+ {
+ rect = (RECT *)lParam;
+ }
+
+ wxUxThemeHandle hTheme((const wxWindow *)this, L"EDIT");
+ RECT rcClient = { 0, 0, 0, 0 };
+ wxClientDC dc((wxWindow *)this);
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
+
+ if ( theme->GetThemeBackgroundContentRect
+ (
+ hTheme,
+ GetHdcOf(*impl),
+ EP_EDITTEXT,
+ ETS_NORMAL,
+ rect,
+ &rcClient) == S_OK )
+ {
+ InflateRect(&rcClient, -1, -1);
+ *rect = rcClient;
+ rc.result = WVR_REDRAW;
+ }
+ }
+ }
+ break;
+
+ case WM_NCPAINT:
+ {
+ wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive();
+ const wxBorder border = TranslateBorder(GetBorder());
+ if (theme && border == wxBORDER_THEME)
+ {
+ // first ask the widget to paint its non-client area, such as scrollbars, etc.
+ rc.result = MSWDefWindowProc(message, wParam, lParam);
+ processed = true;
+
+ wxUxThemeHandle hTheme((const wxWindow *)this, L"EDIT");
+ wxWindowDC dc((wxWindow *)this);
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
+
+ // Clip the DC so that you only draw on the non-client area
+ RECT rcBorder;
+ wxCopyRectToRECT(GetSize(), rcBorder);
+
+ RECT rcClient;
+ theme->GetThemeBackgroundContentRect(
+ hTheme, GetHdcOf(*impl), EP_EDITTEXT, ETS_NORMAL, &rcBorder, &rcClient);
+ InflateRect(&rcClient, -1, -1);
+
+ ::ExcludeClipRect(GetHdcOf(*impl), rcClient.left, rcClient.top,
+ rcClient.right, rcClient.bottom);
+
+ // Make sure the background is in a proper state
+ if (theme->IsThemeBackgroundPartiallyTransparent(hTheme, EP_EDITTEXT, ETS_NORMAL))
+ {
+ theme->DrawThemeParentBackground(GetHwnd(), GetHdcOf(*impl), &rcBorder);
+ }
+
+ // Draw the border
+ int nState;
+ if ( !IsEnabled() )
+ nState = ETS_DISABLED;
+ // should we check this?
+ //else if ( ::GetWindowLong(GetHwnd(), GWL_STYLE) & ES_READONLY)
+ // nState = ETS_READONLY;
+ else
+ nState = ETS_NORMAL;
+ theme->DrawThemeBackground(hTheme, GetHdcOf(*impl), EP_EDITTEXT, nState, &rcBorder, NULL);
+ }
+ }
+ break;
+
+#endif // wxUSE_UXTHEME
+
+ default:
+ // try a custom message handler
+ const MSWMessageHandlers::const_iterator
+ i = gs_messageHandlers.find(message);
+ if ( i != gs_messageHandlers.end() )
+ {
+ processed = (*i->second)(this, message, wParam, lParam);
+ }
}
if ( !processed )
// wxWindow <-> HWND map
// ----------------------------------------------------------------------------
-wxWinHashTable *wxWinHandleHash = NULL;
-
-wxWindow *wxFindWinFromHandle(WXHWND hWnd)
+wxWindow *wxFindWinFromHandle(HWND hwnd)
{
- return (wxWindow*)wxWinHandleHash->Get((long)hWnd);
+ WindowHandles::const_iterator i = gs_windowHandles.find(hwnd);
+ return i == gs_windowHandles.end() ? NULL : i->second;
}
-void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win)
+void wxAssociateWinWithHandle(HWND hwnd, wxWindowMSW *win)
{
- // adding NULL hWnd is (first) surely a result of an error and
+ // adding NULL hwnd is (first) surely a result of an error and
// (secondly) breaks menu command processing
- wxCHECK_RET( hWnd != (HWND)NULL,
- wxT("attempt to add a NULL hWnd to window list ignored") );
+ wxCHECK_RET( hwnd != (HWND)NULL,
+ wxT("attempt to add a NULL hwnd to window list ignored") );
- wxWindow *oldWin = wxFindWinFromHandle((WXHWND) hWnd);
#ifdef __WXDEBUG__
- if ( oldWin && (oldWin != win) )
+ WindowHandles::const_iterator i = gs_windowHandles.find(hwnd);
+ if ( i != gs_windowHandles.end() )
{
- wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
- (int) hWnd, win->GetClassInfo()->GetClassName());
+ if ( i->second != win )
+ {
+ wxLogDebug(wxT("HWND %p already associated with another window (%s)"),
+ hwnd, win->GetClassInfo()->GetClassName());
+ }
+ //else: this actually happens currently because we associate the window
+ // with its HWND during creation (if we create it) and also when
+ // SubclassWin() is called later, this is ok
}
- else
#endif // __WXDEBUG__
- if (!oldWin)
- {
- wxWinHandleHash->Put((long)hWnd, (wxWindow *)win);
- }
+
+ gs_windowHandles[hwnd] = (wxWindow *)win;
}
void wxRemoveHandleAssociation(wxWindowMSW *win)
{
- wxWinHandleHash->Delete((long)win->GetHWND());
+ gs_windowHandles.erase(GetHwndOf(win));
}
// ----------------------------------------------------------------------------
m_hWnd = (WXHWND)::CreateWindowEx
(
extendedStyle,
- className,
- title ? title : m_windowName.c_str(),
+ className.wx_str(),
+ title ? title : m_windowName.wx_str(),
style,
x, y, w, h,
(HWND)MSWGetParent(),
- (HMENU)controlId,
+ (HMENU)wxUIntToPtr(controlId),
wxGetInstance(),
NULL // no extra data
);
#ifndef __WXMICROWIN__
LPNMHDR hdr = (LPNMHDR)lParam;
HWND hWnd = hdr->hwndFrom;
- wxWindow *win = wxFindWinFromHandle((WXHWND)hWnd);
+ wxWindow *win = wxFindWinFromHandle(hWnd);
// if the control is one of our windows, let it handle the message itself
if ( win )
(
CP_ACP,
0, // no flags
- ttip,
+ ttip.wx_str(),
tipLength,
buf,
WXSIZEOF(buf) - 1
m_windowId);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleSetFocus(WXHWND hwnd)
// notify the parent keeping track of focus for the kbd navigation
// purposes that we got it
wxChildFocusEvent eventFocus((wxWindow *)this);
- (void)GetEventHandler()->ProcessEvent(eventFocus);
+ (void)HandleWindowEvent(eventFocus);
#if wxUSE_CARET
// Deal with caret
}
#endif // wxUSE_CARET
-#if wxUSE_TEXTCTRL
- // If it's a wxTextCtrl don't send the event as it will be done
- // after the control gets to process it from EN_FOCUS handler
- if ( wxDynamicCastThis(wxTextCtrl) )
- {
- return false;
- }
-#endif // wxUSE_TEXTCTRL
-
wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId);
event.SetEventObject(this);
// wxFindWinFromHandle() may return NULL, it is ok
event.SetWindow(wxFindWinFromHandle(hwnd));
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleKillFocus(WXHWND hwnd)
}
#endif // wxUSE_CARET
-#if wxUSE_TEXTCTRL
- // If it's a wxTextCtrl don't send the event as it will be done
- // after the control gets to process it.
- wxTextCtrl *ctrl = wxDynamicCastThis(wxTextCtrl);
- if ( ctrl )
- {
- return false;
- }
-#endif
-
// Don't send the event when in the process of being deleted. This can
// only cause problems if the event handler tries to access the object.
if ( m_isBeingDeleted )
// wxFindWinFromHandle() may return NULL, it is ok
event.SetWindow(wxFindWinFromHandle(hwnd));
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
// ---------------------------------------------------------------------------
wxShowEvent event(GetId(), show);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus))
wxInitDialogEvent event(GetId());
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
event.m_pos.x = dropPoint.x;
event.m_pos.y = dropPoint.y;
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
#endif
}
{
#ifndef __WXMICROWIN__
// the logic is as follows:
- // -1. don't set cursor for non client area, including but not limited to
- // the title bar, scrollbars, &c
- // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
- // 1. if we have the cursor set it unless wxIsBusy()
- // 2. if we're a top level window, set some cursor anyhow
- // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
+ // 0. if we're busy, set the busy cursor (even for non client elements)
+ // 1. don't set custom cursor for non client area of enabled windows
+ // 2. ask user EVT_SET_CURSOR handler for the cursor
+ // 3. if still no cursor but we're in a TLW, set the global cursor
- if ( nHitTest != HTCLIENT )
+ HCURSOR hcursor = 0;
+ if ( wxIsBusy() )
{
- return false;
+ hcursor = wxGetCurrentBusyCursor();
}
+ else // not busy
+ {
+ if ( nHitTest != HTCLIENT )
+ return false;
- HCURSOR hcursor = 0;
-
- // first ask the user code - it may wish to set the cursor in some very
- // specific way (for example, depending on the current position)
- POINT pt;
+ // first ask the user code - it may wish to set the cursor in some very
+ // specific way (for example, depending on the current position)
+ POINT pt;
#ifdef __WXWINCE__
- if ( !::GetCursorPosWinCE(&pt))
+ if ( !::GetCursorPosWinCE(&pt))
#else
- if ( !::GetCursorPos(&pt) )
+ if ( !::GetCursorPos(&pt) )
#endif
- {
- wxLogLastError(wxT("GetCursorPos"));
- }
-
- int x = pt.x,
- y = pt.y;
- ScreenToClient(&x, &y);
- wxSetCursorEvent event(x, y);
-
- bool processedEvtSetCursor = GetEventHandler()->ProcessEvent(event);
- if ( processedEvtSetCursor && event.HasCursor() )
- {
- hcursor = GetHcursorOf(event.GetCursor());
- }
+ {
+ wxLogLastError(wxT("GetCursorPos"));
+ }
- if ( !hcursor )
- {
- bool isBusy = wxIsBusy();
+ int x = pt.x,
+ y = pt.y;
+ ScreenToClient(&x, &y);
+ wxSetCursorEvent event(x, y);
- // the test for processedEvtSetCursor is here to prevent using m_cursor
- // if the user code caught EVT_SET_CURSOR() and returned nothing from
- // it - this is a way to say that our cursor shouldn't be used for this
- // point
- if ( !processedEvtSetCursor && m_cursor.Ok() )
+ bool processedEvtSetCursor = HandleWindowEvent(event);
+ if ( processedEvtSetCursor && event.HasCursor() )
{
- hcursor = GetHcursorOf(m_cursor);
+ hcursor = GetHcursorOf(event.GetCursor());
}
- if ( !GetParent() )
+ if ( !hcursor )
{
- if ( isBusy )
+ // the test for processedEvtSetCursor is here to prevent using
+ // m_cursor if the user code caught EVT_SET_CURSOR() and returned
+ // nothing from it - this is a way to say that our cursor shouldn't
+ // be used for this point
+ if ( !processedEvtSetCursor && m_cursor.Ok() )
{
- hcursor = wxGetCurrentBusyCursor();
+ hcursor = GetHcursorOf(m_cursor);
}
- else if ( !hcursor )
+
+ if ( !hcursor && !GetParent() )
{
const wxCursor *cursor = wxGetGlobalCursor();
if ( cursor && cursor->Ok() )
}
}
+
if ( hcursor )
{
-// wxLogDebug("HandleSetCursor: Setting cursor %ld", (long) hcursor);
-
::SetCursor(hcursor);
// cursor set, stop here
break;
case PBT_APMRESUMESUSPEND:
-#ifdef PBT_APMRESUMEAUTOMATIC
- case PBT_APMRESUMEAUTOMATIC:
-#endif
evtType = wxEVT_POWER_RESUME;
break;
case PBT_APMPOWERSTATUSCHANGE:
case PBT_APMOEMEVENT:
case PBT_APMRESUMECRITICAL:
+#ifdef PBT_APMRESUMEAUTOMATIC
+ case PBT_APMRESUMEAUTOMATIC:
+#endif
evtType = wxEVT_NULL;
break;
}
// TODO: notify about PBTF_APMRESUMEFROMFAILURE in case of resume events?
wxPowerEvent event(evtType);
- if ( !GetEventHandler()->ProcessEvent(event) )
+ if ( !HandleWindowEvent(event) )
return false;
*vetoed = event.IsVetoed();
#endif
}
+bool wxWindowMSW::IsDoubleBuffered() const
+{
+ for ( const wxWindowMSW *wnd = this;
+ wnd && !wnd->IsTopLevel(); wnd =
+ wnd->GetParent() )
+ {
+ if ( ::GetWindowLong(GetHwndOf(wnd), GWL_EXSTYLE) & WS_EX_COMPOSITED )
+ return true;
+ }
+
+ return false;
+}
+
// ---------------------------------------------------------------------------
// owner drawn stuff
// ---------------------------------------------------------------------------
wxSysColourChangedEvent event;
event.SetEventObject(this);
- (void)GetEventHandler()->ProcessEvent(event);
+ (void)HandleWindowEvent(event);
// always let the system carry on the default processing to allow the
// native controls to react to the colours update
wxDisplayChangedEvent event;
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
#ifndef __WXMICROWIN__
event.SetEventObject(this);
event.SetChangedWindow(wxFindWinFromHandle(hWndPalChange));
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
{
- wxMouseCaptureChangedEvent event(GetId(), wxFindWinFromHandle(hWndGainedCapture));
- event.SetEventObject(this);
+ // notify windows on the capture stack about lost capture
+ // (see http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863):
+ wxWindowBase::NotifyCaptureLost();
- return GetEventHandler()->ProcessEvent(event);
+ wxWindow *win = wxFindWinFromHandle(hWndGainedCapture);
+ wxMouseCaptureChangedEvent event(GetId(), win);
+ event.SetEventObject(this);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleSettingChange(WXWPARAM wParam, WXLPARAM lParam)
wxQueryNewPaletteEvent event(GetId());
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event) && event.GetPaletteRealized();
+ return HandleWindowEvent(event) && event.GetPaletteRealized();
}
// Responds to colour changes: passes event on to children.
wxPaintEvent event(m_windowId);
event.SetEventObject(this);
- bool processed = GetEventHandler()->ProcessEvent(event);
+ bool processed = HandleWindowEvent(event);
// note that we must generate NC event after the normal one as otherwise
// BeginPaint() will happily overwrite our decorations with the background
// colour
wxNcPaintEvent eventNc(m_windowId);
eventNc.SetEventObject(this);
- GetEventHandler()->ProcessEvent(eventNc);
+ HandleWindowEvent(eventNc);
+
+ // don't keep an HRGN we don't need any longer (GetUpdateRegion() can only
+ // be called from inside the event handlers called above)
+ m_updateRegion.Clear();
return processed;
}
#ifdef __WXUNIVERSAL__
event.Skip();
#else
- HDC hDC = (HDC) wxPaintDC::FindDCInCache((wxWindow*) event.GetEventObject());
+ HDC hDC = (HDC) wxPaintDCImpl::FindDCInCache((wxWindow*) event.GetEventObject());
if (hDC != 0)
{
MSWDefWindowProc(WM_PAINT, (WPARAM) hDC, 0);
bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc)
{
- wxDCTemp dc(hdc);
+ wxDCTemp dc(hdc, GetClientSize());
+ wxDCTempImpl *impl = (wxDCTempImpl*) dc.GetImpl();
- dc.SetHDC(hdc);
- dc.SetWindow((wxWindow *)this);
+ impl->SetHDC(hdc);
+ impl->SetWindow((wxWindow *)this);
wxEraseEvent event(m_windowId, &dc);
event.SetEventObject(this);
- bool rc = GetEventHandler()->ProcessEvent(event);
+ bool rc = HandleWindowEvent(event);
// must be called manually as ~wxDC doesn't do anything for wxDCTemp
- dc.SelectOldObjects(hdc);
+ impl->SelectOldObjects(hdc);
return rc;
}
return;
}
+ wxDC *dc = event.GetDC();
+ if (!dc) return;
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) dc->GetImpl();
// do default background painting
- if ( !DoEraseBackground(GetHdcOf(*event.GetDC())) )
+ if ( !DoEraseBackground(GetHdcOf(*impl)) )
{
// let the system paint the background
event.Skip();
wxIconizeEvent event(m_windowId);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleMaximize()
wxMaximizeEvent event(m_windowId);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleMove(int x, int y)
wxMoveEvent event(point, m_windowId);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleMoving(wxRect& rect)
wxMoveEvent event(rect, m_windowId);
event.SetEventObject(this);
- bool rc = GetEventHandler()->ProcessEvent(event);
+ bool rc = HandleWindowEvent(event);
if (rc)
rect = event.GetRect();
return rc;
}
+bool wxWindowMSW::HandleEnterSizeMove()
+{
+ wxMoveEvent event(wxPoint(0,0), m_windowId);
+ event.SetEventType(wxEVT_MOVE_START);
+ event.SetEventObject(this);
+
+ return HandleWindowEvent(event);
+}
+
+bool wxWindowMSW::HandleExitSizeMove()
+{
+ wxMoveEvent event(wxPoint(0,0), m_windowId);
+ event.SetEventType(wxEVT_MOVE_END);
+ event.SetEventObject(this);
+
+ return HandleWindowEvent(event);
+}
+
bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
{
#if USE_DEFERRED_SIZING
wxSizeEvent event(GetSize(), m_windowId);
event.SetEventObject(this);
- processed = GetEventHandler()->ProcessEvent(event);
+ processed = HandleWindowEvent(event);
}
#if USE_DEFERRED_SIZING
wxSizeEvent event(rect, m_windowId);
event.SetEventObject(this);
- bool rc = GetEventHandler()->ProcessEvent(event);
+ bool rc = HandleWindowEvent(event);
if (rc)
rect = event.GetRect();
return rc;
// command messages
// ---------------------------------------------------------------------------
-bool wxWindowMSW::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control)
+bool wxWindowMSW::HandleCommand(WXWORD id_, WXWORD cmd, WXHWND control)
{
+ // sign extend to int from short before comparing with the other int ids
+ int id = (signed short)id_;
+
#if wxUSE_MENUS_NATIVE
if ( !cmd && wxCurrentPopupMenu )
{
// try the id
if ( !win )
{
- // must cast to a signed type before comparing with other ids!
- win = FindItem((signed short)id);
+ win = FindItem(id);
}
if ( win )
event.SetId(id);
event.SetInt(id);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
else
{
event.m_leftDown = (flags & MK_LBUTTON) != 0;
event.m_middleDown = (flags & MK_MBUTTON) != 0;
event.m_rightDown = (flags & MK_RBUTTON) != 0;
- event.m_altDown = ::GetKeyState(VK_MENU) < 0;
+#ifdef wxHAS_XBUTTON
+ event.m_aux1Down = (flags & MK_XBUTTON1) != 0;
+ event.m_aux2Down = (flags & MK_XBUTTON2) != 0;
+#endif // wxHAS_XBUTTON
+ event.m_altDown = ::wxIsAltDown();
#ifndef __WXWINCE__
event.SetTimestamp(::GetMessageTime());
::IsWindowVisible(hwndUnderMouse) &&
::IsWindowEnabled(hwndUnderMouse) )
{
- wxWindow *winUnderMouse = wxFindWinFromHandle((WXHWND)hwndUnderMouse);
+ wxWindow *winUnderMouse = wxFindWinFromHandle(hwndUnderMouse);
if ( winUnderMouse )
{
// translate the mouse coords to the other window coords
wxEVT_RIGHT_DCLICK,
wxEVT_MIDDLE_DOWN,
wxEVT_MIDDLE_UP,
- wxEVT_MIDDLE_DCLICK
+ wxEVT_MIDDLE_DCLICK,
+ 0, // this one is for wxEVT_MOTION which is not used here
+ wxEVT_AUX1_DOWN,
+ wxEVT_AUX1_UP,
+ wxEVT_AUX1_DCLICK,
+ wxEVT_AUX2_DOWN,
+ wxEVT_AUX2_UP,
+ wxEVT_AUX2_DCLICK
};
+#ifdef wxHAS_XBUTTON
+ // the same messages are used for both auxillary mouse buttons so we need
+ // to adjust the index manually
+ switch ( msg )
+ {
+ case WM_XBUTTONDOWN:
+ case WM_XBUTTONUP:
+ case WM_XBUTTONDBLCLK:
+ if ( flags & MK_XBUTTON2 )
+ msg += wxEVT_AUX2_DOWN - wxEVT_AUX1_DOWN;
+ }
+#endif // wxHAS_XBUTTON
+
wxMouseEvent event(eventsMouse[msg - WM_MOUSEMOVE]);
InitMouseEvent(event, x, y, flags);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags)
m_mouseInWindow = true;
#ifdef HAVE_TRACKMOUSEEVENT
- WinStruct<TRACKMOUSEEVENT> trackinfo;
+ typedef BOOL (WINAPI *_TrackMouseEvent_t)(LPTRACKMOUSEEVENT);
+#ifdef __WXWINCE__
+ static const _TrackMouseEvent_t
+ s_pfn_TrackMouseEvent = _TrackMouseEvent;
+#else // !__WXWINCE__
+ static _TrackMouseEvent_t s_pfn_TrackMouseEvent;
+ static bool s_initDone = false;
+ if ( !s_initDone )
+ {
+ wxLogNull noLog;
+
+ wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
+ if ( dllComCtl32.IsLoaded() )
+ {
+ s_pfn_TrackMouseEvent = (_TrackMouseEvent_t)
+ dllComCtl32.GetSymbol(_T("_TrackMouseEvent"));
+ }
+
+ s_initDone = true;
+
+ // notice that it's ok to unload comctl32.dll here as it won't
+ // be really unloaded, being still in use because we link to it
+ // statically too
+ }
+
+ if ( s_pfn_TrackMouseEvent )
+#endif // __WXWINCE__/!__WXWINCE__
+ {
+ WinStruct<TRACKMOUSEEVENT> trackinfo;
- trackinfo.dwFlags = TME_LEAVE;
- trackinfo.hwndTrack = GetHwnd();
+ trackinfo.dwFlags = TME_LEAVE;
+ trackinfo.hwndTrack = GetHwnd();
- // Use the commctrl.h _TrackMouseEvent(), which will call the real
- // TrackMouseEvent() if available or emulate it
- _TrackMouseEvent(&trackinfo);
+ (*s_pfn_TrackMouseEvent)(&trackinfo);
+ }
#endif // HAVE_TRACKMOUSEEVENT
wxMouseEvent event(wxEVT_ENTER_WINDOW);
InitMouseEvent(event, x, y, flags);
- (void)GetEventHandler()->ProcessEvent(event);
+ (void)HandleWindowEvent(event);
}
}
#ifdef HAVE_TRACKMOUSEEVENT
- else
+ else // mouse not in window
{
// Check if we need to send a LEAVE event
// Windows doesn't send WM_MOUSELEAVE if the mouse has been captured so
}
event.m_linesPerAction = s_linesPerRotation;
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
#else // !wxUSE_MOUSEWHEEL
wxUnusedVar(wParam);
wxMouseEvent event(wxEVT_LEAVE_WINDOW);
InitMouseEvent(event, pt.x, pt.y, state);
- (void)GetEventHandler()->ProcessEvent(event);
+ (void)HandleWindowEvent(event);
}
// ---------------------------------------------------------------------------
event.m_altDown = false;
}
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam)
}
wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam));
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
}
wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam));
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
+#if wxUSE_MENUS
int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel),
WXLPARAM WXUNUSED_IN_WINCE(lParam))
{
// menu creation code
wxMenuItem *item = (wxMenuItem*)mii.dwItemData;
- const wxChar *p = wxStrchr(item->GetText(), _T('&'));
+ const wxChar *p = wxStrchr(item->GetItemLabel().wx_str(), _T('&'));
while ( p++ )
{
if ( *p == _T('&') )
evt.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(evt);
+ return HandleWindowEvent(evt);
}
+#endif // wxUSE_MENUS
// ---------------------------------------------------------------------------
// joystick
event.SetPosition(wxPoint(x, y));
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
#else
wxUnusedVar(msg);
wxUnusedVar(x);
return false;
}
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
+}
+
+// ----------------------------------------------------------------------------
+// custom message handlers
+// ----------------------------------------------------------------------------
+
+/* static */ bool
+wxWindowMSW::MSWRegisterMessageHandler(int msg, MSWMessageHandler handler)
+{
+ wxCHECK_MSG( gs_messageHandlers.find(msg) == gs_messageHandlers.end(),
+ false, _T("registering handler for the same message twice") );
+
+ gs_messageHandlers[msg] = handler;
+ return true;
+}
+
+/* static */ void
+wxWindowMSW::MSWUnregisterMessageHandler(int msg, MSWMessageHandler handler)
+{
+ const MSWMessageHandlers::iterator i = gs_messageHandlers.find(msg);
+ wxCHECK_RET( i != gs_messageHandlers.end() && i->second == handler,
+ _T("unregistering non-registered handler?") );
+
+ gs_messageHandlers.erase(i);
}
// ===========================================================================
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:
+ // no VkKeyScan() under CE unfortunately, we need to test how does
+ // it handle OEM keys
+#ifndef __WXWINCE__
+ // check to see if its one of the OEM key codes.
+ BYTE vks = LOBYTE(VkKeyScan(wxk));
+ if ( vks != 0xff )
+ {
+ vk = vks;
+ }
+ else
+#endif // !__WXWINCE__
+ {
+ if ( isVirtual )
+ *isVirtual = false;
+ vk = (WXWORD)wxk;
+ }
+ }
+
+ return vk;
+}
+
+// small helper for wxGetKeyState() and wxGetMouseState()
+static inline bool wxIsKeyDown(WXWORD vk)
+{
+ // SM_SWAPBUTTON is not available under CE, so don't swap buttons there
+#ifdef SM_SWAPBUTTON
+ if ( vk == VK_LBUTTON || vk == VK_RBUTTON )
+ {
+ if ( ::GetSystemMetrics(SM_SWAPBUTTON) )
+ {
+ if ( vk == VK_LBUTTON )
+ vk = VK_RBUTTON;
+ else // vk == VK_RBUTTON
+ vk = VK_LBUTTON;
}
}
- return keySym;
+#endif // SM_SWAPBUTTON
+
+ // 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.SetControlDown( (GetAsyncKeyState(VK_CONTROL) & (1<<15)) != 0 );
- ms.SetShiftDown( (GetAsyncKeyState(VK_SHIFT) & (1<<15)) != 0 );
- ms.SetAltDown( (GetAsyncKeyState(VK_MENU) & (1<<15)) != 0 );
+ ms.SetLeftDown(wxIsKeyDown(VK_LBUTTON));
+ ms.SetMiddleDown(wxIsKeyDown(VK_MBUTTON));
+ ms.SetRightDown(wxIsKeyDown(VK_RBUTTON));
+#ifdef wxHAS_XBUTTON
+ ms.SetAux1Down(wxIsKeyDown(VK_XBUTTON1));
+ ms.SetAux2Down(wxIsKeyDown(VK_XBUTTON2));
+#endif // wxHAS_XBUTTON
+
+ ms.SetControlDown(wxIsCtrlDown ());
+ ms.SetShiftDown (wxIsShiftDown());
+ ms.SetAltDown (wxIsAltDown ());
// ms.SetMetaDown();
return ms;
HWND hWnd = GetActiveWindow();
if ( hWnd != 0 )
{
- return wxFindWinFromHandle((WXHWND) hWnd);
+ return wxFindWinFromHandle(hWnd);
}
return NULL;
}
wxWindow *win = (wxWindow *)NULL;
if ( hwnd )
{
- win = wxFindWinFromHandle((WXHWND)hwnd);
+ win = wxFindWinFromHandle(hwnd);
if ( !win )
{
#if wxUSE_RADIOBOX
#endif
hwnd = ::GetParent(hwnd);
- win = wxFindWinFromHandle((WXHWND)hwnd);
+ win = wxFindWinFromHandle(hwnd);
}
return win;
case 0x00A7: return wxT("WM_NCMBUTTONDOWN");
case 0x00A8: return wxT("WM_NCMBUTTONUP");
case 0x00A9: return wxT("WM_NCMBUTTONDBLCLK");
+
+ case 0x00B0: return wxT("EM_GETSEL");
+ case 0x00B1: return wxT("EM_SETSEL");
+ case 0x00B2: return wxT("EM_GETRECT");
+ case 0x00B3: return wxT("EM_SETRECT");
+ case 0x00B4: return wxT("EM_SETRECTNP");
+ case 0x00B5: return wxT("EM_SCROLL");
+ case 0x00B6: return wxT("EM_LINESCROLL");
+ case 0x00B7: return wxT("EM_SCROLLCARET");
+ case 0x00B8: return wxT("EM_GETMODIFY");
+ case 0x00B9: return wxT("EM_SETMODIFY");
+ case 0x00BA: return wxT("EM_GETLINECOUNT");
+ case 0x00BB: return wxT("EM_LINEINDEX");
+ case 0x00BC: return wxT("EM_SETHANDLE");
+ case 0x00BD: return wxT("EM_GETHANDLE");
+ case 0x00BE: return wxT("EM_GETTHUMB");
+ case 0x00C1: return wxT("EM_LINELENGTH");
+ case 0x00C2: return wxT("EM_REPLACESEL");
+ case 0x00C4: return wxT("EM_GETLINE");
+ case 0x00C5: return wxT("EM_LIMITTEXT/EM_SETLIMITTEXT"); /* ;win40 Name change */
+ case 0x00C6: return wxT("EM_CANUNDO");
+ case 0x00C7: return wxT("EM_UNDO");
+ case 0x00C8: return wxT("EM_FMTLINES");
+ case 0x00C9: return wxT("EM_LINEFROMCHAR");
+ case 0x00CB: return wxT("EM_SETTABSTOPS");
+ case 0x00CC: return wxT("EM_SETPASSWORDCHAR");
+ case 0x00CD: return wxT("EM_EMPTYUNDOBUFFER");
+ case 0x00CE: return wxT("EM_GETFIRSTVISIBLELINE");
+ case 0x00CF: return wxT("EM_SETREADONLY");
+ case 0x00D0: return wxT("EM_SETWORDBREAKPROC");
+ case 0x00D1: return wxT("EM_GETWORDBREAKPROC");
+ case 0x00D2: return wxT("EM_GETPASSWORDCHAR");
+ case 0x00D3: return wxT("EM_SETMARGINS");
+ case 0x00D4: return wxT("EM_GETMARGINS");
+ case 0x00D5: return wxT("EM_GETLIMITTEXT");
+ case 0x00D6: return wxT("EM_POSFROMCHAR");
+ case 0x00D7: return wxT("EM_CHARFROMPOS");
+ case 0x00D8: return wxT("EM_SETIMESTATUS");
+ case 0x00D9: return wxT("EM_GETIMESTATUS");
+
case 0x0100: return wxT("WM_KEYDOWN");
case 0x0101: return wxT("WM_KEYUP");
case 0x0102: return wxT("WM_CHAR");
case 0x011F: return wxT("WM_MENUSELECT");
case 0x0120: return wxT("WM_MENUCHAR");
case 0x0121: return wxT("WM_ENTERIDLE");
+
+ case 0x0132: return wxT("WM_CTLCOLORMSGBOX");
+ case 0x0133: return wxT("WM_CTLCOLOREDIT");
+ case 0x0134: return wxT("WM_CTLCOLORLISTBOX");
+ case 0x0135: return wxT("WM_CTLCOLORBTN");
+ case 0x0136: return wxT("WM_CTLCOLORDLG");
+ case 0x0137: return wxT("WM_CTLCOLORSCROLLBAR");
+ case 0x0138: return wxT("WM_CTLCOLORSTATIC");
+ case 0x01E1: return wxT("MN_GETHMENU");
+
case 0x0200: return wxT("WM_MOUSEMOVE");
case 0x0201: return wxT("WM_LBUTTONDOWN");
case 0x0202: return wxT("WM_LBUTTONUP");
case 0x0208: return wxT("WM_MBUTTONUP");
case 0x0209: return wxT("WM_MBUTTONDBLCLK");
case 0x020A: return wxT("WM_MOUSEWHEEL");
+ case 0x020B: return wxT("WM_XBUTTONDOWN");
+ case 0x020C: return wxT("WM_XBUTTONUP");
+ case 0x020D: return wxT("WM_XBUTTONDBLCLK");
case 0x0210: return wxT("WM_PARENTNOTIFY");
case 0x0211: return wxT("WM_ENTERMENULOOP");
case 0x0212: return wxT("WM_EXITMENULOOP");
case 0x0290: return wxT("WM_IME_KEYDOWN");
case 0x0291: return wxT("WM_IME_KEYUP");
+ case 0x02A0: return wxT("WM_NCMOUSEHOVER");
+ case 0x02A1: return wxT("WM_MOUSEHOVER");
+ case 0x02A2: return wxT("WM_NCMOUSELEAVE");
+ case 0x02A3: return wxT("WM_MOUSELEAVE");
+
case 0x0300: return wxT("WM_CUT");
case 0x0301: return wxT("WM_COPY");
case 0x0302: return wxT("WM_PASTE");
case 0x030F: return wxT("WM_QUERYNEWPALETTE");
case 0x0310: return wxT("WM_PALETTEISCHANGING");
case 0x0311: return wxT("WM_PALETTECHANGED");
-#if wxUSE_HOTKEY
case 0x0312: return wxT("WM_HOTKEY");
-#endif
+
+ case 0x0317: return wxT("WM_PRINT");
+ case 0x0318: return wxT("WM_PRINTCLIENT");
// common controls messages - although they're not strictly speaking
// standard, it's nice to decode them nevertheless
event.m_altDown = (win_modifiers & MOD_ALT) != 0;
event.m_metaDown = (win_modifiers & MOD_WIN) != 0;
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
#endif // wxUSE_ACCEL
}
return CallNextHookEx(ms_hMsgHookProc, nCode, wParam, lParam);
- };
+ }
private:
static HHOOK ms_hMsgHookProc;