#endif
#include "wx/msw/private.h"
+#include "wx/msw/dcclient.h"
#if wxUSE_TOOLTIPS
#include "wx/tooltip.h"
#define ETS_ASSIST 7
#endif
+// define the constants used by AnimateWindow() if our SDK doesn't have them
+#ifndef AW_CENTER
+ #define AW_HOR_POSITIVE 0x00000001
+ #define AW_HOR_NEGATIVE 0x00000002
+ #define AW_VER_POSITIVE 0x00000004
+ #define AW_VER_NEGATIVE 0x00000008
+ #define AW_CENTER 0x00000010
+ #define AW_HIDE 0x00010000
+ #define AW_ACTIVATE 0x00020000
+ #define AW_SLIDE 0x00040000
+ #define AW_BLEND 0x00080000
+#endif
+
#if defined(TME_LEAVE) && defined(WM_MOUSELEAVE) && wxUSE_DYNLIB_CLASS
#define HAVE_TRACKMOUSEEVENT
#endif // everything needed for TrackMouseEvent()
-// if this is set to 1, we use deferred window sizing to reduce flicker when
-// resizing complicated window hierarchies, but this can in theory result in
-// different behaviour than the old code so we keep the possibility to use it
-// by setting this to 0 (in the future this should be removed completely)
-#ifdef __WXWINCE__
-#define USE_DEFERRED_SIZING 0
-#else
-#define USE_DEFERRED_SIZING 1
-#endif
-
// set this to 1 to filter out duplicate mouse events, e.g. mouse move events
// when mouse position didnd't change
#ifdef __WXWINCE__
// ---------------------------------------------------------------------------
#if wxUSE_MENUS_NATIVE
-wxMenu *wxCurrentPopupMenu = NULL;
-#endif // wxUSE_MENUS_NATIVE
-
-#ifdef __WXWINCE__
-extern wxChar *wxCanvasClassName;
-#else
-extern const wxChar *wxCanvasClassName;
+extern wxMenu *wxCurrentPopupMenu;
#endif
// true if we had already created the std colour map, used by
static MSWMessageHandlers gs_messageHandlers;
+// hash containing all our windows, it uses HWND keys and wxWindow* values
+WX_DECLARE_HASH_MAP(HWND, wxWindow *,
+ wxPointerHash, wxPointerEqual,
+ WindowHandles);
+
+static WindowHandles gs_windowHandles;
+
// ---------------------------------------------------------------------------
// private functions
// ---------------------------------------------------------------------------
WPARAM wParam, LPARAM lParam);
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL >= 2
const wxChar *wxGetMessageName(int message);
-#endif //__WXDEBUG__
+#endif // wxDEBUG_LEVEL >= 2
void wxRemoveHandleAssociation(wxWindowMSW *win);
extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
-wxWindow *wxFindWinFromHandle(WXHWND hWnd);
// get the text metrics for the current font
static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win);
*/
while ( parent && !parent->IsTopLevel() )
{
- LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE);
+ LONG exStyle = wxGetWindowExStyle(parent);
if ( !(exStyle & WS_EX_CONTROLPARENT) )
{
// force the parent to have this style
- ::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE,
- exStyle | WS_EX_CONTROLPARENT);
+ wxSetWindowExStyle(parent, exStyle | WS_EX_CONTROLPARENT);
}
parent = parent->GetParent();
void wxWindowMSW::Init()
{
// MSW specific
- m_isBeingDeleted = false;
m_oldWndProc = NULL;
m_mouseInWindow = false;
m_lastKeydownProcessed = false;
- m_frozenness = 0;
-
m_hWnd = 0;
- m_hDWP = 0;
m_xThumbSize = 0;
m_yThumbSize = 0;
+#if wxUSE_DEFERRED_SIZING
+ m_hDWP = 0;
m_pendingPosition = wxDefaultPosition;
m_pendingSize = wxDefaultSize;
+#endif // wxUSE_DEFERRED_SIZING
#ifdef __POCKETPC__
m_contextMenuEnabled = false;
// Destructor
wxWindowMSW::~wxWindowMSW()
{
- m_isBeingDeleted = true;
+ SendDestroyEvent();
#ifndef __WXUNIVERSAL__
// VS: make sure there's no wxFrame with last focus set to us:
}
+/* static */
+const wxChar *wxWindowMSW::MSWGetRegisteredClassName()
+{
+ return wxApp::GetRegisteredClassName(_T("wxWindow"), COLOR_BTNFACE);
+}
+
// real construction (Init() must have been called before!)
bool wxWindowMSW::Create(wxWindow *parent,
wxWindowID id,
msflags |= WS_VISIBLE;
}
- if ( !MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle) )
+ if ( !MSWCreate(MSWGetRegisteredClassName(),
+ NULL, pos, size, msflags, exstyle) )
return false;
InheritAttributes();
HWND hWnd = GetHwnd();
wxCHECK_RET( hWnd, _T("can't set focus to invalid window") );
-#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
+#if !defined(__WXWINCE__)
::SetLastError(0);
#endif
if ( !::SetFocus(hWnd) )
{
-#if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
// was there really an error?
DWORD dwRes = ::GetLastError();
if ( dwRes )
wxLogApiError(_T("SetFocus"), dwRes);
}
}
-#endif // Debug
}
}
::ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
}
+ if ( IsFrozen() )
+ {
+ // DoFreeze/DoThaw don't do anything if the window is not shown, so
+ // we have to call them from here now
+ if ( show )
+ DoFreeze();
+ else
+ DoThaw();
+ }
+
+ return true;
+}
+
+bool
+wxWindowMSW::MSWShowWithEffect(bool show,
+ wxShowEffect effect,
+ unsigned timeout)
+{
+ if ( !wxWindowBase::Show(show) )
+ return false;
+
+ typedef BOOL (WINAPI *AnimateWindow_t)(HWND, DWORD, DWORD);
+
+ static AnimateWindow_t s_pfnAnimateWindow = NULL;
+ static bool s_initDone = false;
+ if ( !s_initDone )
+ {
+ wxDynamicLibrary dllUser32(_T("user32.dll"), wxDL_VERBATIM | wxDL_QUIET);
+ 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);
+
+ // Show() has a side effect of sending a WM_SIZE to the window, which helps
+ // ensuring that it's laid out correctly, but AnimateWindow() doesn't do
+ // this so send the event ourselves
+ SendSizeEvent();
+
+ // prepare to use AnimateWindow()
+
+ if ( !timeout )
+ timeout = 200; // this is the default animation timeout, per MSDN
+
+ DWORD dwFlags = show ? 0 : AW_HIDE;
+
+ switch ( effect )
+ {
+ case wxSHOW_EFFECT_ROLL_TO_LEFT:
+ dwFlags |= AW_HOR_NEGATIVE;
+ break;
+
+ case wxSHOW_EFFECT_ROLL_TO_RIGHT:
+ dwFlags |= AW_HOR_POSITIVE;
+ break;
+
+ case wxSHOW_EFFECT_ROLL_TO_TOP:
+ dwFlags |= AW_VER_NEGATIVE;
+ break;
+
+ case wxSHOW_EFFECT_ROLL_TO_BOTTOM:
+ dwFlags |= AW_VER_POSITIVE;
+ break;
+
+ case wxSHOW_EFFECT_SLIDE_TO_LEFT:
+ dwFlags |= AW_SLIDE | AW_HOR_NEGATIVE;
+ break;
+
+ case wxSHOW_EFFECT_SLIDE_TO_RIGHT:
+ dwFlags |= AW_SLIDE | AW_HOR_POSITIVE;
+ break;
+
+ case wxSHOW_EFFECT_SLIDE_TO_TOP:
+ dwFlags |= AW_SLIDE | AW_VER_NEGATIVE;
+ break;
+
+ case wxSHOW_EFFECT_SLIDE_TO_BOTTOM:
+ dwFlags |= AW_SLIDE | AW_VER_POSITIVE;
+ 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 ( !(*s_pfnAnimateWindow)(GetHwnd(), timeout, dwFlags) )
+ {
+ wxLogLastError(_T("AnimateWindow"));
+
+ return false;
+ }
+
return true;
}
/* static */ wxWindow *wxWindowBase::GetCapture()
{
HWND hwnd = ::GetCapture();
- return hwnd ? wxFindWinFromHandle((WXHWND)hwnd) : (wxWindow *)NULL;
+ return hwnd ? wxFindWinFromHandle(hwnd) : NULL;
}
bool wxWindowMSW::SetFont(const wxFont& font)
HWND hWnd = GetHwnd();
if ( hWnd != 0 )
{
- WXHANDLE hFont = m_font.GetResourceHandle();
+ // note the use of GetFont() instead of m_font: our own font could have
+ // just been reset and in this case we need to change the font used by
+ // the native window to the default for this class, i.e. exactly what
+ // GetFont() returns
+ WXHANDLE hFont = GetFont().GetResourceHandle();
wxASSERT_MSG( hFont, wxT("should have valid font") );
// scrolling stuff
// ---------------------------------------------------------------------------
+namespace
+{
+
inline int GetScrollPosition(HWND hWnd, int wOrient)
{
#ifdef __WXMICROWIN__
#endif
}
+inline UINT WXOrientToSB(int orient)
+{
+ return orient == wxHORIZONTAL ? SB_HORZ : SB_VERT;
+}
+
+} // anonymous namespace
+
int wxWindowMSW::GetScrollPos(int orient) const
{
HWND hWnd = GetHwnd();
wxCHECK_MSG( hWnd, 0, _T("no HWND in GetScrollPos") );
- return GetScrollPosition(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT);
+ return GetScrollPosition(hWnd, WXOrientToSB(orient));
}
// This now returns the whole range, not just the number
HWND hWnd = GetHwnd();
if ( !hWnd )
return 0;
-#if 0
- ::GetScrollRange(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
- &minPos, &maxPos);
-#endif
WinStruct<SCROLLINFO> scrollInfo;
scrollInfo.fMask = SIF_RANGE;
- if ( !::GetScrollInfo(hWnd,
- orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
- &scrollInfo) )
+ if ( !::GetScrollInfo(hWnd, WXOrientToSB(orient), &scrollInfo) )
{
// Most of the time this is not really an error, since the return
// value can also be zero when there is no scrollbar yet.
info.fMask |= SIF_DISABLENOSCROLL;
}
- ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
- &info, refresh);
+ ::SetScrollInfo(hWnd, WXOrientToSB(orient), &info, refresh);
}
// New function that will replace some of the above.
int range,
bool refresh)
{
+ // We have to set the variables here to make them valid in events
+ // triggered by ::SetScrollInfo()
+ *(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize;
+
+ HWND hwnd = GetHwnd();
+ if ( !hwnd )
+ return;
+
WinStruct<SCROLLINFO> info;
- info.nPage = pageSize;
- info.nMin = 0; // range is nMax - nMin + 1
- info.nMax = range - 1; // as both nMax and nMax are inclusive
- info.nPos = pos;
+ if ( range != -1 )
+ {
+ info.nPage = pageSize;
+ info.nMin = 0; // range is nMax - nMin + 1
+ info.nMax = range - 1; // as both nMax and nMax are inclusive
+ info.nPos = pos;
+
+ // enable the scrollbar if it had been disabled before by specifying
+ // SIF_DISABLENOSCROLL below: as we can't know whether this had been
+ // done or not just do it always
+ ::EnableScrollBar(hwnd, WXOrientToSB(orient), ESB_ENABLE_BOTH);
+ }
+ //else: leave all the fields to be 0
+
info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
- if ( HasFlag(wxALWAYS_SHOW_SB) )
+ if ( HasFlag(wxALWAYS_SHOW_SB) || range == -1 )
{
// disable scrollbar instead of removing it then
info.fMask |= SIF_DISABLENOSCROLL;
}
- HWND hWnd = GetHwnd();
- if ( hWnd )
- {
- // We have to set the variables here to make them valid in events
- // triggered by ::SetScrollInfo()
- *(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize;
-
- ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
- &info, refresh);
- }
+ ::SetScrollInfo(hwnd, WXOrientToSB(orient), &info, refresh);
}
void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect)
#ifdef __WXWINCE__
wxUnusedVar(dir);
#else
- const HWND hwnd = GetHwnd();
- wxCHECK_RET( hwnd, _T("layout direction must be set after window creation") );
+ wxCHECK_RET( GetHwnd(),
+ _T("layout direction must be set after window creation") );
- LONG styleOld = ::GetWindowLong(hwnd, GWL_EXSTYLE);
+ LONG styleOld = wxGetWindowExStyle(this);
LONG styleNew = styleOld;
switch ( dir )
if ( styleNew != styleOld )
{
- ::SetWindowLong(hwnd, GWL_EXSTYLE, styleNew);
+ wxSetWindowExStyle(this, styleNew);
}
#endif
}
#ifdef __WXWINCE__
return wxLayout_Default;
#else
- const HWND hwnd = GetHwnd();
- wxCHECK_MSG( hwnd, wxLayout_Default, _T("invalid window") );
+ wxCHECK_MSG( GetHwnd(), wxLayout_Default, _T("invalid window") );
- return ::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL
- ? wxLayout_RightToLeft
- : wxLayout_LeftToRight;
+ return wxHasWindowExStyle(this, WS_EX_LAYOUTRTL) ? wxLayout_RightToLeft
+ : wxLayout_LeftToRight;
#endif
}
HWND hwnd = (HWND)hWnd;
wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in SubclassWin") );
+ SetHWND(hWnd);
+
wxAssociateWinWithHandle(hwnd, this);
m_oldWndProc = (WXFARPROC)wxGetWindowProc((HWND)hWnd);
// we're officially created now, send the event
wxWindowCreateEvent event((wxWindow *)this);
- (void)GetEventHandler()->ProcessEvent(event);
+ (void)HandleWindowEvent(event);
}
void wxWindowMSW::UnsubclassWin()
WXHWND wxhwnd = (WXHWND)handle;
- SetHWND(wxhwnd);
+ // this also calls SetHWND(wxhwnd)
SubclassWin(wxhwnd);
}
bool wxCheckWindowWndProc(WXHWND hWnd,
WXFARPROC WXUNUSED(wndProc))
{
-// TODO: This list of window class names should be factored out so they can be
-// managed in one place and then accessed from here and other places, such as
-// wxApp::RegisterWindowClasses() and wxApp::UnregisterWindowClasses()
+ const wxString str(wxGetWindowClass(hWnd));
-#ifdef __WXWINCE__
- extern wxChar *wxCanvasClassName;
- extern wxChar *wxCanvasClassNameNR;
-#else
- extern const wxChar *wxCanvasClassName;
- extern const wxChar *wxCanvasClassNameNR;
-#endif
- extern const wxChar *wxMDIFrameClassName;
- extern const wxChar *wxMDIFrameClassNameNoRedraw;
- extern const wxChar *wxMDIChildFrameClassName;
- extern const wxChar *wxMDIChildFrameClassNameNoRedraw;
- wxString str(wxGetWindowClass(hWnd));
- if (str == wxCanvasClassName ||
- str == wxCanvasClassNameNR ||
-#if wxUSE_GLCANVAS
- str == _T("wxGLCanvasClass") ||
- str == _T("wxGLCanvasClassNR") ||
-#endif // wxUSE_GLCANVAS
- str == wxMDIFrameClassName ||
- str == wxMDIFrameClassNameNoRedraw ||
- str == wxMDIChildFrameClassName ||
- str == wxMDIChildFrameClassNameNoRedraw ||
- str == _T("wxTLWHiddenParent"))
- return true; // Effectively means don't subclass
- else
- return false;
+ // TODO: get rid of wxTLWHiddenParent special case (currently it's not
+ // registered by wxApp but using ad hoc code in msw/toplevel.cpp);
+ // there is also a hidden window class used by sockets &c
+ return wxApp::IsRegisteredClassName(str) || str == _T("wxTLWHiddenParent");
}
// ----------------------------------------------------------------------------
}
// and the extended style
- long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
+ long exstyleReal = wxGetWindowExStyle(this);
if ( exstyle != exstyleOld )
{
exstyleReal &= ~exstyleOld;
exstyleReal |= exstyle;
- ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal);
+ wxSetWindowExStyle(this, exstyleReal);
// ex style changes don't take effect without calling SetWindowPos
callSWP = true;
wxBorder wxWindowMSW::GetDefaultBorderForControl() const
{
- // we want to automatically give controls a sunken style (confusingly,
- // it may not really mean sunken at all as we map it to WS_EX_CLIENTEDGE
- // which is not sunken at all under Windows XP -- rather, just the default)
+ 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__)
- return wxBORDER_SIMPLE;
+ if (border == wxBORDER_THEME || border == wxBORDER_SUNKEN || border == wxBORDER_SIMPLE)
+ return wxBORDER_SIMPLE;
+ else
+ return wxBORDER_NONE;
#else
#if wxUSE_UXTHEME
- if (CanApplyThemeBorder())
+ if (border == wxBORDER_THEME)
{
- wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive();
- if (theme)
- return wxBORDER_THEME;
+ if (CanApplyThemeBorder())
+ {
+ wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive();
+ if (theme)
+ return wxBORDER_THEME;
+ }
+ return wxBORDER_SUNKEN;
}
#endif
- return wxBORDER_SUNKEN;
+ return border;
#endif
}
-wxBorder wxWindowMSW::GetDefaultBorder() const
-{
- return GetDefaultBorderForControl();
-}
WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
{
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 )
}
#endif // !HAVE_TRACKMOUSEEVENT
- if (wxUpdateUIEvent::CanUpdate(this))
+ if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
}
::SetParent(hWndChild, hWndParent);
#ifndef __WXWINCE__
- if ( ::GetWindowLong(hWndChild, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
+ if ( wxHasWindowExStyle(this, WS_EX_CONTROLPARENT) )
{
EnsureParentHasControlParentStyle(GetParent());
}
#endif
}
-void wxWindowMSW::Freeze()
+void wxWindowMSW::DoFreeze()
{
- if ( !m_frozenness++ )
- {
- if ( IsShown() )
- SendSetRedraw(GetHwnd(), false);
- }
+ if ( !IsShown() )
+ return; // no point in freezing hidden window
+
+ SendSetRedraw(GetHwnd(), false);
}
-void wxWindowMSW::Thaw()
+void wxWindowMSW::DoThaw()
{
- wxASSERT_MSG( m_frozenness > 0, _T("Thaw() without matching Freeze()") );
+ if ( !IsShown() )
+ return; // hidden windows aren't frozen by DoFreeze
- if ( --m_frozenness == 0 )
- {
- if ( IsShown() )
- {
- SendSetRedraw(GetHwnd(), true);
+ SendSetRedraw(GetHwnd(), true);
- // we need to refresh everything or otherwise the invalidated area
- // is not going to be repainted
- Refresh();
- }
- }
+ // we need to refresh everything or otherwise the invalidated area
+ // is not going to be repainted
+ Refresh();
}
void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
bool wxWindowMSW::IsSizeDeferred() const
{
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
if ( m_pendingPosition != wxDefaultPosition ||
m_pendingSize != wxDefaultSize )
return true;
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
return false;
}
// Get total size
void wxWindowMSW::DoGetSize(int *x, int *y) const
{
-#if USE_DEFERRED_SIZING
+#if wxUSE_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
+#endif // wxUSE_DEFERRED_SIZING
{
RECT rect = wxGetWindowRect(GetHwnd());
// Get size *available for subwindows* i.e. excluding menu bar etc.
void wxWindowMSW::DoGetClientSize(int *x, int *y) const
{
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
if ( m_pendingSize != wxDefaultSize )
{
// we need to calculate the client size corresponding to pending size
*y = rect.bottom - rect.top;
}
else
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
{
RECT rect = wxGetClientRect(GetHwnd());
bool
wxWindowMSW::DoMoveSibling(WXHWND hwnd, int x, int y, int width, int height)
{
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
// if our parent had prepared a defer window handle for us, use it (unless
// we are a top level window)
wxWindowMSW * const parent = IsTopLevel() ? NULL : GetParent();
}
// otherwise (or if deferring failed) move the window in place immediately
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
if ( !::MoveWindow((HWND)hwnd, x, y, width, height, IsShown()) )
{
wxLogLastError(wxT("MoveWindow"));
}
- // if USE_DEFERRED_SIZING, indicates that we didn't use deferred move,
+ // if wxUSE_DEFERRED_SIZING, indicates that we didn't use deferred move,
// ignored otherwise
return false;
}
if ( DoMoveSibling(m_hWnd, x, y, width, height) )
{
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
m_pendingPosition = wxPoint(x, y);
m_pendingSize = wxSize(width, height);
-#endif // USE_DEFERRED_SIZING
+ }
+ else // window was moved immediately, without deferring it
+ {
+ m_pendingPosition = wxDefaultPosition;
+ m_pendingSize = wxDefaultSize;
+#endif // wxUSE_DEFERRED_SIZING
}
}
width == currentW && height == currentH &&
!(sizeFlags & wxSIZE_FORCE) )
{
+ if (sizeFlags & wxSIZE_FORCE_EVENT)
+ {
+ wxSizeEvent event( wxSize(width,height), GetId() );
+ event.SetEventObject( this );
+ HandleWindowEvent( event );
+ }
return;
}
void wxWindowMSW::GetTextExtent(const wxString& string,
int *x, int *y,
int *descent, int *externalLeading,
- const wxFont *theFont) const
+ const wxFont *fontToUse) const
{
- wxASSERT_MSG( !theFont || theFont->Ok(),
+ wxASSERT_MSG( !fontToUse || fontToUse->Ok(),
_T("invalid font in GetTextExtent()") );
- wxFont fontToUse;
- if (theFont)
- fontToUse = *theFont;
+ HFONT hfontToUse;
+ if ( fontToUse )
+ hfontToUse = GetHfontOf(*fontToUse);
else
- fontToUse = GetFont();
+ hfontToUse = GetHfontOf(GetFont());
WindowHDC hdc(GetHwnd());
- SelectInHDC selectFont(hdc, GetHfontOf(fontToUse));
+ SelectInHDC selectFont(hdc, hfontToUse);
SIZE sizeRect;
TEXTMETRIC tm;
point.x = x;
point.y = y;
::ClientToScreen(hWnd, &point);
- wxCurrentPopupMenu = menu;
#if defined(__WXWINCE__)
static const UINT flags = 0;
#else // !__WXWINCE__
// for example) and so we do need to process the event immediately
wxYieldForCommandsOnly();
- wxCurrentPopupMenu = NULL;
-
menu->SetInvokingWindow(NULL);
return true;
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
if ( (style & BS_OWNERDRAW) == BS_OWNERDRAW )
{
// emulate the button click
- btn = wxFindWinFromHandle((WXHWND)msg->hwnd);
+ btn = wxFindWinFromHandle(msg->hwnd);
}
bProcess = false;
}
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(),
// map Enter presses into button presses on PDAs
wxJoystickEvent event(wxEVT_JOY_BUTTON_DOWN);
event.SetEventObject(this);
- if ( GetEventHandler()->ProcessEvent(event) )
+ if ( HandleWindowEvent(event) )
return true;
#endif // __WXWINCE__
}
event.SetFromTab(bFromTab);
event.SetEventObject(this);
- if ( GetEventHandler()->ProcessEvent(event) )
+ if ( HandleWindowEvent(event) )
{
// as we don't call IsDialogMessage(), which would take of
// this by default, we need to manually send this message
{
wxWindow * const win = node->GetData();
if ( win->CanAcceptFocus() &&
- !(::GetWindowLong(GetHwndOf(win), GWL_EXSTYLE) &
- WS_EX_CONTROLPARENT) )
+ !wxHasWindowExStyle(win, WS_EX_CONTROLPARENT) )
{
// it shouldn't hang...
canSafelyCallIsDlgMsg = true;
// Main window proc
LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
- // trace all messages - useful for the debugging
-#ifdef __WXDEBUG__
+ // trace all messages: useful for the debugging but noticeably slows down
+ // the code so don't do it by default
+#if wxDEBUG_LEVEL >= 2
wxLogTrace(wxTraceMessages,
- wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"),
- wxGetMessageName(message), (long)hWnd, (long)wParam, lParam);
-#endif // __WXDEBUG__
+ wxT("Processing %s(hWnd=%p, wParam=%08lx, lParam=%08lx)"),
+ wxGetMessageName(message), hWnd, (long)wParam, lParam);
+#endif // wxDEBUG_LEVEL >= 2
- wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd);
+ wxWindowMSW *wnd = wxFindWinFromHandle(hWnd);
// when we get the first message for the HWND we just created, we associate
// it with wxWindow stored in gs_winBeingCreated
break;
case WM_SETFOCUS:
- processed = HandleSetFocus((WXHWND)(HWND)wParam);
+ processed = HandleSetFocus((WXHWND)wParam);
break;
case WM_KILLFOCUS:
- processed = HandleKillFocus((WXHWND)(HWND)wParam);
+ processed = HandleKillFocus((WXHWND)wParam);
break;
case WM_PRINTCLIENT:
wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
evtCtx.SetEventObject(this);
- if (GetEventHandler()->ProcessEvent(evtCtx))
+ if (HandleWindowEvent(evtCtx))
{
processed = true;
return true;
// for these messages we must return true if process the message
#ifdef WM_DRAWITEM
case WM_DRAWITEM:
- case WM_MEASUREITEM:
- {
- int idCtrl = (UINT)wParam;
- if ( message == WM_DRAWITEM )
- {
- processed = MSWOnDrawItem(idCtrl,
- (WXDRAWITEMSTRUCT *)lParam);
- }
- else
- {
- processed = MSWOnMeasureItem(idCtrl,
- (WXMEASUREITEMSTRUCT *)lParam);
- }
+ processed = MSWOnDrawItem(wParam, (WXDRAWITEMSTRUCT *)lParam);
+ if ( processed )
+ rc.result = TRUE;
+ break;
- if ( processed )
- rc.result = TRUE;
- }
+ case WM_MEASUREITEM:
+ processed = MSWOnMeasureItem(wParam, (WXMEASUREITEMSTRUCT *)lParam);
+ if ( processed )
+ rc.result = TRUE;
break;
#endif // defined(WM_DRAWITEM)
break;
#endif // wxUSE_HOTKEY
+ case WM_CUT:
+ case WM_COPY:
+ case WM_PASTE:
+ processed = HandleClipboardEvent(message);
+ break;
+
case WM_HSCROLL:
case WM_VSCROLL:
{
#endif
case WM_PALETTECHANGED:
- processed = HandlePaletteChanged((WXHWND) (HWND) wParam);
+ processed = HandlePaletteChanged((WXHWND)wParam);
break;
case WM_CAPTURECHANGED:
- processed = HandleCaptureChanged((WXHWND) (HWND) lParam);
+ processed = HandleCaptureChanged((WXHWND)lParam);
break;
case WM_SETTINGCHANGE:
break;
case WM_ERASEBKGND:
- processed = HandleEraseBkgnd((WXHDC)(HDC)wParam);
+ processed = HandleEraseBkgnd((WXHDC)wParam);
if ( processed )
{
// we processed the message, i.e. erased the background
#endif
case WM_INITDIALOG:
- processed = HandleInitDialog((WXHWND)(HWND)wParam);
+ processed = HandleInitDialog((WXHWND)wParam);
if ( processed )
{
#endif
case WM_SETCURSOR:
- processed = HandleSetCursor((WXHWND)(HWND)wParam,
+ processed = HandleSetCursor((WXHWND)wParam,
LOWORD(lParam), // hit test
HIWORD(lParam)); // mouse msg
);
helpEvent.SetEventObject(this);
- GetEventHandler()->ProcessEvent(helpEvent);
+ HandleWindowEvent(helpEvent);
#ifndef __WXWINCE__
}
else if ( info->iContextType == HELPINFO_MENUITEM )
{
wxHelpEvent helpEvent(wxEVT_HELP, info->iCtrlId);
helpEvent.SetEventObject(this);
- GetEventHandler()->ProcessEvent(helpEvent);
+ HandleWindowEvent(helpEvent);
}
else // unknown help event?
// we could have got an event from our child, reflect it back
// to it if this is the case
wxWindowMSW *win = NULL;
- if ( (WXHWND)wParam != m_hWnd )
+ WXHWND hWnd = (WXHWND)wParam;
+ if ( hWnd != m_hWnd )
{
- win = FindItemByHWND((WXHWND)wParam);
+ win = FindItemByHWND(hWnd);
}
if ( !win )
win = this;
evtCtx.SetEventObject(win);
- processed = win->GetEventHandler()->ProcessEvent(evtCtx);
+ processed = win->HandleWindowEvent(evtCtx);
}
break;
#endif
case WM_NCCALCSIZE:
{
wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive();
- if (theme && GetBorder() == wxBORDER_THEME)
+ 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)
+ // now alter the client size making room for drawing a
+ // themed border
+ RECT *rect;
+ if ( wParam )
{
- csparam = (NCCALCSIZE_PARAMS*)lParam;
- rect = csparam->rgrc[0];
+ NCCALCSIZE_PARAMS *csparam = (NCCALCSIZE_PARAMS *)lParam;
+ rect = &csparam->rgrc[0];
}
else
{
- rect = *((RECT*)lParam);
+ rect = (RECT *)lParam;
}
- wxUxThemeHandle hTheme(this, L"EDIT");
+
+ wxUxThemeHandle hTheme((const wxWindow *)this, L"EDIT");
RECT rcClient = { 0, 0, 0, 0 };
- wxClientDC dc(this);
+ wxClientDC dc((wxWindow *)this);
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
- if (theme->GetThemeBackgroundContentRect(
- hTheme, GetHdcOf(dc), EP_EDITTEXT, ETS_NORMAL,
- &rect, &rcClient) == S_OK)
+ if ( theme->GetThemeBackgroundContentRect
+ (
+ hTheme,
+ GetHdcOf(*impl),
+ EP_EDITTEXT,
+ ETS_NORMAL,
+ rect,
+ &rcClient) == S_OK )
{
InflateRect(&rcClient, -1, -1);
- if (wParam)
- csparam->rgrc[0] = rcClient;
- else
- *((RECT*)lParam) = rcClient;
+ *rect = rcClient;
rc.result = WVR_REDRAW;
}
}
case WM_NCPAINT:
{
wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive();
- if (theme && GetBorder() == wxBORDER_THEME)
+ 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(this, L"EDIT");
- wxWindowDC dc(this);
+ wxUxThemeHandle hTheme((const wxWindow *)this, L"EDIT");
+ wxWindowDC dc((wxWindow *)this);
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
// Clip the DC so that you only draw on the non-client area
RECT rcBorder;
RECT rcClient;
theme->GetThemeBackgroundContentRect(
- hTheme, GetHdcOf(dc), EP_EDITTEXT, ETS_NORMAL, &rcBorder, &rcClient);
+ hTheme, GetHdcOf(*impl), EP_EDITTEXT, ETS_NORMAL, &rcBorder, &rcClient);
InflateRect(&rcClient, -1, -1);
- ::ExcludeClipRect(GetHdcOf(dc), rcClient.left, rcClient.top,
+ ::ExcludeClipRect(GetHdcOf(*impl), 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);
+ theme->DrawThemeParentBackground(GetHwnd(), GetHdcOf(*impl), &rcBorder);
}
// Draw the border
// nState = ETS_READONLY;
else
nState = ETS_NORMAL;
- theme->DrawThemeBackground(hTheme, GetHdcOf(dc), EP_EDITTEXT, nState, &rcBorder, NULL);
+ theme->DrawThemeBackground(hTheme, GetHdcOf(*impl), EP_EDITTEXT, nState, &rcBorder, NULL);
}
}
break;
if ( !processed )
{
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL >= 2
wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."),
wxGetMessageName(message));
-#endif // __WXDEBUG__
+#endif // wxDEBUG_LEVEL >= 2
rc.result = MSWDefWindowProc(message, wParam, lParam);
}
// wxWindow <-> HWND map
// ----------------------------------------------------------------------------
-wxWinHashTable *wxWinHandleHash = NULL;
-
-wxWindow *wxFindWinFromHandle(WXHWND hWnd)
+wxWindow *wxFindWinFromHandle(HWND hwnd)
{
- return (wxWindow*)wxWinHandleHash->Get((long)hWnd);
+ WindowHandles::const_iterator i = gs_windowHandles.find(hwnd);
+ return i == gs_windowHandles.end() ? NULL : i->second;
}
-void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win)
+void wxAssociateWinWithHandle(HWND hwnd, wxWindowMSW *win)
{
- // adding NULL hWnd is (first) surely a result of an error and
+ // adding NULL hwnd is (first) surely a result of an error and
// (secondly) breaks menu command processing
- wxCHECK_RET( hWnd != (HWND)NULL,
- wxT("attempt to add a NULL hWnd to window list ignored") );
+ wxCHECK_RET( hwnd != (HWND)NULL,
+ wxT("attempt to add a NULL hwnd to window list ignored") );
- wxWindow *oldWin = wxFindWinFromHandle((WXHWND) hWnd);
-#ifdef __WXDEBUG__
- if ( oldWin && (oldWin != win) )
+#if wxDEBUG_LEVEL
+ WindowHandles::const_iterator i = gs_windowHandles.find(hwnd);
+ if ( i != gs_windowHandles.end() )
{
- wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
- (int) hWnd, win->GetClassInfo()->GetClassName());
- }
- else
-#endif // __WXDEBUG__
- if (!oldWin)
- {
- wxWinHandleHash->Put((long)hWnd, (wxWindow *)win);
+ if ( i->second != win )
+ {
+ wxFAIL_MSG(
+ wxString::Format(
+ wxT("HWND %p already associated with another window (%s)"),
+ hwnd, win->GetClassInfo()->GetClassName()
+ )
+ );
+ }
+ //else: this actually happens currently because we associate the window
+ // with its HWND during creation (if we create it) and also when
+ // SubclassWin() is called later, this is ok
}
+#endif // wxDEBUG_LEVEL
+
+ gs_windowHandles[hwnd] = (wxWindow *)win;
}
void wxRemoveHandleAssociation(wxWindowMSW *win)
{
- wxWinHandleHash->Delete((long)win->GetHWND());
+ gs_windowHandles.erase(GetHwndOf(win));
}
// ----------------------------------------------------------------------------
WXDWORD style,
WXDWORD extendedStyle)
{
+ // check a common bug in the user code: if the window is created with a
+ // non-default ctor and Create() is called too, we'd create 2 HWND for a
+ // single wxWindow object and this results in all sorts of trouble,
+ // especially for wxTLWs
+ wxCHECK_MSG( !m_hWnd, true, "window can't be recreated" );
+
+ // this can happen if this function is called using the return value of
+ // wxApp::GetRegisteredClassName() which failed
+ wxCHECK_MSG( wclass, false, "failed to register window class?" );
+
+
// choose the position/size for the new window
int x, y, w, h;
(void)MSWGetCreateWindowCoords(pos, size, x, y, w, h);
wxString className(wclass);
if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) )
{
- className += wxT("NR");
+ className += wxApp::GetNoRedrawClassSuffix();
}
// do create the window
style,
x, y, w, h,
(HWND)MSWGetParent(),
- (HMENU)controlId,
+ (HMENU)wxUIntToPtr(controlId),
wxGetInstance(),
NULL // no extra data
);
#ifndef __WXMICROWIN__
LPNMHDR hdr = (LPNMHDR)lParam;
HWND hWnd = hdr->hwndFrom;
- wxWindow *win = wxFindWinFromHandle((WXHWND)hWnd);
+ wxWindow *win = wxFindWinFromHandle(hWnd);
// if the control is one of our windows, let it handle the message itself
if ( win )
// if we got TTN_NEEDTEXTW in Unicode build: in this case we just have
// to copy the string we have into the buffer
static wxChar buf[513];
- wxStrncpy(buf, ttip.c_str(), WXSIZEOF(buf) - 1);
- buf[WXSIZEOF(buf) - 1] = _T('\0');
+ wxStrlcpy(buf, ttip.c_str(), WXSIZEOF(buf));
ttText->lpszText = buf;
}
wxCloseEvent event(wxEVT_END_SESSION, wxID_ANY);
event.SetEventObject(wxTheApp);
event.SetCanVeto(false);
- event.SetLoggingOff( (logOff == (long)ENDSESSION_LOGOFF) );
+ event.SetLoggingOff((logOff & ENDSESSION_LOGOFF) != 0);
return wxTheApp->ProcessEvent(event);
#else
bool wxWindowMSW::HandleDestroy()
{
- SendDestroyEvent();
-
// delete our drop target if we've got one
#if wxUSE_DRAG_AND_DROP
if ( m_dropTarget != NULL )
m_windowId);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleSetFocus(WXHWND hwnd)
// notify the parent keeping track of focus for the kbd navigation
// purposes that we got it
wxChildFocusEvent eventFocus((wxWindow *)this);
- (void)GetEventHandler()->ProcessEvent(eventFocus);
+ (void)HandleWindowEvent(eventFocus);
#if wxUSE_CARET
// Deal with caret
}
#endif // wxUSE_CARET
-#if wxUSE_TEXTCTRL
- // If it's a wxTextCtrl don't send the event as it will be done
- // after the control gets to process it from EN_FOCUS handler
- if ( wxDynamicCastThis(wxTextCtrl) )
- {
- return false;
- }
-#endif // wxUSE_TEXTCTRL
-
wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId);
event.SetEventObject(this);
// wxFindWinFromHandle() may return NULL, it is ok
event.SetWindow(wxFindWinFromHandle(hwnd));
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleKillFocus(WXHWND hwnd)
}
#endif // wxUSE_CARET
-#if wxUSE_TEXTCTRL
- // If it's a wxTextCtrl don't send the event as it will be done
- // after the control gets to process it.
- wxTextCtrl *ctrl = wxDynamicCastThis(wxTextCtrl);
- if ( ctrl )
- {
- return false;
- }
-#endif
-
// Don't send the event when in the process of being deleted. This can
// only cause problems if the event handler tries to access the object.
if ( m_isBeingDeleted )
// wxFindWinFromHandle() may return NULL, it is ok
event.SetWindow(wxFindWinFromHandle(hwnd));
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
// ---------------------------------------------------------------------------
wxShowEvent event(GetId(), show);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus))
wxInitDialogEvent event(GetId());
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
::DragQueryFile(hFilesInfo, wIndex,
wxStringBuffer(files[wIndex], len), len);
}
- DragFinish (hFilesInfo);
wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files);
event.SetEventObject(this);
event.m_pos.x = dropPoint.x;
event.m_pos.y = dropPoint.y;
- return GetEventHandler()->ProcessEvent(event);
+ DragFinish(hFilesInfo);
+
+ return HandleWindowEvent(event);
#endif
}
ScreenToClient(&x, &y);
wxSetCursorEvent event(x, y);
- bool processedEvtSetCursor = GetEventHandler()->ProcessEvent(event);
+ bool processedEvtSetCursor = HandleWindowEvent(event);
if ( processedEvtSetCursor && event.HasCursor() )
{
hcursor = GetHcursorOf(event.GetCursor());
break;
case PBT_APMRESUMESUSPEND:
-#ifdef PBT_APMRESUMEAUTOMATIC
- case PBT_APMRESUMEAUTOMATIC:
-#endif
evtType = wxEVT_POWER_RESUME;
break;
case PBT_APMPOWERSTATUSCHANGE:
case PBT_APMOEMEVENT:
case PBT_APMRESUMECRITICAL:
+#ifdef PBT_APMRESUMEAUTOMATIC
+ case PBT_APMRESUMEAUTOMATIC:
+#endif
evtType = wxEVT_NULL;
break;
}
// TODO: notify about PBTF_APMRESUMEFROMFAILURE in case of resume events?
wxPowerEvent event(evtType);
- if ( !GetEventHandler()->ProcessEvent(event) )
+ if ( !HandleWindowEvent(event) )
return false;
*vetoed = event.IsVetoed();
bool wxWindowMSW::IsDoubleBuffered() const
{
- for ( const wxWindowMSW *wnd = this;
- wnd && !wnd->IsTopLevel(); wnd =
- wnd->GetParent() )
+ for ( const wxWindowMSW *win = this; win; win = win->GetParent() )
{
- if ( ::GetWindowLong(GetHwndOf(wnd), GWL_EXSTYLE) & WS_EX_COMPOSITED )
+ if ( wxHasWindowExStyle(win, WS_EX_COMPOSITED) )
return true;
+
+ if ( win->IsTopLevel() )
+ break;
}
return false;
}
+void wxWindowMSW::SetDoubleBuffered(bool on)
+{
+ // Get the current extended style bits
+ long exstyle = wxGetWindowExStyle(this);
+
+ // Twiddle the bit as needed
+ if ( on )
+ exstyle |= WS_EX_COMPOSITED;
+ else
+ exstyle &= ~WS_EX_COMPOSITED;
+
+ // put it back
+ wxSetWindowExStyle(this, exstyle);
+}
+
// ---------------------------------------------------------------------------
// owner drawn stuff
// ---------------------------------------------------------------------------
wxSysColourChangedEvent event;
event.SetEventObject(this);
- (void)GetEventHandler()->ProcessEvent(event);
+ (void)HandleWindowEvent(event);
// always let the system carry on the default processing to allow the
// native controls to react to the colours update
wxDisplayChangedEvent event;
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
#ifndef __WXMICROWIN__
event.SetEventObject(this);
event.SetChangedWindow(wxFindWinFromHandle(hWndPalChange));
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
wxWindow *win = wxFindWinFromHandle(hWndGainedCapture);
wxMouseCaptureChangedEvent event(GetId(), win);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleSettingChange(WXWPARAM wParam, WXLPARAM lParam)
wxQueryNewPaletteEvent event(GetId());
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event) && event.GetPaletteRealized();
+ return HandleWindowEvent(event) && event.GetPaletteRealized();
}
// Responds to colour changes: passes event on to children.
wxPaintEvent event(m_windowId);
event.SetEventObject(this);
- bool processed = GetEventHandler()->ProcessEvent(event);
+ bool processed = HandleWindowEvent(event);
// note that we must generate NC event after the normal one as otherwise
// BeginPaint() will happily overwrite our decorations with the background
// colour
wxNcPaintEvent eventNc(m_windowId);
eventNc.SetEventObject(this);
- GetEventHandler()->ProcessEvent(eventNc);
+ HandleWindowEvent(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;
}
#ifdef __WXUNIVERSAL__
event.Skip();
#else
- HDC hDC = (HDC) wxPaintDC::FindDCInCache((wxWindow*) event.GetEventObject());
+ HDC hDC = (HDC) wxPaintDCImpl::FindDCInCache((wxWindow*) event.GetEventObject());
if (hDC != 0)
{
MSWDefWindowProc(WM_PAINT, (WPARAM) hDC, 0);
bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc)
{
wxDCTemp dc(hdc, GetClientSize());
+ wxDCTempImpl *impl = (wxDCTempImpl*) dc.GetImpl();
- dc.SetHDC(hdc);
- dc.SetWindow((wxWindow *)this);
+ impl->SetHDC(hdc);
+ impl->SetWindow((wxWindow *)this);
wxEraseEvent event(m_windowId, &dc);
event.SetEventObject(this);
- bool rc = GetEventHandler()->ProcessEvent(event);
+ bool rc = HandleWindowEvent(event);
// must be called manually as ~wxDC doesn't do anything for wxDCTemp
- dc.SelectOldObjects(hdc);
+ impl->SelectOldObjects(hdc);
return rc;
}
return;
}
+ wxDC *dc = event.GetDC();
+ if (!dc) return;
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) dc->GetImpl();
// do default background painting
- if ( !DoEraseBackground(GetHdcOf(*event.GetDC())) )
+ if ( !DoEraseBackground(GetHdcOf(*impl)) )
{
// let the system paint the background
event.Skip();
wxIconizeEvent event(m_windowId);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleMaximize()
wxMaximizeEvent event(m_windowId);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleMove(int x, int y)
wxMoveEvent event(point, m_windowId);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleMoving(wxRect& rect)
wxMoveEvent event(rect, m_windowId);
event.SetEventObject(this);
- bool rc = GetEventHandler()->ProcessEvent(event);
+ bool rc = HandleWindowEvent(event);
if (rc)
rect = event.GetRect();
return rc;
event.SetEventType(wxEVT_MOVE_START);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleExitSizeMove()
event.SetEventType(wxEVT_MOVE_END);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
{
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
// when we resize this window, its children are probably going to be
// repositioned as well, prepare to use DeferWindowPos() for them
int numChildren = 0;
useDefer = true;
}
}
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
// update this window size
bool processed = false;
wxSizeEvent event(GetSize(), m_windowId);
event.SetEventObject(this);
- processed = GetEventHandler()->ProcessEvent(event);
+ processed = HandleWindowEvent(event);
}
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
// and finally change the positions of all child windows at once
if ( useDefer && m_hDWP )
{
node;
node = node->GetNext() )
{
- wxWindowMSW *child = node->GetData();
- child->m_pendingPosition = wxDefaultPosition;
- child->m_pendingSize = wxDefaultSize;
+ wxWindowMSW * const child = node->GetData();
+ child->MSWEndDeferWindowPos();
}
}
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
return processed;
}
wxSizeEvent event(rect, m_windowId);
event.SetEventObject(this);
- bool rc = GetEventHandler()->ProcessEvent(event);
+ bool rc = HandleWindowEvent(event);
if (rc)
rect = event.GetRect();
return rc;
// 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 )
// coming from a control to wxEVT_COMMAND_MENU_SELECTED
if ( !control )
{
- // If no child window, it may be an accelerator, e.g. for a popup menu
- // command
-
- wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED);
+ wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, id);
event.SetEventObject(this);
- event.SetId(id);
event.SetInt(id);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
else
{
event.m_aux1Down = (flags & MK_XBUTTON1) != 0;
event.m_aux2Down = (flags & MK_XBUTTON2) != 0;
#endif // wxHAS_XBUTTON
- event.m_altDown = ::GetKeyState(VK_MENU) < 0;
+ event.m_altDown = ::wxIsAltDown();
#ifndef __WXWINCE__
event.SetTimestamp(::GetMessageTime());
::IsWindowVisible(hwndUnderMouse) &&
::IsWindowEnabled(hwndUnderMouse) )
{
- wxWindow *winUnderMouse = wxFindWinFromHandle((WXHWND)hwndUnderMouse);
+ wxWindow *winUnderMouse = wxFindWinFromHandle(hwndUnderMouse);
if ( winUnderMouse )
{
// translate the mouse coords to the other window coords
wxMouseEvent event(eventsMouse[msg - WM_MOUSEMOVE]);
InitMouseEvent(event, x, y, flags);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags)
static bool s_initDone = false;
if ( !s_initDone )
{
- wxLogNull noLog;
-
- wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
+ // see comment in wxApp::GetComCtl32Version() explaining the
+ // use of wxLoadedDLL
+ wxLoadedDLL dllComCtl32(_T("comctl32.dll"));
if ( dllComCtl32.IsLoaded() )
{
s_pfn_TrackMouseEvent = (_TrackMouseEvent_t)
- dllComCtl32.GetSymbol(_T("_TrackMouseEvent"));
+ dllComCtl32.RawGetSymbol(_T("_TrackMouseEvent"));
}
s_initDone = true;
-
- // 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 )
wxMouseEvent event(wxEVT_ENTER_WINDOW);
InitMouseEvent(event, x, y, flags);
- (void)GetEventHandler()->ProcessEvent(event);
+ (void)HandleWindowEvent(event);
}
}
#ifdef HAVE_TRACKMOUSEEVENT
}
event.m_linesPerAction = s_linesPerRotation;
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
#else // !wxUSE_MOUSEWHEEL
wxUnusedVar(wParam);
wxMouseEvent event(wxEVT_LEAVE_WINDOW);
InitMouseEvent(event, pt.x, pt.y, state);
- (void)GetEventHandler()->ProcessEvent(event);
+ (void)HandleWindowEvent(event);
}
// ---------------------------------------------------------------------------
event.m_altDown = false;
}
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam)
}
wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam));
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
}
wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam));
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
#if wxUSE_MENUS
return wxNOT_FOUND;
}
-bool wxWindowMSW::HandleClipboardEvent( WXUINT nMsg )
+#endif // wxUSE_MENUS
+
+bool wxWindowMSW::HandleClipboardEvent(WXUINT nMsg)
{
- const wxEventType type = ( nMsg == WM_CUT ) ? wxEVT_COMMAND_TEXT_CUT :
- ( nMsg == WM_COPY ) ? wxEVT_COMMAND_TEXT_COPY :
- /*( nMsg == WM_PASTE ) ? */ wxEVT_COMMAND_TEXT_PASTE;
+ const wxEventType type = nMsg == WM_CUT ? wxEVT_COMMAND_TEXT_CUT
+ : nMsg == WM_COPY ? wxEVT_COMMAND_TEXT_COPY
+ : /* nMsg == WM_PASTE */ wxEVT_COMMAND_TEXT_PASTE;
wxClipboardTextEvent evt(type, GetId());
evt.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(evt);
+ return HandleWindowEvent(evt);
}
-#endif // wxUSE_MENUS
// ---------------------------------------------------------------------------
// joystick
event.SetPosition(wxPoint(x, y));
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
#else
wxUnusedVar(msg);
wxUnusedVar(x);
scrollInfo.fMask = SIF_TRACKPOS;
if ( !::GetScrollInfo(GetHwnd(),
- orientation == wxHORIZONTAL ? SB_HORZ
- : SB_VERT,
+ WXOrientToSB(orientation),
&scrollInfo) )
{
// Not necessarily an error, if there are no scrollbars yet.
return false;
}
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
// ----------------------------------------------------------------------------
break;
default:
- if ( isVirtual )
- *isVirtual = false;
- vk = (WXWORD)wxk;
- break;
+ // no VkKeyScan() under CE unfortunately, we need to test how does
+ // it handle OEM keys
+#ifndef __WXWINCE__
+ // check to see if its one of the OEM key codes.
+ BYTE vks = LOBYTE(VkKeyScan(wxk));
+ if ( vks != 0xff )
+ {
+ vk = vks;
+ }
+ else
+#endif // !__WXWINCE__
+ {
+ if ( isVirtual )
+ *isVirtual = false;
+ vk = (WXWORD)wxk;
+ }
}
return vk;
}
-#ifndef SM_SWAPBUTTON
- #define SM_SWAPBUTTON 23
-#endif
-
// small helper for wxGetKeyState() and wxGetMouseState()
static inline bool wxIsKeyDown(WXWORD vk)
{
- switch (vk)
+ // SM_SWAPBUTTON is not available under CE, so don't swap buttons there
+#ifdef SM_SWAPBUTTON
+ if ( vk == VK_LBUTTON || vk == VK_RBUTTON )
{
- case VK_LBUTTON:
- if (GetSystemMetrics(SM_SWAPBUTTON)) vk = VK_RBUTTON;
- break;
- case VK_RBUTTON:
- if (GetSystemMetrics(SM_SWAPBUTTON)) vk = VK_LBUTTON;
- break;
+ if ( ::GetSystemMetrics(SM_SWAPBUTTON) )
+ {
+ if ( vk == VK_LBUTTON )
+ vk = VK_RBUTTON;
+ else // vk == VK_RBUTTON
+ vk = VK_LBUTTON;
+ }
}
+#endif // SM_SWAPBUTTON
+
// 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
ms.SetAux2Down(wxIsKeyDown(VK_XBUTTON2));
#endif // wxHAS_XBUTTON
- ms.SetControlDown(wxIsKeyDown(VK_CONTROL));
- ms.SetShiftDown(wxIsKeyDown(VK_SHIFT));
- ms.SetAltDown(wxIsKeyDown(VK_MENU));
+ ms.SetControlDown(wxIsCtrlDown ());
+ ms.SetShiftDown (wxIsShiftDown());
+ ms.SetAltDown (wxIsAltDown ());
// ms.SetMetaDown();
return ms;
HWND hWnd = GetActiveWindow();
if ( hWnd != 0 )
{
- return wxFindWinFromHandle((WXHWND) hWnd);
+ return wxFindWinFromHandle(hWnd);
}
return NULL;
}
// For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
// by code in msw/radiobox.cpp), for all the others we just search up the
// window hierarchy
- wxWindow *win = (wxWindow *)NULL;
+ wxWindow *win = NULL;
if ( hwnd )
{
- win = wxFindWinFromHandle((WXHWND)hwnd);
+ win = wxFindWinFromHandle(hwnd);
if ( !win )
{
#if wxUSE_RADIOBOX
#endif
hwnd = ::GetParent(hwnd);
- win = wxFindWinFromHandle((WXHWND)hwnd);
+ win = wxFindWinFromHandle(hwnd);
}
return win;
// Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
// in active frames and dialogs, regardless of where the focus is.
static HHOOK wxTheKeyboardHook = 0;
-static FARPROC wxTheKeyboardHookProc = 0;
-int APIENTRY _EXPORT
-wxKeyboardHook(int nCode, WORD wParam, DWORD lParam);
-
-void wxSetKeyboardHook(bool doIt)
-{
- if ( doIt )
- {
- wxTheKeyboardHookProc = MakeProcInstance((FARPROC) wxKeyboardHook, wxGetInstance());
- wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(),
-
- GetCurrentThreadId()
- // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
- );
- }
- else
- {
- UnhookWindowsHookEx(wxTheKeyboardHook);
- }
-}
-int APIENTRY _EXPORT
+int APIENTRY
wxKeyboardHook(int nCode, WORD wParam, DWORD lParam)
{
DWORD hiWord = HIWORD(lParam);
return (int)CallNextHookEx(wxTheKeyboardHook, nCode, wParam, lParam);
}
+void wxSetKeyboardHook(bool doIt)
+{
+ if ( doIt )
+ {
+ wxTheKeyboardHook = ::SetWindowsHookEx
+ (
+ WH_KEYBOARD,
+ (HOOKPROC)wxKeyboardHook,
+ NULL, // must be NULL for process hook
+ ::GetCurrentThreadId()
+ );
+ if ( !wxTheKeyboardHook )
+ {
+ wxLogLastError(_T("SetWindowsHookEx(wxKeyboardHook)"));
+ }
+ }
+ else // uninstall
+ {
+ if ( wxTheKeyboardHook )
+ ::UnhookWindowsHookEx(wxTheKeyboardHook);
+ }
+}
+
#endif // !__WXMICROWIN__
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL >= 2
const wxChar *wxGetMessageName(int message)
{
switch ( message )
case 0x0120: return wxT("WM_MENUCHAR");
case 0x0121: return wxT("WM_ENTERIDLE");
+ case 0x0127: return wxT("WM_CHANGEUISTATE");
+ case 0x0128: return wxT("WM_UPDATEUISTATE");
+ case 0x0129: return wxT("WM_QUERYUISTATE");
+
case 0x0132: return wxT("WM_CTLCOLORMSGBOX");
case 0x0133: return wxT("WM_CTLCOLOREDIT");
case 0x0134: return wxT("WM_CTLCOLORLISTBOX");
return s_szBuf.c_str();
}
}
-#endif //__WXDEBUG__
+#endif // wxDEBUG_LEVEL >= 2
static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win)
{
event.m_altDown = (win_modifiers & MOD_ALT) != 0;
event.m_metaDown = (win_modifiers & MOD_WIN) != 0;
- return GetEventHandler()->ProcessEvent(event);
+ return HandleWindowEvent(event);
}
#endif // wxUSE_ACCEL