// headers
// ---------------------------------------------------------------------------
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "window.h"
#endif
#endif
#ifndef WX_PRECOMP
- #include <windows.h>
- #include "wx/msw/winundef.h"
+ #include "wx/msw/wrapwin.h"
#include "wx/window.h"
#include "wx/accel.h"
#include "wx/setup.h"
#include "wx/statbox.h"
#endif
-#if wxUSE_OWNER_DRAWN
+#if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
#include "wx/ownerdrw.h"
#endif
+#include "wx/module.h"
+
#if wxUSE_DRAG_AND_DROP
#include "wx/dnd.h"
#endif
#if wxUSE_ACCESSIBILITY
#include "wx/access.h"
+ #include <ole2.h>
#include <oleacc.h>
#ifndef WM_GETOBJECT
#define WM_GETOBJECT 0x003D
#include "wx/textctrl.h"
#include "wx/notebook.h"
+#include "wx/listctrl.h"
#include <string.h>
-#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__)
+#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__)
#include <shellapi.h>
#include <mmsystem.h>
#endif
#include <windowsx.h>
#endif
-#if (!defined(__GNUWIN32_OLD__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__)
+#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__)
#ifdef __WIN95__
#include <commctrl.h>
#endif
-#elif !defined(__WXMICROWIN__) // broken compiler
- #ifndef __TWIN32__
- #include "wx/msw/gnuwin32/extra.h"
- #endif
+#elif !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // broken compiler
+ #include "wx/msw/gnuwin32/extra.h"
#endif
-// ----------------------------------------------------------------------------
-// standard constants not available with all compilers/headers
-// ----------------------------------------------------------------------------
+#include "wx/msw/missing.h"
-// This didn't appear in mingw until 2.95.2
-#ifndef SIF_TRACKPOS
-#define SIF_TRACKPOS 16
-#endif
-
-#if wxUSE_MOUSEWHEEL
- #ifndef WM_MOUSEWHEEL
- #define WM_MOUSEWHEEL 0x020A
- #endif
- #ifndef WHEEL_DELTA
- #define WHEEL_DELTA 120
- #endif
- #ifndef SPI_GETWHEELSCROLLLINES
- #define SPI_GETWHEELSCROLLLINES 104
- #endif
-#endif // wxUSE_MOUSEWHEEL
-
-#ifndef VK_OEM_1
- #define VK_OEM_1 0xBA
- #define VK_OEM_2 0xBF
- #define VK_OEM_3 0xC0
- #define VK_OEM_4 0xDB
- #define VK_OEM_5 0xDC
- #define VK_OEM_6 0xDD
- #define VK_OEM_7 0xDE
-#endif
-
-#ifndef VK_OEM_COMMA
- #define VK_OEM_PLUS 0xBB
- #define VK_OEM_COMMA 0xBC
- #define VK_OEM_MINUS 0xBD
- #define VK_OEM_PERIOD 0xBE
+#if defined(__WXWINCE__)
+#include "wx/msw/wince/missing.h"
#endif
// ---------------------------------------------------------------------------
// global variables
// ---------------------------------------------------------------------------
-// the last Windows message we got (FIXME-MT)
-extern MSG s_currentMsg;
-
#if wxUSE_MENUS_NATIVE
wxMenu *wxCurrentPopupMenu = NULL;
#endif // wxUSE_MENUS_NATIVE
// true if we had already created the std colour map, used by
// wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT)
-static bool gs_hasStdCmap = FALSE;
+static bool gs_hasStdCmap = false;
// ---------------------------------------------------------------------------
// private functions
// ---------------------------------------------------------------------------
// the window proc for all our windows
-#ifdef __DIGITALMARS__
-extern "C" LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
- WPARAM wParam, LPARAM lParam);
-#else
LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam);
-#endif
-
+
#ifdef __WXDEBUG__
const char *wxGetMessageName(int message);
#endif //__WXDEBUG__
void wxRemoveHandleAssociation(wxWindowMSW *win);
-#ifdef __DIGITALMARS__
-extern "C" void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
-#else
extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
-#endif
wxWindow *wxFindWinFromHandle(WXHWND hWnd);
// this magical function is used to translate VK_APPS key presses to right
// activate (set focus to) specified window
::SetFocus(hwnd);
+#endif
// raise top level parent to top of z order
- ::SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
-#else // !__WXMICROWIN__
- if ( !::BringWindowToTop(hwnd) )
+ if (!::SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE))
+ {
+ wxLogLastError(_T("SetWindowPos"));
+ }
+}
+
+// ensure that all our parent windows have WS_EX_CONTROLPARENT style
+static void EnsureParentHasControlParentStyle(wxWindow *parent)
+{
+ /*
+ If we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our
+ parent as well as otherwise several Win32 functions using
+ GetNextDlgTabItem() to iterate over all controls such as
+ IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed,
+ all of them iterate over all the controls starting from the currently
+ focused one and stop iterating when they get back to the focus but
+ unless all parents have WS_EX_CONTROLPARENT bit set, they would never
+ get back to the initial (focused) window: as we do have this style,
+ GetNextDlgTabItem() will leave this window and continue in its parent,
+ but if the parent doesn't have it, it wouldn't recurse inside it later
+ on and so wouldn't have a chance of getting back to this window neither.
+ */
+#ifndef __WXWINCE__
+ while ( parent && !parent->IsTopLevel() )
{
- wxLogLastError(_T("BringWindowToTop"));
+ LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE);
+ if ( !(exStyle & WS_EX_CONTROLPARENT) )
+ {
+ // force the parent to have this style
+ ::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE,
+ exStyle | WS_EX_CONTROLPARENT);
+ }
+
+ parent = parent->GetParent();
}
-#endif // __WXMICROWIN__/!__WXMICROWIN__
+#endif // !__WXWINCE__
}
// ---------------------------------------------------------------------------
#ifdef __WXUNIVERSAL__
IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW, wxWindowBase)
#else // __WXMSW__
+#if wxUSE_EXTENDED_RTTI
+
+// windows that are created from a parent window during its Create method, eg. spin controls in a calendar controls
+// must never been streamed out separately otherwise chaos occurs. Right now easiest is to test for negative ids, as
+// windows with negative ids never can be recreated anyway
+
+bool wxWindowStreamingCallback( const wxObject *object, wxWriter * , wxPersister * , wxxVariantArray & )
+{
+ const wxWindow * win = dynamic_cast<const wxWindow*>(object) ;
+ if ( win && win->GetId() < 0 )
+ return false ;
+ return true ;
+}
+
+IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxWindow, wxWindowBase,"wx/window.h", wxWindowStreamingCallback)
+
+// make wxWindowList known before the property is used
+
+wxCOLLECTION_TYPE_INFO( wxWindow* , wxWindowList ) ;
+
+template<> void wxCollectionToVariantArray( wxWindowList const &theList, wxxVariantArray &value)
+{
+ wxListCollectionToVariantArray<wxWindowList::compatibility_iterator>( theList , value ) ;
+}
+
+WX_DEFINE_FLAGS( wxWindowStyle )
+
+wxBEGIN_FLAGS( wxWindowStyle )
+ // new style border flags, we put them first to
+ // use them for streaming out
+
+ wxFLAGS_MEMBER(wxBORDER_SIMPLE)
+ wxFLAGS_MEMBER(wxBORDER_SUNKEN)
+ wxFLAGS_MEMBER(wxBORDER_DOUBLE)
+ wxFLAGS_MEMBER(wxBORDER_RAISED)
+ wxFLAGS_MEMBER(wxBORDER_STATIC)
+ wxFLAGS_MEMBER(wxBORDER_NONE)
+
+ // old style border flags
+ wxFLAGS_MEMBER(wxSIMPLE_BORDER)
+ wxFLAGS_MEMBER(wxSUNKEN_BORDER)
+ wxFLAGS_MEMBER(wxDOUBLE_BORDER)
+ wxFLAGS_MEMBER(wxRAISED_BORDER)
+ wxFLAGS_MEMBER(wxSTATIC_BORDER)
+ wxFLAGS_MEMBER(wxBORDER)
+
+ // standard window styles
+ wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
+ wxFLAGS_MEMBER(wxCLIP_CHILDREN)
+ wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
+ wxFLAGS_MEMBER(wxWANTS_CHARS)
+ wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
+ wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
+ wxFLAGS_MEMBER(wxVSCROLL)
+ wxFLAGS_MEMBER(wxHSCROLL)
+
+wxEND_FLAGS( wxWindowStyle )
+
+wxBEGIN_PROPERTIES_TABLE(wxWindow)
+ wxEVENT_PROPERTY( Close , wxEVT_CLOSE_WINDOW , wxCloseEvent)
+ wxEVENT_PROPERTY( Create , wxEVT_CREATE , wxWindowCreateEvent )
+ wxEVENT_PROPERTY( Destroy , wxEVT_DESTROY , wxWindowDestroyEvent )
+ // Always constructor Properties first
+
+ wxREADONLY_PROPERTY( Parent,wxWindow*, GetParent, , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
+ wxPROPERTY( Id,wxWindowID, SetId, GetId, -1, 0 /*flags*/ , wxT("Helpstring") , wxT("group") )
+ wxPROPERTY( Position,wxPoint, SetPosition , GetPosition, wxPoint(-1,-1) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // pos
+ wxPROPERTY( Size,wxSize, SetSize, GetSize, wxSize(-1,-1) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // size
+ wxPROPERTY( WindowStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
+
+ // Then all relations of the object graph
+
+ wxREADONLY_PROPERTY_COLLECTION( Children , wxWindowList , wxWindowBase* , GetWindowChildren , wxPROP_OBJECT_GRAPH /*flags*/ , wxT("Helpstring") , wxT("group"))
+
+ // and finally all other properties
+
+ wxPROPERTY( ExtraStyle , long , SetExtraStyle , GetExtraStyle , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // extstyle
+ wxPROPERTY( BackgroundColour , wxColour , SetBackgroundColour , GetBackgroundColour , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // bg
+ wxPROPERTY( ForegroundColour , wxColour , SetForegroundColour , GetForegroundColour , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // fg
+ wxPROPERTY( Enabled , bool , Enable , IsEnabled , wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
+ wxPROPERTY( Shown , bool , Show , IsShown , wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
+#if 0
+ // possible property candidates (not in xrc) or not valid in all subclasses
+ wxPROPERTY( Title,wxString, SetTitle, GetTitle, wxT("") )
+ wxPROPERTY( Font , wxFont , SetFont , GetWindowFont , )
+ wxPROPERTY( Label,wxString, SetLabel, GetLabel, wxT("") )
+ // MaxHeight, Width , MinHeight , Width
+ // TODO switch label to control and title to toplevels
+
+ wxPROPERTY( ThemeEnabled , bool , SetThemeEnabled , GetThemeEnabled , )
+ //wxPROPERTY( Cursor , wxCursor , SetCursor , GetCursor , )
+ // wxPROPERTY( ToolTip , wxString , SetToolTip , GetToolTipText , )
+ wxPROPERTY( AutoLayout , bool , SetAutoLayout , GetAutoLayout , )
+
+
+
+#endif
+wxEND_PROPERTIES_TABLE()
+
+wxBEGIN_HANDLERS_TABLE(wxWindow)
+wxEND_HANDLERS_TABLE()
+
+wxCONSTRUCTOR_DUMMY(wxWindow)
+
+#else
IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
+#endif
#endif // __WXUNIVERSAL__/__WXMSW__
BEGIN_EVENT_TABLE(wxWindowMSW, wxWindowBase)
EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground)
EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged)
EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog)
- EVT_IDLE(wxWindowMSW::OnIdle)
END_EVENT_TABLE()
// ===========================================================================
}
#endif // wxUSE_CONTROLS
- wxWindowList::Node *current = GetChildren().GetFirst();
+ wxWindowList::compatibility_iterator current = GetChildren().GetFirst();
while (current)
{
wxWindow *childWin = current->GetData();
// Find an item given the MS Windows handle
wxWindow *wxWindowMSW::FindItemByHWND(WXHWND hWnd, bool controlOnly) const
{
- wxWindowList::Node *current = GetChildren().GetFirst();
+ wxWindowList::compatibility_iterator current = GetChildren().GetFirst();
while (current)
{
wxWindow *parent = current->GetData();
// Default command handler
bool wxWindowMSW::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id))
{
- return FALSE;
+ return false;
}
// ----------------------------------------------------------------------------
void wxWindowMSW::Init()
{
- // generic
- InitBase();
-
// MSW specific
- m_isBeingDeleted = FALSE;
+ m_isBeingDeleted = false;
m_oldWndProc = NULL;
- m_useCtl3D = FALSE;
- m_mouseInWindow = FALSE;
- m_lastKeydownProcessed = FALSE;
+ m_mouseInWindow = false;
+ m_lastKeydownProcessed = false;
m_childrenDisabled = NULL;
m_xThumbSize = 0;
m_yThumbSize = 0;
- m_backgroundTransparent = FALSE;
// as all windows are created with WS_VISIBLE style...
- m_isShown = TRUE;
+ m_isShown = true;
#if wxUSE_MOUSEEVENT_HACK
m_lastMouseX =
// Destructor
wxWindowMSW::~wxWindowMSW()
{
- m_isBeingDeleted = TRUE;
+ m_isBeingDeleted = true;
#ifndef __WXUNIVERSAL__
// VS: make sure there's no wxFrame with last focus set to us:
// find their parent frame (see above).
DestroyChildren();
- if ( m_parent )
- m_parent->RemoveChild(this);
-
if ( m_hWnd )
{
// VZ: test temp removed to understand what really happens here
long style,
const wxString& name)
{
- wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") );
+ wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") );
if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
- return FALSE;
+ return false;
parent->AddChild(this);
if ( style & wxPOPUP_WINDOW )
{
msflags &= ~WS_VISIBLE;
- m_isShown = FALSE;
+ m_isShown = false;
}
else
{
HWND hWnd = GetHwnd();
wxCHECK_RET( hWnd, _T("can't set focus to invalid window") );
-#ifndef __WXMICROWIN__
+#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
::SetLastError(0);
#endif
void wxWindowMSW::SetFocusFromKbd()
{
- wxWindowBase::SetFocusFromKbd();
-
// when the focus is given to the control with DLGC_HASSETSEL style from
// keyboard its contents should be entirely selected: this is what
// ::IsDialogMessage() does and so we should do it as well to provide the
{
::SendMessage(GetHwnd(), EM_SETSEL, 0, -1);
}
+
+ // do this after (maybe) setting the selection as like this when
+ // wxEVT_SET_FOCUS handler is called, the selection would have been already
+ // set correctly -- this may be important
+ wxWindowBase::SetFocusFromKbd();
}
// Get the window with the focus
bool wxWindowMSW::Enable(bool enable)
{
if ( !wxWindowBase::Enable(enable) )
- return FALSE;
+ return false;
HWND hWnd = GetHwnd();
if ( hWnd )
// showing a modal dialog would result in total greying out (and ungreying
// out later) of everything which would be really ugly
if ( IsTopLevel() )
- return TRUE;
+ return true;
// when the parent is disabled, all of its children should be disabled as
// well but when it is enabled back, only those of the children which
// hadn't been already disabled in the beginning should be enabled again,
// so we have to keep the list of those children
- for ( wxWindowList::Node *node = GetChildren().GetFirst();
+ for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
node;
node = node->GetNext() )
{
m_childrenDisabled = NULL;
}
- return TRUE;
+ return true;
}
bool wxWindowMSW::Show(bool show)
{
if ( !wxWindowBase::Show(show) )
- return FALSE;
+ return false;
HWND hWnd = GetHwnd();
int cshow = show ? SW_SHOW : SW_HIDE;
::ShowWindow(hWnd, cshow);
- if ( show )
+ if ( show && IsTopLevel() )
{
wxBringWindowToTop(hWnd);
}
- return TRUE;
+ return true;
}
// Raise the window to the top of the Z order
if ( !wxWindowBase::SetFont(font) )
{
// nothing to do
- return FALSE;
+ return false;
}
HWND hWnd = GetHwnd();
::SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
}
- return TRUE;
+ return true;
}
bool wxWindowMSW::SetCursor(const wxCursor& cursor)
{
if ( !wxWindowBase::SetCursor(cursor) )
{
// no change
- return FALSE;
+ return false;
}
if ( m_cursor.Ok() )
::SetCursor(GetHcursorOf(m_cursor));
}
- return TRUE;
+ return true;
}
void wxWindowMSW::WarpPointer (int x, int y)
}
}
-#if WXWIN_COMPATIBILITY
-void wxWindowMSW::MSWDeviceToLogical (float *x, float *y) const
-{
-}
-#endif // WXWIN_COMPATIBILITY
-
// ---------------------------------------------------------------------------
// scrolling stuff
// ---------------------------------------------------------------------------
return orient == wxHORIZONTAL ? SB_HORZ : SB_VERT;
}
-#if WXWIN_COMPATIBILITY
-void wxWindowMSW::SetScrollRange(int orient, int range, bool refresh)
-{
- int range1 = range;
-
- // Try to adjust the range to cope with page size > 1
- // - a Windows API quirk
- int pageSize = GetScrollPage(orient);
- if ( pageSize > 1 && range > 0)
- {
- range1 += (pageSize - 1);
- }
-
- WinStruct<SCROLLINFO> info;
- info.nPage = pageSize; // Have to set this, or scrollbar goes awry
- info.nMin = 0;
- info.nMax = range1;
- info.fMask = SIF_RANGE | SIF_PAGE;
-
- HWND hWnd = GetHwnd();
- if ( hWnd )
- ::SetScrollInfo(hWnd, wxDirToWinStyle(orient), &info, refresh);
-}
-
-void wxWindowMSW::SetScrollPage(int orient, int page, bool refresh)
-{
- WinStruct<SCROLLINFO> info;
- info.nPage = page;
- info.fMask = SIF_PAGE;
-
- HWND hWnd = GetHwnd();
- if ( hWnd )
- ::SetScrollInfo(hWnd, wxDirToWinStyle(orient), &info, refresh);
-}
-
-int wxWindowMSW::GetScrollPage(int orient) const
-{
- return orient == wxHORIZONTAL ? m_xThumbSize : m_yThumbSize;
-}
-
-#endif // WXWIN_COMPATIBILITY
-
inline int GetScrollPosition(HWND hWnd, int wOrient)
{
#ifdef __WXMICROWIN__
return ::GetScrollPosWX(hWnd, wOrient);
#else
- return ::GetScrollPos(hWnd, wOrient);
+ WinStruct<SCROLLINFO> scrollInfo;
+ scrollInfo.cbSize = sizeof(SCROLLINFO);
+ scrollInfo.fMask = SIF_POS;
+ if ( !::GetScrollInfo(hWnd,
+ wOrient,
+ &scrollInfo) )
+ {
+ // Not neccessarily an error, if there are no scrollbars yet.
+ // wxLogLastError(_T("GetScrollInfo"));
+ }
+ return scrollInfo.nPos;
+// return ::GetScrollPos(hWnd, wOrient);
#endif
}
// of positions that we can scroll.
int wxWindowMSW::GetScrollRange(int orient) const
{
- int minPos, maxPos;
+ int maxPos;
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) )
+ {
+ // Most of the time this is not really an error, since the return
+ // value can also be zero when there is no scrollbar yet.
+ // wxLogLastError(_T("GetScrollInfo"));
+ }
+ maxPos = scrollInfo.nMax;
// undo "range - 1" done in SetScrollbar()
return maxPos + 1;
info.nMin = 0;
info.nPos = pos;
info.fMask = SIF_POS;
+ if ( HasFlag(wxALWAYS_SHOW_SB) )
+ {
+ // disable scrollbar instead of removing it then
+ info.fMask |= SIF_DISABLENOSCROLL;
+ }
::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
&info, refresh);
info.nMax = range - 1; // as both nMax and nMax are inclusive
info.nPos = pos;
info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+ if ( HasFlag(wxALWAYS_SHOW_SB) )
+ {
+ // disable scrollbar instead of removing it then
+ info.fMask |= SIF_DISABLENOSCROLL;
+ }
HWND hWnd = GetHwnd();
if ( hWnd )
pr = NULL;
}
+#ifdef __WXWINCE__
+ // FIXME: is this the exact equivalent of the line below?
+ ::ScrollWindowEx(GetHwnd(), dx, dy, pr, pr, 0, 0, SW_ERASE|SW_INVALIDATE);
+#else
::ScrollWindow(GetHwnd(), dx, dy, pr, pr);
+#endif
}
static bool ScrollVertically(HWND hwnd, int kind, int count)
wxAssociateWinWithHandle(hwnd, this);
- m_oldWndProc = (WXFARPROC)::GetWindowLong((HWND)hWnd, GWL_WNDPROC);
+ m_oldWndProc = (WXFARPROC)wxGetWindowProc((HWND)hWnd);
// we don't need to subclass the window of our own class (in the Windows
// sense of the word)
- if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) )
+ if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) )
{
- ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) wxWndProc);
+ wxSetWindowProc(hwnd, wxWndProc);
}
else
{
// don't bother restoring it neither: this also makes it easy to
- // implement IsOfStandardClass() method which returns TRUE for the
- // standard controls and FALSE for the wxWindows own windows as it can
+ // implement IsOfStandardClass() method which returns true for the
+ // standard controls and false for the wxWindows own windows as it can
// simply check m_oldWndProc
m_oldWndProc = NULL;
}
{
if ( !wxCheckWindowWndProc((WXHWND)hwnd, m_oldWndProc) )
{
- ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) m_oldWndProc);
+ wxSetWindowProc(hwnd, (WNDPROC)m_oldWndProc);
}
m_oldWndProc = NULL;
// unicows.dll, we can override unicows hooks by setting
// Unicows_{Set,Get}WindowLong and Unicows_RegisterClass to our own
// versions that keep track of fake<->real wnd proc mapping.
+
+ // On WinCE (at least), the wndproc comparison doesn't work,
+ // so have to use something like this.
+#ifdef __WXWINCE__
+ extern const wxChar *wxCanvasClassName;
+ extern const wxChar *wxCanvasClassNameNR;
+ 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 ||
+ str == wxMDIFrameClassName ||
+ str == wxMDIFrameClassNameNoRedraw ||
+ str == wxMDIChildFrameClassName ||
+ str == wxMDIChildFrameClassNameNoRedraw ||
+ str == _T("wxTLWHiddenParent"))
+ return true; // Effectively means don't subclass
+ else
+ return false;
+#else
WNDCLASS cls;
if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd), &cls) )
{
wxLogLastError(_T("GetClassInfo"));
- return FALSE;
+ return false;
}
return wndProc == (WXFARPROC)cls.lpfnWndProc;
+#endif
}
// ----------------------------------------------------------------------------
if ( flags & wxCLIP_SIBLINGS )
style |= WS_CLIPSIBLINGS;
- wxBorder border = (wxBorder)(flags & wxBORDER_MASK);
-
- // Check if we want to automatically give it a sunken style.
- // Note than because 'sunken' actually maps to WS_EX_CLIENTEDGE, which
- // is a more neutral term, we don't necessarily get a sunken effect in
- // Windows XP. Instead we get the appropriate style for the theme.
-
- if (border == wxBORDER_DEFAULT && wxTheApp->GetAuto3D() &&
- GetParent() && (GetParent()->IsKindOf(CLASSINFO(wxPanel)) ||
- GetParent()->IsKindOf(CLASSINFO(wxDialog))) &&
- ((GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS) != wxUSER_COLOURS))
- {
- border = (wxBorder)((flags & wxBORDER_MASK) | wxBORDER_SUNKEN);
- }
-
- // Only give it WS_BORDER for wxBORDER_SIMPLE
- if (border & wxBORDER_SIMPLE)
+ if ( flags & wxVSCROLL )
+ style |= WS_VSCROLL;
+
+ if ( flags & wxHSCROLL )
+ style |= WS_HSCROLL;
+
+ const wxBorder border = GetBorder(flags);
+
+ // WS_BORDER is only required for wxBORDER_SIMPLE
+ if ( border == wxBORDER_SIMPLE )
style |= WS_BORDER;
-
+
// now deal with ext style if the caller wants it
if ( exstyle )
{
*exstyle = 0;
+#ifndef __WXWINCE__
if ( flags & wxTRANSPARENT_WINDOW )
*exstyle |= WS_EX_TRANSPARENT;
+#endif
switch ( border )
{
default:
+ case wxBORDER_DEFAULT:
wxFAIL_MSG( _T("unknown border style") );
// fall through
case wxBORDER_NONE:
case wxBORDER_SIMPLE:
- case wxBORDER_DEFAULT:
break;
case wxBORDER_STATIC:
}
// wxUniv doesn't use Windows dialog navigation functions at all
-#ifndef __WXUNIVERSAL__
+#if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__)
// to make the dialog navigation work with the nested panels we must
// use this style (top level windows such as dialogs don't need it)
if ( (flags & wxTAB_TRAVERSAL) && !IsTopLevel() )
return style;
}
-#if WXWIN_COMPATIBILITY
-// If nothing defined for this, try the parent.
-// E.g. we may be a button loaded from a resource, with no callback function
-// defined.
-void wxWindowMSW::OnCommand(wxWindow& win, wxCommandEvent& event)
-{
- if ( GetEventHandler()->ProcessEvent(event) )
- return;
- if ( m_parent )
- m_parent->GetEventHandler()->OnCommand(win, event);
-}
-#endif // WXWIN_COMPATIBILITY_2
-
-#if WXWIN_COMPATIBILITY
-wxObject* wxWindowMSW::GetChild(int number) const
-{
- // Return a pointer to the Nth object in the Panel
- wxNode *node = GetChildren().First();
- int n = number;
- while (node && n--)
- node = node->Next();
- if ( node )
- {
- wxObject *obj = (wxObject *)node->Data();
- return(obj);
- }
- else
- return NULL;
-}
-#endif // WXWIN_COMPATIBILITY
-
// Setup background and foreground colours correctly
void wxWindowMSW::SetupColours()
{
return hwnd != NULL;
}
-void wxWindowMSW::OnIdle(wxIdleEvent& WXUNUSED(event))
+void wxWindowMSW::OnInternalIdle()
{
// Check if we need to send a LEAVE event
if ( m_mouseInWindow )
if ( !IsMouseInWindow() )
{
// Generate a LEAVE event
- m_mouseInWindow = FALSE;
+ m_mouseInWindow = false;
// Unfortunately the mouse button and keyboard state may have
- // changed by the time the OnIdle function is called, so 'state'
+ // changed by the time the OnInternalIdle function is called, so 'state'
// may be meaningless.
int state = 0;
if ( wxIsShiftDown() )
}
}
- UpdateWindowUI();
+ if (wxUpdateUIEvent::CanUpdate(this))
+ UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
}
// Set this window to be the child of 'parent'.
bool wxWindowMSW::Reparent(wxWindowBase *parent)
{
if ( !wxWindowBase::Reparent(parent) )
- return FALSE;
+ return false;
HWND hWndChild = GetHwnd();
HWND hWndParent = GetParent() ? GetWinHwnd(GetParent()) : (HWND)0;
::SetParent(hWndChild, hWndParent);
- return TRUE;
-}
+#ifndef __WXWINCE__
+ if ( ::GetWindowLong(hWndChild, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
+ {
+ EnsureParentHasControlParentStyle(GetParent());
+ }
+#endif // !__WXWINCE__
-void wxWindowMSW::Clear()
-{
- wxClientDC dc((wxWindow *)this);
- wxBrush brush(GetBackgroundColour(), wxSOLID);
- dc.SetBackground(brush);
- dc.Clear();
+ return true;
}
static inline void SendSetRedraw(HWND hwnd, bool on)
void wxWindowMSW::Freeze()
{
- SendSetRedraw(GetHwnd(), FALSE);
+ SendSetRedraw(GetHwnd(), false);
}
void wxWindowMSW::Thaw()
{
- SendSetRedraw(GetHwnd(), TRUE);
+ SendSetRedraw(GetHwnd(), true);
// we need to refresh everything or otherwise he invalidated area is not
// repainted
wxLogLastError(_T("UpdateWindow"));
}
-#if defined(__WIN32__) && !defined(__WXMICROWIN__)
+#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
// just calling UpdateWindow() is not enough, what we did in our WM_PAINT
// handler needs to be really drawn right now
(void)::GdiFlush();
// DragAcceptFiles in parallel with SetDropTarget.
void wxWindowMSW::DragAcceptFiles(bool accept)
{
+#if !defined(__WXWINCE__)
HWND hWnd = GetHwnd();
if ( hWnd )
::DragAcceptFiles(hWnd, (BOOL)accept);
+#endif
}
// ----------------------------------------------------------------------------
*externalLeading = tm.tmExternalLeading;
}
-#if wxUSE_CARET && WXWIN_COMPATIBILITY
-// ---------------------------------------------------------------------------
-// Caret manipulation
-// ---------------------------------------------------------------------------
-
-void wxWindowMSW::CreateCaret(int w, int h)
-{
- SetCaret(new wxCaret(this, w, h));
-}
-
-void wxWindowMSW::CreateCaret(const wxBitmap *WXUNUSED(bitmap))
-{
- wxFAIL_MSG("not implemented");
-}
-
-void wxWindowMSW::ShowCaret(bool show)
-{
- wxCHECK_RET( m_caret, "no caret to show" );
-
- m_caret->Show(show);
-}
-
-void wxWindowMSW::DestroyCaret()
-{
- SetCaret(NULL);
-}
-
-void wxWindowMSW::SetCaretPos(int x, int y)
-{
- wxCHECK_RET( m_caret, "no caret to move" );
-
- m_caret->Move(x, y);
-}
-
-void wxWindowMSW::GetCaretPos(int *x, int *y) const
-{
- wxCHECK_RET( m_caret, "no caret to get position of" );
-
- m_caret->GetPosition(x, y);
-}
-#endif // wxUSE_CARET
-
// ---------------------------------------------------------------------------
// popup menu
// ---------------------------------------------------------------------------
// peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
// want to process it here)
MSG msg;
- while ( ::PeekMessage(&msg, (HWND)0, WM_COMMAND, WM_COMMAND, PM_REMOVE)
- && msg.message != WM_QUIT )
+ while ( ::PeekMessage(&msg, (HWND)0, WM_COMMAND, WM_COMMAND, PM_REMOVE) )
{
- wxTheApp->DoMessage((WXMSG *)&msg);
- }
+ if ( msg.message == WM_QUIT )
+ {
+ // if we retrieved a WM_QUIT, insert back into the message queue.
+ ::PostQuitMessage(0);
+ break;
+ }
- // If we retrieved a WM_QUIT, insert back into the message queue.
- if (msg.message == WM_QUIT)
- ::PostQuitMessage(0);
+ // luckily (as we don't have access to wxEventLoopImpl method from here
+ // anyhow...) we don't need to pre process WM_COMMANDs so dispatch it
+ // immediately
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ }
}
bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y)
point.y = y;
::ClientToScreen(hWnd, &point);
wxCurrentPopupMenu = menu;
- ::TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL);
+ UINT flags = 0;
+#if !defined(__WXWINCE__)
+ flags = TPM_RIGHTBUTTON;
+#endif
+ ::TrackPopupMenu(hMenu, flags, point.x, point.y, 0, hWnd, NULL);
// we need to do it righ now as otherwise the events are never going to be
// sent to wxCurrentPopupMenu from HandleCommand()
menu->SetInvokingWindow(NULL);
- return TRUE;
+ return true;
}
#endif // wxUSE_MENUS_NATIVE
long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{
if ( m_oldWndProc )
-#ifdef __DIGITALMARS__
- return ::CallWindowProc( (FARPROC) m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
-#else
return ::CallWindowProc(CASTWNDPROC m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
-#endif
else
return ::DefWindowProc(GetHwnd(), nMsg, wParam, lParam);
}
}
}
- bool bForward = TRUE,
- bWindowChange = FALSE;
+ bool bForward = true,
+ bWindowChange = false;
// should we process this message specially?
- bool bProcess = TRUE;
+ bool bProcess = true;
switch ( msg->wParam )
{
case VK_TAB:
- // assume that nobody wants Shift-TAB for himself - if we
- // don't do it there is no easy way for a control to grab
- // TABs but still let Shift-TAB work as navugation key
- if ( (lDlgCode & DLGC_WANTTAB) && !bShiftDown ) {
- bProcess = FALSE;
+ if ( lDlgCode & DLGC_WANTTAB ) {
+ bProcess = false;
}
else {
// Ctrl-Tab cycles thru notebook pages
case VK_UP:
case VK_LEFT:
if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown )
- bProcess = FALSE;
+ bProcess = false;
else
- bForward = FALSE;
+ bForward = false;
break;
case VK_DOWN:
case VK_RIGHT:
if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown )
- bProcess = FALSE;
+ bProcess = false;
+ break;
+
+ case VK_ESCAPE:
+ {
+#if wxUSE_BUTTON
+ wxButton *btn = wxDynamicCast(FindWindow(wxID_CANCEL),
+ wxButton);
+ if ( btn && btn->IsEnabled() )
+ {
+ // if we do have a cancel button, do press it
+ btn->MSWCommand(BN_CLICKED, 0 /* unused */);
+
+ // we consumed the message
+ return true;
+ }
+#endif // wxUSE_BUTTON
+
+ bProcess = false;
+ }
break;
case VK_RETURN:
// control wants to process Enter itself, don't
// call IsDialogMessage() which would interpret
// it
- return FALSE;
+ return false;
}
else if ( lDlgCode & DLGC_BUTTON )
{
btn->MSWCommand(BN_CLICKED, 0 /* unused */);
}
- bProcess = FALSE;
+ bProcess = false;
}
// FIXME: this should be handled by
// wxNavigationKeyEvent handler and not here!!
// if we do have a default button, do press it
btn->MSWCommand(BN_CLICKED, 0 /* unused */);
- return TRUE;
+ return true;
}
else // no default button
{
// need it for itself and don't let
// ::IsDialogMessage() have it as it can
// eat the Enter events sometimes
- return FALSE;
+ return false;
}
else if (!IsTopLevel())
{
// if not a top level window, let parent
// handle it
- return FALSE;
+ return false;
}
//else: treat Enter as TAB: pass to the next
// control as this is the best thing to do
break;
default:
- bProcess = FALSE;
+ bProcess = false;
}
if ( bProcess )
if ( GetEventHandler()->ProcessEvent(event) )
{
- return TRUE;
+ return true;
}
}
}
}
#endif // 1/0
- // we handle VK_ESCAPE ourselves in wxDialog::OnCharHook() and we
- // shouldn't let IsDialogMessage() get it as it _always_ eats the
+ // don't let IsDialogMessage() get VK_ESCAPE as it _always_ eats the
// message even when there is no cancel button and when the message is
// needed by the control itself: in particular, it prevents the tree in
// place edit control from being closed with Escape in a dialog
if ( msg->message != WM_KEYDOWN || msg->wParam != VK_ESCAPE )
{
- // ::IsDialogMessage() can enter in an infinite loop when the
- // currently focused window is disabled or hidden and its parent
- // has WS_EX_CONTROLPARENT style, so don't call it in this case
- bool canSafelyCallIsDlgMsg = TRUE;
+ // ::IsDialogMessage() is broken and may sometimes hang the
+ // application by going into an infinite loop, so we try to detect
+ // [some of] the situatations when this may happen and not call it
+ // then
+
+ // assume we can call it by default
+ bool canSafelyCallIsDlgMsg = true;
HWND hwndFocus = ::GetFocus();
- while ( hwndFocus )
+
+ // if the currently focused window itself has WS_EX_CONTROLPARENT style, ::IsDialogMessage() will also enter
+ // an infinite loop, because it will recursively check the child
+ // windows but not the window itself and so if none of the children
+ // accepts focus it loops forever (as it only stops when it gets
+ // back to the window it started from)
+ //
+ // while it is very unusual that a window with WS_EX_CONTROLPARENT
+ // style has the focus, it can happen. One such possibility is if
+ // all windows are either toplevel, wxDialog, wxPanel or static
+ // controls and no window can actually accept keyboard input.
+#if !defined(__WXWINCE__)
+ if ( ::GetWindowLong(hwndFocus, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
{
- if ( !::IsWindowEnabled(hwndFocus) ||
- !::IsWindowVisible(hwndFocus) )
+ // passimistic by default
+ canSafelyCallIsDlgMsg = false;
+ for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+ node;
+ node = node->GetNext() )
{
- // it would enter an infinite loop if we do this!
- canSafelyCallIsDlgMsg = FALSE;
+ wxWindow * const win = node->GetData();
+ if ( win->AcceptsFocus() &&
+ !(::GetWindowLong(GetHwndOf(win), GWL_EXSTYLE) &
+ WS_EX_CONTROLPARENT) )
+ {
+ // it shouldn't hang...
+ canSafelyCallIsDlgMsg = true;
- break;
+ break;
+ }
}
+ }
+#endif // !__WXWINCE__
- if ( !(::GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD) )
+ if ( canSafelyCallIsDlgMsg )
+ {
+ // ::IsDialogMessage() can enter in an infinite loop when the
+ // currently focused window is disabled or hidden and its
+ // parent has WS_EX_CONTROLPARENT style, so don't call it in
+ // this case
+ while ( hwndFocus )
{
- // it's a top level window, don't go further -- e.g. even
- // if the parent of a dialog is disabled, this doesn't
- // break navigation inside the dialog
- break;
- }
+ if ( !::IsWindowEnabled(hwndFocus) ||
+ !::IsWindowVisible(hwndFocus) )
+ {
+ // it would enter an infinite loop if we do this!
+ canSafelyCallIsDlgMsg = false;
- hwndFocus = ::GetParent(hwndFocus);
+ break;
+ }
+
+ if ( !(::GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD) )
+ {
+ // it's a top level window, don't go further -- e.g. even
+ // if the parent of a dialog is disabled, this doesn't
+ // break navigation inside the dialog
+ break;
+ }
+
+ hwndFocus = ::GetParent(hwndFocus);
+ }
}
+ // let IsDialogMessage() have the message if it's safe to call it
if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) )
{
// IsDialogMessage() did something...
- return TRUE;
+ return true;
}
}
}
}
#endif // wxUSE_TOOLTIPS
- return FALSE;
+ return false;
}
bool wxWindowMSW::MSWTranslateMessage(WXMSG* pMsg)
return m_acceleratorTable.Translate(this, pMsg);
#else
(void) pMsg;
- return FALSE;
+ return false;
#endif // wxUSE_ACCEL
}
bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG* WXUNUSED(pMsg))
{
// preprocess all messages by default
- return TRUE;
+ return true;
}
// ---------------------------------------------------------------------------
-// message params unpackers (different for Win16 and Win32)
+// message params unpackers
// ---------------------------------------------------------------------------
-#ifdef __WIN32__
-
void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam,
WORD *id, WXHWND *hwnd, WORD *cmd)
{
*hmenu = (WXHMENU)lParam;
}
-#else // Win16
-
-void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam,
- WXWORD *id, WXHWND *hwnd, WXWORD *cmd)
-{
- *id = (WXWORD)wParam;
- *hwnd = (WXHWND)LOWORD(lParam);
- *cmd = HIWORD(lParam);
-}
-
-void wxWindowMSW::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam,
- WXWORD *state, WXWORD *minimized, WXHWND *hwnd)
-{
- *state = (WXWORD)wParam;
- *minimized = LOWORD(lParam);
- *hwnd = (WXHWND)HIWORD(lParam);
-}
-
-void wxWindowMSW::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam,
- WXWORD *code, WXWORD *pos, WXHWND *hwnd)
-{
- *code = (WXWORD)wParam;
- *pos = LOWORD(lParam);
- *hwnd = (WXHWND)HIWORD(lParam);
-}
-
-void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam,
- WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd)
-{
- *hwnd = (WXHWND)LOWORD(lParam);
- *nCtlColor = (int)HIWORD(lParam);
- *hdc = (WXHDC)wParam;
-}
-
-void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam,
- WXWORD *item, WXWORD *flags, WXHMENU *hmenu)
-{
- *item = (WXWORD)wParam;
- *flags = LOWORD(lParam);
- *hmenu = (WXHMENU)HIWORD(lParam);
-}
-
-#endif // Win32/16
-
// ---------------------------------------------------------------------------
// Main wxWindows window proc and the window proc for wxWindow
// ---------------------------------------------------------------------------
{
// trace all messages - useful for the debugging
#ifdef __WXDEBUG__
-#if wxUSE_LOG
- wxLogTrace(wxTraceMessages, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
- wxGetMessageName(message), (long) wParam, lParam);
-#endif // wxUSE_LOG
+ wxLogTrace(wxTraceMessages,
+ wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"),
+ wxGetMessageName(message), (long)hWnd, (long)wParam, lParam);
#endif // __WXDEBUG__
wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd);
long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
// did we process the message?
- bool processed = FALSE;
+ bool processed = false;
// the return value
union
break;
case WM_DESTROY:
- // never set processed to TRUE and *always* pass WM_DESTROY to
+ // never set processed to true and *always* pass WM_DESTROY to
// DefWindowProc() as Windows may do some internal cleanup when
// processing it and failing to pass the message along may cause
// memory and resource leaks!
processed = HandleMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
+#if !defined(__WXWINCE__)
+ case WM_MOVING:
+ {
+ LPRECT pRect = (LPRECT)lParam;
+ wxRect rc;
+ rc.SetLeft(pRect->left);
+ rc.SetTop(pRect->top);
+ rc.SetRight(pRect->right);
+ rc.SetBottom(pRect->bottom);
+ processed = HandleMoving(rc);
+ if (processed) {
+ pRect->left = rc.GetLeft();
+ pRect->top = rc.GetTop();
+ pRect->right = rc.GetRight();
+ pRect->bottom = rc.GetBottom();
+ }
+ }
+ break;
+#endif
+
case WM_SIZE:
switch ( wParam )
{
}
break;
-#ifndef __WXMICROWIN__
+#if !defined(__WXWINCE__)
+ case WM_SIZING:
+ {
+ LPRECT pRect = (LPRECT)lParam;
+ wxRect rc;
+ rc.SetLeft(pRect->left);
+ rc.SetTop(pRect->top);
+ rc.SetRight(pRect->right);
+ rc.SetBottom(pRect->bottom);
+ processed = HandleSizing(rc);
+ if (processed) {
+ pRect->left = rc.GetLeft();
+ pRect->top = rc.GetTop();
+ pRect->right = rc.GetRight();
+ pRect->bottom = rc.GetBottom();
+ }
+ }
+ break;
+#endif
+
+#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
case WM_ACTIVATEAPP:
wxTheApp->SetActive(wParam != 0, FindFocus());
break;
break;
case WM_PAINT:
- processed = HandlePaint();
+ {
+ if ( wParam )
+ {
+ // cast to wxWindow is needed for wxUniv
+ wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
+ processed = HandlePaint();
+ }
+ else
+ {
+ processed = HandlePaint();
+ }
+ break;
+ }
+
+#ifndef __WXWINCE__
+ case WM_PRINT:
+ {
+ // Don't call the wx handlers in this case
+ if ( wxIsKindOf(this, wxListCtrl) )
+ break;
+
+ if ( lParam & PRF_ERASEBKGND )
+ HandleEraseBkgnd((WXHDC)(HDC)wParam);
+
+ wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
+ processed = HandlePaint();
+ }
break;
+#endif
case WM_CLOSE:
#ifdef __WXUNIVERSAL__
// Universal uses its own wxFrame/wxDialog, so we don't receive
// close events unless we have this.
Close();
- processed = TRUE;
+ processed = true;
rc.result = TRUE;
#else
// don't let the DefWindowProc() destroy our window - we'll do it
// ourselves in ~wxWindow
- processed = TRUE;
+ processed = true;
rc.result = TRUE;
#endif
break;
wParam);
break;
+ // Seems to be broken currently
+#if 0 // ndef __WXWINCE__
+ 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) )
+ {
+ 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);
+ }
+ // 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__
+
#if wxUSE_MOUSEWHEEL
case WM_MOUSEWHEEL:
processed = HandleMouseWheel(wParam, lParam);
{
if (!win->IsEnabled())
{
- processed = TRUE;
+ processed = true;
break;
}
}
break;
-#ifdef __WIN95__
case WM_NOTIFY:
processed = HandleNotify((int)wParam, lParam, &rc.result);
break;
-#endif // Win95
- // for these messages we must return TRUE if process the message
+ // for these messages we must return true if process the message
#ifdef WM_DRAWITEM
case WM_DRAWITEM:
case WM_MEASUREITEM:
DLGC_WANTALLKEYS;
}
- processed = TRUE;
+ processed = true;
}
//else: get the dlg code from the DefWindowProc()
break;
m_lastKeydownProcessed = HandleKeyDown((WORD) wParam, lParam);
if ( m_lastKeydownProcessed )
{
- processed = TRUE;
+ processed = true;
}
if ( !processed )
case VK_CAPITAL:
case VK_NUMLOCK:
case VK_SCROLL:
- processed = TRUE;
+ processed = true;
break;
// avoid duplicate messages to OnChar for these ASCII keys:
case VK_OEM_COMMA:
case VK_OEM_MINUS:
case VK_OEM_PERIOD:
- // but set processed to FALSE, not TRUE to still pass them
+ // but set processed to false, not true to still pass them
// to the control's default window proc - otherwise
// built-in keyboard handling won't work
- processed = FALSE;
+ processed = false;
break;
#ifdef VK_APPS
}
}
if (message == WM_SYSKEYDOWN) // Let Windows still handle the SYSKEYs
- processed = FALSE;
+ processed = false;
break;
case WM_SYSKEYUP:
// The key was handled in the EVT_KEY_DOWN and handling
// a key in an EVT_KEY_DOWN handler is meant, by
// design, to prevent EVT_CHARs from happening
- m_lastKeydownProcessed = FALSE;
- processed = TRUE;
+ m_lastKeydownProcessed = false;
+ processed = true;
}
else
{
- processed = HandleChar((WORD)wParam, lParam, TRUE);
+ processed = HandleChar((WORD)wParam, lParam, true);
}
break;
+#if wxUSE_HOTKEY
+ case WM_HOTKEY:
+ processed = HandleHotKey((WORD)wParam, lParam);
+ break;
+#endif // wxUSE_HOTKEY
+
case WM_HSCROLL:
case WM_VSCROLL:
{
// CTLCOLOR messages are sent by children to query the parent for their
// colors#ifndef __WXMICROWIN__
#ifndef __WXMICROWIN__
-#ifdef __WIN32__
case WM_CTLCOLORMSGBOX:
case WM_CTLCOLOREDIT:
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLORDLG:
case WM_CTLCOLORSCROLLBAR:
case WM_CTLCOLORSTATIC:
-#else // Win16
- case WM_CTLCOLOR:
-#endif // Win32/16
{
WXWORD nCtlColor;
WXHDC hdc;
processed = HandleSysColorChange();
break;
+#if !defined(__WXWINCE__)
case WM_DISPLAYCHANGE:
processed = HandleDisplayChange();
break;
+#endif
case WM_PALETTECHANGED:
processed = HandlePaletteChanged((WXHWND) (HWND) wParam);
}
break;
+#if !defined(__WXWINCE__)
case WM_DROPFILES:
processed = HandleDropFiles(wParam);
break;
+#endif
case WM_INITDIALOG:
processed = HandleInitDialog((WXHWND)(HWND)wParam);
}
break;
+#if !defined(__WXWINCE__)
case WM_QUERYENDSESSION:
processed = HandleQueryEndSession(lParam, &rc.allow);
break;
case WM_GETMINMAXINFO:
processed = HandleGetMinMaxInfo((MINMAXINFO*)lParam);
break;
+#endif
case WM_SETCURSOR:
processed = HandleSetCursor((WXHWND)(HWND)wParam,
//WPARAM dwFlags = (WPARAM) (DWORD) wParam;
LPARAM dwObjId = (LPARAM) (DWORD) lParam;
- if (dwObjId == OBJID_CLIENT && GetOrCreateAccessible())
+ if (dwObjId == (LPARAM)OBJID_CLIENT && GetOrCreateAccessible())
{
return LresultFromObject(IID_IAccessible, wParam, (IUnknown*) GetAccessible()->GetIAccessible());
}
}
#endif
-#if defined(__WIN32__) && defined(WM_HELP)
+#if defined(WM_HELP)
case WM_HELP:
{
+ // HELPINFO doesn't seem to be supported on WinCE.
+#ifndef __WXWINCE__
HELPINFO* info = (HELPINFO*) lParam;
// Don't yet process menu help events, just windows
if (info->iContextType == HELPINFO_WINDOW)
{
+#endif
wxWindowMSW* subjectOfHelp = this;
- bool eventProcessed = FALSE;
+ bool eventProcessed = false;
while (subjectOfHelp && !eventProcessed)
{
wxHelpEvent helpEvent(wxEVT_HELP,
subjectOfHelp->GetId(),
- wxPoint(info->MousePos.x,
- info->MousePos.y) );
+#ifdef __WXWINCE__
+ wxPoint(0, 0)
+#else
+ wxPoint(info->MousePos.x, info->MousePos.y)
+#endif
+ );
+
helpEvent.SetEventObject(this);
eventProcessed =
GetEventHandler()->ProcessEvent(helpEvent);
}
processed = eventProcessed;
+#ifndef __WXWINCE__
}
else if (info->iContextType == HELPINFO_MENUITEM)
{
processed = GetEventHandler()->ProcessEvent(helpEvent);
}
- //else: processed is already FALSE
+ //else: processed is already false
+#endif
}
break;
+#endif
+#if !defined(__WXWINCE__)
case WM_CONTEXTMENU:
{
// we don't convert from screen to client coordinates as
wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
- processed = GetEventHandler()->ProcessEvent(evtCtx);
+
+ // we could have got an event from our child, reflect it back
+ // to it if this is the case
+ wxWindowMSW *win = NULL;
+ if ( wParam != m_hWnd )
+ {
+ win = FindItemByHWND((WXHWND)wParam);
+ }
+
+ if ( !win )
+ win = this;
+
+ evtCtx.SetEventObject(win);
+ processed = win->GetEventHandler()->ProcessEvent(evtCtx);
}
break;
+#endif
case WM_MENUCHAR:
// we're only interested in our own menus, not MF_SYSMENU
if ( i != wxNOT_FOUND )
{
rc.result = MAKELRESULT(i, MNC_EXECUTE);
- processed = TRUE;
+ processed = true;
}
}
break;
-#endif // __WIN32__
}
if ( !processed )
{
#ifdef __WXDEBUG__
-#if wxUSE_LOG
wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."),
wxGetMessageName(message));
-#endif // wxUSE_LOG
#endif // __WXDEBUG__
rc.result = MSWDefWindowProc(message, wParam, lParam);
}
int& x, int& y,
int& w, int& h) const
{
+ // yes, those are just some arbitrary hardcoded numbers
static const int DEFAULT_Y = 200;
+ static const int DEFAULT_W = 400;
static const int DEFAULT_H = 250;
- bool nonDefault = FALSE;
+ bool nonDefault = false;
if ( pos.x == -1 )
{
- // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
- // just as well set it to CW_USEDEFAULT as well
+ // if x is set to CW_USEDEFAULT, y parameter is ignored anyhow so we
+ // can just as well set it to CW_USEDEFAULT as well
x =
y = CW_USEDEFAULT;
}
x = pos.x;
y = pos.y == -1 ? DEFAULT_Y : pos.y;
- nonDefault = TRUE;
+ nonDefault = true;
}
/*
*/
if ( size.x == -1 )
{
- // as above, h is not used at all in this case anyhow
- w =
- h = CW_USEDEFAULT;
+ // we don't use CW_USEDEFAULT here for several reasons:
+ //
+ // 1. it results in huge frames on modern screens (1000*800 is not
+ // uncommon on my 1280*1024 screen) which is way too big for a half
+ // empty frame of most of wxWindows samples for example)
+ //
+ // 2. it is buggy for frames with wxFRAME_TOOL_WINDOW style for which
+ // the default is for whatever reason 8*8 which breaks client <->
+ // window size calculations (it would be nice if it didn't, but it
+ // does and the simplest way to fix it seemed to change the broken
+ // default size anyhow)
+ //
+ // 3. there is just no advantage in doing it: with x and y it is
+ // possible that [future versions of] Windows position the new top
+ // level window in some smart way which we can't do, but we can
+ // guess a reasonably good size for a new window just as well
+ // ourselves
+ w = DEFAULT_W;
+ h = DEFAULT_H;
}
else
{
w = size.x;
h = size.y == -1 ? DEFAULT_H : size.y;
- nonDefault = TRUE;
+ nonDefault = true;
}
+ AdjustForParentClientOrigin(x, y);
+
return nonDefault;
}
// which is the same but without CS_[HV]REDRAW class styles so using it
// ensures that the window is not fully repainted on each resize
wxString className(wclass);
- if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE )
+ if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) )
{
className += wxT("NR");
}
// do create the window
wxWindowCreationHook hook(this);
- m_hWnd = (WXHWND)::CreateWindowEx
- (
- extendedStyle,
- className,
- title ? title : wxT(""),
- style,
- x, y, w, h,
- (HWND)MSWGetParent(),
- (HMENU)controlId,
- wxGetInstance(),
- NULL // no extra data
- );
+#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
+ {
+ m_hWnd = (WXHWND)::CreateWindowEx
+ (
+ extendedStyle,
+ className,
+ title ? title : wxEmptyString,
+ 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);
- return FALSE;
+ return false;
}
SubclassWin(m_hWnd);
SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
- return TRUE;
+ return true;
}
// ===========================================================================
// correct button tooltips
#if 0
// try all our children
- wxWindowList::Node *node = GetChildren().GetFirst();
+ wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
while ( node )
{
wxWindow *child = node->GetData();
if ( child->MSWOnNotify(idCtrl, lParam, result) )
{
- return TRUE;
+ return true;
}
node = node->GetNext();
// by default, handle it ourselves
return MSWOnNotify(idCtrl, lParam, result);
#else // __WXMICROWIN__
- return FALSE;
+ return false;
#endif
}
// this message is supposed to be sent to Unicode programs only) -- hence
// we need to handle it as well, otherwise no tooltips will be shown in
// this case
-
+#ifndef __WXWINCE__
if ( !(code == (WXUINT) TTN_NEEDTEXTA || code == (WXUINT) TTN_NEEDTEXTW) || ttip.empty() )
{
// not a tooltip message or no tooltip to show anyhow
- return FALSE;
+ return false;
}
+#endif
LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam;
// in Unicode mode this is just what we need
ttText->lpszText = (wxChar *)ttip.c_str();
#else // !Unicode
- MultiByteToWideChar(CP_ACP, 0, ttip, ttip.length()+1,
- (wchar_t *)ttText->szText,
- sizeof(ttText->szText) / sizeof(wchar_t));
+ // Convert tooltip from multi byte to Unicode.
+
+ // We don't want to use the szText buffer because it has a limit of 80
+ // bytes, for now use our own static buffer with a higher fixed max
+ // length.
+ // Preferably a dynamic buffer should be used, but who frees the buffer?
+
+ static const int MAX_LENGTH = 512;
+ static wchar_t buf[MAX_LENGTH+1];
+
+ ttText->lpszText = (LPSTR) buf;
+
+ // Truncate tooltip length if needed
+ size_t tipLength = wxMin(ttip.Len(), MAX_LENGTH);
+
+ // Convert to WideChar without adding the NULL character. The NULL
+ // character is added afterwards (this is more efficient).
+ ::MultiByteToWideChar(CP_ACP, 0, ttip, tipLength, buf, MAX_LENGTH);
+
+ buf[tipLength] = '\0';
+
#endif // Unicode/!Unicode
}
- return TRUE;
+ return true;
}
#endif // wxUSE_TOOLTIPS
if ( HandleTooltipNotify(hdr->code, lParam, m_tooltip->GetTip()))
{
// processed
- return TRUE;
+ return true;
}
}
#endif // wxUSE_TOOLTIPS
- return FALSE;
+ return false;
}
#endif // __WIN95__
bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd)
{
+#ifndef __WXWINCE__
wxCloseEvent event(wxEVT_QUERY_END_SESSION, -1);
event.SetEventObject(wxTheApp);
- event.SetCanVeto(TRUE);
+ event.SetCanVeto(true);
event.SetLoggingOff(logOff == (long)ENDSESSION_LOGOFF);
bool rc = wxTheApp->ProcessEvent(event);
}
return rc;
+#else
+ return false;
+#endif
}
bool wxWindowMSW::HandleEndSession(bool endSession, long logOff)
{
+#ifndef __WXWINCE__
// do nothing if the session isn't ending
if ( !endSession )
- return FALSE;
+ return false;
// only send once
if ( (this != wxTheApp->GetTopWindow()) )
- return FALSE;
+ return false;
wxCloseEvent event(wxEVT_END_SESSION, -1);
event.SetEventObject(wxTheApp);
- event.SetCanVeto(FALSE);
+ event.SetCanVeto(false);
event.SetLoggingOff( (logOff == (long)ENDSESSION_LOGOFF) );
return wxTheApp->ProcessEvent(event);
+#else
+ return false;
+#endif
}
// ---------------------------------------------------------------------------
bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate)
{
- // if we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our
- // parent as well as otherwise several Win32 functions using
- // GetNextDlgTabItem() to iterate over all controls such as
- // IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed,
- // all of them iterate over all the controls starting from the focus and
- // stop iterating when they get back to the focus but unless all parents
- // have WS_EX_CONTROLPARENT bit set, they would never get back to focus
+ // VZ: why is this commented out for WinCE? If it doesn't support
+ // WS_EX_CONTROLPARENT at all it should be somehow handled globally,
+ // not with multiple #ifdef's!
+#ifndef __WXWINCE__
if ( ((CREATESTRUCT *)cs)->dwExStyle & WS_EX_CONTROLPARENT )
- {
- // there is no need to do anything for the top level windows
- const wxWindow *parent = GetParent();
- while ( parent && !parent->IsTopLevel() )
- {
- LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE);
- if ( !(exStyle & WS_EX_CONTROLPARENT) )
- {
- // force the parent to have this style
- ::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE,
- exStyle | WS_EX_CONTROLPARENT);
- }
-
- parent = parent->GetParent();
- }
- }
+ EnsureParentHasControlParentStyle(GetParent());
+#endif // !__WXWINCE__
// TODO: should generate this event from WM_NCCREATE
wxWindowCreateEvent event((wxWindow *)this);
(void)GetEventHandler()->ProcessEvent(event);
- *mayCreate = TRUE;
+ *mayCreate = true;
- return TRUE;
+ return true;
}
bool wxWindowMSW::HandleDestroy()
#endif // wxUSE_DRAG_AND_DROP
// WM_DESTROY handled
- return TRUE;
+ return true;
}
// ---------------------------------------------------------------------------
// after the control gets to process it from EN_FOCUS handler
if ( wxDynamicCastThis(wxTextCtrl) )
{
- return FALSE;
+ return false;
}
#endif // wxUSE_TEXTCTRL
wxTextCtrl *ctrl = wxDynamicCastThis(wxTextCtrl);
if ( ctrl )
{
- return FALSE;
+ return false;
}
#endif
// only cause problems if the event handler tries to access the object.
if ( m_isBeingDeleted )
{
- return FALSE;
+ return false;
}
wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId);
bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
{
-#if defined (__WXMICROWIN__)
- return FALSE;
+#if defined (__WXMICROWIN__) || defined(__WXWINCE__)
+ return false;
#else // __WXMICROWIN__
HDROP hFilesInfo = (HDROP) wParam;
// and now get the file name
::DragQueryFile(hFilesInfo, wIndex,
- files[wIndex].GetWriteBuf(len), len);
-
- files[wIndex].UngetWriteBuf();
+ wxStringBuffer(files[wIndex], len), len);
}
DragFinish (hFilesInfo);
#endif
}
-#ifdef __DIGITALMARS__
-extern "C" HCURSOR wxGetCurrentBusyCursor();
-#endif
bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd),
short nHitTest,
if ( nHitTest != HTCLIENT )
{
- return FALSE;
+ 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;
-#ifdef __WIN32__
if ( !::GetCursorPos(&pt) )
{
wxLogLastError(wxT("GetCursorPos"));
}
-#else
- // In WIN16 it doesn't return a value.
- ::GetCursorPos(&pt);
-#endif
int x = pt.x,
y = pt.y;
::SetCursor(hcursor);
// cursor set, stop here
- return TRUE;
+ return true;
}
#endif // __WXMICROWIN__
// pass up the window chain
- return FALSE;
+ return false;
}
// ---------------------------------------------------------------------------
// owner drawn stuff
// ---------------------------------------------------------------------------
-bool wxWindowMSW::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct)
+#if (wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE) || \
+ (wxUSE_CONTROLS && !defined(__WXUNIVERSAL__))
+ #define WXUNUSED_UNLESS_ODRAWN(param) param
+#else
+ #define WXUNUSED_UNLESS_ODRAWN(param)
+#endif
+
+bool
+wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id),
+ WXDRAWITEMSTRUCT * WXUNUSED_UNLESS_ODRAWN(itemStruct))
{
#if wxUSE_OWNER_DRAWN
{
wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData);
- wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
+ wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), false );
// prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
// the DC from being released
}
#endif // wxUSE_MENUS_NATIVE
-#if wxUSE_CONTROLS
- wxWindow *item = FindItem(id);
- if ( item && item->IsKindOf(CLASSINFO(wxControl)) )
+#endif // USE_OWNER_DRAWN
+
+#if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__)
+
+#if wxUSE_OWNER_DRAWN
+ wxControl *item = wxDynamicCast(FindItem(id), wxControl);
+#else // !wxUSE_OWNER_DRAWN
+ // we may still have owner-drawn buttons internally because we have to make
+ // them owner-drawn to support colour change
+ wxControl *item = wxDynamicCast(FindItem(id), wxButton);
+#endif // USE_OWNER_DRAWN
+
+ if ( item )
{
- return ((wxControl *)item)->MSWOnDraw(itemStruct);
+ return item->MSWOnDraw(itemStruct);
}
-#endif // wxUSE_CONTROLS
-#endif // USE_OWNER_DRAWN
+#endif // wxUSE_CONTROLS
- return FALSE;
+ return false;
}
-bool wxWindowMSW::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct)
+bool
+wxWindowMSW::MSWOnMeasureItem(int WXUNUSED_UNLESS_ODRAWN(id),
+ WXMEASUREITEMSTRUCT *
+ WXUNUSED_UNLESS_ODRAWN(itemStruct))
{
-#if wxUSE_OWNER_DRAWN
+#if wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE
// is it a menu item?
MEASUREITEMSTRUCT *pMeasureStruct = (MEASUREITEMSTRUCT *)itemStruct;
if ( id == 0 && pMeasureStruct->CtlType == ODT_MENU )
{
wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData);
- wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
+ wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), false );
+
+ size_t w, h;
+ bool rc = pMenuItem->OnMeasureItem(&w, &h);
- return pMenuItem->OnMeasureItem(&pMeasureStruct->itemWidth,
- &pMeasureStruct->itemHeight);
+ pMeasureStruct->itemWidth = w;
+ pMeasureStruct->itemHeight = h;
+
+ return rc;
}
- wxWindow *item = FindItem(id);
- if ( item && item->IsKindOf(CLASSINFO(wxControl)) )
+ wxControl *item = wxDynamicCast(FindItem(id), wxControl);
+ if ( item )
{
- return ((wxControl *)item)->MSWOnMeasure(itemStruct);
+ return item->MSWOnMeasure(itemStruct);
}
-#endif // owner-drawn menus
- return FALSE;
+#endif // wxUSE_OWNER_DRAWN
+
+ return false;
}
// ---------------------------------------------------------------------------
// always let the system carry on the default processing to allow the
// native controls to react to the colours update
- return FALSE;
+ return false;
}
bool wxWindowMSW::HandleDisplayChange()
#ifndef __WXMICROWIN__
WXHBRUSH hBrush = 0;
+#ifdef __WXWINCE__
+ if (false)
+#else
if ( nCtlColor == CTLCOLOR_DLG )
+#endif
{
hBrush = OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam);
}
#if wxUSE_CONTROLS
else
{
- wxControl *item = (wxControl *)FindItemByHWND(pWnd, TRUE);
+ wxControl *item = (wxControl *)FindItemByHWND(pWnd, true);
if ( item )
hBrush = item->OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam);
}
return hBrush != 0;
#else // __WXMICROWIN__
- return FALSE;
+ return false;
#endif
}
// now check for the need to redraw
if (result > 0)
- InvalidateRect((HWND) hWndPalChange, NULL, TRUE);
+ ::InvalidateRect((HWND) hWndPalChange, NULL, TRUE);
}
}
if ( IsTopLevel() )
{
// FIXME-MT
- gs_hasStdCmap = FALSE;
+ gs_hasStdCmap = false;
}
- wxWindowList::Node *node = GetChildren().GetFirst();
+ wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
while ( node )
{
// Only propagate to non-top-level windows because Windows already
if ( !gs_hasStdCmap )
{
- static bool s_coloursInit = FALSE;
+ static bool s_coloursInit = false;
if ( !s_coloursInit )
{
//s_stdColours[5] = RGB(255,000,255); // magenta
}
- s_coloursInit = TRUE;
+ s_coloursInit = true;
}
- gs_hasStdCmap = TRUE;
+ gs_hasStdCmap = true;
// create the colour map
#define INIT_CMAP_ENTRY(col) \
bool wxWindowMSW::HandlePaint()
{
-#ifdef __WIN32__
+// if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND)
+// return FALSE;
+
HRGN hRegion = ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
if ( !hRegion )
wxLogLastError(wxT("CreateRectRgn"));
wxLogLastError(wxT("GetUpdateRgn"));
m_updateRegion = wxRegion((WXHRGN) hRegion);
-#else // Win16
- RECT updateRect;
- ::GetUpdateRect(GetHwnd(), &updateRect, FALSE);
-
- m_updateRegion = wxRegion(updateRect.left, updateRect.top,
- updateRect.right - updateRect.left,
- updateRect.bottom - updateRect.top);
-#endif // Win32/16
wxPaintEvent event(m_windowId);
event.SetEventObject(this);
{
// Prevents flicker when dragging
if ( ::IsIconic(GetHwnd()) )
- return TRUE;
+ return true;
+
+#if 0
+ if (GetParent() && GetParent()->GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND)
+ {
+ return false;
+ }
+
+ if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND)
+ {
+ if (wxUxThemeEngine::Get())
+ {
+ WXHTHEME hTheme = wxUxThemeEngine::Get()->m_pfnOpenThemeData(GetHWND(), L"TAB");
+ if (hTheme)
+ {
+ WXURECT rect;
+ ::GetClientRect((HWND) GetHWND(), (RECT*) & rect);
+ wxUxThemeEngine::Get()->m_pfnDrawThemeBackground(hTheme, hdc, 10 /* TABP_BODY */, 0, &rect, &rect);
+ wxUxThemeEngine::Get()->m_pfnCloseThemeData(hTheme);
+ return true;
+ }
+ }
+ }
+#endif
wxDCTemp dc(hdc);
HDC hdc = (HDC)event.GetDC()->GetHDC();
+#ifndef __WXWINCE__
int mode = ::SetMapMode(hdc, MM_TEXT);
+#endif
::FillRect(hdc, &rect, hBrush);
::DeleteObject(hBrush);
+
+#ifndef __WXWINCE__
::SetMapMode(hdc, mode);
+#endif
}
// ---------------------------------------------------------------------------
return GetEventHandler()->ProcessEvent(event);
}
+bool wxWindowMSW::HandleMoving(wxRect& rect)
+{
+ wxMoveEvent event(rect, m_windowId);
+ event.SetEventObject(this);
+
+ bool rc = GetEventHandler()->ProcessEvent(event);
+ if (rc)
+ rect = event.GetRect();
+ return rc;
+}
+
bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h),
WXUINT WXUNUSED(flag))
{
return GetEventHandler()->ProcessEvent(event);
}
+bool wxWindowMSW::HandleSizing(wxRect& rect)
+{
+ wxSizeEvent event(rect, m_windowId);
+ event.SetEventObject(this);
+
+ bool rc = GetEventHandler()->ProcessEvent(event);
+ if (rc)
+ rect = event.GetRect();
+ return rc;
+}
+
bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo)
{
+#ifdef __WXWINCE__
+ return false;
+#else
MINMAXINFO *info = (MINMAXINFO *)mmInfo;
- bool rc = FALSE;
+ bool rc = false;
int minWidth = GetMinWidth(),
minHeight = GetMinHeight(),
if ( minWidth != -1 )
{
info->ptMinTrackSize.x = minWidth;
- rc = TRUE;
+ rc = true;
}
if ( minHeight != -1 )
{
info->ptMinTrackSize.y = minHeight;
- rc = TRUE;
+ rc = true;
}
if ( maxWidth != -1 )
{
info->ptMaxTrackSize.x = maxWidth;
- rc = TRUE;
+ rc = true;
}
if ( maxHeight != -1 )
{
info->ptMaxTrackSize.y = maxHeight;
- rc = TRUE;
+ rc = true;
}
return rc;
+#endif
}
// ---------------------------------------------------------------------------
// wxSpinCtrl
wxSpinCtrl *spin = wxSpinCtrl::GetSpinForTextCtrl(control);
if ( spin && spin->ProcessTextCommand(cmd, id) )
- return TRUE;
+ return true;
}
#endif // wxUSE_SPINCTRL
- return FALSE;
+ return false;
}
bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam))
{
+#ifndef __WXWINCE__
// 4 bits are reserved
switch ( wParam & 0xFFFFFFF0 )
{
case SC_MINIMIZE:
return HandleMinimize();
}
+#endif
- return FALSE;
+ return false;
}
// ---------------------------------------------------------------------------
// so simply test for negative value.
event.m_altDown = ::GetKeyState(VK_MENU) < 0;
- event.SetTimestamp(s_currentMsg.time);
+#ifndef __WXWINCE__
+ event.SetTimestamp(::GetMessageTime());
+#endif
+
event.m_eventObject = this;
event.SetId(GetId());
HWND hwnd = GetHwndOf(win),
hwndUnderMouse;
-#ifdef __WIN32__
+#ifdef __WXWINCE__
+ hwndUnderMouse = ::ChildWindowFromPoint
+ (
+ hwnd,
+ pt
+ );
+#else
hwndUnderMouse = ::ChildWindowFromPointEx
(
hwnd,
CWP_SKIPDISABLED |
CWP_SKIPTRANSPARENT
);
+#endif
if ( !hwndUnderMouse || hwndUnderMouse == hwnd )
-#endif // __WIN32__
{
// now try any child window at all
hwndUnderMouse = ::ChildWindowFromPoint(hwnd, pt);
if ( !HasCapture() || IsMouseInWindow() )
{
// Generate an ENTER event
- m_mouseInWindow = TRUE;
-
+ m_mouseInWindow = true;
+#if _WIN32_WINNT >= 0x0400
+#ifndef __WXWINCE__
+ TRACKMOUSEEVENT trackinfo;
+
+ trackinfo.cbSize = sizeof(trackinfo);
+ trackinfo.dwFlags = TME_LEAVE;
+ trackinfo.hwndTrack = GetHwnd();
+ //Use the commctrl.h _TrackMouseEvent, which will call the
+ // appropriate TrackMouseEvent or emulate it ( win95 )
+ // else we need _WIN32_WINNT >= 0x0400
+ _TrackMouseEvent(&trackinfo);
+#endif
+#endif
wxMouseEvent event(wxEVT_ENTER_WINDOW);
InitMouseEvent(event, x, y, flags);
{
m_lastMouseEvent = wxEVT_MOTION;
- return FALSE;
+ return false;
}
#endif // wxUSE_MOUSEEVENT_HACK
event.m_wheelRotation = (short)HIWORD(wParam);
event.m_wheelDelta = WHEEL_DELTA;
-#ifdef __WIN32__
static int s_linesPerRotation = -1;
if ( s_linesPerRotation == -1 )
{
s_linesPerRotation = 3;
}
}
-#else // Win16
- // no SystemParametersInfo() under Win16
- static const int s_linesPerRotation = 3;
-#endif
event.m_linesPerAction = s_linesPerRotation;
return GetEventHandler()->ProcessEvent(event);
(void) wParam;
(void) lParam;
- return FALSE;
+ return false;
#endif
}
event.m_keyCode = id;
event.m_rawCode = (wxUint32) wParam;
event.m_rawFlags = (wxUint32) lParam;
- event.SetTimestamp(s_currentMsg.time);
+#ifndef __WXWINCE__
+ event.SetTimestamp(::GetMessageTime());
+#endif
// translate the position to client coords
POINT pt;
return event;
}
-// isASCII is TRUE only when we're called from WM_CHAR handler and not from
+// isASCII is true only when we're called from WM_CHAR handler and not from
// WM_KEYDOWN one
bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII)
{
- bool ctrlDown = FALSE;
-
int id;
if ( isASCII )
{
// If 1 -> 26, translate to either special keycode or just set
// ctrlDown. IOW, Ctrl-C should result in keycode == 3 and
- // ControlDown() == TRUE.
+ // ControlDown() == true.
id = wParam;
if ( (id > 0) && (id < 27) )
{
break;
default:
- ctrlDown = TRUE;
+ //ctrlDown = true;
break;
}
}
if ( id == 0 )
{
// it's ASCII and will be processed here only when called from
- // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
- return FALSE;
+ // WM_CHAR (i.e. when isASCII = true), don't process it now
+ return false;
}
}
(id >= 32 && id < 256) )
{
event.m_controlDown =
- event.m_altDown = FALSE;
+ event.m_altDown = false;
}
return GetEventHandler()->ProcessEvent(event);
wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam));
if ( GetEventHandler()->ProcessEvent(event) )
{
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
{
wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam));
if ( GetEventHandler()->ProcessEvent(event) )
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-#ifdef __WIN32__
-
int wxWindowMSW::HandleMenuChar(int chAccel, WXLPARAM lParam)
{
+ // FIXME: implement GetMenuItemCount for WinCE, possibly
+ // in terms of GetMenuItemInfo
+#ifndef __WXWINCE__
const HMENU hmenu = (HMENU)lParam;
MENUITEMINFO mii;
}
}
}
- else // failed ot get the menu text?
+ else // failed to get the menu text?
{
// it's not fatal, so don't show error, but still log
// it
wxLogLastError(_T("GetMenuItemInfo"));
}
}
-
+#endif
return wxNOT_FOUND;
}
-#endif // __WIN32__
-
// ---------------------------------------------------------------------------
// joystick
// ---------------------------------------------------------------------------
default:
wxFAIL_MSG(wxT("no such joystick event"));
- return FALSE;
+ return false;
}
wxJoystickEvent event(eventType, buttons, joystick, change);
return GetEventHandler()->ProcessEvent(event);
#else
- return FALSE;
+ return false;
#endif
}
bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam,
WXWORD pos, WXHWND control)
-{
- if ( control )
+{
+ if ( control && control != m_hWnd ) // Prevent infinite recursion
{
wxWindow *child = wxFindWinFromHandle(control);
if ( child )
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
-#ifdef __WIN32__
// under Win32, the scrollbar range and position are 32 bit integers,
// but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
// explicitly query the scrollbar for the correct position (this must
: SB_VERT,
&scrollInfo) )
{
- wxLogLastError(_T("GetScrollInfo"));
+ // Not neccessarily an error, if there are no scrollbars yet.
+ // wxLogLastError(_T("GetScrollInfo"));
}
event.SetPosition(scrollInfo.nTrackPos);
}
-#endif // Win32
event.m_eventType = wParam == SB_THUMBPOSITION
? wxEVT_SCROLLWIN_THUMBRELEASE
break;
default:
- return FALSE;
+ return false;
}
return GetEventHandler()->ProcessEvent(event);
int wxCharCodeWXToMSW(int id, bool *isVirtual)
{
- *isVirtual = TRUE;
- int keySym = 0;
+ *isVirtual = true;
+ int keySym;
switch (id)
{
case WXK_CANCEL: keySym = VK_CANCEL; break;
case WXK_SCROLL: keySym = VK_SCROLL; break;
default:
{
- *isVirtual = FALSE;
+ *isVirtual = false;
keySym = id;
break;
}
return keySym;
}
+bool wxGetKeyState(wxKeyCode key)
+{
+ bool bVirtual;
+ int vkey = wxCharCodeWXToMSW(key, &bVirtual);
+
+ //there aren't WXK_ macros for non-virtual key codes
+ if (bVirtual == false)
+ return false;
+
+ return GetKeyState(vkey) < 0;
+}
+
wxWindow *wxGetActiveWindow()
{
HWND hWnd = GetActiveWindow();
win = wxFindWinFromHandle((WXHWND)hwnd);
if ( !win )
{
- // all these hacks only work under Win32 anyhow
-#ifdef __WIN32__
-
#if wxUSE_RADIOBOX
// native radiobuttons return DLGC_RADIOBUTTON here and for any
// wxWindow class which overrides WM_GETDLGCODE processing to
// do it as well, win would be already non NULL
if ( ::SendMessage(hwnd, WM_GETDLGCODE, 0, 0) & DLGC_RADIOBUTTON )
{
- win = (wxWindow *)::GetWindowLong(hwnd, GWL_USERDATA);
+ win = (wxWindow *)wxGetWindowUserData(hwnd);
}
//else: it's a wxRadioButton, not a radiobutton from wxRadioBox
#endif // wxUSE_RADIOBOX
win = wxSpinCtrl::GetSpinForTextCtrl((WXHWND)hwnd);
}
#endif // wxUSE_SPINCTRL
-
-#endif // Win32
}
}
return win;
}
-#ifndef __WXMICROWIN__
+#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
// Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
// in active frames and dialogs, regardless of where the focus is.
wxTheKeyboardHookProc = MakeProcInstance((FARPROC) wxKeyboardHook, wxGetInstance());
wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(),
-#if defined(__WIN32__) && !defined(__TWIN32__)
GetCurrentThreadId()
// (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
-#else
- GetCurrentTask()
-#endif
);
}
else
{
UnhookWindowsHookEx(wxTheKeyboardHook);
-
- // avoids warning about statement with no effect (FreeProcInstance
- // doesn't do anything under Win32)
-#if !defined(__WIN32__) && !defined(__NT__)
- FreeProcInstance(wxTheKeyboardHookProc);
-#endif
}
}
{
wxKeyEvent event(wxEVT_CHAR_HOOK);
if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN )
- event.m_altDown = TRUE;
+ event.m_altDown = true;
event.m_eventObject = NULL;
event.m_keyCode = id;
event.m_shiftDown = wxIsShiftDown();
event.m_controlDown = wxIsCtrlDown();
- event.SetTimestamp(s_currentMsg.time);
-
+#ifndef __WXWINCE__
+ event.SetTimestamp(::GetMessageTime());
+#endif
wxWindow *win = wxGetActiveWindow();
wxEvtHandler *handler;
if ( win )
case 0x0047: return "WM_WINDOWPOSCHANGED";
case 0x0048: return "WM_POWER";
-#ifdef __WIN32__
case 0x004A: return "WM_COPYDATA";
case 0x004B: return "WM_CANCELJOURNAL";
case 0x004E: return "WM_NOTIFY";
case 0x007E: return "WM_DISPLAYCHANGE";
case 0x007F: return "WM_GETICON";
case 0x0080: return "WM_SETICON";
-#endif //WIN32
case 0x0081: return "WM_NCCREATE";
case 0x0082: return "WM_NCDESTROY";
case 0x0107: return "WM_SYSDEADCHAR";
case 0x0108: return "WM_KEYLAST";
-#ifdef __WIN32__
case 0x010D: return "WM_IME_STARTCOMPOSITION";
case 0x010E: return "WM_IME_ENDCOMPOSITION";
case 0x010F: return "WM_IME_COMPOSITION";
-#endif //WIN32
case 0x0110: return "WM_INITDIALOG";
case 0x0111: return "WM_COMMAND";
case 0x0211: return "WM_ENTERMENULOOP";
case 0x0212: return "WM_EXITMENULOOP";
-#ifdef __WIN32__
case 0x0213: return "WM_NEXTMENU";
case 0x0214: return "WM_SIZING";
case 0x0215: return "WM_CAPTURECHANGED";
case 0x0216: return "WM_MOVING";
case 0x0218: return "WM_POWERBROADCAST";
case 0x0219: return "WM_DEVICECHANGE";
-#endif //WIN32
case 0x0220: return "WM_MDICREATE";
case 0x0221: return "WM_MDIDESTROY";
case 0x0230: return "WM_MDISETMENU";
case 0x0233: return "WM_DROPFILES";
-#ifdef __WIN32__
case 0x0281: return "WM_IME_SETCONTEXT";
case 0x0282: return "WM_IME_NOTIFY";
case 0x0283: return "WM_IME_CONTROL";
case 0x0286: return "WM_IME_CHAR";
case 0x0290: return "WM_IME_KEYDOWN";
case 0x0291: return "WM_IME_KEYUP";
-#endif //WIN32
case 0x0300: return "WM_CUT";
case 0x0301: return "WM_COPY";
case 0x030F: return "WM_QUERYNEWPALETTE";
case 0x0310: return "WM_PALETTEISCHANGING";
case 0x0311: return "WM_PALETTECHANGED";
+#if wxUSE_HOTKEY
+ case 0x0312: return "WM_HOTKEY";
+#endif
-#ifdef __WIN32__
// common controls messages - although they're not strictly speaking
// standard, it's nice to decode them nevertheless
case WM_USER+61: return "TB_GETTEXTROWS";
case WM_USER+41: return "TB_GETBITMAPFLAGS";
-#endif //WIN32
-
default:
static char s_szBuf[128];
sprintf(s_szBuf, "<unknown message = %d>", message);
return wxPoint(pt.x, pt.y);
}
+#if wxUSE_HOTKEY
+
+bool wxWindowMSW::RegisterHotKey(int hotkeyId, int modifiers, int keycode)
+{
+ UINT win_modifiers=0;
+ if ( modifiers & wxMOD_ALT )
+ win_modifiers |= MOD_ALT;
+ if ( modifiers & wxMOD_SHIFT )
+ win_modifiers |= MOD_SHIFT;
+ if ( modifiers & wxMOD_CONTROL )
+ win_modifiers |= MOD_CONTROL;
+ if ( modifiers & wxMOD_WIN )
+ win_modifiers |= MOD_WIN;
+
+ if ( !::RegisterHotKey(GetHwnd(), hotkeyId, win_modifiers, keycode) )
+ {
+ wxLogLastError(_T("RegisterHotKey"));
+
+ return false;
+ }
+
+ return true;
+}
+
+bool wxWindowMSW::UnregisterHotKey(int hotkeyId)
+{
+ if ( !::UnregisterHotKey(GetHwnd(), hotkeyId) )
+ {
+ wxLogLastError(_T("UnregisterHotKey"));
+
+ return false;
+ }
+
+ return true;
+}
+
+bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam)
+{
+ int hotkeyId = wParam;
+ int virtualKey = HIWORD(lParam);
+ int win_modifiers = LOWORD(lParam);
+
+ wxKeyEvent event(CreateKeyEvent(wxEVT_HOTKEY, virtualKey, wParam, lParam));
+ event.SetId(hotkeyId);
+ event.m_shiftDown = (win_modifiers & MOD_SHIFT) != 0;
+ event.m_controlDown = (win_modifiers & MOD_CONTROL) != 0;
+ event.m_altDown = (win_modifiers & MOD_ALT) != 0;
+ event.m_metaDown = (win_modifiers & MOD_WIN) != 0;
+
+ return GetEventHandler()->ProcessEvent(event);
+}
+
+#endif // wxUSE_HOTKEY
+
+// Not tested under WinCE
+#ifndef __WXWINCE__
+
+// this class installs a message hook which really wakes up our idle processing
+// each time a WM_NULL is received (wxWakeUpIdle does this), even if we're
+// sitting inside a local modal loop (e.g. a menu is opened or scrollbar is
+// being dragged or even inside ::MessageBox()) and so don't control message
+// dispatching otherwise
+class wxIdleWakeUpModule : public wxModule
+{
+public:
+ virtual bool OnInit()
+ {
+ ms_hMsgHookProc = ::SetWindowsHookEx
+ (
+ WH_GETMESSAGE,
+ &wxIdleWakeUpModule::MsgHookProc,
+ NULL,
+ GetCurrentThreadId()
+ );
+
+ if ( !ms_hMsgHookProc )
+ {
+ wxLogLastError(_T("SetWindowsHookEx(WH_GETMESSAGE)"));
+
+ return false;
+ }
+
+ return true;
+ }
+
+ virtual void OnExit()
+ {
+ ::UnhookWindowsHookEx(wxIdleWakeUpModule::ms_hMsgHookProc);
+ }
+
+ static LRESULT CALLBACK MsgHookProc(int nCode, WPARAM wParam, LPARAM lParam)
+ {
+ MSG *msg = (MSG*)lParam;
+ if ( msg->message == WM_NULL )
+ {
+ wxTheApp->ProcessPendingEvents();
+ }
+
+ return CallNextHookEx(ms_hMsgHookProc, nCode, wParam, lParam);
+ };
+
+private:
+ static HHOOK ms_hMsgHookProc;
+
+ DECLARE_DYNAMIC_CLASS(wxIdleWakeUpModule)
+};
+
+HHOOK wxIdleWakeUpModule::ms_hMsgHookProc = 0;
+
+IMPLEMENT_DYNAMIC_CLASS(wxIdleWakeUpModule, wxModule)
+
+#endif // __WXWINCE__
+