#include "wx/msgdlg.h"
#include "wx/settings.h"
#include "wx/statbox.h"
+ #include "wx/sizer.h"
#endif
#if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
#include <windowsx.h>
#endif
-#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__)
- #ifdef __WIN95__
- #include <commctrl.h>
- #endif
-#elif !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // broken compiler
- #include "wx/msw/gnuwin32/extra.h"
-#endif
+#include <commctrl.h>
#include "wx/msw/missing.h"
#define HAVE_TRACKMOUSEEVENT
#endif // everything needed for TrackMouseEvent()
+#define USE_DEFERRED_SIZING 1
+#define USE_DEFER_BUG_WORKAROUND 1
+
// ---------------------------------------------------------------------------
// global variables
// ---------------------------------------------------------------------------
#endif // !__WXWINCE__
+#ifdef __WXWINCE__
+// On Windows CE, GetCursorPos can return an error, so use this function
+// instead
+bool GetCursorPosWinCE(POINT* pt)
+{
+ if (!GetCursorPos(pt))
+ {
+ DWORD pos = GetMessagePos();
+ pt->x = LOWORD(pos);
+ pt->y = HIWORD(pos);
+ }
+ return true;
+}
+#endif
+
// ---------------------------------------------------------------------------
// event tables
// ---------------------------------------------------------------------------
m_lastMouseY = -1;
m_lastMouseEvent = -1;
#endif // wxUSE_MOUSEEVENT_HACK
+
+ m_pendingPosition = wxDefaultPosition;
+ m_pendingSize = wxDefaultSize;
}
// Destructor
{
frame->SetLastFocus(NULL);
}
- break;
+
+ // apparently sometimes we can end up with our grand parent
+ // pointing to us as well: this is surely a bug in focus handling
+ // code but it's not clear where it happens so for now just try to
+ // fix it here by not breaking out of the loop
+ //break;
}
}
#endif // __WXUNIVERSAL__
}
delete m_childrenDisabled;
+
}
// real construction (Init() must have been called before!)
// Change the cursor NOW if we're within the correct window
POINT point;
+#ifdef __WXWINCE__
+ ::GetCursorPosWinCE(&point);
+#else
::GetCursorPos(&point);
+#endif
RECT rect = wxGetWindowRect(hWnd);
{
// get the mouse position
POINT pt;
+#ifdef __WXWINCE__
+ ::GetCursorPosWinCE(&pt);
+#else
::GetCursorPos(&pt);
+#endif
// find the window which currently has the cursor and go up the window
// chain until we find this window - or exhaust it
pRect = NULL;
}
-#ifndef __SMARTPHONE__
+ // RedrawWindow not available on SmartPhone or eVC++ 3
+#if !defined(__SMARTPHONE__) && !(defined(_WIN32_WCE) && _WIN32_WCE < 400)
UINT flags = RDW_INVALIDATE | RDW_ALLCHILDREN;
if ( eraseBack )
flags |= RDW_ERASE;
// if our parent had prepared a defer window handle for us, use it (unless
// we are a top level window)
wxWindowMSW *parent = GetParent();
+
+#if USE_DEFERRED_SIZING
HDWP hdwp = parent && !IsTopLevel() ? (HDWP)parent->m_hDWP : NULL;
- if ( hdwp )
- {
- hdwp = ::DeferWindowPos(hdwp, GetHwnd(), NULL,
- x, y, width, height,
- SWP_NOZORDER);
- if ( !hdwp )
- {
- wxLogLastError(_T("DeferWindowPos"));
- }
+#else
+ HDWP hdwp = 0;
+#endif
+
+ wxMoveWindowDeferred(hdwp, this, GetHwnd(), x, y, width, height);
+#if USE_DEFERRED_SIZING
+ if ( parent )
// hdwp must be updated as it may have been changed
parent->m_hDWP = (WXHANDLE)hdwp;
- }
-
- // otherwise (or if deferring failed) move the window in place immediately
- if ( !hdwp )
- {
- if ( !::MoveWindow(GetHwnd(), x, y, width, height, IsShown()) )
- {
- wxLogLastError(wxT("MoveWindow"));
- }
- }
+#endif
}
// set the size of the window: if the dimensions are positive, just use them,
{
// get the current size and position...
int currentX, currentY;
+ int currentW, currentH;
+
+#if USE_DEFER_BUG_WORKAROUND
+ currentX = m_pendingPosition.x;
+ if (currentX == wxDefaultCoord)
+ GetPosition(¤tX, NULL);
+
+ currentY = m_pendingPosition.y;
+ if (currentY == wxDefaultCoord)
+ GetPosition(NULL, ¤tY);
+
+ currentW = m_pendingSize.x;
+ if (currentW == wxDefaultCoord)
+ GetSize(¤tW, NULL);
+
+ currentH = m_pendingSize.y;
+ if (currentH == wxDefaultCoord)
+ GetSize(NULL, ¤tH);
+#else
GetPosition(¤tX, ¤tY);
- int currentW,currentH;
GetSize(¤tW, ¤tH);
+#endif
// ... and don't do anything (avoiding flicker) if it's already ok
if ( x == currentX && y == currentY &&
}
}
+#if USE_DEFER_BUG_WORKAROUND
+ // We don't actually use the hdwp here, but we need to know whether to
+ // save the pending dimensions or not. This isn't done in DoMoveWindow
+ // (where the hdwp is used) because some controls have thier own
+ // DoMoveWindow so it is easier to catch it here.
+ HDWP hdwp = GetParent() && !IsTopLevel() ? (HDWP)GetParent()->m_hDWP : NULL;
+ if (hdwp)
+ {
+ m_pendingPosition = wxPoint(x, y);
+ m_pendingSize = wxSize(width, height);
+ }
+ else
+ {
+ m_pendingPosition = wxDefaultPosition;
+ m_pendingSize = wxDefaultSize;
+ }
+#endif
+
DoMoveWindow(x, y, width, height);
}
SIZE sizeRect;
TEXTMETRIC tm;
- GetTextExtentPoint(hdc, string, string.length(), &sizeRect);
+ ::GetTextExtentPoint32(hdc, string, string.length(), &sizeRect);
GetTextMetrics(hdc, &tm);
if ( x )
break;
#endif // !__WXWINCE__
+ case WM_WINDOWPOSCHANGED:
+ {
+ WINDOWPOS *lpPos = (WINDOWPOS *)lParam;
+
+ if ( !(lpPos->flags & SWP_NOSIZE) )
+ {
+ RECT rc;
+ ::GetClientRect(GetHwnd(), &rc);
+
+ AutoHRGN hrgnClient(::CreateRectRgnIndirect(&rc));
+ AutoHRGN hrgnNew(::CreateRectRgn(lpPos->x, lpPos->y,
+ lpPos->cx, lpPos->cy));
+ AutoHRGN hrgn(::CreateRectRgn(0, 0, 0, 0));
+
+ // we need to invalidate any new exposed areas here
+ // to force them to repaint
+ if ( ::CombineRgn(hrgn, hrgnNew, hrgnClient, RGN_DIFF) != NULLREGION )
+ ::InvalidateRgn(GetHwnd(), hrgn, TRUE);
+ if ( ::CombineRgn(hrgn, hrgnClient, hrgnNew, RGN_DIFF) != NULLREGION )
+ ::InvalidateRgn(GetHwnd(), hrgn, TRUE);
+
+ }
+ }
+ break;
+
#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
case WM_ACTIVATEAPP:
// This implicitly sends a wxEVT_ACTIVATE_APP event
break;
case WM_PRINTCLIENT:
- // we receive this message when DrawThemeParentBackground() is
- // called from def window proc of several controls under XP and we
- // must draw properly themed background here
- //
- // note that naively I'd expect filling the client rect with the
- // brush returned by MSWGetBgBrush() work -- but for some reason it
- // doesn't and we have to call parents MSWPrintChild() which is
- // supposed to call DrawThemeBackground() with appropriate params
- //
- // also note that in this case lParam == PRF_CLIENT but we're
- // clearly expected to paint the background and nothing else!
- {
- for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
- {
- if ( win->MSWPrintChild((WXHDC)wParam, (wxWindow *)this) )
- {
- processed = true;
- break;
- }
-
- if ( win->IsTopLevel() || win->InheritsBackgroundColour() )
- break;
- }
- }
+ processed = HandlePrintClient((WXHDC)wParam);
break;
case WM_PAINT:
// 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))
+#else
if ( !::GetCursorPos(&pt) )
+#endif
{
wxLogLastError(wxT("GetCursorPos"));
}
{
wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData);
- wxCHECK_MSG( pMenuItem && pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)),
+ // see comment before the same test in MSWOnMeasureItem() below
+ if ( !pMenuItem )
+ return false;
+
+ wxCHECK_MSG( wxDynamicCast(pMenuItem, wxMenuItem),
false, _T("MSWOnDrawItem: bad wxMenuItem pointer") );
// prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
#ifndef __WXMICROWIN__
-bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC pDC, WXHWND hWnd)
+bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC hDC, WXHWND hWnd)
{
#if !wxUSE_CONTROLS || defined(__WXUNIVERSAL__)
- wxUnusedVar(pDC);
+ wxUnusedVar(hDC);
wxUnusedVar(hWnd);
#else
wxControl *item = wxDynamicCast(FindItemByHWND(hWnd, true), wxControl);
if ( item )
- *brush = item->MSWControlColor(pDC, hWnd);
+ *brush = item->MSWControlColor(hDC, hWnd);
else
#endif // wxUSE_CONTROLS
*brush = NULL;
// we want to avoid Windows' "help" and for this we need to have a
// reference bitmap which can tell us what the RGB values change
// to.
+ wxLogNull logNo; // suppress error if we couldn't load the bitmap
wxBitmap stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
if ( stdColourBitmap.Ok() )
{
return 0;
}
+bool wxWindowMSW::HandlePrintClient(WXHDC hDC)
+{
+ // we receive this message when DrawThemeParentBackground() is
+ // called from def window proc of several controls under XP and we
+ // must draw properly themed background here
+ //
+ // note that naively I'd expect filling the client rect with the
+ // brush returned by MSWGetBgBrush() work -- but for some reason it
+ // doesn't and we have to call parents MSWPrintChild() which is
+ // supposed to call DrawThemeBackground() with appropriate params
+ //
+ // also note that in this case lParam == PRF_CLIENT but we're
+ // clearly expected to paint the background and nothing else!
+
+ if ( IsTopLevel() || InheritsBackgroundColour() )
+ return false;
+
+ for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
+ {
+ if ( win->MSWPrintChild(hDC, (wxWindow *)this) )
+ return true;
+
+ if ( win->IsTopLevel() || win->InheritsBackgroundColour() )
+ break;
+ }
+
+ return false;
+}
+
// ---------------------------------------------------------------------------
// moving and resizing
// ---------------------------------------------------------------------------
bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
{
+#if USE_DEFERRED_SIZING
// 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();
+ int numChildren = 0;
+ for ( HWND child = ::GetWindow(GetHwndOf(this), GW_CHILD);
+ child;
+ child = ::GetWindow(child, GW_HWNDNEXT) )
+ {
+ numChildren ++;
+ }
+
+ // Protect against valid m_hDWP being overwritten
+ bool useDefer = false;
+
if ( numChildren > 1 )
{
- m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
- if ( !m_hDWP )
+ if (!m_hDWP)
{
- wxLogLastError(_T("BeginDeferWindowPos"));
+ m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
+ if ( !m_hDWP )
+ {
+ wxLogLastError(_T("BeginDeferWindowPos"));
+ }
+ if (m_hDWP)
+ useDefer = true;
}
}
+#endif
// update this window size
bool processed = false;
processed = GetEventHandler()->ProcessEvent(event);
}
+#if USE_DEFERRED_SIZING
// and finally change the positions of all child windows at once
- if ( m_hDWP )
+ if ( useDefer && 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
{
wxLogLastError(_T("EndDeferWindowPos"));
}
+
+#if USE_DEFER_BUG_WORKAROUND
+ // Reset our children's pending pos/size values.
+ for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ wxWindow *child = node->GetData();
+ child->m_pendingPosition = wxDefaultPosition;
+ child->m_pendingSize = wxDefaultSize;
+ }
+#endif
}
+#endif
return processed;
}
state |= MK_RBUTTON;
POINT pt;
+#ifdef __WXWINCE__
+ if ( !::GetCursorPosWinCE(&pt) )
+#else
if ( !::GetCursorPos(&pt) )
+#endif
{
wxLogLastError(_T("GetCursorPos"));
}
// translate the position to client coords
POINT pt;
+#ifdef __WXWINCE__
+ GetCursorPosWinCE(&pt);
+#else
GetCursorPos(&pt);
+#endif
RECT rect;
GetWindowRect(GetHwnd(),&rect);
pt.x -= rect.left;
wxPoint wxGetMousePosition()
{
POINT pt;
+#ifdef __WXWINCE__
+ GetCursorPosWinCE(&pt);
+#else
GetCursorPos( & pt );
+#endif
return wxPoint(pt.x, pt.y);
}
#endif // wxUSE_HOTKEY
+// Moves a window by deferred method or normal method
+bool wxMoveWindowDeferred(HDWP& hdwp, wxWindowBase* win, HWND hWnd, int x, int y, int width, int height)
+{
+ if ( hdwp )
+ {
+ hdwp = ::DeferWindowPos(hdwp, hWnd, NULL,
+ x, y, width, height,
+ SWP_NOZORDER);
+ if ( !hdwp )
+ {
+ wxLogLastError(_T("DeferWindowPos"));
+ }
+ }
+
+ // otherwise (or if deferring failed) move the window in place immediately
+ if ( !hdwp )
+ {
+ if ( !::MoveWindow(hWnd, x, y, width, height, win->IsShown()) )
+ {
+ wxLogLastError(wxT("MoveWindow"));
+ }
+ }
+ return hdwp != NULL;
+}
+
// Not tested under WinCE
#ifndef __WXWINCE__