#include "wx/notebook.h"
#include "wx/listctrl.h"
+#include "wx/dynlib.h"
#include <string.h>
#endif
#endif
-#if defined(TME_LEAVE) && defined(WM_MOUSELEAVE)
+#if defined(TME_LEAVE) && defined(WM_MOUSELEAVE) && wxUSE_DYNLIB_CLASS
#define HAVE_TRACKMOUSEEVENT
#endif // everything needed for TrackMouseEvent()
bool wxWindowMSW::Enable(bool enable)
{
+ // we shouldn't really enable the window if our parent is currently
+ // disabled because under MSW this would indeed show the window in enabled
+ // state but it still wouldn't respond to the input (as its parent is
+ // disabled), so just update the internal m_childrenDisabled list in this
+ // case and our state will be really changed when the parent is enabled
+
+ // the logic above doesn't apply to top level windows, of course
+ wxWindowMSW * const parent = IsTopLevel() ? NULL : GetParent();
+ if ( parent && !parent->IsEnabled() && !IsEnabled() )
+ {
+ // it's a reference as we can create it below
+ wxWindowList *& disabledSiblings = parent->m_childrenDisabled;
+
+ bool rc = false;
+ if ( enable )
+ {
+ // shouldn't be disabled when the parent is reenabled
+ if ( disabledSiblings )
+ {
+ wxWindowList::compatibility_iterator
+ i = disabledSiblings->Find(this);
+ if ( i )
+ {
+ disabledSiblings->Erase(i);
+ rc = true;
+ }
+ }
+ //else: nothing to do
+ }
+ else // !enable
+ {
+ // should disable this window when the parent is enabled
+ if ( !disabledSiblings )
+ disabledSiblings = new wxWindowList;
+
+ disabledSiblings->Append(this);
+ }
+
+ return rc;
+ }
+
if ( !wxWindowBase::Enable(enable) )
return false;
// 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;
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;
// 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 )
+ if ( (lDlgCode & DLGC_WANTARROWS) && !bCtrlDown )
bProcess = false;
- else
+ else // OTOH Ctrl-PageUp/Dn works as [Shift-]Ctrl-Tab
bWindowChange = true;
break;
#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();
#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 |
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;
- trackinfo.dwFlags = TME_LEAVE;
- trackinfo.hwndTrack = GetHwnd();
+ // 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;
- // Use the commctrl.h _TrackMouseEvent(), which will call the real
- // TrackMouseEvent() if available or emulate it
- _TrackMouseEvent(&trackinfo);
+ trackinfo.dwFlags = TME_LEAVE;
+ trackinfo.hwndTrack = GetHwnd();
+
+ (*s_pfn_TrackMouseEvent)(&trackinfo);
+ }
#endif // HAVE_TRACKMOUSEEVENT
wxMouseEvent event(wxEVT_ENTER_WINDOW);
}
}
#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
return vk;
}
+#ifndef SM_SWAPBUTTON
+ #define SM_SWAPBUTTON 23
+#endif
+
// small helper for wxGetKeyState() and wxGetMouseState()
static inline bool wxIsKeyDown(WXWORD vk)
{
+ switch (vk)
+ {
+ case VK_LBUTTON:
+ if (GetSystemMetrics(SM_SWAPBUTTON)) vk = VK_RBUTTON;
+ break;
+ case VK_RBUTTON:
+ if (GetSystemMetrics(SM_SWAPBUTTON)) vk = VK_LBUTTON;
+ break;
+ }
// 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;
+ return (GetAsyncKeyState(vk) & (1<<15)) != 0;
}
bool wxGetKeyState(wxKeyCode key)
// 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;
+ return GetKeyState(vk) != 0;
}
else // normal key