#endif
#include "wx/module.h"
+#include "wx/sysopt.h"
#if wxUSE_DRAG_AND_DROP
#include "wx/dnd.h"
// using this flag results in very significant reduction in flicker,
// especially with controls inside the static boxes (as the interior of the
// box is not redrawn twice)
- style |= WS_CLIPCHILDREN;
+ if (!wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children")) == 1)
+ style |= WS_CLIPCHILDREN;
// it doesn't seem useful to use WS_CLIPSIBLINGS here as we officially
// don't support overlapping windows and it only makes sense for them and,
void wxWindowMSW::OnInternalIdle()
{
+#ifdef __WXWINCE__
// Check if we need to send a LEAVE event
if ( m_mouseInWindow )
{
// or doesn't have mouse capture
if ( !IsMouseInWindow() )
{
- // Generate a LEAVE event
- m_mouseInWindow = false;
-
- // Unfortunately the mouse button and keyboard state may have
- // changed by the time the OnInternalIdle function is called, so 'state'
- // may be meaningless.
- int state = 0;
- if ( wxIsShiftDown() )
- state |= MK_SHIFT;
- if ( wxIsCtrlDown() )
- state |= MK_CONTROL;
-
- // Only the high-order bit should be tested
- if ( GetKeyState( VK_LBUTTON ) & (1<<15) )
- state |= MK_LBUTTON;
- if ( GetKeyState( VK_MBUTTON ) & (1<<15) )
- state |= MK_MBUTTON;
- if ( GetKeyState( VK_RBUTTON ) & (1<<15) )
- state |= MK_RBUTTON;
-
- POINT pt;
- if ( !::GetCursorPos(&pt) )
- {
- wxLogLastError(_T("GetCursorPos"));
- }
-
- // we need to have client coordinates here for symmetry with
- // wxEVT_ENTER_WINDOW
- RECT rect = wxGetWindowRect(GetHwnd());
- pt.x -= rect.left;
- pt.y -= rect.top;
-
- wxMouseEvent event2(wxEVT_LEAVE_WINDOW);
- InitMouseEvent(event2, pt.x, pt.y, state);
-
- (void)GetEventHandler()->ProcessEvent(event2);
+ GenerateMouseLeave();
}
}
+#endif // !__WXWINCE__
if (wxUpdateUIEvent::CanUpdate(this))
UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
if (height < 0)
height = 0;
- // if our parent had prepared a defer window handle for us, use it
+ // if our parent had prepared a defer window handle for us, use it (unless
+ // we are a top level window)
wxWindowMSW *parent = GetParent();
- HDWP hdwp = parent ? (HDWP)parent->m_hDWP : NULL;
+ HDWP hdwp = (parent && !IsTopLevel()) ? (HDWP)parent->m_hDWP : NULL;
if ( hdwp )
{
hdwp = ::DeferWindowPos(hdwp, GetHwnd(), NULL,
(void)HandleDestroy();
break;
-#ifndef __SMARTPHONE__ // or wxWinCE in general ?
- case WM_WINDOWPOSCHANGING:
- {
- WINDOWPOS *wp = wx_reinterpret_cast(WINDOWPOS *, lParam);
-
- if ( wp->flags & SWP_NOSIZE )
- break;
-
- // when we resize this window, its children are probably going
- // to be repositioned as well, prepare to use DeferWindowPos()
- // for them
- const int numChildren = GetChildren().GetCount();
- if ( numChildren > 1 )
- {
- m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
- if ( !m_hDWP )
- {
- wxLogLastError(_T("BeginDeferWindowPos"));
- }
- }
- }
- break;
-
- case WM_WINDOWPOSCHANGED:
- // first let DefWindowProc() handle the message: it will generate
- // WM_MOVE and WM_SIZE as needed
- processed = MSWDefWindowProc(message, wParam, lParam) == 0;
-
- // then change the positions of all child windows at once
- if ( m_hDWP )
- {
- HDWP hDWP = (HDWP)m_hDWP;
- m_hDWP = NULL;
-
- // put all child controls in place at once now
- if ( !::EndDeferWindowPos(hDWP) )
- {
- wxLogLastError(_T("EndDeferWindowPos"));
- }
- }
- break;
-#endif // __SMARTPHONE__
-
case WM_SIZE:
processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
break;
break;
#if !defined(__WXWINCE__)
- // TODO: move those in WM_WINDOWPOSCHANGING case above
case WM_MOVING:
{
LPRECT pRect = (LPRECT)lParam;
wParam);
break;
- // Seems to be broken currently
-#if 0 // ndef __WXWINCE__
+#ifdef WM_MOUSELEAVE
case WM_MOUSELEAVE:
- {
- wxASSERT_MSG( !m_mouseInWindow, wxT("the mouse should be in a window to generate this event!") );
-
- // only process this message if the mouse is not in the window,
- // This can also check for children in composite windows.
- // however, this may mean the the wxEVT_LEAVE_WINDOW is never sent
- // if the mouse does not enter the window from it's child before
- // leaving the scope of the window. ( perhaps this can be picked
- // up in the OnIdle code as before, for this special case )
- if ( /*IsComposite() && */ !IsMouseInWindow() )
{
- m_mouseInWindow = false;
-
- // Unfortunately no mouse state is passed with a WM_MOUSE_LEAVE
- int state = 0;
- if ( wxIsShiftDown() )
- state |= MK_SHIFT;
- if ( wxIsCtrlDown() )
- state |= MK_CONTROL;
- if ( GetKeyState( VK_LBUTTON ) )
- state |= MK_LBUTTON;
- if ( GetKeyState( VK_MBUTTON ) )
- state |= MK_MBUTTON;
- if ( GetKeyState( VK_RBUTTON ) )
- state |= MK_RBUTTON;
-
- POINT pt;
- if ( !::GetCursorPos(&pt) )
+ // filter out excess WM_MOUSELEAVE events sent after PopupMenu() (on XP at least)
+ if ( m_mouseInWindow )
{
- wxLogLastError(_T("GetCursorPos"));
+ GenerateMouseLeave();
}
- // we need to have client coordinates here for symmetry with
- // wxEVT_ENTER_WINDOW
- RECT rect = wxGetWindowRect(GetHwnd());
- pt.x -= rect.left;
- pt.y -= rect.top;
-
- wxMouseEvent event2(wxEVT_LEAVE_WINDOW);
- InitMouseEvent(event2, pt.x, pt.y, state);
-
- (void)GetEventHandler()->ProcessEvent(event2);
+ // always pass processed back as false, this allows the window
+ // manager to process the message too. This is needed to
+ // ensure windows XP themes work properly as the mouse moves
+ // over widgets like buttons.
+ processed = false;
}
- // always pass processed back as false, this allows the window
- // manager to process the message too. This is needed to ensure
- // windows XP themes work properly as the mouse moves over widgets
- // like buttons.
- processed = false;
- }
- break;
-#endif
- // __WXWINCE__
+ break;
+#endif // WM_MOUSELEAVE
#if wxUSE_MOUSEWHEEL
case WM_MOUSEWHEEL:
// do create the window
wxWindowCreationHook hook(this);
- // VZ: anyone care to explain why this is done for CE?
-#ifdef __WXWINCE__
- if (extendedStyle == 0)
- {
- m_hWnd = (WXHWND)::CreateWindow
- (
- className,
- title ? title : wxEmptyString,
- style,
- x, y, w, h,
- (HWND)MSWGetParent(),
- (HMENU)controlId,
- wxGetInstance(),
- NULL // no extra data
- );
- }
- else
-#endif // __WXWINCE__
- {
- m_hWnd = (WXHWND)::CreateWindowEx
- (
- extendedStyle,
- className,
- title ? title : wxEmptyString,
- style,
- x, y, w, h,
- (HWND)MSWGetParent(),
- (HMENU)controlId,
- wxGetInstance(),
- NULL // no extra data
- );
- }
+ m_hWnd = (WXHWND)::CreateWindowEx
+ (
+ extendedStyle,
+ className,
+ title ? title : m_windowName.c_str(),
+ style,
+ x, y, w, h,
+ (HWND)MSWGetParent(),
+ (HMENU)controlId,
+ wxGetInstance(),
+ NULL // no extra data
+ );
if ( !m_hWnd )
{
- wxLogSysError(_("Can't create window of class %s"), wclass);
+ wxLogSysError(_("Can't create window of class %s"), className.c_str());
return false;
}
bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
{
- bool processed = false;
+ // when we resize this window, its children are probably going to be
+ // repositioned as well, prepare to use DeferWindowPos() for them
+ const int numChildren = GetChildren().GetCount();
+ if ( numChildren > 1 )
+ {
+ m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
+ if ( !m_hDWP )
+ {
+ wxLogLastError(_T("BeginDeferWindowPos"));
+ }
+ }
+ // update this window size
+ bool processed = false;
switch ( wParam )
{
default:
processed = GetEventHandler()->ProcessEvent(event);
}
+ // and finally change the positions of all child windows at once
+ if ( m_hDWP )
+ {
+ // reset m_hDWP to NULL so that child windows don't try to use our
+ // m_hDWP after we call EndDeferWindowPos() on it (this shouldn't
+ // happen anyhow normally but who knows what weird flow of control we
+ // may have depending on what the users EVT_SIZE handler does...)
+ HDWP hDWP = (HDWP)m_hDWP;
+ m_hDWP = NULL;
+
+ // do put all child controls in place at once
+ if ( !::EndDeferWindowPos(hDWP) )
+ {
+ wxLogLastError(_T("EndDeferWindowPos"));
+ }
+ }
+
return processed;
}
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) & 0x80000000) != 0;
- // Returns different negative values on WinME and WinNT,
- // so simply test for negative value.
event.m_altDown = ::GetKeyState(VK_MENU) < 0;
#ifndef __WXWINCE__
{
// Generate an ENTER event
m_mouseInWindow = true;
-#if _WIN32_WINNT >= 0x0400
#ifndef __WXWINCE__
TRACKMOUSEEVENT trackinfo;
// appropriate TrackMouseEvent or emulate it ( win95 )
// else we need _WIN32_WINNT >= 0x0400
_TrackMouseEvent(&trackinfo);
-#endif
-#endif
+#endif // __WXWINCE__
wxMouseEvent event(wxEVT_ENTER_WINDOW);
InitMouseEvent(event, x, y, flags);
event.m_linesPerAction = s_linesPerRotation;
return GetEventHandler()->ProcessEvent(event);
-#else
- (void) wParam;
- (void) lParam;
+#else // !wxUSE_MOUSEWHEEL
+ wxUnusedVar(wParam);
+ wxUnusedVar(lParam);
return false;
-#endif
+#endif // wxUSE_MOUSEWHEEL/!wxUSE_MOUSEWHEEL
}
+void wxWindowMSW::GenerateMouseLeave()
+{
+ m_mouseInWindow = false;
+
+ int state = 0;
+ if ( wxIsShiftDown() )
+ state |= MK_SHIFT;
+ if ( wxIsCtrlDown() )
+ state |= MK_CONTROL;
+
+ // Only the high-order bit should be tested
+ if ( GetKeyState( VK_LBUTTON ) & (1<<15) )
+ state |= MK_LBUTTON;
+ if ( GetKeyState( VK_MBUTTON ) & (1<<15) )
+ state |= MK_MBUTTON;
+ if ( GetKeyState( VK_RBUTTON ) & (1<<15) )
+ state |= MK_RBUTTON;
+
+ POINT pt;
+ if ( !::GetCursorPos(&pt) )
+ {
+ wxLogLastError(_T("GetCursorPos"));
+ }
+
+ // we need to have client coordinates here for symmetry with
+ // wxEVT_ENTER_WINDOW
+ RECT rect = wxGetWindowRect(GetHwnd());
+ pt.x -= rect.left;
+ pt.y -= rect.top;
+
+ wxMouseEvent event(wxEVT_LEAVE_WINDOW);
+ InitMouseEvent(event, pt.x, pt.y, state);
+
+ (void)GetEventHandler()->ProcessEvent(event);
+}
// ---------------------------------------------------------------------------
// keyboard handling