#include "wx/log.h"
#include "wx/textctrl.h"
#include "wx/menuitem.h"
+ #include "wx/module.h"
#endif
#if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
#endif
#include "wx/evtloop.h"
-#include "wx/module.h"
#include "wx/power.h"
#include "wx/sysopt.h"
// include <commctrl.h> "properly"
#include "wx/msw/wrapcctl.h"
-#ifndef __WXWINCE__
+#if !defined __WXWINCE__ && !defined NEED_PBT_H
#include <pbt.h>
#endif
if ( s_needToUpdate == -1 )
{
int verMaj, verMin;
- s_needToUpdate = wxGetOsVersion(&verMaj, &verMin) == wxWINDOWS_NT &&
+ s_needToUpdate = wxGetOsVersion(&verMaj, &verMin) == wxOS_WINDOWS_NT &&
verMaj >= 5;
}
down ? pages : -pages);
}
+// ----------------------------------------------------------------------------
+// RTL support
+// ----------------------------------------------------------------------------
+
+void wxWindowMSW::SetLayoutDirection(wxLayoutDirection dir)
+{
+ 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);
+ }
+}
+
+wxLayoutDirection wxWindowMSW::GetLayoutDirection() const
+{
+ const HWND hwnd = GetHwnd();
+ wxCHECK_MSG( hwnd, wxLayout_Default, _T("invalid window") );
+
+ return ::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL
+ ? wxLayout_RightToLeft
+ : wxLayout_LeftToRight;
+}
+
+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
// ---------------------------------------------------------------------------
// 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
// 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,
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
+ 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
+ // 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
+ // 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((WXHWND)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() )
+ wxTopLevelWindow *
+ tlw = wxDynamicCast(wxGetTopLevelParent(this),
+ wxTopLevelWindow);
+ if ( tlw )
{
- // if we do have a default button, do press it
- btn->MSWCommand(BN_CLICKED, 0 /* unused */);
-
- return true;
+ btn = wxDynamicCast(tlw->GetDefaultItem(),
+ wxButton);
}
- else // no default button
+ }
+
+ if ( btn && btn->IsEnabled() )
+ {
+ btn->MSWCommand(BN_CLICKED, 0 /* unused */);
+ return true;
+ }
+
#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) )
- {
- // 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;
- }
- 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
- }
- }
+ // map Enter presses into button presses on PDAs
+ wxJoystickEvent event(wxEVT_JOY_BUTTON_DOWN);
+ event.SetEventObject(this);
+ if ( GetEventHandler()->ProcessEvent(event) )
+ return true;
+#endif // __WXWINCE__
}
break;
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();
+ wxWindow *win = wxFindWinFromHandle(hWndGainedCapture);
+ wxMouseCaptureChangedEvent event(GetId(), win);
+ event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
}
return 0;
}
-bool wxWindowMSW::HandlePrintClient(WXHDC hDC)
+bool wxWindowMSW::HandlePrintClient(WXHDC WXUNUSED(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;
-
- // sometimes we don't want the parent to handle it at all, instead
- // return whatever value this window wants
- if ( !MSWShouldPropagatePrintChild() )
- return MSWPrintChild(hDC, (wxWindow *)this);
-
- for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
- {
- if ( win->MSWPrintChild(hDC, (wxWindow *)this) )
- return true;
-
- if ( win->IsTopLevel() || win->InheritsBackgroundColour() )
- break;
- }
-
+ // TODO: handle wxBG_STYLE_CUSTOM and/or wxBG_STYLE_COLOUR here so when
+ // DrawParentThemeBackground() from uxtheme.dll is called we don't get
+ // the default background e.g. the border when custom drawing buttons
return false;
}
{ VK_SELECT, WXK_SELECT },
{ VK_PRINT, WXK_PRINT },
{ VK_EXECUTE, WXK_EXECUTE },
- { VK_HELP , WXK_HELP },
+ { VK_SNAPSHOT, WXK_SNAPSHOT },
+ { VK_HELP, WXK_HELP },
{ VK_NUMPAD0, WXK_NUMPAD0 },
{ VK_NUMPAD1, WXK_NUMPAD1 },