#endif
#endif
+#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
+
#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
// ---------------------------------------------------------------------------
return true;
}
+bool
+wxWindowMSW::MSWShowWithEffect(bool show,
+ wxShowEffect effect,
+ unsigned timeout,
+ wxDirection dir)
+{
+ typedef BOOL (WINAPI *AnimateWindow_t)(HWND, DWORD, DWORD);
+
+ static AnimateWindow_t s_pfnAnimateWindow = NULL;
+ static bool s_initDone = false;
+ if ( !s_initDone )
+ {
+ wxLogNull noLog;
+
+ wxDynamicLibrary dllUser32(_T("user32.dll"), wxDL_VERBATIM);
+ 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;
+}
+
// Raise the window to the top of the Z order
void wxWindowMSW::Raise()
{
}
}
+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;
+ }
+ }
+#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) && IsShown())
UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
}
case VK_RETURN:
{
- if ( (lDlgCode & DLGC_WANTMESSAGE) && !bCtrlDown )
- {
- // control wants to process Enter itself, don't
- // call IsDialogMessage() which would consume it
- return false;
- }
-
#if wxUSE_BUTTON
// currently active button should get enter press even
// if there is a default button elsewhere so check if
}
else // not a button itself, do we have default button?
{
- wxTopLevelWindow *
- tlw = wxDynamicCast(wxGetTopLevelParent(this),
- wxTopLevelWindow);
+ // 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 )
+ {
+ // this will contain the dialog code of this
+ // window and all of its parent windows in turn
+ LONG lDlgCode2 = lDlgCode;
+
+ while ( win )
+ {
+ 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 // bCtrlDown
+ {
+ win = wxGetTopLevelParent(win);
+ }
+
+ wxTopLevelWindow * const
+ tlw = wxDynamicCast(win, wxTopLevelWindow);
if ( tlw )
{
btn = wxDynamicCast(tlw->GetDefaultItem(),
}
}
break;
+#if 0
+ case WM_ENTERSIZEMOVE:
+ {
+ processed = HandleEnterSizeMove();
+ }
+ break;
+ case WM_EXITSIZEMOVE:
+ {
+ processed = HandleExitSizeMove();
+ }
+ break;
+#endif
case WM_SIZING:
{
LPRECT pRect = (LPRECT)lParam;
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
// problems, so don't do it for them (unnecessary anyhow)
if ( !win->IsOfStandardClass() )
{
- if ( message == WM_LBUTTONDOWN && win->CanAcceptFocus() )
+ if ( message == WM_LBUTTONDOWN && win->IsFocusable() )
win->SetFocus();
}
}
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((wxWindow *)this, L"EDIT");
+ RECT rcClient = { 0, 0, 0, 0 };
+ wxClientDC dc((wxWindow *)this);
+
+ if (theme->GetThemeBackgroundContentRect(
+ hTheme, GetHdcOf(dc), EP_EDITTEXT, ETS_NORMAL,
+ &rect, &rcClient) == S_OK)
+ {
+ InflateRect(&rcClient, -1, -1);
+ if (wParam)
+ csparam->rgrc[0] = rcClient;
+ else
+ *((RECT*)lParam) = 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((wxWindow *)this, L"EDIT");
+ wxWindowDC dc((wxWindow *)this);
+
+ // Clip the DC so that you only draw on the non-client area
+ RECT rcBorder;
+ wxCopyRectToRECT(GetSize(), rcBorder);
+
+ RECT rcClient;
+ theme->GetThemeBackgroundContentRect(
+ hTheme, GetHdcOf(dc), EP_EDITTEXT, ETS_NORMAL, &rcBorder, &rcClient);
+ InflateRect(&rcClient, -1, -1);
+
+ ::ExcludeClipRect(GetHdcOf(dc), 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(dc), &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(dc), EP_EDITTEXT, nState, &rcBorder, NULL);
+ }
+ }
+ break;
+
+#endif // wxUSE_UXTHEME
+
default:
// try a custom message handler
const MSWMessageHandlers::const_iterator
{
#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 = GetEventHandler()->ProcessEvent(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
eventNc.SetEventObject(this);
GetEventHandler()->ProcessEvent(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;
}
return rc;
}
+bool wxWindowMSW::HandleEnterSizeMove()
+{
+ wxMoveEvent event(wxPoint(0,0), m_windowId);
+ event.SetEventType(wxEVT_MOVE_START);
+ event.SetEventObject(this);
+
+ return GetEventHandler()->ProcessEvent(event);
+}
+
+bool wxWindowMSW::HandleExitSizeMove()
+{
+ wxMoveEvent event(wxPoint(0,0), m_windowId);
+ event.SetEventType(wxEVT_MOVE_END);
+ event.SetEventObject(this);
+
+ return GetEventHandler()->ProcessEvent(event);
+}
+
bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
{
#if USE_DEFERRED_SIZING
// 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.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());
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);
}
+#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().wx_str(), _T('&'));
+ const wxChar *p = wxStrchr(item->GetItemLabel().wx_str(), _T('&'));
while ( p++ )
{
if ( *p == _T('&') )
return GetEventHandler()->ProcessEvent(evt);
}
+#endif // wxUSE_MENUS
// ---------------------------------------------------------------------------
// joystick
ms.SetLeftDown(wxIsKeyDown(VK_LBUTTON));
ms.SetMiddleDown(wxIsKeyDown(VK_MBUTTON));
ms.SetRightDown(wxIsKeyDown(VK_RBUTTON));
-
- ms.SetControlDown(wxIsKeyDown(VK_CONTROL));
- ms.SetShiftDown(wxIsKeyDown(VK_SHIFT));
- ms.SetAltDown(wxIsKeyDown(VK_MENU));
+#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;
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");