/////////////////////////////////////////////////////////////////////////////
-// Name: src/msw/windows.cpp
-// Purpose: wxWindow
+// Name: src/msw/window.cpp
+// Purpose: wxWindowMSW
// Author: Julian Smart
// Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation
// Created: 04/01/98
// RCS-ID: $Id$
-// Copyright: (c) Julian Smart and Markus Holzem
-// Licence: wxWindows license
+// Copyright: (c) Julian Smart
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ===========================================================================
// headers
// ---------------------------------------------------------------------------
-#ifdef __GNUG__
- #pragma implementation "window.h"
-#endif
-
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#pragma hdrstop
#endif
+#include "wx/window.h"
+
#ifndef WX_PRECOMP
- #include <windows.h>
- #include "wx/msw/winundef.h"
- #include "wx/window.h"
+ #include "wx/msw/wrapwin.h"
+ #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
+ #include "wx/msw/missing.h"
#include "wx/accel.h"
- #include "wx/setup.h"
#include "wx/menu.h"
#include "wx/dc.h"
#include "wx/dcclient.h"
#include "wx/msgdlg.h"
#include "wx/settings.h"
#include "wx/statbox.h"
+ #include "wx/sizer.h"
+ #include "wx/intl.h"
+ #include "wx/log.h"
+ #include "wx/textctrl.h"
+ #include "wx/menuitem.h"
+ #include "wx/module.h"
#endif
-#if wxUSE_OWNER_DRAWN
+#if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
#include "wx/ownerdrw.h"
#endif
+#include "wx/evtloop.h"
+#include "wx/power.h"
+#include "wx/sysopt.h"
+
#if wxUSE_DRAG_AND_DROP
#include "wx/dnd.h"
#endif
-#include "wx/menuitem.h"
-#include "wx/log.h"
+#if wxUSE_ACCESSIBILITY
+ #include "wx/access.h"
+ #include <ole2.h>
+ #include <oleacc.h>
+ #ifndef WM_GETOBJECT
+ #define WM_GETOBJECT 0x003D
+ #endif
+ #ifndef OBJID_CLIENT
+ #define OBJID_CLIENT 0xFFFFFFFC
+ #endif
+#endif
#include "wx/msw/private.h"
#include "wx/spinctrl.h"
#endif // wxUSE_SPINCTRL
-#include "wx/intl.h"
-#include "wx/log.h"
-
-#include "wx/textctrl.h"
#include "wx/notebook.h"
+#include "wx/listctrl.h"
+#include "wx/dynlib.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__)
- #ifdef __WIN95__
- #include <commctrl.h>
- #endif
-#elif !defined(__WXMICROWIN__) // broken compiler
- #ifndef __TWIN32__
- #include "wx/msw/gnuwin32/extra.h"
- #endif
+#if !defined __WXWINCE__ && !defined NEED_PBT_H
+ #include <pbt.h>
#endif
-// ----------------------------------------------------------------------------
-// standard constants not available with all compilers/headers
-// ----------------------------------------------------------------------------
+#if defined(__WXWINCE__)
+ #include "wx/msw/wince/missing.h"
+#ifdef __POCKETPC__
+ #include <windows.h>
+ #include <shellapi.h>
+ #include <ole2.h>
+ #include <aygshell.h>
+#endif
+#endif
-// This didn't appear in mingw until 2.95.2
-#ifndef SIF_TRACKPOS
-#define SIF_TRACKPOS 16
+#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
-#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_PLUS 0xBB
- #define VK_OEM_COMMA 0xBC
- #define VK_OEM_MINUS 0xBD
- #define VK_OEM_PERIOD 0xBE
- #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
+// set this to 1 to filter out duplicate mouse events, e.g. mouse move events
+// when mouse position didnd't change
+#ifdef __WXWINCE__
+ #define wxUSE_MOUSEEVENT_HACK 0
+#else
+ #define wxUSE_MOUSEEVENT_HACK 1
#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
+#ifdef __WXWINCE__
+extern wxChar *wxCanvasClassName;
+#else
extern const wxChar *wxCanvasClassName;
+#endif
// 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;
+
+// last mouse event information we need to filter out the duplicates
+#if wxUSE_MOUSEEVENT_HACK
+static struct MouseEventInfoDummy
+{
+ // mouse position (in screen coordinates)
+ wxPoint pos;
+
+ // last mouse event type
+ wxEventType type;
+} gs_lastMouseEvent;
+#endif // wxUSE_MOUSEEVENT_HACK
// ---------------------------------------------------------------------------
// private functions
LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam);
+
#ifdef __WXDEBUG__
- const char *wxGetMessageName(int message);
+ const wxChar *wxGetMessageName(int message);
#endif //__WXDEBUG__
void wxRemoveHandleAssociation(wxWindowMSW *win);
-void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
+extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
wxWindow *wxFindWinFromHandle(WXHWND hWnd);
-// this magical function is used to translate VK_APPS key presses to right
-// mouse clicks
-static void TranslateKbdEventToMouse(wxWindowMSW *win,
- int *x, int *y, WPARAM *flags);
-
// get the text metrics for the current font
static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win);
+#ifdef __WXWINCE__
// find the window for the mouse event at the specified position
-static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y); //TW:REQ:Univ
+static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y);
+#endif // __WXWINCE__
// wrapper around BringWindowToTop() API
static inline void wxBringWindowToTop(HWND hwnd)
// 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"));
+ }
+}
+
+#ifndef __WXWINCE__
+
+// 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 either.
+ */
+ 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();
+ }
+}
+
+#endif // !__WXWINCE__
+
+#ifdef __WXWINCE__
+// On Windows CE, GetCursorPos can return an error, so use this function
+// instead
+bool GetCursorPosWinCE(POINT* pt)
+{
+ if (!GetCursorPos(pt))
{
- wxLogLastError(_T("BringWindowToTop"));
+ DWORD pos = GetMessagePos();
+ pt->x = LOWORD(pos);
+ pt->y = HIWORD(pos);
}
-#endif // __WXMICROWIN__/!__WXMICROWIN__
+ return true;
}
+#endif
// ---------------------------------------------------------------------------
// event tables
#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, EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
+ wxPROPERTY( Id,wxWindowID, SetId, GetId, -1 /*wxID_ANY*/ , 0 /*flags*/ , wxT("Helpstring") , wxT("group") )
+ wxPROPERTY( Position,wxPoint, SetPosition , GetPosition, wxDefaultPosition , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // pos
+ wxPROPERTY( Size,wxSize, SetSize, GetSize, wxDefaultSize , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // size
+ wxPROPERTY( WindowStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 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 , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // extstyle
+ wxPROPERTY( BackgroundColour , wxColour , SetBackgroundColour , GetBackgroundColour , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // bg
+ wxPROPERTY( ForegroundColour , wxColour , SetForegroundColour , GetForegroundColour , EMPTY_MACROVALUE , 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, wxEmptyString )
+ wxPROPERTY( Font , wxFont , SetFont , GetWindowFont , )
+ wxPROPERTY( Label,wxString, SetLabel, GetLabel, wxEmptyString )
+ // 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_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground)
+#ifdef __WXWINCE__
EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog)
- EVT_IDLE(wxWindowMSW::OnIdle)
+#endif
END_EVENT_TABLE()
// ===========================================================================
wxControl *item = wxDynamicCastThis(wxControl);
if ( item )
{
- // is it we or one of our "internal" children?
+ // is it us or one of our "internal" children?
if ( item->GetId() == id
#ifndef __WXUNIVERSAL__
|| (item->GetSubcontrols().Index(id) != wxNOT_FOUND)
}
#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;
-
- // wxWnd
- m_hMenu = 0;
+ m_frozenness = 0;
m_hWnd = 0;
+ m_hDWP = 0;
m_xThumbSize = 0;
m_yThumbSize = 0;
- m_backgroundTransparent = FALSE;
- // as all windows are created with WS_VISIBLE style...
- m_isShown = TRUE;
+ m_pendingPosition = wxDefaultPosition;
+ m_pendingSize = wxDefaultSize;
-#if wxUSE_MOUSEEVENT_HACK
- m_lastMouseX =
- m_lastMouseY = -1;
- m_lastMouseEvent = -1;
-#endif // wxUSE_MOUSEEVENT_HACK
+#ifdef __POCKETPC__
+ m_contextMenuEnabled = false;
+#endif
}
// Destructor
wxWindowMSW::~wxWindowMSW()
{
- m_isBeingDeleted = TRUE;
+ m_isBeingDeleted = true;
#ifndef __WXUNIVERSAL__
// VS: make sure there's no wxFrame with last focus set to us:
{
frame->SetLastFocus(NULL);
}
- break;
+
+ // apparently sometimes we can end up with our grand parent
+ // pointing to us as well: this is surely a bug in focus handling
+ // code but it's not clear where it happens so for now just try to
+ // fix it here by not breaking out of the loop
+ //break;
}
}
#endif // __WXUNIVERSAL__
// VS: destroy children first and _then_ detach *this from its parent.
- // If we'd do it the other way around, children wouldn't be able
+ // If we did it the other way around, children wouldn't be able
// 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
}
delete m_childrenDisabled;
+
}
// real construction (Init() must have been called before!)
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);
msflags &= ~WS_BORDER;
#endif // wxUniversal
- // all windows are created visible by default except popup ones (which are
- // like the wxTopLevelWindows in this aspect)
- if ( style & wxPOPUP_WINDOW )
- {
- msflags &= ~WS_VISIBLE;
- m_isShown = FALSE;
- }
- else
+ if ( IsShown() )
{
msflags |= WS_VISIBLE;
}
- return MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle);
+ if ( !MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle) )
+ return false;
+
+ InheritAttributes();
+
+ return true;
}
// ---------------------------------------------------------------------------
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
-wxWindow *wxWindowBase::FindFocus()
+wxWindow *wxWindowBase::DoFindFocus()
{
HWND hWnd = ::GetFocus();
if ( hWnd )
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() )
{
if ( enable )
{
- // enable the child back unless it had been disabled before us
+ // re-enable the child unless it had been disabled before us
if ( !m_childrenDisabled || !m_childrenDisabled->Find(child) )
child->Enable();
}
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 )
+ // we could be called before the underlying window is created (this is
+ // actually useful to prevent it from being initially shown), e.g.
+ //
+ // wxFoo *foo = new wxFoo;
+ // foo->Hide();
+ // foo->Create(parent, ...);
+ //
+ // should work without errors
+ if ( hWnd )
{
- wxBringWindowToTop(hWnd);
+ ::ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
}
- return TRUE;
+ return true;
}
// Raise the window to the top of the Z order
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
-void wxWindowMSW::SetTitle( const wxString& title)
-{
- SetWindowText(GetHwnd(), title.c_str());
-}
-
-wxString wxWindowMSW::GetTitle() const
-{
- return wxGetWindowText(GetHWND());
-}
-
void wxWindowMSW::DoCaptureMouse()
{
HWND hWnd = GetHwnd();
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() )
+ // don't "overwrite" busy cursor
+ if ( m_cursor.Ok() && !wxIsBusy() )
{
- HWND hWnd = GetHwnd();
-
- // Change the cursor NOW if we're within the correct window
- POINT point;
- ::GetCursorPos(&point);
-
- RECT rect = wxGetWindowRect(hWnd);
-
- if ( ::PtInRect(&rect, point) && !wxIsBusy() )
- ::SetCursor(GetHcursorOf(m_cursor));
+ ::SetCursor(GetHcursorOf(m_cursor));
}
- return TRUE;
+ return true;
}
-void wxWindowMSW::WarpPointer (int x, int y)
+void wxWindowMSW::WarpPointer(int x, int y)
{
ClientToScreen(&x, &y);
}
}
-#if WXWIN_COMPATIBILITY
-void wxWindowMSW::MSWDeviceToLogical (float *x, float *y) const
-{
-}
-#endif // WXWIN_COMPATIBILITY
-
-// ---------------------------------------------------------------------------
-// scrolling stuff
-// ---------------------------------------------------------------------------
-
-#if WXWIN_COMPATIBILITY
-void wxWindowMSW::SetScrollRange(int orient, int range, bool refresh)
+void wxWindowMSW::MSWUpdateUIState(int action, int state)
{
-#if defined(__WIN95__)
-
- 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)
+ // WM_CHANGEUISTATE only appeared in Windows 2000 so it can do us no good
+ // to use it on older systems -- and could possibly do some harm
+ static int s_needToUpdate = -1;
+ if ( s_needToUpdate == -1 )
{
- range1 += (pageSize - 1);
- }
-
- SCROLLINFO info;
- int dir;
-
- if ( orient == wxHORIZONTAL ) {
- dir = SB_HORZ;
- } else {
- dir = SB_VERT;
- }
-
- info.cbSize = sizeof(SCROLLINFO);
- info.nPage = pageSize; // Have to set this, or scrollbar goes awry
- info.nMin = 0;
- info.nMax = range1;
- info.nPos = 0;
- info.fMask = SIF_RANGE | SIF_PAGE;
-
- HWND hWnd = GetHwnd();
- if ( hWnd )
- ::SetScrollInfo(hWnd, dir, &info, refresh);
-#else
- int wOrient;
- if ( orient == wxHORIZONTAL )
- wOrient = SB_HORZ;
- else
- wOrient = SB_VERT;
-
- HWND hWnd = GetHwnd();
- if ( hWnd )
- ::SetScrollRange(hWnd, wOrient, 0, range, refresh);
-#endif
-}
-
-void wxWindowMSW::SetScrollPage(int orient, int page, bool refresh)
-{
-#if defined(__WIN95__)
- SCROLLINFO info;
- int dir;
-
- if ( orient == wxHORIZONTAL ) {
- dir = SB_HORZ;
- m_xThumbSize = page;
- } else {
- dir = SB_VERT;
- m_yThumbSize = page;
+ int verMaj, verMin;
+ s_needToUpdate = wxGetOsVersion(&verMaj, &verMin) == wxOS_WINDOWS_NT &&
+ verMaj >= 5;
}
- info.cbSize = sizeof(SCROLLINFO);
- info.nPage = page;
- info.nMin = 0;
- info.fMask = SIF_PAGE;
-
- HWND hWnd = GetHwnd();
- if ( hWnd )
- ::SetScrollInfo(hWnd, dir, &info, refresh);
-#else
- if ( orient == wxHORIZONTAL )
- m_xThumbSize = page;
- else
- m_yThumbSize = page;
-#endif
-}
-
-int wxWindowMSW::OldGetScrollRange(int orient) const
-{
- int wOrient;
- if ( orient == wxHORIZONTAL )
- wOrient = SB_HORZ;
- else
- wOrient = SB_VERT;
-
-#if __WATCOMC__ && defined(__WINDOWS_386__)
- short minPos, maxPos;
-#else
- int minPos, maxPos;
-#endif
- HWND hWnd = GetHwnd();
- if ( hWnd )
+ if ( s_needToUpdate )
{
- ::GetScrollRange(hWnd, wOrient, &minPos, &maxPos);
-#if defined(__WIN95__)
- // Try to adjust the range to cope with page size > 1
- // - a Windows API quirk
- int pageSize = GetScrollPage(orient);
- if ( pageSize > 1 )
- {
- maxPos -= (pageSize - 1);
- }
-#endif
- return maxPos;
+ // we send WM_CHANGEUISTATE so if nothing needs changing then the system
+ // won't send WM_UPDATEUISTATE
+ ::SendMessage(GetHwnd(), WM_CHANGEUISTATE, MAKEWPARAM(action, state), 0);
}
- else
- return 0;
-}
-
-int wxWindowMSW::GetScrollPage(int orient) const
-{
- if ( orient == wxHORIZONTAL )
- return m_xThumbSize;
- else
- return m_yThumbSize;
}
-#endif // WXWIN_COMPATIBILITY
+// ---------------------------------------------------------------------------
+// scrolling stuff
+// ---------------------------------------------------------------------------
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;
+ ::GetScrollInfo(hWnd, wOrient, &scrollInfo );
+
+ return scrollInfo.nPos;
+
#endif
}
int wxWindowMSW::GetScrollPos(int orient) const
{
- int wOrient;
- if ( orient == wxHORIZONTAL )
- wOrient = SB_HORZ;
- else
- wOrient = SB_VERT;
-
HWND hWnd = GetHwnd();
wxCHECK_MSG( hWnd, 0, _T("no HWND in GetScrollPos") );
- return GetScrollPosition(hWnd, wOrient);
+ return GetScrollPosition(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT);
}
// This now returns the whole range, not just the number
// of positions that we can scroll.
int wxWindowMSW::GetScrollRange(int orient) const
{
- int wOrient;
- if ( orient == wxHORIZONTAL )
- wOrient = SB_HORZ;
- else
- wOrient = SB_VERT;
-
-#if __WATCOMC__ && defined(__WINDOWS_386__)
- short minPos, maxPos;
-#else
- int minPos, maxPos;
-#endif
+ int maxPos;
HWND hWnd = GetHwnd();
- if ( hWnd )
- {
- ::GetScrollRange(hWnd, wOrient, &minPos, &maxPos);
-#if defined(__WIN95__)
- // Try to adjust the range to cope with page size > 1
- // - a Windows API quirk
- int pageSize = GetScrollThumb(orient);
- if ( pageSize > 1 )
- {
- maxPos -= (pageSize - 1);
- }
- // October 10th: new range concept.
- maxPos += pageSize;
+ if ( !hWnd )
+ return 0;
+#if 0
+ ::GetScrollRange(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
+ &minPos, &maxPos);
#endif
-
- return maxPos;
+ 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"));
}
- else
- return 0;
+ maxPos = scrollInfo.nMax;
+
+ // undo "range - 1" done in SetScrollbar()
+ return maxPos + 1;
}
int wxWindowMSW::GetScrollThumb(int orient) const
{
- if ( orient == wxHORIZONTAL )
- return m_xThumbSize;
- else
- return m_yThumbSize;
+ return orient == wxHORIZONTAL ? m_xThumbSize : m_yThumbSize;
}
void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh)
HWND hWnd = GetHwnd();
wxCHECK_RET( hWnd, _T("SetScrollPos: no HWND") );
- int dir = orient == wxHORIZONTAL ? SB_HORZ : SB_VERT;
-
-#if defined(__WIN95__)
- SCROLLINFO info;
- info.cbSize = sizeof(SCROLLINFO);
+ WinStruct<SCROLLINFO> info;
info.nPage = 0;
info.nMin = 0;
info.nPos = pos;
info.fMask = SIF_POS;
-
- ::SetScrollInfo(hWnd, dir, &info, refresh);
-#else // !__WIN95__
- ::SetScrollPos(hWnd, dir, pos, refresh);
-#endif // __WIN95__/!__WIN95__
-}
-
-// New function that will replace some of the above.
-void wxWindowMSW::SetScrollbar(int orient, int pos, int thumbVisible,
- int range, bool refresh)
-{
-#if defined(__WIN95__)
- int oldRange = range - thumbVisible;
-
- int range1 = oldRange;
-
- // Try to adjust the range to cope with page size > 1
- // - a Windows API quirk
- int pageSize = thumbVisible;
- if ( pageSize > 1 && range > 0)
+ if ( HasFlag(wxALWAYS_SHOW_SB) )
{
- range1 += (pageSize - 1);
+ // disable scrollbar instead of removing it then
+ info.fMask |= SIF_DISABLENOSCROLL;
}
- SCROLLINFO info;
- int dir;
-
- if ( orient == wxHORIZONTAL ) {
- dir = SB_HORZ;
- } else {
- dir = SB_VERT;
- }
+ ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
+ &info, refresh);
+}
- info.cbSize = sizeof(SCROLLINFO);
- info.nPage = pageSize; // Have to set this, or scrollbar goes awry
- info.nMin = 0;
- info.nMax = range1;
+// New function that will replace some of the above.
+void wxWindowMSW::SetScrollbar(int orient,
+ int pos,
+ int pageSize,
+ int range,
+ bool refresh)
+{
+ 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;
info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
-
- HWND hWnd = GetHwnd();
- if ( hWnd )
- ::SetScrollInfo(hWnd, dir, &info, refresh);
-#else
- int wOrient;
- if ( orient == wxHORIZONTAL )
- wOrient = SB_HORZ;
- else
- wOrient = SB_VERT;
+ if ( HasFlag(wxALWAYS_SHOW_SB) )
+ {
+ // disable scrollbar instead of removing it then
+ info.fMask |= SIF_DISABLENOSCROLL;
+ }
HWND hWnd = GetHwnd();
if ( hWnd )
{
- ::SetScrollRange(hWnd, wOrient, 0, range, FALSE);
- ::SetScrollPos(hWnd, wOrient, pos, refresh);
- }
-#endif
- if ( orient == wxHORIZONTAL ) {
- m_xThumbSize = thumbVisible;
- } else {
- m_yThumbSize = thumbVisible;
+ // 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);
}
}
else
{
pr = NULL;
+
}
+#ifdef __WXWINCE__
+ // FIXME: is this the exact equivalent of the line below?
+ ::ScrollWindowEx(GetHwnd(), dx, dy, pr, pr, 0, 0, SW_SCROLLCHILDREN|SW_ERASE|SW_INVALIDATE);
+#else
::ScrollWindow(GetHwnd(), dx, dy, pr, pr);
+#endif
}
static bool ScrollVertically(HWND hwnd, int kind, int count)
down ? pages : -pages);
}
+// ----------------------------------------------------------------------------
+// RTL support
+// ----------------------------------------------------------------------------
+
+void wxWindowMSW::SetLayoutDirection(wxLayoutDirection dir)
+{
+#ifdef __WXWINCE__
+ wxUnusedVar(dir);
+#else
+ const HWND hwnd = GetHwnd();
+ wxCHECK_RET( hwnd, _T("layout direction must be set after window creation") );
+
+ LONG styleOld = ::GetWindowLong(hwnd, GWL_EXSTYLE);
+
+ LONG styleNew = styleOld;
+ switch ( dir )
+ {
+ case wxLayout_LeftToRight:
+ styleNew &= ~WS_EX_LAYOUTRTL;
+ break;
+
+ case wxLayout_RightToLeft:
+ styleNew |= WS_EX_LAYOUTRTL;
+ break;
+
+ default:
+ wxFAIL_MSG(_T("unsupported layout direction"));
+ break;
+ }
+
+ if ( styleNew != styleOld )
+ {
+ ::SetWindowLong(hwnd, GWL_EXSTYLE, styleNew);
+ }
+#endif
+}
+
+wxLayoutDirection wxWindowMSW::GetLayoutDirection() const
+{
+#ifdef __WXWINCE__
+ return wxLayout_Default;
+#else
+ const HWND hwnd = GetHwnd();
+ wxCHECK_MSG( hwnd, wxLayout_Default, _T("invalid window") );
+
+ return ::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL
+ ? wxLayout_RightToLeft
+ : wxLayout_LeftToRight;
+#endif
+}
+
+wxCoord
+wxWindowMSW::AdjustForLayoutDirection(wxCoord x,
+ wxCoord WXUNUSED(width),
+ wxCoord WXUNUSED(widthTotal)) const
+{
+ // Win32 mirrors the coordinates of RTL windows automatically, so don't
+ // redo it ourselves
+ return x;
+}
+
// ---------------------------------------------------------------------------
// subclassing
// ---------------------------------------------------------------------------
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) )
{
- ::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
+ // don't bother restoring it either: this also makes it easy to
+ // implement IsOfStandardClass() method which returns true for the
+ // standard controls and false for the wxWidgets own windows as it can
// simply check m_oldWndProc
m_oldWndProc = NULL;
}
-}
+
+ // we're officially created now, send the event
+ wxWindowCreateEvent event((wxWindow *)this);
+ (void)GetEventHandler()->ProcessEvent(event);
+}
void wxWindowMSW::UnsubclassWin()
{
HWND hwnd = GetHwnd();
if ( hwnd )
{
- m_hWnd = 0;
+ SetHWND(0);
wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in UnsubclassWin") );
{
if ( !wxCheckWindowWndProc((WXHWND)hwnd, m_oldWndProc) )
{
- ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) m_oldWndProc);
+ wxSetWindowProc(hwnd, (WNDPROC)m_oldWndProc);
}
m_oldWndProc = NULL;
}
}
-bool wxCheckWindowWndProc(WXHWND hWnd, WXFARPROC wndProc)
+void wxWindowMSW::AssociateHandle(WXWidget handle)
{
- // Unicows note: the code below works, but only because WNDCLASS contains
- // original window handler rather that the unicows fake one. This may not
- // be on purpose, though; if it stops working with future versions of
- // 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.
- WNDCLASS cls;
- if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd), &cls) )
+ if ( m_hWnd )
{
- wxLogLastError(_T("GetClassInfo"));
-
- return FALSE;
+ if ( !::DestroyWindow(GetHwnd()) )
+ wxLogLastError(wxT("DestroyWindow"));
}
- return wndProc == (WXFARPROC)cls.lpfnWndProc;
+ WXHWND wxhwnd = (WXHWND)handle;
+
+ SetHWND(wxhwnd);
+ SubclassWin(wxhwnd);
+}
+
+void wxWindowMSW::DissociateHandle()
+{
+ // this also calls SetHWND(0) for us
+ UnsubclassWin();
+}
+
+
+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()
+
+#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;
}
// ----------------------------------------------------------------------------
// update the internal variable
wxWindowBase::SetWindowStyleFlag(flags);
+ // and the real window flags
+ MSWUpdateStyle(flagsOld, GetExtraStyle());
+}
+
+void wxWindowMSW::SetExtraStyle(long exflags)
+{
+ long exflagsOld = GetExtraStyle();
+ if ( exflags == exflagsOld )
+ return;
+
+ // update the internal variable
+ wxWindowBase::SetExtraStyle(exflags);
+
+ // and the real window flags
+ MSWUpdateStyle(GetWindowStyleFlag(), exflagsOld);
+}
+
+void wxWindowMSW::MSWUpdateStyle(long flagsOld, long exflagsOld)
+{
// now update the Windows style as well if needed - and if the window had
// been already created
if ( !GetHwnd() )
return;
- WXDWORD exstyle, exstyleOld;
- long style = MSWGetStyle(flags, &exstyle),
- styleOld = MSWGetStyle(flagsOld, &exstyleOld);
+ // we may need to call SetWindowPos() when we change some styles
+ bool callSWP = false;
+
+ WXDWORD exstyle;
+ long style = MSWGetStyle(GetWindowStyleFlag(), &exstyle);
+
+ // this is quite a horrible hack but we need it because MSWGetStyle()
+ // doesn't take exflags as parameter but uses GetExtraStyle() internally
+ // and so we have to modify the window exflags temporarily to get the
+ // correct exstyleOld
+ long exflagsNew = GetExtraStyle();
+ wxWindowBase::SetExtraStyle(exflagsOld);
+
+ WXDWORD exstyleOld;
+ long styleOld = MSWGetStyle(flagsOld, &exstyleOld);
+
+ wxWindowBase::SetExtraStyle(exflagsNew);
+
if ( style != styleOld )
{
styleReal |= style;
::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal);
+
+ // we need to call SetWindowPos() if any of the styles affecting the
+ // frame appearance have changed
+ callSWP = ((styleOld ^ style ) & (WS_BORDER |
+ WS_THICKFRAME |
+ WS_CAPTION |
+ WS_DLGFRAME |
+ WS_MAXIMIZEBOX |
+ WS_MINIMIZEBOX |
+ WS_SYSMENU) ) != 0;
}
// and the extended style
+ long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
+
if ( exstyle != exstyleOld )
{
- long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
exstyleReal &= ~exstyleOld;
exstyleReal |= exstyle;
::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal);
- // we must call SetWindowPos() to flash the cached extended style and
+ // ex style changes don't take effect without calling SetWindowPos
+ callSWP = true;
+ }
+
+ if ( callSWP )
+ {
+ // we must call SetWindowPos() to flush the cached extended style and
// also to make the change to wxSTAY_ON_TOP style take effect: just
// setting the style simply doesn't work
if ( !::SetWindowPos(GetHwnd(),
exstyleReal & WS_EX_TOPMOST ? HWND_TOPMOST
: HWND_NOTOPMOST,
0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE) )
+ SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED) )
{
wxLogLastError(_T("SetWindowPos"));
}
WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
{
- // translate the style
+ // translate common wxWidgets styles to Windows ones
+
+ // most of windows are child ones, those which are not (such as
+ // wxTopLevelWindow) should remove WS_CHILD in their MSWGetStyle()
WXDWORD style = WS_CHILD;
- if ( flags & wxCLIP_CHILDREN )
+ // using this flag results in very significant reduction in flicker,
+ // especially with controls inside the static boxes (as the interior of the
+ // box is not redrawn twice), but sometimes results in redraw problems, so
+ // optionally allow the old code to continue to use it provided a special
+ // system option is turned on
+ if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children"))
+ || (flags & wxCLIP_CHILDREN) )
style |= WS_CLIPCHILDREN;
- if ( flags & wxCLIP_SIBLINGS )
- style |= WS_CLIPSIBLINGS;
+ // it doesn't seem useful to use WS_CLIPSIBLINGS here as we officially
+ // don't support overlapping windows and it only makes sense for them and,
+ // presumably, gives the system some extra work (to manage more clipping
+ // regions), so avoid it alltogether
- wxBorder border = (wxBorder)(flags & wxBORDER_MASK);
- if ( border != wxBORDER_NONE && border != wxBORDER_DEFAULT )
+
+ 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
{
*exstyle = 0;
+#ifndef __WXWINCE__
if ( flags & wxTRANSPARENT_WINDOW )
*exstyle |= WS_EX_TRANSPARENT;
+#endif
- switch ( flags & wxBORDER_MASK )
+ 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:
break;
case wxBORDER_RAISED:
- *exstyle |= WS_EX_WINDOWEDGE;
+ *exstyle |= WS_EX_DLGMODALFRAME;
break;
case wxBORDER_SUNKEN:
*exstyle |= WS_EX_CLIENTEDGE;
+ style &= ~WS_BORDER;
break;
case wxBORDER_DOUBLE:
}
// 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;
}
-// Make a Windows extended style from the given wxWindows window style
-WXDWORD wxWindowMSW::MakeExtendedStyle(long style, bool eliminateBorders)
-{
- WXDWORD exStyle = 0;
- if ( style & wxTRANSPARENT_WINDOW )
- exStyle |= WS_EX_TRANSPARENT;
-
- if ( !eliminateBorders )
- {
- if ( style & wxSUNKEN_BORDER )
- exStyle |= WS_EX_CLIENTEDGE;
- if ( style & wxDOUBLE_BORDER )
- exStyle |= WS_EX_DLGMODALFRAME;
-#if defined(__WIN95__)
- if ( style & wxRAISED_BORDER )
- // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
- exStyle |= WS_EX_DLGMODALFRAME; /* WS_EX_WINDOWEDGE */;
- if ( style & wxSTATIC_BORDER )
- exStyle |= WS_EX_STATICEDGE;
-#endif
- }
-
- return exStyle;
-}
-
-// Determines whether native 3D effects or CTL3D should be used,
-// applying a default border style if required, and returning an extended
-// style to pass to CreateWindowEx.
-WXDWORD wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle,
- bool *want3D) const
-{
- // If matches certain criteria, then assume no 3D effects
- // unless specifically requested (dealt with in MakeExtendedStyle)
- if ( !GetParent()
-#if wxUSE_CONTROLS
- || !IsKindOf(CLASSINFO(wxControl))
-#endif // wxUSE_CONTROLS
- || (m_windowStyle & wxNO_BORDER) )
- {
- *want3D = FALSE;
- return MakeExtendedStyle(m_windowStyle);
- }
-
- // Determine whether we should be using 3D effects or not.
- bool nativeBorder = FALSE; // by default, we don't want a Win95 effect
-
- // 1) App can specify global 3D effects
- *want3D = wxTheApp->GetAuto3D();
-
- // 2) If the parent is being drawn with user colours, or simple border specified,
- // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
- if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS) || (m_windowStyle & wxSIMPLE_BORDER) )
- *want3D = FALSE;
-
- // 3) Control can override this global setting by defining
- // a border style, e.g. wxSUNKEN_BORDER
- if ( m_windowStyle & wxSUNKEN_BORDER )
- *want3D = TRUE;
-
- // 4) If it's a special border, CTL3D can't cope so we want a native border
- if ( (m_windowStyle & wxDOUBLE_BORDER) || (m_windowStyle & wxRAISED_BORDER) ||
- (m_windowStyle & wxSTATIC_BORDER) )
- {
- *want3D = TRUE;
- nativeBorder = TRUE;
- }
-
- // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
- // effects from extended style
-#if wxUSE_CTL3D
- if ( *want3D )
- nativeBorder = FALSE;
-#endif
-
- DWORD exStyle = MakeExtendedStyle(m_windowStyle, !nativeBorder);
-
- // If we want 3D, but haven't specified a border here,
- // apply the default border style specified.
- // TODO what about non-Win95 WIN32? Does it have borders?
-#if defined(__WIN95__) && !wxUSE_CTL3D
- if ( defaultBorderStyle && (*want3D) && ! ((m_windowStyle & wxDOUBLE_BORDER) || (m_windowStyle & wxRAISED_BORDER ) ||
- (m_windowStyle & wxSTATIC_BORDER) || (m_windowStyle & wxSIMPLE_BORDER) ))
- exStyle |= defaultBorderStyle; // WS_EX_CLIENTEDGE;
-#endif
-
- return exStyle;
-}
-
-#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()
{
{
// get the mouse position
POINT pt;
+#ifdef __WXWINCE__
+ ::GetCursorPosWinCE(&pt);
+#else
::GetCursorPos(&pt);
+#endif
// find the window which currently has the cursor and go up the window
// chain until we find this window - or exhaust it
return hwnd != NULL;
}
-void wxWindowMSW::OnIdle(wxIdleEvent& WXUNUSED(event))
+void wxWindowMSW::OnInternalIdle()
{
+#ifndef HAVE_TRACKMOUSEEVENT
// Check if we need to send a LEAVE event
if ( m_mouseInWindow )
{
// or doesn't have mouse capture
if ( !IsMouseInWindow() )
{
- // Generate a LEAVE event
- m_mouseInWindow = FALSE;
-
- // Unfortunately the mouse button and keyboard state may have
- // changed by the time the OnIdle function is called, so 'state'
- // may be meaningless.
- 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);
+ GenerateMouseLeave();
}
}
+#endif // !HAVE_TRACKMOUSEEVENT
- 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);
+ if ( !m_frozenness++ )
+ {
+ if ( IsShown() )
+ SendSetRedraw(GetHwnd(), false);
+ }
}
void wxWindowMSW::Thaw()
{
- SendSetRedraw(GetHwnd(), TRUE);
+ wxASSERT_MSG( m_frozenness > 0, _T("Thaw() without matching Freeze()") );
- // we need to refresh everything or otherwise he invalidated area is not
- // repainted
- Refresh();
+ if ( --m_frozenness == 0 )
+ {
+ if ( IsShown() )
+ {
+ SendSetRedraw(GetHwnd(), true);
+
+ // 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)
HWND hWnd = GetHwnd();
if ( hWnd )
{
+ RECT mswRect;
+ const RECT *pRect;
if ( rect )
{
- RECT mswRect;
mswRect.left = rect->x;
mswRect.top = rect->y;
mswRect.right = rect->x + rect->width;
mswRect.bottom = rect->y + rect->height;
- ::InvalidateRect(hWnd, &mswRect, eraseBack);
+ pRect = &mswRect;
}
else
- ::InvalidateRect(hWnd, NULL, eraseBack);
+ {
+ pRect = NULL;
+ }
+
+ // RedrawWindow not available on SmartPhone or eVC++ 3
+#if !defined(__SMARTPHONE__) && !(defined(_WIN32_WCE) && _WIN32_WCE < 400)
+ UINT flags = RDW_INVALIDATE | RDW_ALLCHILDREN;
+ if ( eraseBack )
+ flags |= RDW_ERASE;
+
+ ::RedrawWindow(hWnd, pRect, NULL, flags);
+#else
+ ::InvalidateRect(hWnd, pRect, eraseBack);
+#endif
}
}
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();
// drag and drop
// ---------------------------------------------------------------------------
-#if wxUSE_DRAG_AND_DROP
+#if wxUSE_DRAG_AND_DROP || !defined(__WXWINCE__)
+
+#if wxUSE_STATBOX
+
+// we need to lower the sibling static boxes so controls contained within can be
+// a drop target
+static void AdjustStaticBoxZOrder(wxWindow *parent)
+{
+ // no sibling static boxes if we have no parent (ie TLW)
+ if ( !parent )
+ return;
+
+ for ( wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ wxStaticBox *statbox = wxDynamicCast(node->GetData(), wxStaticBox);
+ if ( statbox )
+ {
+ ::SetWindowPos(GetHwndOf(statbox), HWND_BOTTOM, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ }
+ }
+}
+
+#else // !wxUSE_STATBOX
+
+static inline void AdjustStaticBoxZOrder(wxWindow * WXUNUSED(parent))
+{
+}
+#endif // wxUSE_STATBOX/!wxUSE_STATBOX
+
+#endif // drag and drop is used
+
+#if wxUSE_DRAG_AND_DROP
void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
{
if ( m_dropTarget != 0 ) {
m_dropTarget = pDropTarget;
if ( m_dropTarget != 0 )
+ {
+ AdjustStaticBoxZOrder(GetParent());
m_dropTarget->Register(m_hWnd);
+ }
}
-
#endif // wxUSE_DRAG_AND_DROP
-// old style file-manager drag&drop support: we retain the old-style
+// old-style file manager drag&drop support: we retain the old-style
// DragAcceptFiles in parallel with SetDropTarget.
-void wxWindowMSW::DragAcceptFiles(bool accept)
+void wxWindowMSW::DragAcceptFiles(bool WXUNUSED_IN_WINCE(accept))
{
+#ifndef __WXWINCE__
HWND hWnd = GetHwnd();
if ( hWnd )
+ {
+ AdjustStaticBoxZOrder(GetParent());
::DragAcceptFiles(hWnd, (BOOL)accept);
+ }
+#endif
}
// ----------------------------------------------------------------------------
// moving and resizing
// ---------------------------------------------------------------------------
+bool wxWindowMSW::IsSizeDeferred() const
+{
+#if USE_DEFERRED_SIZING
+ if ( m_pendingPosition != wxDefaultPosition ||
+ m_pendingSize != wxDefaultSize )
+ return true;
+#endif // USE_DEFERRED_SIZING
+
+ return false;
+}
+
// Get total size
void wxWindowMSW::DoGetSize(int *x, int *y) const
{
- RECT rect = wxGetWindowRect(GetHwnd());
+#if USE_DEFERRED_SIZING
+ // if SetSize() had been called at wx level but not realized at Windows
+ // level yet (i.e. EndDeferWindowPos() not called), we still should return
+ // the new and not the old position to the other wx code
+ if ( m_pendingSize != wxDefaultSize )
+ {
+ if ( x )
+ *x = m_pendingSize.x;
+ if ( y )
+ *y = m_pendingSize.y;
+ }
+ else // use current size
+#endif // USE_DEFERRED_SIZING
+ {
+ RECT rect = wxGetWindowRect(GetHwnd());
- if ( x )
- *x = rect.right - rect.left;
- if ( y )
- *y = rect.bottom - rect.top;
+ if ( x )
+ *x = rect.right - rect.left;
+ if ( y )
+ *y = rect.bottom - rect.top;
+ }
}
// Get size *available for subwindows* i.e. excluding menu bar etc.
void wxWindowMSW::DoGetClientSize(int *x, int *y) const
{
- RECT rect = wxGetClientRect(GetHwnd());
+#if USE_DEFERRED_SIZING
+ if ( m_pendingSize != wxDefaultSize )
+ {
+ // we need to calculate the client size corresponding to pending size
+ RECT rect;
+ rect.left = m_pendingPosition.x;
+ rect.top = m_pendingPosition.y;
+ rect.right = rect.left + m_pendingSize.x;
+ rect.bottom = rect.top + m_pendingSize.y;
- if ( x )
- *x = rect.right;
- if ( y )
- *y = rect.bottom;
+ ::SendMessage(GetHwnd(), WM_NCCALCSIZE, FALSE, (LPARAM)&rect);
+
+ if ( x )
+ *x = rect.right - rect.left;
+ if ( y )
+ *y = rect.bottom - rect.top;
+ }
+ else
+#endif // USE_DEFERRED_SIZING
+ {
+ RECT rect = wxGetClientRect(GetHwnd());
+
+ if ( x )
+ *x = rect.right;
+ if ( y )
+ *y = rect.bottom;
+ }
}
void wxWindowMSW::DoGetPosition(int *x, int *y) const
{
- RECT rect = wxGetWindowRect(GetHwnd());
-
- POINT point;
- point.x = rect.left;
- point.y = rect.top;
+ wxWindow * const parent = GetParent();
- // we do the adjustments with respect to the parent only for the "real"
- // children, not for the dialogs/frames
- if ( !IsTopLevel() )
+ wxPoint pos;
+ if ( m_pendingPosition != wxDefaultPosition )
{
- HWND hParentWnd = 0;
- wxWindow *parent = GetParent();
- if ( parent )
- hParentWnd = GetWinHwnd(parent);
+ pos = m_pendingPosition;
+ }
+ else // use current position
+ {
+ RECT rect = wxGetWindowRect(GetHwnd());
- // Since we now have the absolute screen coords, if there's a parent we
- // must subtract its top left corner
- if ( hParentWnd )
- {
- ::ScreenToClient(hParentWnd, &point);
- }
+ POINT point;
+ point.x = rect.left;
+ point.y = rect.top;
- if ( parent )
+ // we do the adjustments with respect to the parent only for the "real"
+ // children, not for the dialogs/frames
+ if ( !IsTopLevel() )
{
- // We may be faking the client origin. So a window that's really at (0,
- // 30) may appear (to wxWin apps) to be at (0, 0).
- wxPoint pt(parent->GetClientAreaOrigin());
- point.x -= pt.x;
- point.y -= pt.y;
+ if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
+ {
+ // In RTL mode, we want the logical left x-coordinate,
+ // which would be the physical right x-coordinate.
+ point.x = rect.right;
+ }
+
+ // Since we now have the absolute screen coords, if there's a
+ // parent we must subtract its top left corner
+ if ( parent )
+ {
+ ::ScreenToClient(GetHwndOf(parent), &point);
+ }
}
+
+ pos.x = point.x;
+ pos.y = point.y;
+ }
+
+ // we also must adjust by the client area offset: a control which is just
+ // under a toolbar could be at (0, 30) in Windows but at (0, 0) in wx
+ if ( parent && !IsTopLevel() )
+ {
+ const wxPoint pt(parent->GetClientAreaOrigin());
+ pos.x -= pt.x;
+ pos.y -= pt.y;
}
if ( x )
- *x = point.x;
+ *x = pos.x;
if ( y )
- *y = point.y;
+ *y = pos.y;
}
void wxWindowMSW::DoScreenToClient(int *x, int *y) const
*y = pt.y;
}
+bool
+wxWindowMSW::DoMoveSibling(WXHWND hwnd, int x, int y, int width, int height)
+{
+#if USE_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();
+
+ HDWP hdwp = parent ? (HDWP)parent->m_hDWP : NULL;
+ if ( hdwp )
+ {
+ hdwp = ::DeferWindowPos(hdwp, (HWND)hwnd, NULL, x, y, width, height,
+ SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
+ if ( !hdwp )
+ {
+ wxLogLastError(_T("DeferWindowPos"));
+ }
+ }
+
+ if ( parent )
+ {
+ // hdwp must be updated as it may have been changed
+ parent->m_hDWP = (WXHANDLE)hdwp;
+ }
+
+ if ( hdwp )
+ {
+ // did deferred move, remember new coordinates of the window as they're
+ // different from what Windows would return for it
+ return true;
+ }
+
+ // otherwise (or if deferring failed) move the window in place immediately
+#endif // USE_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,
+ // ignored otherwise
+ return false;
+}
+
void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
{
// TODO: is this consistent with other platforms?
width = 0;
if (height < 0)
height = 0;
- if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) )
+
+ if ( DoMoveSibling(m_hWnd, x, y, width, height) )
{
- wxLogLastError(wxT("MoveWindow"));
+#if USE_DEFERRED_SIZING
+ m_pendingPosition = wxPoint(x, y);
+ m_pendingSize = wxSize(width, height);
+#endif // USE_DEFERRED_SIZING
}
}
{
// get the current size and position...
int currentX, currentY;
+ int currentW, currentH;
+
GetPosition(¤tX, ¤tY);
- int currentW,currentH;
GetSize(¤tW, ¤tH);
- // ... and don't do anything (avoiding flicker) if it's already ok
+ // ... and don't do anything (avoiding flicker) if it's already ok unless
+ // we're forced to resize the window
if ( x == currentX && y == currentY &&
- width == currentW && height == currentH )
+ width == currentW && height == currentH &&
+ !(sizeFlags & wxSIZE_FORCE) )
{
return;
}
- if ( x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
+ if ( x == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
x = currentX;
- if ( y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
+ if ( y == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
y = currentY;
AdjustForParentClientOrigin(x, y, sizeFlags);
- wxSize size(-1, -1);
- if ( width == -1 )
+ wxSize size = wxDefaultSize;
+ if ( width == wxDefaultCoord )
{
if ( sizeFlags & wxSIZE_AUTO_WIDTH )
{
}
}
- if ( height == -1 )
+ if ( height == wxDefaultCoord )
{
if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
{
- if ( size.x == -1 )
+ if ( size.x == wxDefaultCoord )
{
size = DoGetBestSize();
}
void wxWindowMSW::DoSetClientSize(int width, int height)
{
- // setting the client size is less obvious than it it could have been
+ // setting the client size is less obvious than it could have been
// because in the result of changing the total size the window scrollbar
- // may [dis]appear and/or its menubar may [un]wrap and so the client size
- // will not be correct as the difference between the total and client size
- // changes - so we keep changing it until we get it right
+ // may [dis]appear and/or its menubar may [un]wrap (and AdjustWindowRect()
+ // doesn't take neither into account) and so the client size will not be
+ // correct as the difference between the total and client size changes --
+ // so we keep changing it until we get it right
//
// normally this loop shouldn't take more than 3 iterations (usually 1 but
// if scrollbars [dis]appear as the result of the first call, then 2 and it
RECT rectClient;
::GetClientRect(GetHwnd(), &rectClient);
- // if the size is already ok, stop here (rectClient.left = top = 0)
- if ( (rectClient.right == width || width == -1) &&
- (rectClient.bottom == height || height == -1) )
+ // if the size is already ok, stop here (NB: rectClient.left = top = 0)
+ if ( (rectClient.right == width || width == wxDefaultCoord) &&
+ (rectClient.bottom == height || height == wxDefaultCoord) )
{
break;
}
- int widthClient = width,
- heightClient = height;
-
// Find the difference between the entire window (title bar and all)
// and the client area; add this to the new client size to move the
// window
RECT rectWin;
::GetWindowRect(GetHwnd(), &rectWin);
- widthClient += rectWin.right - rectWin.left - rectClient.right;
- heightClient += rectWin.bottom - rectWin.top - rectClient.bottom;
-
- POINT point;
- point.x = rectWin.left;
- point.y = rectWin.top;
+ const int widthWin = rectWin.right - rectWin.left,
+ heightWin = rectWin.bottom - rectWin.top;
// MoveWindow positions the child windows relative to the parent, so
// adjust if necessary
wxWindow *parent = GetParent();
if ( parent )
{
- ::ScreenToClient(GetHwndOf(parent), &point);
+ ::ScreenToClient(GetHwndOf(parent), (POINT *)&rectWin);
}
}
- DoMoveWindow(point.x, point.y, widthClient, heightClient);
+ // don't call DoMoveWindow() because we want to move window immediately
+ // and not defer it here as otherwise the value returned by
+ // GetClient/WindowRect() wouldn't change as the window wouldn't be
+ // really resized
+ if ( !::MoveWindow(GetHwnd(),
+ rectWin.left,
+ rectWin.top,
+ width + widthWin - rectClient.right,
+ height + heightWin - rectClient.bottom,
+ TRUE) )
+ {
+ wxLogLastError(_T("MoveWindow"));
+ }
}
}
-// For implementation purposes - sometimes decorations make the client area
-// smaller
-wxPoint wxWindowMSW::GetClientAreaOrigin() const
-{
- return wxPoint(0, 0);
-}
-
// ---------------------------------------------------------------------------
// text metrics
// ---------------------------------------------------------------------------
int *descent, int *externalLeading,
const wxFont *theFont) const
{
- const wxFont *fontToUse = theFont;
- if ( !fontToUse )
- fontToUse = &m_font;
+ wxASSERT_MSG( !theFont || theFont->Ok(),
+ _T("invalid font in GetTextExtent()") );
- HWND hWnd = GetHwnd();
- HDC dc = ::GetDC(hWnd);
+ wxFont fontToUse;
+ if (theFont)
+ fontToUse = *theFont;
+ else
+ fontToUse = GetFont();
- HFONT fnt = 0;
- HFONT hfontOld = 0;
- if ( fontToUse && fontToUse->Ok() )
- {
- fnt = (HFONT)((wxFont *)fontToUse)->GetResourceHandle(); // const_cast
- if ( fnt )
- hfontOld = (HFONT)SelectObject(dc,fnt);
- }
+ WindowHDC hdc(GetHwnd());
+ SelectInHDC selectFont(hdc, GetHfontOf(fontToUse));
SIZE sizeRect;
TEXTMETRIC tm;
- GetTextExtentPoint(dc, string, (int)string.Length(), &sizeRect);
- GetTextMetrics(dc, &tm);
-
- if ( fontToUse && fnt && hfontOld )
- SelectObject(dc, hfontOld);
-
- ReleaseDC(hWnd, dc);
+ ::GetTextExtentPoint32(hdc, string, string.length(), &sizeRect);
+ GetTextMetrics(hdc, &tm);
if ( x )
*x = sizeRect.cx;
*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;
+ }
+
+ // 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);
}
-
- // If we retrieved a WM_QUIT, insert back into the message queue.
- if (msg.message == WM_QUIT)
- ::PostQuitMessage(0);
}
bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y)
menu->SetInvokingWindow(this);
menu->UpdateUI();
+ if ( x == wxDefaultCoord && y == wxDefaultCoord )
+ {
+ wxPoint mouse = ScreenToClient(wxGetMousePosition());
+ x = mouse.x; y = mouse.y;
+ }
+
HWND hWnd = GetHwnd();
HMENU hMenu = GetHmenuOf(menu);
POINT point;
point.y = y;
::ClientToScreen(hWnd, &point);
wxCurrentPopupMenu = menu;
- ::TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL);
+#if defined(__WXWINCE__)
+ UINT flags = 0;
+#else
+ UINT flags = TPM_RIGHTBUTTON | TPM_RECURSE;
+#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
+ // we need to do it right now as otherwise the events are never going to be
// sent to wxCurrentPopupMenu from HandleCommand()
//
// note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
menu->SetInvokingWindow(NULL);
- return TRUE;
+ return true;
}
#endif // wxUSE_MENUS_NATIVE
// pre/post message processing
// ===========================================================================
-long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
+WXLRESULT wxWindowMSW::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{
if ( m_oldWndProc )
return ::CallWindowProc(CASTWNDPROC m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
// here we try to do all the job which ::IsDialogMessage() usually does
// internally
-#if 1
if ( msg->message == WM_KEYDOWN )
{
bool bCtrlDown = wxIsCtrlDown();
// WM_GETDLGCODE: ask the control if it wants the key for itself,
// don't process it if it's the case (except for Ctrl-Tab/Enter
// combinations which are always processed)
- LONG lDlgCode = 0;
- if ( !bCtrlDown )
- {
- lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0);
+ LONG lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0);
- // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the
- // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically,
- // it, of course, implies them
- if ( lDlgCode & DLGC_WANTALLKEYS )
- {
- lDlgCode |= DLGC_WANTTAB | DLGC_WANTARROWS;
- }
+ // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the
+ // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically,
+ // it, of course, implies them
+ if ( lDlgCode & DLGC_WANTALLKEYS )
+ {
+ lDlgCode |= DLGC_WANTTAB | DLGC_WANTARROWS;
}
- bool bForward = TRUE,
- bWindowChange = FALSE;
+ bool bForward = true,
+ bWindowChange = false,
+ bFromTab = 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
bWindowChange = bCtrlDown;
bForward = !bShiftDown;
+ bFromTab = true;
}
break;
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_RETURN:
- {
+ case VK_PRIOR:
+ bForward = false;
+ // fall through
+
+ case VK_NEXT:
+ // we treat PageUp/Dn as arrows because chances are that
+ // a control which needs arrows also needs them for
+ // navigation (e.g. wxTextCtrl, wxListCtrl, ...)
+ if ( (lDlgCode & DLGC_WANTARROWS) || !bCtrlDown )
+ bProcess = false;
+ else
+ bWindowChange = true;
+ break;
+
+ case VK_RETURN:
+ {
if ( (lDlgCode & DLGC_WANTMESSAGE) && !bCtrlDown )
{
// control wants to process Enter itself, don't
- // call IsDialogMessage() which would interpret
- // it
- return FALSE;
+ // call IsDialogMessage() which would consume it
+ return false;
}
- else if ( lDlgCode & DLGC_BUTTON )
+
+#if wxUSE_BUTTON
+ // currently active button should get enter press even
+ // if there is a default button elsewhere so check if
+ // this window is a button first
+ wxWindow *btn = NULL;
+ if ( lDlgCode & DLGC_DEFPUSHBUTTON )
{
// let IsDialogMessage() handle this for all
// buttons except the owner-drawn ones which it
if ( (style & BS_OWNERDRAW) == BS_OWNERDRAW )
{
// emulate the button click
- wxWindow *btn = wxFindWinFromHandle((WXHWND)msg->hwnd);
- if ( btn )
- btn->MSWCommand(BN_CLICKED, 0 /* unused */);
+ btn = wxFindWinFromHandle((WXHWND)msg->hwnd);
}
- bProcess = FALSE;
+ bProcess = false;
}
- // FIXME: this should be handled by
- // wxNavigationKeyEvent handler and not here!!
- else
+ else // not a button itself, do we have default button?
{
-#if wxUSE_BUTTON
- wxButton *btn = wxDynamicCast(GetDefaultItem(),
- wxButton);
- if ( btn && btn->IsEnabled() )
- {
- // if we do have a default button, do press it
- btn->MSWCommand(BN_CLICKED, 0 /* unused */);
-
- return TRUE;
- }
- else // no default button
+ wxTopLevelWindow *
+ tlw = wxDynamicCast(wxGetTopLevelParent(this),
+ wxTopLevelWindow);
+ if ( tlw )
{
-#endif // wxUSE_BUTTON
- // this is a quick and dirty test for a text
- // control
- if ( !(lDlgCode & DLGC_HASSETSEL) )
- {
- // don't process Enter, the control might
- // need it for itself and don't let
- // ::IsDialogMessage() have it as it can
- // eat the Enter events sometimes
- return FALSE;
- }
- else if (!IsTopLevel())
- {
- // if not a top level window, let parent
- // handle it
- return FALSE;
- }
- //else: treat Enter as TAB: pass to the next
- // control as this is the best thing to do
- // if the text doesn't handle Enter itself
+ btn = wxDynamicCast(tlw->GetDefaultItem(),
+ wxButton);
}
}
+
+ if ( btn && btn->IsEnabled() )
+ {
+ btn->MSWCommand(BN_CLICKED, 0 /* unused */);
+ return true;
+ }
+
+#endif // wxUSE_BUTTON
+
+#ifdef __WXWINCE__
+ // map Enter presses into button presses on PDAs
+ wxJoystickEvent event(wxEVT_JOY_BUTTON_DOWN);
+ event.SetEventObject(this);
+ if ( GetEventHandler()->ProcessEvent(event) )
+ return true;
+#endif // __WXWINCE__
}
break;
default:
- bProcess = FALSE;
+ bProcess = false;
}
if ( bProcess )
wxNavigationKeyEvent event;
event.SetDirection(bForward);
event.SetWindowChange(bWindowChange);
+ event.SetFromTab(bFromTab);
event.SetEventObject(this);
if ( GetEventHandler()->ProcessEvent(event) )
{
- return TRUE;
- }
- }
- }
-#else // 0
- // let ::IsDialogMessage() do almost everything and handle just the
- // things it doesn't here: Ctrl-TAB for switching notebook pages
- if ( msg->message == WM_KEYDOWN )
- {
- // don't process system keys here
- if ( !(HIWORD(msg->lParam) & KF_ALTDOWN) )
- {
- if ( (msg->wParam == VK_TAB) && wxIsCtrlDown() )
- {
- // find the first notebook parent and change its page
- wxWindow *win = this;
- wxNotebook *nbook = NULL;
- while ( win && !nbook )
- {
- nbook = wxDynamicCast(win, wxNotebook);
- win = win->GetParent();
- }
-
- if ( nbook )
- {
- bool forward = !wxIsShiftDown();
+ // as we don't call IsDialogMessage(), which would take of
+ // this by default, we need to manually send this message
+ // so that controls can change their UI state if needed
+ MSWUpdateUIState(UIS_CLEAR, UISF_HIDEFOCUS);
- nbook->AdvanceSelection(forward);
- }
+ 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
- // 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;
-
- HWND hwndFocus = ::GetFocus();
- while ( hwndFocus )
- {
- if ( !::IsWindowEnabled(hwndFocus) ||
- !::IsWindowVisible(hwndFocus) )
- {
- // it would enter an infinite loop if we do this!
- canSafelyCallIsDlgMsg = FALSE;
-
- 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);
- }
-
- if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) )
- {
- // IsDialogMessage() did something...
- return TRUE;
- }
+ if ( ::IsDialogMessage(GetHwnd(), msg) )
+ {
+ // IsDialogMessage() did something...
+ return true;
}
}
#endif // __WXUNIVERSAL__
// relay mouse move events to the tooltip control
MSG *msg = (MSG *)pMsg;
if ( msg->message == WM_MOUSEMOVE )
- m_tooltip->RelayEvent(pMsg);
+ wxToolTip::RelayEvent(pMsg);
}
#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))
+bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG* msg)
{
- // preprocess all messages by default
- return TRUE;
+ // all tests below have to deal with various bugs/misfeatures of
+ // IsDialogMessage(): we have to prevent it from being called from our
+ // MSWProcessMessage() in some situations
+
+ // 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 )
+ {
+ return false;
+ }
+
+ // ::IsDialogMessage() is broken and may sometimes hang the application by
+ // going into an infinite loop when it tries to find the control to give
+ // focus to when Alt-<key> is pressed, so we try to detect [some of] the
+ // situations when this may happen and not call it then
+ if ( msg->message != WM_SYSCHAR )
+ return true;
+
+ // assume we can call it by default
+ bool canSafelyCallIsDlgMsg = true;
+
+ HWND hwndFocus = ::GetFocus();
+
+ // 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 )
+ {
+ // pessimistic by default
+ canSafelyCallIsDlgMsg = false;
+ for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ wxWindow * const win = node->GetData();
+ if ( win->AcceptsFocus() &&
+ !(::GetWindowLong(GetHwndOf(win), GWL_EXSTYLE) &
+ WS_EX_CONTROLPARENT) )
+ {
+ // it shouldn't hang...
+ canSafelyCallIsDlgMsg = true;
+
+ break;
+ }
+ }
+ }
+#endif // !__WXWINCE__
+
+ 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 )
+ {
+ if ( !::IsWindowEnabled(hwndFocus) ||
+ !::IsWindowVisible(hwndFocus) )
+ {
+ // it would enter an infinite loop if we do this!
+ canSafelyCallIsDlgMsg = false;
+
+ 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);
+ }
+ }
+
+ return canSafelyCallIsDlgMsg;
}
// ---------------------------------------------------------------------------
-// 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)
{
}
void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam,
- WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd)
+ WXHDC *hdc, WXHWND *hwnd)
{
-#ifndef __WXMICROWIN__
- *nCtlColor = CTLCOLOR_BTN;
*hwnd = (WXHWND)lParam;
*hdc = (WXHDC)wParam;
-#endif
}
void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam,
*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
+// Main wxWidgets window proc and the window proc for wxWindow
// ---------------------------------------------------------------------------
// Hook for new window just as it's being created, when the window isn't yet
{
// 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);
LRESULT rc;
- if ( wnd )
+ if ( wnd && wxEventLoop::AllowProcessing(wnd) )
rc = wnd->MSWWindowProc(message, wParam, lParam);
else
rc = ::DefWindowProc(hWnd, message, wParam, lParam);
return rc;
}
-long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
+WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
// did we process the message?
- bool processed = FALSE;
+ bool processed = false;
// the return value
union
{
bool allow;
- long result;
- WXHICON hIcon;
+ WXLRESULT result;
WXHBRUSH hBrush;
} rc;
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!
(void)HandleDestroy();
break;
+ case WM_SIZE:
+ processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
+ break;
+
case WM_MOVE:
processed = HandleMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
- case WM_SIZE:
- switch ( wParam )
+#if !defined(__WXWINCE__)
+ case WM_MOVING:
{
- case SIZE_MAXHIDE:
- case SIZE_MAXSHOW:
- // we're not interested in these messages at all
- break;
-
- case SIZE_MINIMIZED:
- // we shouldn't send sizev events for these messages as the
- // client size may be negative which breaks existing code
- //
- // OTOH we might send another (wxMinimizedEvent?) one or
- // add an additional parameter to wxSizeEvent if this is
- // useful to anybody
- break;
-
- default:
- wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
- // fall through nevertheless
+ 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;
- case SIZE_MAXIMIZED:
- case SIZE_RESTORED:
- processed = HandleSize(LOWORD(lParam), HIWORD(lParam),
- wParam);
+ 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 // !__WXWINCE__
-#ifndef __WXMICROWIN__
+#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
case WM_ACTIVATEAPP:
+ // This implicitly sends a wxEVT_ACTIVATE_APP event
wxTheApp->SetActive(wParam != 0, FindFocus());
break;
#endif
processed = HandleKillFocus((WXHWND)(HWND)wParam);
break;
+ case WM_PRINTCLIENT:
+ processed = HandlePrintClient((WXHDC)wParam);
+ break;
+
case WM_PAINT:
- processed = HandlePaint();
+ if ( wParam )
+ {
+ wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
+
+ processed = HandlePaint();
+ }
+ else // no DC given
+ {
+ processed = HandlePaint();
+ }
break;
case WM_CLOSE:
// Universal uses its own wxFrame/wxDialog, so we don't receive
// close events unless we have this.
Close();
- processed = TRUE;
- rc.result = TRUE;
-#else
+#endif // __WXUNIVERSAL__
+
// don't let the DefWindowProc() destroy our window - we'll do it
// ourselves in ~wxWindow
- processed = TRUE;
+ processed = true;
rc.result = TRUE;
-#endif
break;
case WM_SHOWWINDOW:
wParam);
break;
+#ifdef HAVE_TRACKMOUSEEVENT
+ case WM_MOUSELEAVE:
+ // filter out excess WM_MOUSELEAVE events sent after PopupMenu()
+ // (on XP at least)
+ if ( m_mouseInWindow )
+ {
+ GenerateMouseLeave();
+ }
+
+ // 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. So don't set processed to true here.
+ break;
+#endif // HAVE_TRACKMOUSEEVENT
+
#if wxUSE_MOUSEWHEEL
case WM_MOUSEWHEEL:
processed = HandleMouseWheel(wParam, lParam);
{
if (!win->IsEnabled())
{
- processed = TRUE;
+ processed = true;
break;
}
int x = GET_X_LPARAM(lParam),
y = GET_Y_LPARAM(lParam);
+#ifdef __WXWINCE__
// redirect the event to a static control if necessary by
- // finding one under mouse
+ // finding one under mouse because under CE the static controls
+ // don't generate mouse events (even with SS_NOTIFY)
wxWindowMSW *win;
if ( GetCapture() == this )
{
// this should never happen
wxCHECK_MSG( win, 0,
_T("FindWindowForMouseEvent() returned NULL") );
+ }
+#ifdef __POCKETPC__
+ if (IsContextMenuEnabled() && message == WM_LBUTTONDOWN)
+ {
+ SHRGINFO shrgi = {0};
+ shrgi.cbSize = sizeof(SHRGINFO);
+ shrgi.hwndClient = (HWND) GetHWND();
+ shrgi.ptDown.x = x;
+ shrgi.ptDown.y = y;
+
+ shrgi.dwFlags = SHRG_RETURNCMD;
+ // shrgi.dwFlags = SHRG_NOTIFYPARENT;
+
+ if (GN_CONTEXTMENU == ::SHRecognizeGesture(&shrgi))
+ {
+ wxPoint pt(x, y);
+ pt = ClientToScreen(pt);
+
+ wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
+
+ evtCtx.SetEventObject(this);
+ if (GetEventHandler()->ProcessEvent(evtCtx))
+ {
+ processed = true;
+ return true;
+ }
+ }
+ }
+#endif
+
+#else // !__WXWINCE__
+ wxWindowMSW *win = this;
+#endif // __WXWINCE__/!__WXWINCE__
+
+ processed = win->HandleMouseEvent(message, x, y, wParam);
+
+ // if the app didn't eat the event, handle it in the default
+ // way, that is by giving this window the focus
+ if ( !processed )
+ {
// for the standard classes their WndProc sets the focus to
// them anyhow and doing it from here results in some weird
- // problems, but for our windows we want them to acquire
- // focus when clicked
+ // problems, so don't do it for them (unnecessary anyhow)
if ( !win->IsOfStandardClass() )
{
if ( message == WM_LBUTTONDOWN && win->AcceptsFocus() )
win->SetFocus();
}
}
-
- processed = win->HandleMouseEvent(message, x, y, wParam);
}
break;
break;
#endif // __WXMICROWIN__
- case WM_SYSCOMMAND:
- processed = HandleSysCommand(wParam, lParam);
- break;
-
case WM_COMMAND:
{
WORD id, cmd;
}
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
+ // we only need to reply to WM_NOTIFYFORMAT manually when using MSLU,
+ // otherwise DefWindowProc() does it perfectly fine for us, but MSLU
+ // apparently doesn't always behave properly and needs some help
+#if wxUSE_UNICODE_MSLU && defined(NF_QUERY)
+ case WM_NOTIFYFORMAT:
+ if ( lParam == NF_QUERY )
+ {
+ processed = true;
+ rc.result = NFR_UNICODE;
+ }
+ break;
+#endif // wxUSE_UNICODE_MSLU
+
+ // 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 )
{
switch ( wParam )
{
- // we consider these message "not interesting" to OnChar, so
+ // we consider these messages "not interesting" to OnChar, so
// just don't do anything more with them
case VK_SHIFT:
case VK_CONTROL:
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_SUBTRACT:
case VK_MULTIPLY:
case VK_DIVIDE:
+ case VK_NUMPAD0:
+ case VK_NUMPAD1:
+ case VK_NUMPAD2:
+ case VK_NUMPAD3:
+ case VK_NUMPAD4:
+ case VK_NUMPAD5:
+ case VK_NUMPAD6:
+ case VK_NUMPAD7:
+ case VK_NUMPAD8:
+ case VK_NUMPAD9:
case VK_OEM_1:
case VK_OEM_2:
case VK_OEM_3:
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
// special case of VK_APPS: treat it the same as right mouse
// click because both usually pop up a context menu
case VK_APPS:
- {
- WPARAM flags;
- int x, y;
-
- TranslateKbdEventToMouse(this, &x, &y, &flags);
- processed = HandleMouseEvent(WM_RBUTTONDOWN, x, y, flags);
- }
+ processed = HandleMouseEvent(WM_RBUTTONDOWN, -1, -1, 0);
break;
#endif // VK_APPS
}
}
if (message == WM_SYSKEYDOWN) // Let Windows still handle the SYSKEYs
- processed = FALSE;
+ processed = false;
break;
case WM_SYSKEYUP:
// special case of VK_APPS: treat it the same as right mouse button
if ( wParam == VK_APPS )
{
- WPARAM flags;
- int x, y;
-
- TranslateKbdEventToMouse(this, &x, &y, &flags);
- processed = HandleMouseEvent(WM_RBUTTONUP, x, y, flags);
+ processed = HandleMouseEvent(WM_RBUTTONUP, -1, -1, 0);
}
else
#endif // VK_APPS
// 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:
{
break;
// CTLCOLOR messages are sent by children to query the parent for their
- // colors#ifndef __WXMICROWIN__
+ // colors
#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;
WXHWND hwnd;
- UnpackCtlColor(wParam, lParam, &nCtlColor, &hdc, &hwnd);
-
- processed = HandleCtlColor(&rc.hBrush,
- (WXHDC)hdc,
- (WXHWND)hwnd,
- nCtlColor,
- message,
- wParam,
- lParam);
+ UnpackCtlColor(wParam, lParam, &hdc, &hwnd);
+
+ processed = HandleCtlColor(&rc.hBrush, (WXHDC)hdc, (WXHWND)hwnd);
}
break;
#endif // !__WXMICROWIN__
processed = HandleSysColorChange();
break;
+#if !defined(__WXWINCE__)
case WM_DISPLAYCHANGE:
processed = HandleDisplayChange();
break;
+#endif
case WM_PALETTECHANGED:
processed = HandlePaletteChanged((WXHWND) (HWND) wParam);
processed = HandleCaptureChanged((WXHWND) (HWND) lParam);
break;
+ case WM_SETTINGCHANGE:
+ processed = HandleSettingChange(wParam, lParam);
+ break;
+
case WM_QUERYNEWPALETTE:
processed = HandleQueryNewPalette();
break;
}
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,
}
break;
-#if defined(__WIN32__) && defined(WM_HELP)
+#if wxUSE_ACCESSIBILITY
+ case WM_GETOBJECT:
+ {
+ //WPARAM dwFlags = (WPARAM) (DWORD) wParam;
+ LPARAM dwObjId = (LPARAM) (DWORD) lParam;
+
+ if (dwObjId == (LPARAM)OBJID_CLIENT && GetOrCreateAccessible())
+ {
+ return LresultFromObject(IID_IAccessible, wParam, (IUnknown*) GetAccessible()->GetIAccessible());
+ }
+ break;
+ }
+#endif
+
+#if defined(WM_HELP)
case WM_HELP:
{
+ // by default, WM_HELP is propagated by DefWindowProc() upwards
+ // to the window parent but as we do it ourselves already
+ // (wxHelpEvent is derived from wxCommandEvent), we don't want
+ // to get the other events if we process this message at all
+ processed = true;
+
+ // WM_HELP doesn't use lParam under CE
+#ifndef __WXWINCE__
HELPINFO* info = (HELPINFO*) lParam;
- // Don't yet process menu help events, just windows
- if (info->iContextType == HELPINFO_WINDOW)
+ if ( info->iContextType == HELPINFO_WINDOW )
{
- wxWindowMSW* subjectOfHelp = this;
- bool eventProcessed = FALSE;
- while (subjectOfHelp && !eventProcessed)
- {
- wxHelpEvent helpEvent(wxEVT_HELP,
- subjectOfHelp->GetId(),
- wxPoint(info->MousePos.x,
- info->MousePos.y) );
- helpEvent.SetEventObject(this);
- eventProcessed =
- GetEventHandler()->ProcessEvent(helpEvent);
-
- // Go up the window hierarchy until the event is
- // handled (or not)
- subjectOfHelp = subjectOfHelp->GetParent();
- }
+#endif // !__WXWINCE__
+ wxHelpEvent helpEvent
+ (
+ wxEVT_HELP,
+ GetId(),
+#ifdef __WXWINCE__
+ wxGetMousePosition() // what else?
+#else
+ wxPoint(info->MousePos.x, info->MousePos.y)
+#endif
+ );
- processed = eventProcessed;
+ helpEvent.SetEventObject(this);
+ GetEventHandler()->ProcessEvent(helpEvent);
+#ifndef __WXWINCE__
}
- else if (info->iContextType == HELPINFO_MENUITEM)
+ else if ( info->iContextType == HELPINFO_MENUITEM )
{
wxHelpEvent helpEvent(wxEVT_HELP, info->iCtrlId);
helpEvent.SetEventObject(this);
- processed = GetEventHandler()->ProcessEvent(helpEvent);
+ GetEventHandler()->ProcessEvent(helpEvent);
}
- //else: processed is already FALSE
+ else // unknown help event?
+ {
+ processed = false;
+ }
+#endif // !__WXWINCE__
}
break;
+#endif // WM_HELP
+#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 ( (WXHWND)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__
+
+#ifndef __WXWINCE__
+ case WM_POWERBROADCAST:
+ {
+ bool vetoed;
+ processed = HandlePower(wParam, lParam, &vetoed);
+ rc.result = processed && vetoed ? BROADCAST_QUERY_DENY : TRUE;
+ }
+ break;
+#endif // __WXWINCE__
}
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);
}
wxWindow *wxFindWinFromHandle(WXHWND hWnd)
{
- return wxWinHandleHash->Get((long)hWnd);
+ return (wxWindow*)wxWinHandleHash->Get((long)hWnd);
}
void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win)
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_H = 250;
- bool nonDefault = FALSE;
+ bool nonDefault = false;
- if ( pos.x == -1 )
+ if ( pos.x == wxDefaultCoord )
{
- // 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;
}
// neither because it is not handled as a special value by Windows then
// and so we have to choose some default value for it
x = pos.x;
- y = pos.y == -1 ? DEFAULT_Y : pos.y;
+ y = pos.y == wxDefaultCoord ? DEFAULT_Y : pos.y;
- nonDefault = TRUE;
+ nonDefault = true;
}
/*
NB: there used to be some code here which set the initial size of the
window to the client size of the parent if no explicit size was
- specified. This was wrong because wxWindows programs often assume
+ specified. This was wrong because wxWidgets programs often assume
that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
it. To see why, you should understand that Windows sends WM_SIZE from
inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
event goes to some base class OnSize() instead). So the WM_SIZE we
rely on is the one sent when the parent frame resizes its children
but here is the problem: if the child already has just the right
- size, nothing will happen as both wxWindows and Windows check for
+ size, nothing will happen as both wxWidgets and Windows check for
this and ignore any attempts to change the window size to the size it
already has - so no WM_SIZE would be sent.
*/
- if ( size.x == -1 )
- {
- // as above, h is not used at all in this case anyhow
- w =
+
+
+ // 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 wxWidgets 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
+
+ // However, on PocketPC devices, we must use the default
+ // size if possible.
+#ifdef _WIN32_WCE
+ if (size.x == wxDefaultCoord)
+ w = CW_USEDEFAULT;
+ else
+ w = size.x;
+ if (size.y == wxDefaultCoord)
h = CW_USEDEFAULT;
- }
else
+ h = size.y;
+#else
+ if ( size.x == wxDefaultCoord || size.y == wxDefaultCoord)
{
- // and, again as above, we can't set the height to CW_USEDEFAULT here
- w = size.x;
- h = size.y == -1 ? DEFAULT_H : size.y;
-
- nonDefault = TRUE;
+ nonDefault = true;
}
+ w = WidthDefault(size.x);
+ h = HeightDefault(size.y);
+#endif
+
+ 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");
}
m_hWnd = (WXHWND)::CreateWindowEx
(
- extendedStyle,
- className,
- title ? title : wxT(""),
- style,
- x, y, w, h,
- (HWND)MSWGetParent(),
- (HMENU)controlId,
- wxGetInstance(),
- NULL // no extra data
+ extendedStyle,
+ className,
+ title ? title : m_windowName.c_str(),
+ 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);
+ wxLogSysError(_("Can't create window of class %s"), className.c_str());
- return FALSE;
+ return false;
}
SubclassWin(m_hWnd);
- SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
-
- return TRUE;
+ return true;
}
// ===========================================================================
// WM_NOTIFY
// ---------------------------------------------------------------------------
-#ifdef __WIN95__
-
bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
{
#ifndef __WXMICROWIN__
// 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
-
- if ( !(code == (WXUINT) TTN_NEEDTEXTA || code == (WXUINT) TTN_NEEDTEXTW) || ttip.empty() )
+#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;
+ // We don't want to use the szText buffer because it has a limit of 80
+ // bytes and this is not enough, especially for Unicode build where it
+ // limits the tooltip string length to only 40 characters
+ //
+ // The best would be, of course, to not impose any length limitations at
+ // all but then the buffer would have to be dynamic and someone would have
+ // to free it and we don't have the tooltip owner object here any more, so
+ // for now use our own static buffer with a higher fixed max length.
+ //
+ // Note that using a static buffer should not be a problem as only a single
+ // tooltip can be shown at the same time anyhow.
#if !wxUSE_UNICODE
- if ( code == (WXUINT) TTN_NEEDTEXTA )
- {
- // we pass just the pointer as we store the string internally anyhow
- ttText->lpszText = (char *)ttip.c_str();
- }
- else // TTN_NEEDTEXTW
-#endif // !Unicode
- {
-#if wxUSE_UNICODE
- // in Unicode mode this is just what we need
- ttText->lpszText = (wxChar *)ttip.c_str();
-#else // !Unicode
- // in ANSI mode we have to convert the string and put it into the
- // provided buffer: be careful not to overrun it
- const size_t lenAnsi = ttip.length();
-
- // some compilers (MetroWerks and Cygwin) don't like calling mbstowcs
- // with NULL argument
- #if defined( __MWERKS__ ) || defined( __CYGWIN__ )
- size_t lenUnicode = 2*lenAnsi;
- #else
- size_t lenUnicode = mbstowcs(NULL, ttip, lenAnsi);
- #endif
-
- // using the pointer of right type avoids us doing all sorts of
- // pointer arithmetics ourselves
- wchar_t *dst = (wchar_t *)ttText->szText,
- *pwz = new wchar_t[lenUnicode + 1];
- mbstowcs(pwz, ttip, lenAnsi + 1);
-
- // stay inside the buffer (-1 because it must be NUL-terminated)
- if ( lenUnicode > WXSIZEOF(ttText->szText) - 1 )
+ if ( code == (WXUINT) TTN_NEEDTEXTW )
+ {
+ // We need to convert tooltip from multi byte to Unicode on the fly.
+ static wchar_t buf[513];
+
+ // Truncate tooltip length if needed as otherwise we might not have
+ // enough space for it in the buffer and MultiByteToWideChar() would
+ // return an error
+ size_t tipLength = wxMin(ttip.length(), WXSIZEOF(buf) - 1);
+
+ // Convert to WideChar without adding the NULL character. The NULL
+ // character is added afterwards (this is more efficient).
+ int len = ::MultiByteToWideChar
+ (
+ CP_ACP,
+ 0, // no flags
+ ttip,
+ tipLength,
+ buf,
+ WXSIZEOF(buf) - 1
+ );
+
+ if ( !len )
{
- lenUnicode = WXSIZEOF(ttText->szText) - 1;
+ wxLogLastError(_T("MultiByteToWideChar()"));
}
- memcpy(dst, pwz, lenUnicode*sizeof(wchar_t));
-
- // put the terminating wide NUL
- dst[lenUnicode] = L'\0';
-
- delete [] pwz;
-#endif // Unicode/!Unicode
+ buf[len] = L'\0';
+ ttText->lpszText = (LPSTR) buf;
+ }
+ else // TTN_NEEDTEXTA
+#endif // !wxUSE_UNICODE
+ {
+ // we get here if we got TTN_NEEDTEXTA (only happens in ANSI build) or
+ // 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');
+ ttText->lpszText = buf;
}
- return TRUE;
+ return true;
}
#endif // wxUSE_TOOLTIPS
if ( HandleTooltipNotify(hdr->code, lParam, m_tooltip->GetTip()))
{
// processed
- return TRUE;
+ return true;
}
}
+#else
+ wxUnusedVar(lParam);
#endif // wxUSE_TOOLTIPS
- return FALSE;
+ return false;
}
-#endif // __WIN95__
-
// ---------------------------------------------------------------------------
// end session messages
// ---------------------------------------------------------------------------
bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd)
{
- wxCloseEvent event(wxEVT_QUERY_END_SESSION, -1);
+#ifdef ENDSESSION_LOGOFF
+ wxCloseEvent event(wxEVT_QUERY_END_SESSION, wxID_ANY);
event.SetEventObject(wxTheApp);
- event.SetCanVeto(TRUE);
+ event.SetCanVeto(true);
event.SetLoggingOff(logOff == (long)ENDSESSION_LOGOFF);
bool rc = wxTheApp->ProcessEvent(event);
}
return rc;
+#else
+ wxUnusedVar(logOff);
+ wxUnusedVar(mayEnd);
+ return false;
+#endif
}
bool wxWindowMSW::HandleEndSession(bool endSession, long logOff)
{
+#ifdef ENDSESSION_LOGOFF
// 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);
+ wxCloseEvent event(wxEVT_END_SESSION, wxID_ANY);
event.SetEventObject(wxTheApp);
- event.SetCanVeto(FALSE);
+ event.SetCanVeto(false);
event.SetLoggingOff( (logOff == (long)ENDSESSION_LOGOFF) );
return wxTheApp->ProcessEvent(event);
+#else
+ wxUnusedVar(endSession);
+ wxUnusedVar(logOff);
+ return false;
+#endif
}
// ---------------------------------------------------------------------------
// window creation/destruction
// ---------------------------------------------------------------------------
-bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate)
+bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT WXUNUSED_IN_WINCE(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()
{
- wxWindowDestroyEvent event((wxWindow *)this);
- (void)GetEventHandler()->ProcessEvent(event);
+ SendDestroyEvent();
// delete our drop target if we've got one
#if wxUSE_DRAG_AND_DROP
#endif // wxUSE_DRAG_AND_DROP
// WM_DESTROY handled
- return TRUE;
+ return true;
}
// ---------------------------------------------------------------------------
bool wxWindowMSW::HandleSetFocus(WXHWND hwnd)
{
+ // Strangly enough, some controls get set focus events when they are being
+ // deleted, even if they already had focus before.
+ if ( m_isBeingDeleted )
+ {
+ return false;
+ }
+
// notify the parent keeping track of focus for the kbd navigation
// purposes that we got it
wxChildFocusEvent eventFocus((wxWindow *)this);
// 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);
return GetEventHandler()->ProcessEvent(event);
}
+// ---------------------------------------------------------------------------
+// labels
+// ---------------------------------------------------------------------------
+
+void wxWindowMSW::SetLabel( const wxString& label)
+{
+ SetWindowText(GetHwnd(), label.c_str());
+}
+
+wxString wxWindowMSW::GetLabel() const
+{
+ return wxGetWindowText(GetHWND());
+}
+
// ---------------------------------------------------------------------------
// miscellaneous
// ---------------------------------------------------------------------------
bool wxWindowMSW::HandleShow(bool show, int WXUNUSED(status))
{
wxShowEvent event(GetId(), show);
- event.m_eventObject = this;
+ event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
}
bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus))
{
wxInitDialogEvent event(GetId());
- event.m_eventObject = this;
+ event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
}
bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
{
-#ifndef __WXMICROWIN__
+#if defined (__WXMICROWIN__) || defined(__WXWINCE__)
+ wxUnusedVar(wParam);
+ return false;
+#else // __WXMICROWIN__
HDROP hFilesInfo = (HDROP) wParam;
// Get the total number of files dropped
// and now get the file name
::DragQueryFile(hFilesInfo, wIndex,
- files[wIndex].GetWriteBuf(len), len);
-
- files[wIndex].UngetWriteBuf();
+ wxStringBuffer(files[wIndex], len), len);
}
DragFinish (hFilesInfo);
wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files);
- event.m_eventObject = this;
+ event.SetEventObject(this);
POINT dropPoint;
DragQueryPoint(hFilesInfo, (LPPOINT) &dropPoint);
event.m_pos.y = dropPoint.y;
return GetEventHandler()->ProcessEvent(event);
-#else // __WXMICROWIN__
- return FALSE;
#endif
}
+
bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd),
short nHitTest,
int WXUNUSED(mouseMsg))
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__
+#ifdef __WXWINCE__
+ if ( !::GetCursorPosWinCE(&pt))
+#else
if ( !::GetCursorPos(&pt) )
+#endif
{
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;
+}
+
+bool wxWindowMSW::HandlePower(WXWPARAM WXUNUSED_IN_WINCE(wParam),
+ WXLPARAM WXUNUSED(lParam),
+ bool *WXUNUSED_IN_WINCE(vetoed))
+{
+#ifdef __WXWINCE__
+ // FIXME
+ return false;
+#else
+ wxEventType evtType;
+ switch ( wParam )
+ {
+ case PBT_APMQUERYSUSPEND:
+ evtType = wxEVT_POWER_SUSPENDING;
+ break;
+
+ case PBT_APMQUERYSUSPENDFAILED:
+ evtType = wxEVT_POWER_SUSPEND_CANCEL;
+ break;
+
+ case PBT_APMSUSPEND:
+ evtType = wxEVT_POWER_SUSPENDED;
+ break;
+
+ case PBT_APMRESUMESUSPEND:
+#ifdef PBT_APMRESUMEAUTOMATIC
+ case PBT_APMRESUMEAUTOMATIC:
+#endif
+ evtType = wxEVT_POWER_RESUME;
+ break;
+
+ default:
+ wxLogDebug(_T("Unknown WM_POWERBROADCAST(%d) event"), wParam);
+ // fall through
+
+ // these messages are currently not mapped to wx events
+ case PBT_APMQUERYSTANDBY:
+ case PBT_APMQUERYSTANDBYFAILED:
+ case PBT_APMSTANDBY:
+ case PBT_APMRESUMESTANDBY:
+ case PBT_APMBATTERYLOW:
+ case PBT_APMPOWERSTATUSCHANGE:
+ case PBT_APMOEMEVENT:
+ case PBT_APMRESUMECRITICAL:
+ evtType = wxEVT_NULL;
+ break;
+ }
+
+ // don't handle unknown messages
+ if ( evtType == wxEVT_NULL )
+ return false;
+
+ // TODO: notify about PBTF_APMRESUMEFROMFAILURE in case of resume events?
+
+ wxPowerEvent event(evtType);
+ if ( !GetEventHandler()->ProcessEvent(event) )
+ return false;
+
+ *vetoed = event.IsVetoed();
+
+ return true;
+#endif
+}
+
+bool wxWindowMSW::IsDoubleBuffered() const
+{
+ for ( const wxWindowMSW *wnd = this;
+ wnd && !wnd->IsTopLevel(); wnd =
+ wnd->GetParent() )
+ {
+ if ( ::GetWindowLong(GetHwndOf(wnd), GWL_EXSTYLE) & WS_EX_COMPOSITED )
+ return true;
+ }
+
+ 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 );
+ // see comment before the same test in MSWOnMeasureItem() below
+ if ( !pMenuItem )
+ return false;
+
+ wxCHECK_MSG( wxDynamicCast(pMenuItem, wxMenuItem),
+ false, _T("MSWOnDrawItem: bad wxMenuItem pointer") );
// prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
// 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 =
+# if wxUSE_BUTTON
+ wxDynamicCast(FindItem(id), wxButton)
+# else
+ NULL
+# endif
+ ;
+#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 id, WXMEASUREITEMSTRUCT *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 );
+ // according to Carsten Fuchs the pointer may be NULL under XP if an
+ // MDI child frame is initially maximized, see this for more info:
+ // http://article.gmane.org/gmane.comp.lib.wxwidgets.general/27745
+ //
+ // so silently ignore it instead of asserting
+ if ( !pMenuItem )
+ return false;
+
+ wxCHECK_MSG( wxDynamicCast(pMenuItem, wxMenuItem),
+ false, _T("MSWOnMeasureItem: bad wxMenuItem pointer") );
- return pMenuItem->OnMeasureItem(&pMeasureStruct->itemWidth,
- &pMeasureStruct->itemHeight);
+ size_t w, h;
+ bool rc = pMenuItem->OnMeasureItem(&w, &h);
+
+ 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;
+#else
+ wxUnusedVar(id);
+ wxUnusedVar(itemStruct);
+#endif // wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE
+
+ 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()
return GetEventHandler()->ProcessEvent(event);
}
-bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush,
- WXHDC pDC,
- WXHWND pWnd,
- WXUINT nCtlColor,
- WXUINT message,
- WXWPARAM wParam,
- WXLPARAM lParam)
-{
#ifndef __WXMICROWIN__
- WXHBRUSH hBrush = 0;
- if ( nCtlColor == CTLCOLOR_DLG )
- {
- hBrush = OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam);
- }
-#if wxUSE_CONTROLS
+bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC hDC, WXHWND hWnd)
+{
+#if !wxUSE_CONTROLS || defined(__WXUNIVERSAL__)
+ wxUnusedVar(hDC);
+ wxUnusedVar(hWnd);
+#else
+ wxControl *item = wxDynamicCast(FindItemByHWND(hWnd, true), wxControl);
+
+ if ( item )
+ *brush = item->MSWControlColor(hDC, hWnd);
else
- {
- wxControl *item = (wxControl *)FindItemByHWND(pWnd, TRUE);
- if ( item )
- hBrush = item->OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam);
- }
#endif // wxUSE_CONTROLS
+ *brush = NULL;
- if ( hBrush )
- *brush = hBrush;
-
- return hBrush != 0;
-#else // __WXMICROWIN__
- return FALSE;
-#endif
+ return *brush != NULL;
}
-// Define for each class of dialog and control
-WXHBRUSH wxWindowMSW::OnCtlColor(WXHDC WXUNUSED(hDC),
- WXHWND WXUNUSED(hWnd),
- WXUINT WXUNUSED(nCtlColor),
- WXUINT WXUNUSED(message),
- WXWPARAM WXUNUSED(wParam),
- WXLPARAM WXUNUSED(lParam))
-{
- return (WXHBRUSH)0;
-}
+#endif // __WXMICROWIN__
bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
{
// now check for the need to redraw
if (result > 0)
- InvalidateRect((HWND) hWndPalChange, NULL, TRUE);
+ ::InvalidateRect((HWND) hWndPalChange, NULL, TRUE);
}
}
bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
{
- wxMouseCaptureChangedEvent event(GetId(), wxFindWinFromHandle(hWndGainedCapture));
- event.SetEventObject(this);
+ // notify windows on the capture stack about lost capture
+ // (see http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863):
+ wxWindowBase::NotifyCaptureLost();
+ wxWindow *win = wxFindWinFromHandle(hWndGainedCapture);
+ wxMouseCaptureChangedEvent event(GetId(), win);
+ event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
}
+bool wxWindowMSW::HandleSettingChange(WXWPARAM wParam, WXLPARAM lParam)
+{
+ // despite MSDN saying "(This message cannot be sent directly to a window.)"
+ // we need to send this to child windows (it is only sent to top-level
+ // windows) so {list,tree}ctrls can adjust their font size if necessary
+ // this is exactly how explorer does it to enable the font size changes
+
+ wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+ while ( node )
+ {
+ // top-level windows already get this message from the system
+ wxWindow *win = node->GetData();
+ if ( !win->IsTopLevel() )
+ {
+ ::SendMessage(GetHwndOf(win), WM_SETTINGCHANGE, wParam, lParam);
+ }
+
+ node = node->GetNext();
+ }
+
+ // let the system handle it
+ return false;
+}
+
bool wxWindowMSW::HandleQueryNewPalette()
{
while (!win->HasCustomPalette() && win->GetParent()) win = win->GetParent();
if (win->HasCustomPalette()) {
/* realize the palette to see whether redrawing is needed */
- HDC hdc = GetDC((HWND) GetHWND());
+ HDC hdc = ::GetDC((HWND) GetHWND());
win->m_palette.SetHPALETTE( (WXHPALETTE)
::SelectPalette(hdc, (HPALETTE) win->m_palette.GetHPALETTE(), FALSE) );
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
node = node->GetNext();
}
-
- // update the colours we use if they were not set explicitly by the user:
- // this must be done or OnCtlColor() would continue to use the old colours
- if ( !m_hasFgCol )
- {
- m_foregroundColour = wxSystemSettings::
- GetSystemColour(wxSYS_COLOUR_WINDOWTEXT);
- }
-
- if ( !m_hasBgCol )
- {
- m_backgroundColour = wxSystemSettings::
- GetSystemColour(wxSYS_COLOUR_BTNFACE);
- }
}
extern wxCOLORMAP *wxGetStdColourMap()
if ( !gs_hasStdCmap )
{
- static bool s_coloursInit = FALSE;
+ static bool s_coloursInit = false;
if ( !s_coloursInit )
{
// we want to avoid Windows' "help" and for this we need to have a
// reference bitmap which can tell us what the RGB values change
// to.
+ wxLogNull logNo; // suppress error if we couldn't load the bitmap
wxBitmap stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
if ( stdColourBitmap.Ok() )
{
//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__
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);
bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc)
{
- // Prevents flicker when dragging
- if ( ::IsIconic(GetHwnd()) )
- return TRUE;
-
- wxDCTemp dc(hdc);
+ wxDCTemp dc(hdc, GetClientSize());
dc.SetHDC(hdc);
dc.SetWindow((wxWindow *)this);
- dc.BeginDrawing();
wxEraseEvent event(m_windowId, &dc);
event.SetEventObject(this);
bool rc = GetEventHandler()->ProcessEvent(event);
- dc.EndDrawing();
-
// must be called manually as ~wxDC doesn't do anything for wxDCTemp
dc.SelectOldObjects(hdc);
void wxWindowMSW::OnEraseBackground(wxEraseEvent& event)
{
- RECT rect;
- ::GetClientRect(GetHwnd(), &rect);
+ // standard non top level controls (i.e. except the dialogs) always erase
+ // their background themselves in HandleCtlColor() or have some control-
+ // specific ways to set the colours (common controls)
+ if ( IsOfStandardClass() && !IsTopLevel() )
+ {
+ event.Skip();
+ return;
+ }
+
+ if ( GetBackgroundStyle() == wxBG_STYLE_CUSTOM )
+ {
+ // don't skip the event here, custom background means that the app
+ // is drawing it itself in its OnPaint(), so don't draw it at all
+ // now to avoid flicker
+ return;
+ }
+
- COLORREF ref = PALETTERGB(m_backgroundColour.Red(),
- m_backgroundColour.Green(),
- m_backgroundColour.Blue());
- HBRUSH hBrush = ::CreateSolidBrush(ref);
- if ( !hBrush )
- wxLogLastError(wxT("CreateSolidBrush"));
+ // do default background painting
+ if ( !DoEraseBackground(GetHdcOf(*event.GetDC())) )
+ {
+ // let the system paint the background
+ event.Skip();
+ }
+}
+
+bool wxWindowMSW::DoEraseBackground(WXHDC hDC)
+{
+ HBRUSH hbr = (HBRUSH)MSWGetBgBrush(hDC);
+ if ( !hbr )
+ return false;
+
+ wxFillRect(GetHwnd(), (HDC)hDC, hbr);
+
+ return true;
+}
+
+WXHBRUSH
+wxWindowMSW::MSWGetBgBrushForChild(WXHDC WXUNUSED(hDC), WXHWND hWnd)
+{
+ if ( m_hasBgCol )
+ {
+ // our background colour applies to:
+ // 1. this window itself, always
+ // 2. all children unless the colour is "not inheritable"
+ // 3. even if it is not inheritable, our immediate transparent
+ // children should still inherit it -- but not any transparent
+ // children because it would look wrong if a child of non
+ // transparent child would show our bg colour when the child itself
+ // does not
+ wxWindow *win = wxFindWinFromHandle(hWnd);
+ if ( win == this ||
+ m_inheritBgCol ||
+ (win && win->HasTransparentBackground() &&
+ win->GetParent() == this) )
+ {
+ // draw children with the same colour as the parent
+ wxBrush *
+ brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour());
+
+ return (WXHBRUSH)GetHbrushOf(*brush);
+ }
+ }
+
+ return 0;
+}
+
+WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC, WXHWND hWndToPaint)
+{
+ if ( !hWndToPaint )
+ hWndToPaint = GetHWND();
+
+ for ( wxWindowMSW *win = this; win; win = win->GetParent() )
+ {
+ WXHBRUSH hBrush = win->MSWGetBgBrushForChild(hDC, hWndToPaint);
+ if ( hBrush )
+ return hBrush;
+
+ // background is not inherited beyond top level windows
+ if ( win->IsTopLevel() )
+ break;
+ }
+
+ return 0;
+}
+
+bool wxWindowMSW::HandlePrintClient(WXHDC hDC)
+{
+ // we receive this message when DrawThemeParentBackground() is
+ // called from def window proc of several controls under XP and we
+ // must draw properly themed background here
+ //
+ // note that naively I'd expect filling the client rect with the
+ // brush returned by MSWGetBgBrush() work -- but for some reason it
+ // doesn't and we have to call parents MSWPrintChild() which is
+ // supposed to call DrawThemeBackground() with appropriate params
+ //
+ // also note that in this case lParam == PRF_CLIENT but we're
+ // clearly expected to paint the background and nothing else!
+
+ if ( IsTopLevel() || InheritsBackgroundColour() )
+ return false;
+
+ // sometimes we don't want the parent to handle it at all, instead
+ // return whatever value this window wants
+ if ( !MSWShouldPropagatePrintChild() )
+ return MSWPrintChild(hDC, (wxWindow *)this);
- HDC hdc = (HDC)event.GetDC()->GetHDC();
+ for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
+ {
+ if ( win->MSWPrintChild(hDC, (wxWindow *)this) )
+ return true;
- int mode = ::SetMapMode(hdc, MM_TEXT);
+ if ( win->IsTopLevel() || win->InheritsBackgroundColour() )
+ break;
+ }
- ::FillRect(hdc, &rect, hBrush);
- ::DeleteObject(hBrush);
- ::SetMapMode(hdc, mode);
+ return false;
}
// ---------------------------------------------------------------------------
bool wxWindowMSW::HandleMove(int x, int y)
{
- wxMoveEvent event(wxPoint(x, y), m_windowId);
+ wxPoint point(x,y);
+ wxMoveEvent event(point, m_windowId);
event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
}
-bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h),
- WXUINT WXUNUSED(flag))
+bool wxWindowMSW::HandleMoving(wxRect& rect)
{
- // don't use w and h parameters as they specify the client size while
- // according to the docs EVT_SIZE handler is supposed to receive the total
- // size
- wxSizeEvent event(GetSize(), m_windowId);
+ wxMoveEvent event(rect, m_windowId);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ bool rc = GetEventHandler()->ProcessEvent(event);
+ if (rc)
+ rect = event.GetRect();
+ return rc;
+}
+
+bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
+{
+#if USE_DEFERRED_SIZING
+ // when we resize this window, its children are probably going to be
+ // repositioned as well, prepare to use DeferWindowPos() for them
+ int numChildren = 0;
+ for ( HWND child = ::GetWindow(GetHwndOf(this), GW_CHILD);
+ child;
+ child = ::GetWindow(child, GW_HWNDNEXT) )
+ {
+ numChildren ++;
+ }
+
+ // Protect against valid m_hDWP being overwritten
+ bool useDefer = false;
+
+ if ( numChildren > 1 )
+ {
+ if (!m_hDWP)
+ {
+ m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
+ if ( !m_hDWP )
+ {
+ wxLogLastError(_T("BeginDeferWindowPos"));
+ }
+ if (m_hDWP)
+ useDefer = true;
+ }
+ }
+#endif // USE_DEFERRED_SIZING
+
+ // update this window size
+ bool processed = false;
+ switch ( wParam )
+ {
+ default:
+ wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
+ // fall through nevertheless
+
+ case SIZE_MAXHIDE:
+ case SIZE_MAXSHOW:
+ // we're not interested in these messages at all
+ break;
+
+ case SIZE_MINIMIZED:
+ processed = HandleMinimize();
+ break;
+
+ case SIZE_MAXIMIZED:
+ /* processed = */ HandleMaximize();
+ // fall through to send a normal size event as well
+
+ case SIZE_RESTORED:
+ // don't use w and h parameters as they specify the client size
+ // while according to the docs EVT_SIZE handler is supposed to
+ // receive the total size
+ wxSizeEvent event(GetSize(), m_windowId);
+ event.SetEventObject(this);
+
+ processed = GetEventHandler()->ProcessEvent(event);
+ }
+
+#if USE_DEFERRED_SIZING
+ // and finally change the positions of all child windows at once
+ if ( useDefer && m_hDWP )
+ {
+ // reset m_hDWP to NULL so that child windows don't try to use our
+ // m_hDWP after we call EndDeferWindowPos() on it (this shouldn't
+ // happen anyhow normally but who knows what weird flow of control we
+ // may have depending on what the users EVT_SIZE handler does...)
+ HDWP hDWP = (HDWP)m_hDWP;
+ m_hDWP = NULL;
+
+ // do put all child controls in place at once
+ if ( !::EndDeferWindowPos(hDWP) )
+ {
+ wxLogLastError(_T("EndDeferWindowPos"));
+ }
+
+ // Reset our children's pending pos/size values.
+ for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ wxWindowMSW *child = node->GetData();
+ child->m_pendingPosition = wxDefaultPosition;
+ child->m_pendingSize = wxDefaultSize;
+ }
+ }
+#endif // USE_DEFERRED_SIZING
+
+ return processed;
+}
+
+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)
+bool wxWindowMSW::HandleGetMinMaxInfo(void *WXUNUSED_IN_WINCE(mmInfo))
{
+#ifdef __WXWINCE__
+ return false;
+#else
MINMAXINFO *info = (MINMAXINFO *)mmInfo;
- bool rc = FALSE;
+ bool rc = false;
int minWidth = GetMinWidth(),
minHeight = GetMinHeight(),
maxWidth = GetMaxWidth(),
maxHeight = GetMaxHeight();
- if ( minWidth != -1 )
+ if ( minWidth != wxDefaultCoord )
{
info->ptMinTrackSize.x = minWidth;
- rc = TRUE;
+ rc = true;
}
- if ( minHeight != -1 )
+ if ( minHeight != wxDefaultCoord )
{
info->ptMinTrackSize.y = minHeight;
- rc = TRUE;
+ rc = true;
}
- if ( maxWidth != -1 )
+ if ( maxWidth != wxDefaultCoord )
{
info->ptMaxTrackSize.x = maxWidth;
- rc = TRUE;
+ rc = true;
}
- if ( maxHeight != -1 )
+ if ( maxHeight != wxDefaultCoord )
{
info->ptMaxTrackSize.y = maxHeight;
- rc = TRUE;
+ rc = true;
}
return rc;
+#endif
}
// ---------------------------------------------------------------------------
return GetEventHandler()->ProcessEvent(event);
}
-#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
else
{
+#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
// the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
// notifications to its parent which we want to reflect back to
// wxSpinCtrl
wxSpinCtrl *spin = wxSpinCtrl::GetSpinForTextCtrl(control);
if ( spin && spin->ProcessTextCommand(cmd, id) )
- return TRUE;
- }
+ return true;
#endif // wxUSE_SPINCTRL
- return FALSE;
-}
-
-bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam))
-{
- // 4 bits are reserved
- switch ( wParam & 0xFFFFFFF0 )
- {
- case SC_MAXIMIZE:
- return HandleMaximize();
-
- case SC_MINIMIZE:
- return HandleMinimize();
+#if wxUSE_CHOICE && defined(__SMARTPHONE__)
+ // the listbox ctrl which is logically part of wxChoice sends WM_COMMAND
+ // notifications to its parent which we want to reflect back to
+ // wxChoice
+ wxChoice *choice = wxChoice::GetChoiceForListBox(control);
+ if ( choice && choice->MSWCommand(cmd, id) )
+ return true;
+#endif
}
- return FALSE;
+ return false;
}
// ---------------------------------------------------------------------------
event.m_leftDown = (flags & MK_LBUTTON) != 0;
event.m_middleDown = (flags & MK_MBUTTON) != 0;
event.m_rightDown = (flags & MK_RBUTTON) != 0;
- event.m_altDown = (::GetKeyState(VK_MENU) & 0x80000000) != 0;
+ event.m_altDown = ::GetKeyState(VK_MENU) < 0;
+
+#ifndef __WXWINCE__
+ event.SetTimestamp(::GetMessageTime());
+#endif
- event.SetTimestamp(s_currentMsg.time);
- event.m_eventObject = this;
+ event.SetEventObject(this);
event.SetId(GetId());
#if wxUSE_MOUSEEVENT_HACK
- m_lastMouseX = x;
- m_lastMouseY = y;
- m_lastMouseEvent = event.GetEventType();
+ gs_lastMouseEvent.pos = ClientToScreen(wxPoint(x, y));
+ gs_lastMouseEvent.type = event.GetEventType();
#endif // wxUSE_MOUSEEVENT_HACK
}
+#ifdef __WXWINCE__
// Windows doesn't send the mouse events to the static controls (which are
// transparent in the sense that their WM_NCHITTEST handler returns
// HTTRANSPARENT) at all but we want all controls to receive the mouse events
// Notice that this is not done for the mouse move events because this could
// (would?) be too slow, but only for clicks which means that the static texts
// still don't get move, enter nor leave events.
-static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y) //TW:REQ:Univ
+static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y)
{
wxCHECK_MSG( x && y, win, _T("NULL pointer in FindWindowForMouseEvent") );
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);
return win;
}
+#endif // __WXWINCE__
bool wxWindowMSW::HandleMouseEvent(WXUINT msg, int x, int y, WXUINT flags)
{
// the mouse events take consecutive IDs from WM_MOUSEFIRST to
- // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
+ // WM_MOUSELAST, so it's enough to subtract WM_MOUSEMOVE == WM_MOUSEFIRST
// from the message id and take the value in the table to get wxWin event
// id
static const wxEventType eventsMouse[] =
if ( !HasCapture() || IsMouseInWindow() )
{
// Generate an ENTER event
- m_mouseInWindow = TRUE;
+ m_mouseInWindow = true;
+
+#ifdef HAVE_TRACKMOUSEEVENT
+ typedef BOOL (WINAPI *_TrackMouseEvent_t)(LPTRACKMOUSEEVENT);
+#ifdef __WXWINCE__
+ static const _TrackMouseEvent_t
+ s_pfn_TrackMouseEvent = _TrackMouseEvent;
+#else // !__WXWINCE__
+ static _TrackMouseEvent_t s_pfn_TrackMouseEvent;
+ static bool s_initDone = false;
+ if ( !s_initDone )
+ {
+ wxLogNull noLog;
+
+ wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
+ if ( dllComCtl32.IsLoaded() )
+ {
+ s_pfn_TrackMouseEvent = (_TrackMouseEvent_t)
+ dllComCtl32.GetSymbol(_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 )
+#endif // __WXWINCE__/!__WXWINCE__
+ {
+ WinStruct<TRACKMOUSEEVENT> trackinfo;
+
+ trackinfo.dwFlags = TME_LEAVE;
+ trackinfo.hwndTrack = GetHwnd();
+
+ (*s_pfn_TrackMouseEvent)(&trackinfo);
+ }
+#endif // HAVE_TRACKMOUSEEVENT
wxMouseEvent event(wxEVT_ENTER_WINDOW);
InitMouseEvent(event, x, y, flags);
(void)GetEventHandler()->ProcessEvent(event);
}
}
+#ifdef HAVE_TRACKMOUSEEVENT
+ else // mouse not in window
+ {
+ // Check if we need to send a LEAVE event
+ // Windows doesn't send WM_MOUSELEAVE if the mouse has been captured so
+ // send it here if we are using native mouse leave tracking
+ if ( HasCapture() && !IsMouseInWindow() )
+ {
+ GenerateMouseLeave();
+ }
+ }
+#endif // HAVE_TRACKMOUSEEVENT
#if wxUSE_MOUSEEVENT_HACK
- // Window gets a click down message followed by a mouse move message even
- // if position isn't changed! We want to discard the trailing move event
- // if x and y are the same.
- if ( (m_lastMouseEvent == wxEVT_RIGHT_DOWN ||
- m_lastMouseEvent == wxEVT_LEFT_DOWN ||
- m_lastMouseEvent == wxEVT_MIDDLE_DOWN) &&
- (m_lastMouseX == x && m_lastMouseY == y) )
- {
- m_lastMouseEvent = wxEVT_MOTION;
+ // Windows often generates mouse events even if mouse position hasn't
+ // changed (http://article.gmane.org/gmane.comp.lib.wxwidgets.devel/66576)
+ //
+ // Filter this out as it can result in unexpected behaviour compared to
+ // other platforms
+ if ( gs_lastMouseEvent.type == wxEVT_RIGHT_DOWN ||
+ gs_lastMouseEvent.type == wxEVT_LEFT_DOWN ||
+ gs_lastMouseEvent.type == wxEVT_MIDDLE_DOWN ||
+ gs_lastMouseEvent.type == wxEVT_MOTION )
+ {
+ if ( ClientToScreen(wxPoint(x, y)) == gs_lastMouseEvent.pos )
+ {
+ gs_lastMouseEvent.type = wxEVT_MOTION;
- return FALSE;
+ return false;
+ }
}
#endif // wxUSE_MOUSEEVENT_HACK
bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam)
{
#if wxUSE_MOUSEWHEEL
+ // notice that WM_MOUSEWHEEL position is in screen coords (as it's
+ // forwarded up to the parent by DefWindowProc()) and not in the client
+ // ones as all the other messages, translate them to the client coords for
+ // consistency
+ const wxPoint
+ pt = ScreenToClient(wxPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
wxMouseEvent event(wxEVT_MOUSEWHEEL);
- InitMouseEvent(event,
- GET_X_LPARAM(lParam),
- GET_Y_LPARAM(lParam),
- LOWORD(wParam));
+ InitMouseEvent(event, pt.x, pt.y, LOWORD(wParam));
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);
-#else
- (void) wParam;
- (void) lParam;
+#else // !wxUSE_MOUSEWHEEL
+ wxUnusedVar(wParam);
+ wxUnusedVar(lParam);
- return FALSE;
-#endif
+ return false;
+#endif // wxUSE_MOUSEWHEEL/!wxUSE_MOUSEWHEEL
}
+void wxWindowMSW::GenerateMouseLeave()
+{
+ m_mouseInWindow = false;
+
+ int state = 0;
+ if ( wxIsShiftDown() )
+ state |= MK_SHIFT;
+ if ( wxIsCtrlDown() )
+ state |= MK_CONTROL;
+
+ // Only the high-order bit should be tested
+ if ( GetKeyState( VK_LBUTTON ) & (1<<15) )
+ state |= MK_LBUTTON;
+ if ( GetKeyState( VK_MBUTTON ) & (1<<15) )
+ state |= MK_MBUTTON;
+ if ( GetKeyState( VK_RBUTTON ) & (1<<15) )
+ state |= MK_RBUTTON;
+
+ POINT pt;
+#ifdef __WXWINCE__
+ if ( !::GetCursorPosWinCE(&pt) )
+#else
+ if ( !::GetCursorPos(&pt) )
+#endif
+ {
+ 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 event(wxEVT_LEAVE_WINDOW);
+ InitMouseEvent(event, pt.x, pt.y, state);
+
+ (void)GetEventHandler()->ProcessEvent(event);
+}
// ---------------------------------------------------------------------------
// keyboard handling
event.m_controlDown = wxIsCtrlDown();
event.m_altDown = (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN;
- event.m_eventObject = (wxWindow *)this; // const_cast
+ event.SetEventObject((wxWindow *)this); // const_cast
event.m_keyCode = id;
+#if wxUSE_UNICODE
+ event.m_uniChar = (wxChar) wParam;
+#endif
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;
+#ifdef __WXWINCE__
+ GetCursorPosWinCE(&pt);
+#else
GetCursorPos(&pt);
+#endif
RECT rect;
GetWindowRect(GetHwnd(),&rect);
pt.x -= rect.left;
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.
id = wParam;
- if ( (id > 0) && (id < 27) )
- {
- switch (id)
- {
- case 13:
- id = WXK_RETURN;
- break;
-
- case 8:
- id = WXK_BACK;
- break;
-
- case 9:
- id = WXK_TAB;
- break;
-
- default:
- ctrlDown = TRUE;
- break;
- }
- }
}
else // we're called from WM_KEYDOWN
{
+ // don't pass lParam to wxCharCodeMSWToWX() here because we don't want
+ // to get numpad key codes: CHAR events should use the logical keys
+ // such as WXK_HOME instead of WXK_NUMPAD_HOME which is for KEY events
id = wxCharCodeMSWToWX(wParam);
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);
bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam)
{
- int id = wxCharCodeMSWToWX(wParam);
+ int id = wxCharCodeMSWToWX(wParam, lParam);
if ( !id )
{
id = wParam;
}
- if ( id != -1 ) // VZ: does this ever happen (FIXME)?
- {
- wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam));
- if ( GetEventHandler()->ProcessEvent(event) )
- {
- return TRUE;
- }
- }
-
- return FALSE;
+ wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam));
+ return GetEventHandler()->ProcessEvent(event);
}
bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
{
- int id = wxCharCodeMSWToWX(wParam);
+ int id = wxCharCodeMSWToWX(wParam, lParam);
if ( !id )
{
id = wParam;
}
- if ( id != -1 ) // VZ: does this ever happen (FIXME)?
- {
- wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam));
- if ( GetEventHandler()->ProcessEvent(event) )
- return TRUE;
- }
-
- return FALSE;
+ wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam));
+ return GetEventHandler()->ProcessEvent(event);
}
-#ifdef __WIN32__
-
-int wxWindowMSW::HandleMenuChar(int chAccel, WXLPARAM lParam)
+int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel),
+ WXLPARAM WXUNUSED_IN_WINCE(lParam))
{
+ // FIXME: implement GetMenuItemCount for WinCE, possibly
+ // in terms of GetMenuItemInfo
+#ifndef __WXWINCE__
const HMENU hmenu = (HMENU)lParam;
MENUITEMINFO mii;
wxZeroMemory(mii);
mii.cbSize = sizeof(MENUITEMINFO);
+
+ // we could use MIIM_FTYPE here as we only need to know if the item is
+ // ownerdrawn or not and not dwTypeData which MIIM_TYPE also returns, but
+ // MIIM_FTYPE is not supported under Win95
mii.fMask = MIIM_TYPE | MIIM_DATA;
// find if we have this letter in any owner drawn item
const int count = ::GetMenuItemCount(hmenu);
for ( int i = 0; i < count; i++ )
{
+ // previous loop iteration could modify it, reset it back before
+ // calling GetMenuItemInfo() to prevent it from overflowing dwTypeData
+ mii.cch = 0;
+
if ( ::GetMenuItemInfo(hmenu, i, TRUE, &mii) )
{
if ( mii.fType == MFT_OWNERDRAW )
// FIXME-UNICODE: this comparison doesn't risk to work
// for non ASCII accelerator characters I'm afraid, but
// what can we do?
- if ( wxToupper(*p) == chAccel )
+ if ( (wchar_t)wxToupper(*p) == (wchar_t)chAccel )
{
return i;
}
}
}
}
- 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
+ // it's not fatal, so don't show error, but still log it
wxLogLastError(_T("GetMenuItemInfo"));
}
}
-
+#endif
return wxNOT_FOUND;
}
-#endif // __WIN32__
+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;
+ wxClipboardTextEvent evt(type, GetId());
+
+ evt.SetEventObject(this);
+
+ return GetEventHandler()->ProcessEvent(evt);
+}
// ---------------------------------------------------------------------------
// 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;
+ wxUnusedVar(msg);
+ wxUnusedVar(x);
+ wxUnusedVar(y);
+ wxUnusedVar(flags);
+ 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 )
wxScrollWinEvent event;
event.SetPosition(pos);
event.SetOrientation(orientation);
- event.m_eventObject = this;
+ event.SetEventObject(this);
switch ( wParam )
{
case SB_TOP:
- event.m_eventType = wxEVT_SCROLLWIN_TOP;
+ event.SetEventType(wxEVT_SCROLLWIN_TOP);
break;
case SB_BOTTOM:
- event.m_eventType = wxEVT_SCROLLWIN_BOTTOM;
+ event.SetEventType(wxEVT_SCROLLWIN_BOTTOM);
break;
case SB_LINEUP:
- event.m_eventType = wxEVT_SCROLLWIN_LINEUP;
+ event.SetEventType(wxEVT_SCROLLWIN_LINEUP);
break;
case SB_LINEDOWN:
- event.m_eventType = wxEVT_SCROLLWIN_LINEDOWN;
+ event.SetEventType(wxEVT_SCROLLWIN_LINEDOWN);
break;
case SB_PAGEUP:
- event.m_eventType = wxEVT_SCROLLWIN_PAGEUP;
+ event.SetEventType(wxEVT_SCROLLWIN_PAGEUP);
break;
case SB_PAGEDOWN:
- event.m_eventType = wxEVT_SCROLLWIN_PAGEDOWN;
+ event.SetEventType(wxEVT_SCROLLWIN_PAGEDOWN);
break;
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
// be done only for these two SB_ events as they are the only one
// carrying the scrollbar position)
{
- SCROLLINFO scrollInfo;
- wxZeroMemory(scrollInfo);
- scrollInfo.cbSize = sizeof(SCROLLINFO);
+ WinStruct<SCROLLINFO> scrollInfo;
scrollInfo.fMask = SIF_TRACKPOS;
if ( !::GetScrollInfo(GetHwnd(),
: SB_VERT,
&scrollInfo) )
{
- wxLogLastError(_T("GetScrollInfo"));
+ // Not necessarily an error, if there are no scrollbars yet.
+ // wxLogLastError(_T("GetScrollInfo"));
}
event.SetPosition(scrollInfo.nTrackPos);
}
-#endif // Win32
- event.m_eventType = wParam == SB_THUMBPOSITION
+ event.SetEventType( wParam == SB_THUMBPOSITION
? wxEVT_SCROLLWIN_THUMBRELEASE
- : wxEVT_SCROLLWIN_THUMBTRACK;
+ : wxEVT_SCROLLWIN_THUMBTRACK );
break;
default:
- return FALSE;
+ return false;
}
return GetEventHandler()->ProcessEvent(event);
// global functions
// ===========================================================================
-void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont *the_font)
+void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont& the_font)
{
TEXTMETRIC tm;
HDC dc = ::GetDC((HWND) wnd);
- HFONT fnt =0;
HFONT was = 0;
- if ( the_font )
- {
- // the_font->UseResource();
- // the_font->RealizeResource();
- fnt = (HFONT)((wxFont *)the_font)->GetResourceHandle(); // const_cast
- if ( fnt )
- was = (HFONT) SelectObject(dc,fnt);
- }
+
+ // the_font.UseResource();
+ // the_font.RealizeResource();
+ HFONT fnt = (HFONT)the_font.GetResourceHandle(); // const_cast
+ if ( fnt )
+ was = (HFONT) SelectObject(dc,fnt);
+
GetTextMetrics(dc, &tm);
- if ( the_font && fnt && was )
+ if ( fnt && was )
{
SelectObject(dc,was);
}
if ( y )
*y = tm.tmHeight + tm.tmExternalLeading;
- // if ( the_font )
- // the_font->ReleaseResource();
+ // the_font.ReleaseResource();
+}
+
+// use the "extended" bit (24) of lParam to distinguish extended keys
+// from normal keys as the same key is sent
+static inline
+int ChooseNormalOrExtended(int lParam, int keyNormal, int keyExtended)
+{
+ // except that if lParam is 0, it means we don't have real lParam from
+ // WM_KEYDOWN but are just translating just a VK constant (e.g. done from
+ // msw/treectrl.cpp when processing TVN_KEYDOWN) -- then assume this is a
+ // non-numpad (hence extended) key as this is a more common case
+ return !lParam || (lParam & (1 << 24)) ? keyExtended : keyNormal;
}
+// this array contains the Windows virtual key codes which map one to one to
+// WXK_xxx constants and is used in wxCharCodeMSWToWX/WXToMSW() below
+//
+// note that keys having a normal and numpad version (e.g. WXK_HOME and
+// WXK_NUMPAD_HOME) are not included in this table as the mapping is not 1-to-1
+static const struct wxKeyMapping
+{
+ int vk;
+ wxKeyCode wxk;
+} gs_specialKeys[] =
+{
+ { VK_CANCEL, WXK_CANCEL },
+ { VK_BACK, WXK_BACK },
+ { VK_TAB, WXK_TAB },
+ { VK_CLEAR, WXK_CLEAR },
+ { VK_SHIFT, WXK_SHIFT },
+ { VK_CONTROL, WXK_CONTROL },
+ { VK_MENU , WXK_ALT },
+ { VK_PAUSE, WXK_PAUSE },
+ { VK_CAPITAL, WXK_CAPITAL },
+ { VK_SPACE, WXK_SPACE },
+ { VK_ESCAPE, WXK_ESCAPE },
+ { VK_SELECT, WXK_SELECT },
+ { VK_PRINT, WXK_PRINT },
+ { VK_EXECUTE, WXK_EXECUTE },
+ { VK_SNAPSHOT, WXK_SNAPSHOT },
+ { VK_HELP, WXK_HELP },
+
+ { VK_NUMPAD0, WXK_NUMPAD0 },
+ { VK_NUMPAD1, WXK_NUMPAD1 },
+ { VK_NUMPAD2, WXK_NUMPAD2 },
+ { VK_NUMPAD3, WXK_NUMPAD3 },
+ { VK_NUMPAD4, WXK_NUMPAD4 },
+ { VK_NUMPAD5, WXK_NUMPAD5 },
+ { VK_NUMPAD6, WXK_NUMPAD6 },
+ { VK_NUMPAD7, WXK_NUMPAD7 },
+ { VK_NUMPAD8, WXK_NUMPAD8 },
+ { VK_NUMPAD9, WXK_NUMPAD9 },
+ { VK_MULTIPLY, WXK_NUMPAD_MULTIPLY },
+ { VK_ADD, WXK_NUMPAD_ADD },
+ { VK_SUBTRACT, WXK_NUMPAD_SUBTRACT },
+ { VK_DECIMAL, WXK_NUMPAD_DECIMAL },
+ { VK_DIVIDE, WXK_NUMPAD_DIVIDE },
+
+ { VK_F1, WXK_F1 },
+ { VK_F2, WXK_F2 },
+ { VK_F3, WXK_F3 },
+ { VK_F4, WXK_F4 },
+ { VK_F5, WXK_F5 },
+ { VK_F6, WXK_F6 },
+ { VK_F7, WXK_F7 },
+ { VK_F8, WXK_F8 },
+ { VK_F9, WXK_F9 },
+ { VK_F10, WXK_F10 },
+ { VK_F11, WXK_F11 },
+ { VK_F12, WXK_F12 },
+ { VK_F13, WXK_F13 },
+ { VK_F14, WXK_F14 },
+ { VK_F15, WXK_F15 },
+ { VK_F16, WXK_F16 },
+ { VK_F17, WXK_F17 },
+ { VK_F18, WXK_F18 },
+ { VK_F19, WXK_F19 },
+ { VK_F20, WXK_F20 },
+ { VK_F21, WXK_F21 },
+ { VK_F22, WXK_F22 },
+ { VK_F23, WXK_F23 },
+ { VK_F24, WXK_F24 },
+
+ { VK_NUMLOCK, WXK_NUMLOCK },
+ { VK_SCROLL, WXK_SCROLL },
+
+#ifdef VK_APPS
+ { VK_LWIN, WXK_WINDOWS_LEFT },
+ { VK_RWIN, WXK_WINDOWS_RIGHT },
+ { VK_APPS, WXK_WINDOWS_MENU },
+#endif // VK_APPS defined
+};
+
// Returns 0 if was a normal ASCII value, not a special key. This indicates that
// the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
-int wxCharCodeMSWToWX(int keySym)
+int wxCharCodeMSWToWX(int vk, WXLPARAM lParam)
+{
+ // check the table first
+ for ( size_t n = 0; n < WXSIZEOF(gs_specialKeys); n++ )
+ {
+ if ( gs_specialKeys[n].vk == vk )
+ return gs_specialKeys[n].wxk;
+ }
+
+ // keys requiring special handling
+ int wxk;
+ switch ( vk )
+ {
+ // the mapping for these keys may be incorrect on non-US keyboards so
+ // maybe we shouldn't map them to ASCII values at all
+ case VK_OEM_1: wxk = ';'; break;
+ case VK_OEM_PLUS: wxk = '+'; break;
+ case VK_OEM_COMMA: wxk = ','; break;
+ case VK_OEM_MINUS: wxk = '-'; break;
+ case VK_OEM_PERIOD: wxk = '.'; break;
+ case VK_OEM_2: wxk = '/'; break;
+ case VK_OEM_3: wxk = '~'; break;
+ case VK_OEM_4: wxk = '['; break;
+ case VK_OEM_5: wxk = '\\'; break;
+ case VK_OEM_6: wxk = ']'; break;
+ case VK_OEM_7: wxk = '\''; break;
+
+ // handle extended keys
+ case VK_PRIOR:
+ wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEUP, WXK_PAGEUP);
+ break;
+
+ case VK_NEXT:
+ wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEDOWN, WXK_PAGEDOWN);
+ break;
+
+ case VK_END:
+ wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_END, WXK_END);
+ break;
+
+ case VK_HOME:
+ wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_HOME, WXK_HOME);
+ break;
+
+ case VK_LEFT:
+ wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_LEFT, WXK_LEFT);
+ break;
+
+ case VK_UP:
+ wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_UP, WXK_UP);
+ break;
+
+ case VK_RIGHT:
+ wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_RIGHT, WXK_RIGHT);
+ break;
+
+ case VK_DOWN:
+ wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DOWN, WXK_DOWN);
+ break;
+
+ case VK_INSERT:
+ wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_INSERT, WXK_INSERT);
+ break;
+
+ case VK_DELETE:
+ wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DELETE, WXK_DELETE);
+ break;
+
+ case VK_RETURN:
+ // don't use ChooseNormalOrExtended() here as the keys are reversed
+ // here: numpad enter is the extended one
+ wxk = lParam && (lParam & (1 << 24)) ? WXK_NUMPAD_ENTER : WXK_RETURN;
+ break;
+
+ default:
+ wxk = 0;
+ }
+
+ return wxk;
+}
+
+WXWORD wxCharCodeWXToMSW(int wxk, bool *isVirtual)
{
- int id;
- switch (keySym)
- {
- case VK_CANCEL: id = WXK_CANCEL; break;
- case VK_BACK: id = WXK_BACK; break;
- case VK_TAB: id = WXK_TAB; break;
- case VK_CLEAR: id = WXK_CLEAR; break;
- case VK_RETURN: id = WXK_RETURN; break;
- case VK_SHIFT: id = WXK_SHIFT; break;
- case VK_CONTROL: id = WXK_CONTROL; break;
- case VK_MENU : id = WXK_MENU; break;
- case VK_PAUSE: id = WXK_PAUSE; break;
- case VK_CAPITAL: id = WXK_CAPITAL; break;
- case VK_SPACE: id = WXK_SPACE; break;
- case VK_ESCAPE: id = WXK_ESCAPE; break;
- case VK_PRIOR: id = WXK_PRIOR; break;
- case VK_NEXT : id = WXK_NEXT; break;
- case VK_END: id = WXK_END; break;
- case VK_HOME : id = WXK_HOME; break;
- case VK_LEFT : id = WXK_LEFT; break;
- case VK_UP: id = WXK_UP; break;
- case VK_RIGHT: id = WXK_RIGHT; break;
- case VK_DOWN : id = WXK_DOWN; break;
- case VK_SELECT: id = WXK_SELECT; break;
- case VK_PRINT: id = WXK_PRINT; break;
- case VK_EXECUTE: id = WXK_EXECUTE; break;
- case VK_INSERT: id = WXK_INSERT; break;
- case VK_DELETE: id = WXK_DELETE; break;
- case VK_HELP : id = WXK_HELP; break;
- case VK_NUMPAD0: id = WXK_NUMPAD0; break;
- case VK_NUMPAD1: id = WXK_NUMPAD1; break;
- case VK_NUMPAD2: id = WXK_NUMPAD2; break;
- case VK_NUMPAD3: id = WXK_NUMPAD3; break;
- case VK_NUMPAD4: id = WXK_NUMPAD4; break;
- case VK_NUMPAD5: id = WXK_NUMPAD5; break;
- case VK_NUMPAD6: id = WXK_NUMPAD6; break;
- case VK_NUMPAD7: id = WXK_NUMPAD7; break;
- case VK_NUMPAD8: id = WXK_NUMPAD8; break;
- case VK_NUMPAD9: id = WXK_NUMPAD9; break;
- case VK_MULTIPLY: id = WXK_NUMPAD_MULTIPLY; break;
- case VK_ADD: id = WXK_NUMPAD_ADD; break;
- case VK_SUBTRACT: id = WXK_NUMPAD_SUBTRACT; break;
- case VK_DECIMAL: id = WXK_NUMPAD_DECIMAL; break;
- case VK_DIVIDE: id = WXK_NUMPAD_DIVIDE; break;
- case VK_F1: id = WXK_F1; break;
- case VK_F2: id = WXK_F2; break;
- case VK_F3: id = WXK_F3; break;
- case VK_F4: id = WXK_F4; break;
- case VK_F5: id = WXK_F5; break;
- case VK_F6: id = WXK_F6; break;
- case VK_F7: id = WXK_F7; break;
- case VK_F8: id = WXK_F8; break;
- case VK_F9: id = WXK_F9; break;
- case VK_F10: id = WXK_F10; break;
- case VK_F11: id = WXK_F11; break;
- case VK_F12: id = WXK_F12; break;
- case VK_F13: id = WXK_F13; break;
- case VK_F14: id = WXK_F14; break;
- case VK_F15: id = WXK_F15; break;
- case VK_F16: id = WXK_F16; break;
- case VK_F17: id = WXK_F17; break;
- case VK_F18: id = WXK_F18; break;
- case VK_F19: id = WXK_F19; break;
- case VK_F20: id = WXK_F20; break;
- case VK_F21: id = WXK_F21; break;
- case VK_F22: id = WXK_F22; break;
- case VK_F23: id = WXK_F23; break;
- case VK_F24: id = WXK_F24; break;
- case VK_NUMLOCK: id = WXK_NUMLOCK; break;
- case VK_SCROLL: id = WXK_SCROLL; break;
-
- case VK_OEM_1: id = ';'; break;
- case VK_OEM_PLUS: id = '+'; break;
- case VK_OEM_COMMA: id = ','; break;
- case VK_OEM_MINUS: id = '-'; break;
- case VK_OEM_PERIOD: id = '.'; break;
- case VK_OEM_2: id = '/'; break;
- case VK_OEM_3: id = '~'; break;
- case VK_OEM_4: id = '['; break;
- case VK_OEM_5: id = '\\'; break;
- case VK_OEM_6: id = ']'; break;
- case VK_OEM_7: id = '\''; break;
+ if ( isVirtual )
+ *isVirtual = true;
+
+ // check the table first
+ for ( size_t n = 0; n < WXSIZEOF(gs_specialKeys); n++ )
+ {
+ if ( gs_specialKeys[n].wxk == wxk )
+ return gs_specialKeys[n].vk;
+ }
+
+ // and then check for special keys not included in the table
+ WXWORD vk;
+ switch ( wxk )
+ {
+ case WXK_PAGEUP:
+ case WXK_NUMPAD_PAGEUP:
+ vk = VK_PRIOR;
+ break;
+
+ case WXK_PAGEDOWN:
+ case WXK_NUMPAD_PAGEDOWN:
+ vk = VK_NEXT;
+ break;
+
+ case WXK_END:
+ case WXK_NUMPAD_END:
+ vk = VK_END;
+ break;
+
+ case WXK_HOME:
+ case WXK_NUMPAD_HOME:
+ vk = VK_HOME;
+ break;
+
+ case WXK_LEFT:
+ case WXK_NUMPAD_LEFT:
+ vk = VK_LEFT;
+ break;
+
+ case WXK_UP:
+ case WXK_NUMPAD_UP:
+ vk = VK_UP;
+ break;
+
+ case WXK_RIGHT:
+ case WXK_NUMPAD_RIGHT:
+ vk = VK_RIGHT;
+ break;
+
+ case WXK_DOWN:
+ case WXK_NUMPAD_DOWN:
+ vk = VK_DOWN;
+ break;
+
+ case WXK_INSERT:
+ case WXK_NUMPAD_INSERT:
+ vk = VK_INSERT;
+ break;
+
+ case WXK_DELETE:
+ case WXK_NUMPAD_DELETE:
+ vk = VK_DELETE;
+ break;
default:
- id = 0;
- }
-
- return id;
-}
-
-int wxCharCodeWXToMSW(int id, bool *isVirtual)
-{
- *isVirtual = TRUE;
- int keySym = 0;
- switch (id)
- {
- case WXK_CANCEL: keySym = VK_CANCEL; break;
- case WXK_CLEAR: keySym = VK_CLEAR; break;
- case WXK_SHIFT: keySym = VK_SHIFT; break;
- case WXK_CONTROL: keySym = VK_CONTROL; break;
- case WXK_MENU : keySym = VK_MENU; break;
- case WXK_PAUSE: keySym = VK_PAUSE; break;
- case WXK_PRIOR: keySym = VK_PRIOR; break;
- case WXK_NEXT : keySym = VK_NEXT; break;
- case WXK_END: keySym = VK_END; break;
- case WXK_HOME : keySym = VK_HOME; break;
- case WXK_LEFT : keySym = VK_LEFT; break;
- case WXK_UP: keySym = VK_UP; break;
- case WXK_RIGHT: keySym = VK_RIGHT; break;
- case WXK_DOWN : keySym = VK_DOWN; break;
- case WXK_SELECT: keySym = VK_SELECT; break;
- case WXK_PRINT: keySym = VK_PRINT; break;
- case WXK_EXECUTE: keySym = VK_EXECUTE; break;
- case WXK_INSERT: keySym = VK_INSERT; break;
- case WXK_DELETE: keySym = VK_DELETE; break;
- case WXK_HELP : keySym = VK_HELP; break;
- case WXK_NUMPAD0: keySym = VK_NUMPAD0; break;
- case WXK_NUMPAD1: keySym = VK_NUMPAD1; break;
- case WXK_NUMPAD2: keySym = VK_NUMPAD2; break;
- case WXK_NUMPAD3: keySym = VK_NUMPAD3; break;
- case WXK_NUMPAD4: keySym = VK_NUMPAD4; break;
- case WXK_NUMPAD5: keySym = VK_NUMPAD5; break;
- case WXK_NUMPAD6: keySym = VK_NUMPAD6; break;
- case WXK_NUMPAD7: keySym = VK_NUMPAD7; break;
- case WXK_NUMPAD8: keySym = VK_NUMPAD8; break;
- case WXK_NUMPAD9: keySym = VK_NUMPAD9; break;
- case WXK_NUMPAD_MULTIPLY: keySym = VK_MULTIPLY; break;
- case WXK_NUMPAD_ADD: keySym = VK_ADD; break;
- case WXK_NUMPAD_SUBTRACT: keySym = VK_SUBTRACT; break;
- case WXK_NUMPAD_DECIMAL: keySym = VK_DECIMAL; break;
- case WXK_NUMPAD_DIVIDE: keySym = VK_DIVIDE; break;
- case WXK_F1: keySym = VK_F1; break;
- case WXK_F2: keySym = VK_F2; break;
- case WXK_F3: keySym = VK_F3; break;
- case WXK_F4: keySym = VK_F4; break;
- case WXK_F5: keySym = VK_F5; break;
- case WXK_F6: keySym = VK_F6; break;
- case WXK_F7: keySym = VK_F7; break;
- case WXK_F8: keySym = VK_F8; break;
- case WXK_F9: keySym = VK_F9; break;
- case WXK_F10: keySym = VK_F10; break;
- case WXK_F11: keySym = VK_F11; break;
- case WXK_F12: keySym = VK_F12; break;
- case WXK_F13: keySym = VK_F13; break;
- case WXK_F14: keySym = VK_F14; break;
- case WXK_F15: keySym = VK_F15; break;
- case WXK_F16: keySym = VK_F16; break;
- case WXK_F17: keySym = VK_F17; break;
- case WXK_F18: keySym = VK_F18; break;
- case WXK_F19: keySym = VK_F19; break;
- case WXK_F20: keySym = VK_F20; break;
- case WXK_F21: keySym = VK_F21; break;
- case WXK_F22: keySym = VK_F22; break;
- case WXK_F23: keySym = VK_F23; break;
- case WXK_F24: keySym = VK_F24; break;
- case WXK_NUMLOCK: keySym = VK_NUMLOCK; break;
- case WXK_SCROLL: keySym = VK_SCROLL; break;
- default:
- {
- *isVirtual = FALSE;
- keySym = id;
+ if ( isVirtual )
+ *isVirtual = false;
+ vk = (WXWORD)wxk;
break;
- }
}
- return keySym;
+
+ return vk;
}
+// small helper for wxGetKeyState() and wxGetMouseState()
+static inline bool wxIsKeyDown(WXWORD vk)
+{
+ // 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
+ return (::GetAsyncKeyState(vk) & (1<<15)) != 0;
+}
+
+bool wxGetKeyState(wxKeyCode key)
+{
+ // although this does work under Windows, it is not supported under other
+ // platforms so don't allow it, you must use wxGetMouseState() instead
+ wxASSERT_MSG( key != VK_LBUTTON &&
+ key != VK_RBUTTON &&
+ key != VK_MBUTTON,
+ wxT("can't use wxGetKeyState() for mouse buttons") );
+
+ const WXWORD vk = wxCharCodeWXToMSW(key);
+
+ // if the requested key is a LED key, return true if the led is pressed
+ if ( key == WXK_NUMLOCK || key == WXK_CAPITAL || key == WXK_SCROLL )
+ {
+ // low order bit means LED is highlighted and high order one means the
+ // key is down; for compatibility with the other ports return true if
+ // either one is set
+ return ::GetKeyState(vk) != 0;
+
+ }
+ else // normal key
+ {
+ return wxIsKeyDown(vk);
+ }
+}
+
+
+wxMouseState wxGetMouseState()
+{
+ wxMouseState ms;
+ POINT pt;
+ GetCursorPos( &pt );
+
+ ms.SetX(pt.x);
+ ms.SetY(pt.y);
+ ms.SetLeftDown(wxIsKeyDown(VK_LBUTTON));
+ ms.SetMiddleDown(wxIsKeyDown(VK_MBUTTON));
+ ms.SetRightDown(wxIsKeyDown(VK_RBUTTON));
+
+ ms.SetControlDown(wxIsKeyDown(VK_CONTROL));
+ ms.SetShiftDown(wxIsKeyDown(VK_SHIFT));
+ ms.SetAltDown(wxIsKeyDown(VK_MENU));
+// ms.SetMetaDown();
+
+ return ms;
+}
+
+
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(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
- FreeProcInstance(wxTheKeyboardHookProc);
-#endif
}
}
DWORD hiWord = HIWORD(lParam);
if ( nCode != HC_NOREMOVE && ((hiWord & KF_UP) == 0) )
{
- int id = wxCharCodeMSWToWX(wParam);
+ int id = wxCharCodeMSWToWX(wParam, lParam);
if ( id != 0 )
{
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.SetEventObject(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 )
else
{
handler = wxTheApp;
- event.SetId(-1);
+ event.SetId(wxID_ANY);
}
if ( handler && handler->ProcessEvent(event) )
#endif // !__WXMICROWIN__
#ifdef __WXDEBUG__
-const char *wxGetMessageName(int message)
+const wxChar *wxGetMessageName(int message)
{
switch ( message )
{
- case 0x0000: return "WM_NULL";
- case 0x0001: return "WM_CREATE";
- case 0x0002: return "WM_DESTROY";
- case 0x0003: return "WM_MOVE";
- case 0x0005: return "WM_SIZE";
- case 0x0006: return "WM_ACTIVATE";
- case 0x0007: return "WM_SETFOCUS";
- case 0x0008: return "WM_KILLFOCUS";
- case 0x000A: return "WM_ENABLE";
- case 0x000B: return "WM_SETREDRAW";
- case 0x000C: return "WM_SETTEXT";
- case 0x000D: return "WM_GETTEXT";
- case 0x000E: return "WM_GETTEXTLENGTH";
- case 0x000F: return "WM_PAINT";
- case 0x0010: return "WM_CLOSE";
- case 0x0011: return "WM_QUERYENDSESSION";
- case 0x0012: return "WM_QUIT";
- case 0x0013: return "WM_QUERYOPEN";
- case 0x0014: return "WM_ERASEBKGND";
- case 0x0015: return "WM_SYSCOLORCHANGE";
- case 0x0016: return "WM_ENDSESSION";
- case 0x0017: return "WM_SYSTEMERROR";
- case 0x0018: return "WM_SHOWWINDOW";
- case 0x0019: return "WM_CTLCOLOR";
- case 0x001A: return "WM_WININICHANGE";
- case 0x001B: return "WM_DEVMODECHANGE";
- case 0x001C: return "WM_ACTIVATEAPP";
- case 0x001D: return "WM_FONTCHANGE";
- case 0x001E: return "WM_TIMECHANGE";
- case 0x001F: return "WM_CANCELMODE";
- case 0x0020: return "WM_SETCURSOR";
- case 0x0021: return "WM_MOUSEACTIVATE";
- case 0x0022: return "WM_CHILDACTIVATE";
- case 0x0023: return "WM_QUEUESYNC";
- case 0x0024: return "WM_GETMINMAXINFO";
- case 0x0026: return "WM_PAINTICON";
- case 0x0027: return "WM_ICONERASEBKGND";
- case 0x0028: return "WM_NEXTDLGCTL";
- case 0x002A: return "WM_SPOOLERSTATUS";
- case 0x002B: return "WM_DRAWITEM";
- case 0x002C: return "WM_MEASUREITEM";
- case 0x002D: return "WM_DELETEITEM";
- case 0x002E: return "WM_VKEYTOITEM";
- case 0x002F: return "WM_CHARTOITEM";
- case 0x0030: return "WM_SETFONT";
- case 0x0031: return "WM_GETFONT";
- case 0x0037: return "WM_QUERYDRAGICON";
- case 0x0039: return "WM_COMPAREITEM";
- case 0x0041: return "WM_COMPACTING";
- case 0x0044: return "WM_COMMNOTIFY";
- case 0x0046: return "WM_WINDOWPOSCHANGING";
- 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 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
- case 0x0051: return "WM_INPUTLANGCHANGE";
- case 0x0052: return "WM_TCARD";
- case 0x0053: return "WM_HELP";
- case 0x0054: return "WM_USERCHANGED";
- case 0x0055: return "WM_NOTIFYFORMAT";
- case 0x007B: return "WM_CONTEXTMENU";
- case 0x007C: return "WM_STYLECHANGING";
- case 0x007D: return "WM_STYLECHANGED";
- 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 0x0083: return "WM_NCCALCSIZE";
- case 0x0084: return "WM_NCHITTEST";
- case 0x0085: return "WM_NCPAINT";
- case 0x0086: return "WM_NCACTIVATE";
- case 0x0087: return "WM_GETDLGCODE";
- case 0x00A0: return "WM_NCMOUSEMOVE";
- case 0x00A1: return "WM_NCLBUTTONDOWN";
- case 0x00A2: return "WM_NCLBUTTONUP";
- case 0x00A3: return "WM_NCLBUTTONDBLCLK";
- case 0x00A4: return "WM_NCRBUTTONDOWN";
- case 0x00A5: return "WM_NCRBUTTONUP";
- case 0x00A6: return "WM_NCRBUTTONDBLCLK";
- case 0x00A7: return "WM_NCMBUTTONDOWN";
- case 0x00A8: return "WM_NCMBUTTONUP";
- case 0x00A9: return "WM_NCMBUTTONDBLCLK";
- case 0x0100: return "WM_KEYDOWN";
- case 0x0101: return "WM_KEYUP";
- case 0x0102: return "WM_CHAR";
- case 0x0103: return "WM_DEADCHAR";
- case 0x0104: return "WM_SYSKEYDOWN";
- case 0x0105: return "WM_SYSKEYUP";
- case 0x0106: return "WM_SYSCHAR";
- 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 0x0112: return "WM_SYSCOMMAND";
- case 0x0113: return "WM_TIMER";
- case 0x0114: return "WM_HSCROLL";
- case 0x0115: return "WM_VSCROLL";
- case 0x0116: return "WM_INITMENU";
- case 0x0117: return "WM_INITMENUPOPUP";
- case 0x011F: return "WM_MENUSELECT";
- case 0x0120: return "WM_MENUCHAR";
- case 0x0121: return "WM_ENTERIDLE";
- case 0x0200: return "WM_MOUSEMOVE";
- case 0x0201: return "WM_LBUTTONDOWN";
- case 0x0202: return "WM_LBUTTONUP";
- case 0x0203: return "WM_LBUTTONDBLCLK";
- case 0x0204: return "WM_RBUTTONDOWN";
- case 0x0205: return "WM_RBUTTONUP";
- case 0x0206: return "WM_RBUTTONDBLCLK";
- case 0x0207: return "WM_MBUTTONDOWN";
- case 0x0208: return "WM_MBUTTONUP";
- case 0x0209: return "WM_MBUTTONDBLCLK";
- case 0x020A: return "WM_MOUSEWHEEL";
- case 0x0210: return "WM_PARENTNOTIFY";
- 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 0x0222: return "WM_MDIACTIVATE";
- case 0x0223: return "WM_MDIRESTORE";
- case 0x0224: return "WM_MDINEXT";
- case 0x0225: return "WM_MDIMAXIMIZE";
- case 0x0226: return "WM_MDITILE";
- case 0x0227: return "WM_MDICASCADE";
- case 0x0228: return "WM_MDIICONARRANGE";
- case 0x0229: return "WM_MDIGETACTIVE";
- 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 0x0284: return "WM_IME_COMPOSITIONFULL";
- case 0x0285: return "WM_IME_SELECT";
- 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 0x0302: return "WM_PASTE";
- case 0x0303: return "WM_CLEAR";
- case 0x0304: return "WM_UNDO";
- case 0x0305: return "WM_RENDERFORMAT";
- case 0x0306: return "WM_RENDERALLFORMATS";
- case 0x0307: return "WM_DESTROYCLIPBOARD";
- case 0x0308: return "WM_DRAWCLIPBOARD";
- case 0x0309: return "WM_PAINTCLIPBOARD";
- case 0x030A: return "WM_VSCROLLCLIPBOARD";
- case 0x030B: return "WM_SIZECLIPBOARD";
- case 0x030C: return "WM_ASKCBFORMATNAME";
- case 0x030D: return "WM_CHANGECBCHAIN";
- case 0x030E: return "WM_HSCROLLCLIPBOARD";
- case 0x030F: return "WM_QUERYNEWPALETTE";
- case 0x0310: return "WM_PALETTEISCHANGING";
- case 0x0311: return "WM_PALETTECHANGED";
+ case 0x0000: return wxT("WM_NULL");
+ case 0x0001: return wxT("WM_CREATE");
+ case 0x0002: return wxT("WM_DESTROY");
+ case 0x0003: return wxT("WM_MOVE");
+ case 0x0005: return wxT("WM_SIZE");
+ case 0x0006: return wxT("WM_ACTIVATE");
+ case 0x0007: return wxT("WM_SETFOCUS");
+ case 0x0008: return wxT("WM_KILLFOCUS");
+ case 0x000A: return wxT("WM_ENABLE");
+ case 0x000B: return wxT("WM_SETREDRAW");
+ case 0x000C: return wxT("WM_SETTEXT");
+ case 0x000D: return wxT("WM_GETTEXT");
+ case 0x000E: return wxT("WM_GETTEXTLENGTH");
+ case 0x000F: return wxT("WM_PAINT");
+ case 0x0010: return wxT("WM_CLOSE");
+ case 0x0011: return wxT("WM_QUERYENDSESSION");
+ case 0x0012: return wxT("WM_QUIT");
+ case 0x0013: return wxT("WM_QUERYOPEN");
+ case 0x0014: return wxT("WM_ERASEBKGND");
+ case 0x0015: return wxT("WM_SYSCOLORCHANGE");
+ case 0x0016: return wxT("WM_ENDSESSION");
+ case 0x0017: return wxT("WM_SYSTEMERROR");
+ case 0x0018: return wxT("WM_SHOWWINDOW");
+ case 0x0019: return wxT("WM_CTLCOLOR");
+ case 0x001A: return wxT("WM_WININICHANGE");
+ case 0x001B: return wxT("WM_DEVMODECHANGE");
+ case 0x001C: return wxT("WM_ACTIVATEAPP");
+ case 0x001D: return wxT("WM_FONTCHANGE");
+ case 0x001E: return wxT("WM_TIMECHANGE");
+ case 0x001F: return wxT("WM_CANCELMODE");
+ case 0x0020: return wxT("WM_SETCURSOR");
+ case 0x0021: return wxT("WM_MOUSEACTIVATE");
+ case 0x0022: return wxT("WM_CHILDACTIVATE");
+ case 0x0023: return wxT("WM_QUEUESYNC");
+ case 0x0024: return wxT("WM_GETMINMAXINFO");
+ case 0x0026: return wxT("WM_PAINTICON");
+ case 0x0027: return wxT("WM_ICONERASEBKGND");
+ case 0x0028: return wxT("WM_NEXTDLGCTL");
+ case 0x002A: return wxT("WM_SPOOLERSTATUS");
+ case 0x002B: return wxT("WM_DRAWITEM");
+ case 0x002C: return wxT("WM_MEASUREITEM");
+ case 0x002D: return wxT("WM_DELETEITEM");
+ case 0x002E: return wxT("WM_VKEYTOITEM");
+ case 0x002F: return wxT("WM_CHARTOITEM");
+ case 0x0030: return wxT("WM_SETFONT");
+ case 0x0031: return wxT("WM_GETFONT");
+ case 0x0037: return wxT("WM_QUERYDRAGICON");
+ case 0x0039: return wxT("WM_COMPAREITEM");
+ case 0x0041: return wxT("WM_COMPACTING");
+ case 0x0044: return wxT("WM_COMMNOTIFY");
+ case 0x0046: return wxT("WM_WINDOWPOSCHANGING");
+ case 0x0047: return wxT("WM_WINDOWPOSCHANGED");
+ case 0x0048: return wxT("WM_POWER");
+
+ case 0x004A: return wxT("WM_COPYDATA");
+ case 0x004B: return wxT("WM_CANCELJOURNAL");
+ case 0x004E: return wxT("WM_NOTIFY");
+ case 0x0050: return wxT("WM_INPUTLANGCHANGEREQUEST");
+ case 0x0051: return wxT("WM_INPUTLANGCHANGE");
+ case 0x0052: return wxT("WM_TCARD");
+ case 0x0053: return wxT("WM_HELP");
+ case 0x0054: return wxT("WM_USERCHANGED");
+ case 0x0055: return wxT("WM_NOTIFYFORMAT");
+ case 0x007B: return wxT("WM_CONTEXTMENU");
+ case 0x007C: return wxT("WM_STYLECHANGING");
+ case 0x007D: return wxT("WM_STYLECHANGED");
+ case 0x007E: return wxT("WM_DISPLAYCHANGE");
+ case 0x007F: return wxT("WM_GETICON");
+ case 0x0080: return wxT("WM_SETICON");
+
+ case 0x0081: return wxT("WM_NCCREATE");
+ case 0x0082: return wxT("WM_NCDESTROY");
+ case 0x0083: return wxT("WM_NCCALCSIZE");
+ case 0x0084: return wxT("WM_NCHITTEST");
+ case 0x0085: return wxT("WM_NCPAINT");
+ case 0x0086: return wxT("WM_NCACTIVATE");
+ case 0x0087: return wxT("WM_GETDLGCODE");
+ case 0x00A0: return wxT("WM_NCMOUSEMOVE");
+ case 0x00A1: return wxT("WM_NCLBUTTONDOWN");
+ case 0x00A2: return wxT("WM_NCLBUTTONUP");
+ case 0x00A3: return wxT("WM_NCLBUTTONDBLCLK");
+ case 0x00A4: return wxT("WM_NCRBUTTONDOWN");
+ case 0x00A5: return wxT("WM_NCRBUTTONUP");
+ case 0x00A6: return wxT("WM_NCRBUTTONDBLCLK");
+ case 0x00A7: return wxT("WM_NCMBUTTONDOWN");
+ case 0x00A8: return wxT("WM_NCMBUTTONUP");
+ case 0x00A9: return wxT("WM_NCMBUTTONDBLCLK");
+ case 0x0100: return wxT("WM_KEYDOWN");
+ case 0x0101: return wxT("WM_KEYUP");
+ case 0x0102: return wxT("WM_CHAR");
+ case 0x0103: return wxT("WM_DEADCHAR");
+ case 0x0104: return wxT("WM_SYSKEYDOWN");
+ case 0x0105: return wxT("WM_SYSKEYUP");
+ case 0x0106: return wxT("WM_SYSCHAR");
+ case 0x0107: return wxT("WM_SYSDEADCHAR");
+ case 0x0108: return wxT("WM_KEYLAST");
+
+ case 0x010D: return wxT("WM_IME_STARTCOMPOSITION");
+ case 0x010E: return wxT("WM_IME_ENDCOMPOSITION");
+ case 0x010F: return wxT("WM_IME_COMPOSITION");
+
+ case 0x0110: return wxT("WM_INITDIALOG");
+ case 0x0111: return wxT("WM_COMMAND");
+ case 0x0112: return wxT("WM_SYSCOMMAND");
+ case 0x0113: return wxT("WM_TIMER");
+ case 0x0114: return wxT("WM_HSCROLL");
+ case 0x0115: return wxT("WM_VSCROLL");
+ case 0x0116: return wxT("WM_INITMENU");
+ case 0x0117: return wxT("WM_INITMENUPOPUP");
+ case 0x011F: return wxT("WM_MENUSELECT");
+ case 0x0120: return wxT("WM_MENUCHAR");
+ case 0x0121: return wxT("WM_ENTERIDLE");
+ case 0x0200: return wxT("WM_MOUSEMOVE");
+ case 0x0201: return wxT("WM_LBUTTONDOWN");
+ case 0x0202: return wxT("WM_LBUTTONUP");
+ case 0x0203: return wxT("WM_LBUTTONDBLCLK");
+ case 0x0204: return wxT("WM_RBUTTONDOWN");
+ case 0x0205: return wxT("WM_RBUTTONUP");
+ case 0x0206: return wxT("WM_RBUTTONDBLCLK");
+ case 0x0207: return wxT("WM_MBUTTONDOWN");
+ case 0x0208: return wxT("WM_MBUTTONUP");
+ case 0x0209: return wxT("WM_MBUTTONDBLCLK");
+ case 0x020A: return wxT("WM_MOUSEWHEEL");
+ case 0x0210: return wxT("WM_PARENTNOTIFY");
+ case 0x0211: return wxT("WM_ENTERMENULOOP");
+ case 0x0212: return wxT("WM_EXITMENULOOP");
+
+ case 0x0213: return wxT("WM_NEXTMENU");
+ case 0x0214: return wxT("WM_SIZING");
+ case 0x0215: return wxT("WM_CAPTURECHANGED");
+ case 0x0216: return wxT("WM_MOVING");
+ case 0x0218: return wxT("WM_POWERBROADCAST");
+ case 0x0219: return wxT("WM_DEVICECHANGE");
+
+ case 0x0220: return wxT("WM_MDICREATE");
+ case 0x0221: return wxT("WM_MDIDESTROY");
+ case 0x0222: return wxT("WM_MDIACTIVATE");
+ case 0x0223: return wxT("WM_MDIRESTORE");
+ case 0x0224: return wxT("WM_MDINEXT");
+ case 0x0225: return wxT("WM_MDIMAXIMIZE");
+ case 0x0226: return wxT("WM_MDITILE");
+ case 0x0227: return wxT("WM_MDICASCADE");
+ case 0x0228: return wxT("WM_MDIICONARRANGE");
+ case 0x0229: return wxT("WM_MDIGETACTIVE");
+ case 0x0230: return wxT("WM_MDISETMENU");
+ case 0x0233: return wxT("WM_DROPFILES");
+
+ case 0x0281: return wxT("WM_IME_SETCONTEXT");
+ case 0x0282: return wxT("WM_IME_NOTIFY");
+ case 0x0283: return wxT("WM_IME_CONTROL");
+ case 0x0284: return wxT("WM_IME_COMPOSITIONFULL");
+ case 0x0285: return wxT("WM_IME_SELECT");
+ case 0x0286: return wxT("WM_IME_CHAR");
+ case 0x0290: return wxT("WM_IME_KEYDOWN");
+ case 0x0291: return wxT("WM_IME_KEYUP");
+
+ case 0x0300: return wxT("WM_CUT");
+ case 0x0301: return wxT("WM_COPY");
+ case 0x0302: return wxT("WM_PASTE");
+ case 0x0303: return wxT("WM_CLEAR");
+ case 0x0304: return wxT("WM_UNDO");
+ case 0x0305: return wxT("WM_RENDERFORMAT");
+ case 0x0306: return wxT("WM_RENDERALLFORMATS");
+ case 0x0307: return wxT("WM_DESTROYCLIPBOARD");
+ case 0x0308: return wxT("WM_DRAWCLIPBOARD");
+ case 0x0309: return wxT("WM_PAINTCLIPBOARD");
+ case 0x030A: return wxT("WM_VSCROLLCLIPBOARD");
+ case 0x030B: return wxT("WM_SIZECLIPBOARD");
+ case 0x030C: return wxT("WM_ASKCBFORMATNAME");
+ case 0x030D: return wxT("WM_CHANGECBCHAIN");
+ case 0x030E: return wxT("WM_HSCROLLCLIPBOARD");
+ case 0x030F: return wxT("WM_QUERYNEWPALETTE");
+ case 0x0310: return wxT("WM_PALETTEISCHANGING");
+ case 0x0311: return wxT("WM_PALETTECHANGED");
+#if wxUSE_HOTKEY
+ case 0x0312: return wxT("WM_HOTKEY");
+#endif
-#ifdef __WIN32__
// common controls messages - although they're not strictly speaking
// standard, it's nice to decode them nevertheless
// listview
- case 0x1000 + 0: return "LVM_GETBKCOLOR";
- case 0x1000 + 1: return "LVM_SETBKCOLOR";
- case 0x1000 + 2: return "LVM_GETIMAGELIST";
- case 0x1000 + 3: return "LVM_SETIMAGELIST";
- case 0x1000 + 4: return "LVM_GETITEMCOUNT";
- case 0x1000 + 5: return "LVM_GETITEMA";
- case 0x1000 + 75: return "LVM_GETITEMW";
- case 0x1000 + 6: return "LVM_SETITEMA";
- case 0x1000 + 76: return "LVM_SETITEMW";
- case 0x1000 + 7: return "LVM_INSERTITEMA";
- case 0x1000 + 77: return "LVM_INSERTITEMW";
- case 0x1000 + 8: return "LVM_DELETEITEM";
- case 0x1000 + 9: return "LVM_DELETEALLITEMS";
- case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
- case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
- case 0x1000 + 12: return "LVM_GETNEXTITEM";
- case 0x1000 + 13: return "LVM_FINDITEMA";
- case 0x1000 + 83: return "LVM_FINDITEMW";
- case 0x1000 + 14: return "LVM_GETITEMRECT";
- case 0x1000 + 15: return "LVM_SETITEMPOSITION";
- case 0x1000 + 16: return "LVM_GETITEMPOSITION";
- case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
- case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
- case 0x1000 + 18: return "LVM_HITTEST";
- case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
- case 0x1000 + 20: return "LVM_SCROLL";
- case 0x1000 + 21: return "LVM_REDRAWITEMS";
- case 0x1000 + 22: return "LVM_ARRANGE";
- case 0x1000 + 23: return "LVM_EDITLABELA";
- case 0x1000 + 118: return "LVM_EDITLABELW";
- case 0x1000 + 24: return "LVM_GETEDITCONTROL";
- case 0x1000 + 25: return "LVM_GETCOLUMNA";
- case 0x1000 + 95: return "LVM_GETCOLUMNW";
- case 0x1000 + 26: return "LVM_SETCOLUMNA";
- case 0x1000 + 96: return "LVM_SETCOLUMNW";
- case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
- case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
- case 0x1000 + 28: return "LVM_DELETECOLUMN";
- case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
- case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
- case 0x1000 + 31: return "LVM_GETHEADER";
- case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
- case 0x1000 + 34: return "LVM_GETVIEWRECT";
- case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
- case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
- case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
- case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
- case 0x1000 + 39: return "LVM_GETTOPINDEX";
- case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
- case 0x1000 + 41: return "LVM_GETORIGIN";
- case 0x1000 + 42: return "LVM_UPDATE";
- case 0x1000 + 43: return "LVM_SETITEMSTATE";
- case 0x1000 + 44: return "LVM_GETITEMSTATE";
- case 0x1000 + 45: return "LVM_GETITEMTEXTA";
- case 0x1000 + 115: return "LVM_GETITEMTEXTW";
- case 0x1000 + 46: return "LVM_SETITEMTEXTA";
- case 0x1000 + 116: return "LVM_SETITEMTEXTW";
- case 0x1000 + 47: return "LVM_SETITEMCOUNT";
- case 0x1000 + 48: return "LVM_SORTITEMS";
- case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
- case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
- case 0x1000 + 51: return "LVM_GETITEMSPACING";
- case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
- case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
- case 0x1000 + 53: return "LVM_SETICONSPACING";
- case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
- case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
- case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
- case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
- case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
- case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
- case 0x1000 + 60: return "LVM_SETHOTITEM";
- case 0x1000 + 61: return "LVM_GETHOTITEM";
- case 0x1000 + 62: return "LVM_SETHOTCURSOR";
- case 0x1000 + 63: return "LVM_GETHOTCURSOR";
- case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
- case 0x1000 + 65: return "LVM_SETWORKAREA";
+ case 0x1000 + 0: return wxT("LVM_GETBKCOLOR");
+ case 0x1000 + 1: return wxT("LVM_SETBKCOLOR");
+ case 0x1000 + 2: return wxT("LVM_GETIMAGELIST");
+ case 0x1000 + 3: return wxT("LVM_SETIMAGELIST");
+ case 0x1000 + 4: return wxT("LVM_GETITEMCOUNT");
+ case 0x1000 + 5: return wxT("LVM_GETITEMA");
+ case 0x1000 + 75: return wxT("LVM_GETITEMW");
+ case 0x1000 + 6: return wxT("LVM_SETITEMA");
+ case 0x1000 + 76: return wxT("LVM_SETITEMW");
+ case 0x1000 + 7: return wxT("LVM_INSERTITEMA");
+ case 0x1000 + 77: return wxT("LVM_INSERTITEMW");
+ case 0x1000 + 8: return wxT("LVM_DELETEITEM");
+ case 0x1000 + 9: return wxT("LVM_DELETEALLITEMS");
+ case 0x1000 + 10: return wxT("LVM_GETCALLBACKMASK");
+ case 0x1000 + 11: return wxT("LVM_SETCALLBACKMASK");
+ case 0x1000 + 12: return wxT("LVM_GETNEXTITEM");
+ case 0x1000 + 13: return wxT("LVM_FINDITEMA");
+ case 0x1000 + 83: return wxT("LVM_FINDITEMW");
+ case 0x1000 + 14: return wxT("LVM_GETITEMRECT");
+ case 0x1000 + 15: return wxT("LVM_SETITEMPOSITION");
+ case 0x1000 + 16: return wxT("LVM_GETITEMPOSITION");
+ case 0x1000 + 17: return wxT("LVM_GETSTRINGWIDTHA");
+ case 0x1000 + 87: return wxT("LVM_GETSTRINGWIDTHW");
+ case 0x1000 + 18: return wxT("LVM_HITTEST");
+ case 0x1000 + 19: return wxT("LVM_ENSUREVISIBLE");
+ case 0x1000 + 20: return wxT("LVM_SCROLL");
+ case 0x1000 + 21: return wxT("LVM_REDRAWITEMS");
+ case 0x1000 + 22: return wxT("LVM_ARRANGE");
+ case 0x1000 + 23: return wxT("LVM_EDITLABELA");
+ case 0x1000 + 118: return wxT("LVM_EDITLABELW");
+ case 0x1000 + 24: return wxT("LVM_GETEDITCONTROL");
+ case 0x1000 + 25: return wxT("LVM_GETCOLUMNA");
+ case 0x1000 + 95: return wxT("LVM_GETCOLUMNW");
+ case 0x1000 + 26: return wxT("LVM_SETCOLUMNA");
+ case 0x1000 + 96: return wxT("LVM_SETCOLUMNW");
+ case 0x1000 + 27: return wxT("LVM_INSERTCOLUMNA");
+ case 0x1000 + 97: return wxT("LVM_INSERTCOLUMNW");
+ case 0x1000 + 28: return wxT("LVM_DELETECOLUMN");
+ case 0x1000 + 29: return wxT("LVM_GETCOLUMNWIDTH");
+ case 0x1000 + 30: return wxT("LVM_SETCOLUMNWIDTH");
+ case 0x1000 + 31: return wxT("LVM_GETHEADER");
+ case 0x1000 + 33: return wxT("LVM_CREATEDRAGIMAGE");
+ case 0x1000 + 34: return wxT("LVM_GETVIEWRECT");
+ case 0x1000 + 35: return wxT("LVM_GETTEXTCOLOR");
+ case 0x1000 + 36: return wxT("LVM_SETTEXTCOLOR");
+ case 0x1000 + 37: return wxT("LVM_GETTEXTBKCOLOR");
+ case 0x1000 + 38: return wxT("LVM_SETTEXTBKCOLOR");
+ case 0x1000 + 39: return wxT("LVM_GETTOPINDEX");
+ case 0x1000 + 40: return wxT("LVM_GETCOUNTPERPAGE");
+ case 0x1000 + 41: return wxT("LVM_GETORIGIN");
+ case 0x1000 + 42: return wxT("LVM_UPDATE");
+ case 0x1000 + 43: return wxT("LVM_SETITEMSTATE");
+ case 0x1000 + 44: return wxT("LVM_GETITEMSTATE");
+ case 0x1000 + 45: return wxT("LVM_GETITEMTEXTA");
+ case 0x1000 + 115: return wxT("LVM_GETITEMTEXTW");
+ case 0x1000 + 46: return wxT("LVM_SETITEMTEXTA");
+ case 0x1000 + 116: return wxT("LVM_SETITEMTEXTW");
+ case 0x1000 + 47: return wxT("LVM_SETITEMCOUNT");
+ case 0x1000 + 48: return wxT("LVM_SORTITEMS");
+ case 0x1000 + 49: return wxT("LVM_SETITEMPOSITION32");
+ case 0x1000 + 50: return wxT("LVM_GETSELECTEDCOUNT");
+ case 0x1000 + 51: return wxT("LVM_GETITEMSPACING");
+ case 0x1000 + 52: return wxT("LVM_GETISEARCHSTRINGA");
+ case 0x1000 + 117: return wxT("LVM_GETISEARCHSTRINGW");
+ case 0x1000 + 53: return wxT("LVM_SETICONSPACING");
+ case 0x1000 + 54: return wxT("LVM_SETEXTENDEDLISTVIEWSTYLE");
+ case 0x1000 + 55: return wxT("LVM_GETEXTENDEDLISTVIEWSTYLE");
+ case 0x1000 + 56: return wxT("LVM_GETSUBITEMRECT");
+ case 0x1000 + 57: return wxT("LVM_SUBITEMHITTEST");
+ case 0x1000 + 58: return wxT("LVM_SETCOLUMNORDERARRAY");
+ case 0x1000 + 59: return wxT("LVM_GETCOLUMNORDERARRAY");
+ case 0x1000 + 60: return wxT("LVM_SETHOTITEM");
+ case 0x1000 + 61: return wxT("LVM_GETHOTITEM");
+ case 0x1000 + 62: return wxT("LVM_SETHOTCURSOR");
+ case 0x1000 + 63: return wxT("LVM_GETHOTCURSOR");
+ case 0x1000 + 64: return wxT("LVM_APPROXIMATEVIEWRECT");
+ case 0x1000 + 65: return wxT("LVM_SETWORKAREA");
// tree view
- case 0x1100 + 0: return "TVM_INSERTITEMA";
- case 0x1100 + 50: return "TVM_INSERTITEMW";
- case 0x1100 + 1: return "TVM_DELETEITEM";
- case 0x1100 + 2: return "TVM_EXPAND";
- case 0x1100 + 4: return "TVM_GETITEMRECT";
- case 0x1100 + 5: return "TVM_GETCOUNT";
- case 0x1100 + 6: return "TVM_GETINDENT";
- case 0x1100 + 7: return "TVM_SETINDENT";
- case 0x1100 + 8: return "TVM_GETIMAGELIST";
- case 0x1100 + 9: return "TVM_SETIMAGELIST";
- case 0x1100 + 10: return "TVM_GETNEXTITEM";
- case 0x1100 + 11: return "TVM_SELECTITEM";
- case 0x1100 + 12: return "TVM_GETITEMA";
- case 0x1100 + 62: return "TVM_GETITEMW";
- case 0x1100 + 13: return "TVM_SETITEMA";
- case 0x1100 + 63: return "TVM_SETITEMW";
- case 0x1100 + 14: return "TVM_EDITLABELA";
- case 0x1100 + 65: return "TVM_EDITLABELW";
- case 0x1100 + 15: return "TVM_GETEDITCONTROL";
- case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
- case 0x1100 + 17: return "TVM_HITTEST";
- case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
- case 0x1100 + 19: return "TVM_SORTCHILDREN";
- case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
- case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
- case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
- case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
- case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
- case 0x1100 + 24: return "TVM_SETTOOLTIPS";
- case 0x1100 + 25: return "TVM_GETTOOLTIPS";
+ case 0x1100 + 0: return wxT("TVM_INSERTITEMA");
+ case 0x1100 + 50: return wxT("TVM_INSERTITEMW");
+ case 0x1100 + 1: return wxT("TVM_DELETEITEM");
+ case 0x1100 + 2: return wxT("TVM_EXPAND");
+ case 0x1100 + 4: return wxT("TVM_GETITEMRECT");
+ case 0x1100 + 5: return wxT("TVM_GETCOUNT");
+ case 0x1100 + 6: return wxT("TVM_GETINDENT");
+ case 0x1100 + 7: return wxT("TVM_SETINDENT");
+ case 0x1100 + 8: return wxT("TVM_GETIMAGELIST");
+ case 0x1100 + 9: return wxT("TVM_SETIMAGELIST");
+ case 0x1100 + 10: return wxT("TVM_GETNEXTITEM");
+ case 0x1100 + 11: return wxT("TVM_SELECTITEM");
+ case 0x1100 + 12: return wxT("TVM_GETITEMA");
+ case 0x1100 + 62: return wxT("TVM_GETITEMW");
+ case 0x1100 + 13: return wxT("TVM_SETITEMA");
+ case 0x1100 + 63: return wxT("TVM_SETITEMW");
+ case 0x1100 + 14: return wxT("TVM_EDITLABELA");
+ case 0x1100 + 65: return wxT("TVM_EDITLABELW");
+ case 0x1100 + 15: return wxT("TVM_GETEDITCONTROL");
+ case 0x1100 + 16: return wxT("TVM_GETVISIBLECOUNT");
+ case 0x1100 + 17: return wxT("TVM_HITTEST");
+ case 0x1100 + 18: return wxT("TVM_CREATEDRAGIMAGE");
+ case 0x1100 + 19: return wxT("TVM_SORTCHILDREN");
+ case 0x1100 + 20: return wxT("TVM_ENSUREVISIBLE");
+ case 0x1100 + 21: return wxT("TVM_SORTCHILDRENCB");
+ case 0x1100 + 22: return wxT("TVM_ENDEDITLABELNOW");
+ case 0x1100 + 23: return wxT("TVM_GETISEARCHSTRINGA");
+ case 0x1100 + 64: return wxT("TVM_GETISEARCHSTRINGW");
+ case 0x1100 + 24: return wxT("TVM_SETTOOLTIPS");
+ case 0x1100 + 25: return wxT("TVM_GETTOOLTIPS");
// header
- case 0x1200 + 0: return "HDM_GETITEMCOUNT";
- case 0x1200 + 1: return "HDM_INSERTITEMA";
- case 0x1200 + 10: return "HDM_INSERTITEMW";
- case 0x1200 + 2: return "HDM_DELETEITEM";
- case 0x1200 + 3: return "HDM_GETITEMA";
- case 0x1200 + 11: return "HDM_GETITEMW";
- case 0x1200 + 4: return "HDM_SETITEMA";
- case 0x1200 + 12: return "HDM_SETITEMW";
- case 0x1200 + 5: return "HDM_LAYOUT";
- case 0x1200 + 6: return "HDM_HITTEST";
- case 0x1200 + 7: return "HDM_GETITEMRECT";
- case 0x1200 + 8: return "HDM_SETIMAGELIST";
- case 0x1200 + 9: return "HDM_GETIMAGELIST";
- case 0x1200 + 15: return "HDM_ORDERTOINDEX";
- case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
- case 0x1200 + 17: return "HDM_GETORDERARRAY";
- case 0x1200 + 18: return "HDM_SETORDERARRAY";
- case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
+ case 0x1200 + 0: return wxT("HDM_GETITEMCOUNT");
+ case 0x1200 + 1: return wxT("HDM_INSERTITEMA");
+ case 0x1200 + 10: return wxT("HDM_INSERTITEMW");
+ case 0x1200 + 2: return wxT("HDM_DELETEITEM");
+ case 0x1200 + 3: return wxT("HDM_GETITEMA");
+ case 0x1200 + 11: return wxT("HDM_GETITEMW");
+ case 0x1200 + 4: return wxT("HDM_SETITEMA");
+ case 0x1200 + 12: return wxT("HDM_SETITEMW");
+ case 0x1200 + 5: return wxT("HDM_LAYOUT");
+ case 0x1200 + 6: return wxT("HDM_HITTEST");
+ case 0x1200 + 7: return wxT("HDM_GETITEMRECT");
+ case 0x1200 + 8: return wxT("HDM_SETIMAGELIST");
+ case 0x1200 + 9: return wxT("HDM_GETIMAGELIST");
+ case 0x1200 + 15: return wxT("HDM_ORDERTOINDEX");
+ case 0x1200 + 16: return wxT("HDM_CREATEDRAGIMAGE");
+ case 0x1200 + 17: return wxT("HDM_GETORDERARRAY");
+ case 0x1200 + 18: return wxT("HDM_SETORDERARRAY");
+ case 0x1200 + 19: return wxT("HDM_SETHOTDIVIDER");
// tab control
- case 0x1300 + 2: return "TCM_GETIMAGELIST";
- case 0x1300 + 3: return "TCM_SETIMAGELIST";
- case 0x1300 + 4: return "TCM_GETITEMCOUNT";
- case 0x1300 + 5: return "TCM_GETITEMA";
- case 0x1300 + 60: return "TCM_GETITEMW";
- case 0x1300 + 6: return "TCM_SETITEMA";
- case 0x1300 + 61: return "TCM_SETITEMW";
- case 0x1300 + 7: return "TCM_INSERTITEMA";
- case 0x1300 + 62: return "TCM_INSERTITEMW";
- case 0x1300 + 8: return "TCM_DELETEITEM";
- case 0x1300 + 9: return "TCM_DELETEALLITEMS";
- case 0x1300 + 10: return "TCM_GETITEMRECT";
- case 0x1300 + 11: return "TCM_GETCURSEL";
- case 0x1300 + 12: return "TCM_SETCURSEL";
- case 0x1300 + 13: return "TCM_HITTEST";
- case 0x1300 + 14: return "TCM_SETITEMEXTRA";
- case 0x1300 + 40: return "TCM_ADJUSTRECT";
- case 0x1300 + 41: return "TCM_SETITEMSIZE";
- case 0x1300 + 42: return "TCM_REMOVEIMAGE";
- case 0x1300 + 43: return "TCM_SETPADDING";
- case 0x1300 + 44: return "TCM_GETROWCOUNT";
- case 0x1300 + 45: return "TCM_GETTOOLTIPS";
- case 0x1300 + 46: return "TCM_SETTOOLTIPS";
- case 0x1300 + 47: return "TCM_GETCURFOCUS";
- case 0x1300 + 48: return "TCM_SETCURFOCUS";
- case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
- case 0x1300 + 50: return "TCM_DESELECTALL";
+ case 0x1300 + 2: return wxT("TCM_GETIMAGELIST");
+ case 0x1300 + 3: return wxT("TCM_SETIMAGELIST");
+ case 0x1300 + 4: return wxT("TCM_GETITEMCOUNT");
+ case 0x1300 + 5: return wxT("TCM_GETITEMA");
+ case 0x1300 + 60: return wxT("TCM_GETITEMW");
+ case 0x1300 + 6: return wxT("TCM_SETITEMA");
+ case 0x1300 + 61: return wxT("TCM_SETITEMW");
+ case 0x1300 + 7: return wxT("TCM_INSERTITEMA");
+ case 0x1300 + 62: return wxT("TCM_INSERTITEMW");
+ case 0x1300 + 8: return wxT("TCM_DELETEITEM");
+ case 0x1300 + 9: return wxT("TCM_DELETEALLITEMS");
+ case 0x1300 + 10: return wxT("TCM_GETITEMRECT");
+ case 0x1300 + 11: return wxT("TCM_GETCURSEL");
+ case 0x1300 + 12: return wxT("TCM_SETCURSEL");
+ case 0x1300 + 13: return wxT("TCM_HITTEST");
+ case 0x1300 + 14: return wxT("TCM_SETITEMEXTRA");
+ case 0x1300 + 40: return wxT("TCM_ADJUSTRECT");
+ case 0x1300 + 41: return wxT("TCM_SETITEMSIZE");
+ case 0x1300 + 42: return wxT("TCM_REMOVEIMAGE");
+ case 0x1300 + 43: return wxT("TCM_SETPADDING");
+ case 0x1300 + 44: return wxT("TCM_GETROWCOUNT");
+ case 0x1300 + 45: return wxT("TCM_GETTOOLTIPS");
+ case 0x1300 + 46: return wxT("TCM_SETTOOLTIPS");
+ case 0x1300 + 47: return wxT("TCM_GETCURFOCUS");
+ case 0x1300 + 48: return wxT("TCM_SETCURFOCUS");
+ case 0x1300 + 49: return wxT("TCM_SETMINTABWIDTH");
+ case 0x1300 + 50: return wxT("TCM_DESELECTALL");
// toolbar
- case WM_USER+1: return "TB_ENABLEBUTTON";
- case WM_USER+2: return "TB_CHECKBUTTON";
- case WM_USER+3: return "TB_PRESSBUTTON";
- case WM_USER+4: return "TB_HIDEBUTTON";
- case WM_USER+5: return "TB_INDETERMINATE";
- case WM_USER+9: return "TB_ISBUTTONENABLED";
- case WM_USER+10: return "TB_ISBUTTONCHECKED";
- case WM_USER+11: return "TB_ISBUTTONPRESSED";
- case WM_USER+12: return "TB_ISBUTTONHIDDEN";
- case WM_USER+13: return "TB_ISBUTTONINDETERMINATE";
- case WM_USER+17: return "TB_SETSTATE";
- case WM_USER+18: return "TB_GETSTATE";
- case WM_USER+19: return "TB_ADDBITMAP";
- case WM_USER+20: return "TB_ADDBUTTONS";
- case WM_USER+21: return "TB_INSERTBUTTON";
- case WM_USER+22: return "TB_DELETEBUTTON";
- case WM_USER+23: return "TB_GETBUTTON";
- case WM_USER+24: return "TB_BUTTONCOUNT";
- case WM_USER+25: return "TB_COMMANDTOINDEX";
- case WM_USER+26: return "TB_SAVERESTOREA";
- case WM_USER+76: return "TB_SAVERESTOREW";
- case WM_USER+27: return "TB_CUSTOMIZE";
- case WM_USER+28: return "TB_ADDSTRINGA";
- case WM_USER+77: return "TB_ADDSTRINGW";
- case WM_USER+29: return "TB_GETITEMRECT";
- case WM_USER+30: return "TB_BUTTONSTRUCTSIZE";
- case WM_USER+31: return "TB_SETBUTTONSIZE";
- case WM_USER+32: return "TB_SETBITMAPSIZE";
- case WM_USER+33: return "TB_AUTOSIZE";
- case WM_USER+35: return "TB_GETTOOLTIPS";
- case WM_USER+36: return "TB_SETTOOLTIPS";
- case WM_USER+37: return "TB_SETPARENT";
- case WM_USER+39: return "TB_SETROWS";
- case WM_USER+40: return "TB_GETROWS";
- case WM_USER+42: return "TB_SETCMDID";
- case WM_USER+43: return "TB_CHANGEBITMAP";
- case WM_USER+44: return "TB_GETBITMAP";
- case WM_USER+45: return "TB_GETBUTTONTEXTA";
- case WM_USER+75: return "TB_GETBUTTONTEXTW";
- case WM_USER+46: return "TB_REPLACEBITMAP";
- case WM_USER+47: return "TB_SETINDENT";
- case WM_USER+48: return "TB_SETIMAGELIST";
- case WM_USER+49: return "TB_GETIMAGELIST";
- case WM_USER+50: return "TB_LOADIMAGES";
- case WM_USER+51: return "TB_GETRECT";
- case WM_USER+52: return "TB_SETHOTIMAGELIST";
- case WM_USER+53: return "TB_GETHOTIMAGELIST";
- case WM_USER+54: return "TB_SETDISABLEDIMAGELIST";
- case WM_USER+55: return "TB_GETDISABLEDIMAGELIST";
- case WM_USER+56: return "TB_SETSTYLE";
- case WM_USER+57: return "TB_GETSTYLE";
- case WM_USER+58: return "TB_GETBUTTONSIZE";
- case WM_USER+59: return "TB_SETBUTTONWIDTH";
- case WM_USER+60: return "TB_SETMAXTEXTROWS";
- case WM_USER+61: return "TB_GETTEXTROWS";
- case WM_USER+41: return "TB_GETBITMAPFLAGS";
-
-#endif //WIN32
+ case WM_USER+1: return wxT("TB_ENABLEBUTTON");
+ case WM_USER+2: return wxT("TB_CHECKBUTTON");
+ case WM_USER+3: return wxT("TB_PRESSBUTTON");
+ case WM_USER+4: return wxT("TB_HIDEBUTTON");
+ case WM_USER+5: return wxT("TB_INDETERMINATE");
+ case WM_USER+9: return wxT("TB_ISBUTTONENABLED");
+ case WM_USER+10: return wxT("TB_ISBUTTONCHECKED");
+ case WM_USER+11: return wxT("TB_ISBUTTONPRESSED");
+ case WM_USER+12: return wxT("TB_ISBUTTONHIDDEN");
+ case WM_USER+13: return wxT("TB_ISBUTTONINDETERMINATE");
+ case WM_USER+17: return wxT("TB_SETSTATE");
+ case WM_USER+18: return wxT("TB_GETSTATE");
+ case WM_USER+19: return wxT("TB_ADDBITMAP");
+ case WM_USER+20: return wxT("TB_ADDBUTTONS");
+ case WM_USER+21: return wxT("TB_INSERTBUTTON");
+ case WM_USER+22: return wxT("TB_DELETEBUTTON");
+ case WM_USER+23: return wxT("TB_GETBUTTON");
+ case WM_USER+24: return wxT("TB_BUTTONCOUNT");
+ case WM_USER+25: return wxT("TB_COMMANDTOINDEX");
+ case WM_USER+26: return wxT("TB_SAVERESTOREA");
+ case WM_USER+76: return wxT("TB_SAVERESTOREW");
+ case WM_USER+27: return wxT("TB_CUSTOMIZE");
+ case WM_USER+28: return wxT("TB_ADDSTRINGA");
+ case WM_USER+77: return wxT("TB_ADDSTRINGW");
+ case WM_USER+29: return wxT("TB_GETITEMRECT");
+ case WM_USER+30: return wxT("TB_BUTTONSTRUCTSIZE");
+ case WM_USER+31: return wxT("TB_SETBUTTONSIZE");
+ case WM_USER+32: return wxT("TB_SETBITMAPSIZE");
+ case WM_USER+33: return wxT("TB_AUTOSIZE");
+ case WM_USER+35: return wxT("TB_GETTOOLTIPS");
+ case WM_USER+36: return wxT("TB_SETTOOLTIPS");
+ case WM_USER+37: return wxT("TB_SETPARENT");
+ case WM_USER+39: return wxT("TB_SETROWS");
+ case WM_USER+40: return wxT("TB_GETROWS");
+ case WM_USER+42: return wxT("TB_SETCMDID");
+ case WM_USER+43: return wxT("TB_CHANGEBITMAP");
+ case WM_USER+44: return wxT("TB_GETBITMAP");
+ case WM_USER+45: return wxT("TB_GETBUTTONTEXTA");
+ case WM_USER+75: return wxT("TB_GETBUTTONTEXTW");
+ case WM_USER+46: return wxT("TB_REPLACEBITMAP");
+ case WM_USER+47: return wxT("TB_SETINDENT");
+ case WM_USER+48: return wxT("TB_SETIMAGELIST");
+ case WM_USER+49: return wxT("TB_GETIMAGELIST");
+ case WM_USER+50: return wxT("TB_LOADIMAGES");
+ case WM_USER+51: return wxT("TB_GETRECT");
+ case WM_USER+52: return wxT("TB_SETHOTIMAGELIST");
+ case WM_USER+53: return wxT("TB_GETHOTIMAGELIST");
+ case WM_USER+54: return wxT("TB_SETDISABLEDIMAGELIST");
+ case WM_USER+55: return wxT("TB_GETDISABLEDIMAGELIST");
+ case WM_USER+56: return wxT("TB_SETSTYLE");
+ case WM_USER+57: return wxT("TB_GETSTYLE");
+ case WM_USER+58: return wxT("TB_GETBUTTONSIZE");
+ case WM_USER+59: return wxT("TB_SETBUTTONWIDTH");
+ case WM_USER+60: return wxT("TB_SETMAXTEXTROWS");
+ case WM_USER+61: return wxT("TB_GETTEXTROWS");
+ case WM_USER+41: return wxT("TB_GETBITMAPFLAGS");
default:
- static char s_szBuf[128];
- sprintf(s_szBuf, "<unknown message = %d>", message);
- return s_szBuf;
+ static wxString s_szBuf;
+ s_szBuf.Printf(wxT("<unknown message = %d>"), message);
+ return s_szBuf.c_str();
}
}
#endif //__WXDEBUG__
-static void TranslateKbdEventToMouse(wxWindowMSW *win,
- int *x, int *y, WPARAM *flags)
-{
- // construct the key mask
- WPARAM& fwKeys = *flags;
-
- fwKeys = MK_RBUTTON;
- if ( wxIsCtrlDown() )
- fwKeys |= MK_CONTROL;
- if ( wxIsShiftDown() )
- fwKeys |= MK_SHIFT;
-
- // simulate right mouse button click
- DWORD dwPos = ::GetMessagePos();
- *x = GET_X_LPARAM(dwPos);
- *y = GET_Y_LPARAM(dwPos);
-
- win->ScreenToClient(x, y);
-}
-
static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win)
{
// prepare the DC
POINT pt2;
pt2.x = pt.x;
pt2.y = pt.y;
- HWND hWndHit = ::WindowFromPoint(pt2);
- wxWindow* win = wxFindWinFromHandle((WXHWND) hWndHit) ;
- HWND hWnd = hWndHit;
+ HWND hWnd = ::WindowFromPoint(pt2);
- // Try to find a window with a wxWindow associated with it
- while (!win && (hWnd != 0))
- {
- hWnd = ::GetParent(hWnd);
- win = wxFindWinFromHandle((WXHWND) hWnd) ;
- }
- return win;
+ return wxGetWindowFromHWND((WXHWND)hWnd);
}
// Get the current mouse position.
wxPoint wxGetMousePosition()
{
POINT pt;
+#ifdef __WXWINCE__
+ GetCursorPosWinCE(&pt);
+#else
GetCursorPos( & pt );
+#endif
return wxPoint(pt.x, pt.y);
}
+#if wxUSE_HOTKEY
+
+#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
+static void WinCEUnregisterHotKey(int modifiers, int id)
+{
+ // Register hotkeys for the hardware buttons
+ HINSTANCE hCoreDll;
+ typedef BOOL (WINAPI *UnregisterFunc1Proc)(UINT, UINT);
+
+ UnregisterFunc1Proc procUnregisterFunc;
+ hCoreDll = LoadLibrary(_T("coredll.dll"));
+ if (hCoreDll)
+ {
+ procUnregisterFunc = (UnregisterFunc1Proc)GetProcAddress(hCoreDll, _T("UnregisterFunc1"));
+ if (procUnregisterFunc)
+ procUnregisterFunc(modifiers, id);
+ FreeLibrary(hCoreDll);
+ }
+}
+#endif
+
+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 defined(__SMARTPHONE__) || defined(__POCKETPC__)
+ // Required for PPC and Smartphone hardware buttons
+ if (keycode >= WXK_SPECIAL1 && keycode <= WXK_SPECIAL20)
+ WinCEUnregisterHotKey(win_modifiers, hotkeyId);
+#endif
+
+ if ( !::RegisterHotKey(GetHwnd(), hotkeyId, win_modifiers, keycode) )
+ {
+ wxLogLastError(_T("RegisterHotKey"));
+
+ return false;
+ }
+
+ return true;
+}
+
+bool wxWindowMSW::UnregisterHotKey(int hotkeyId)
+{
+#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
+ WinCEUnregisterHotKey(MOD_WIN, hotkeyId);
+#endif
+
+ if ( !::UnregisterHotKey(GetHwnd(), hotkeyId) )
+ {
+ wxLogLastError(_T("UnregisterHotKey"));
+
+ return false;
+ }
+
+ return true;
+}
+
+#if wxUSE_ACCEL
+
+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_ACCEL
+
+#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;
+
+ // only process the message if it is actually going to be removed from
+ // the message queue, this prevents that the same event from being
+ // processed multiple times if now someone just called PeekMessage()
+ if ( msg->message == WM_NULL && wParam == PM_REMOVE )
+ {
+ 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__
+
+#ifdef __WXWINCE__
+
+#if wxUSE_STATBOX
+static void wxAdjustZOrder(wxWindow* parent)
+{
+ if (parent->IsKindOf(CLASSINFO(wxStaticBox)))
+ {
+ // Set the z-order correctly
+ SetWindowPos((HWND) parent->GetHWND(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+ }
+
+ wxWindowList::compatibility_iterator current = parent->GetChildren().GetFirst();
+ while (current)
+ {
+ wxWindow *childWin = current->GetData();
+ wxAdjustZOrder(childWin);
+ current = current->GetNext();
+ }
+}
+#endif
+
+// We need to adjust the z-order of static boxes in WinCE, to
+// make 'contained' controls visible
+void wxWindowMSW::OnInitDialog( wxInitDialogEvent& event )
+{
+#if wxUSE_STATBOX
+ wxAdjustZOrder(this);
+#endif
+
+ event.Skip();
+}
+#endif