// 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
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/hashmap.h"
#include "wx/evtloop.h"
#include "wx/power.h"
+#include "wx/scopeguard.h"
#include "wx/sysopt.h"
#if wxUSE_DRAG_AND_DROP
#include "wx/msw/private.h"
#include "wx/msw/private/keyboard.h"
#include "wx/msw/dcclient.h"
+#include "wx/private/textmeasure.h"
#if wxUSE_TOOLTIPS
#include "wx/tooltip.h"
#include <windowsx.h>
#endif
-#if !defined __WXWINCE__ && !defined NEED_PBT_H
- #include <pbt.h>
-#endif
-
#if defined(__WXWINCE__)
#include "wx/msw/wince/missing.h"
#ifdef __POCKETPC__
// This is a hack used by the owner-drawn wxButton implementation to ensure
// that the brush used for erasing its background is correctly aligned with the
// control.
-extern wxWindowMSW *wxWindowBeingErased = NULL;
+wxWindowMSW *wxWindowBeingErased = NULL;
#endif // wxUSE_UXTHEME
namespace
// needed.
int gs_modalEntryWindowCount = 0;
+// Indicates whether we are currently processing WM_CAPTURECHANGED message.
+bool gs_insideCaptureChanged = false;
+
} // anonymous namespace
// ---------------------------------------------------------------------------
#endif // !__WXWINCE__
-#ifdef __WXWINCE__
-// On Windows CE, GetCursorPos can return an error, so use this function
-// instead
-bool GetCursorPosWinCE(POINT* pt)
+// GetCursorPos can return an error, so use this function
+// instead.
+// Error originally observed with WinCE, but later using Remote Desktop
+// to connect to XP.
+void wxGetCursorPosMSW(POINT* pt)
{
if (!GetCursorPos(pt))
{
+#ifdef __WXWINCE__
+ wxLogLastError(wxT("GetCursorPos"));
+#endif
DWORD pos = GetMessagePos();
- pt->x = LOWORD(pos);
- pt->y = HIWORD(pos);
+ // the coordinates may be negative in multi-monitor systems
+ pt->x = GET_X_LPARAM(pos);
+ pt->y = GET_Y_LPARAM(pos);
}
- return true;
}
-#endif
// ---------------------------------------------------------------------------
// event tables
if ( !controlOnly
#if wxUSE_CONTROLS
- || parent->IsKindOf(CLASSINFO(wxControl))
+ || wxDynamicCast(parent, wxControl)
#endif // wxUSE_CONTROLS
)
{
wxShowEffect effect,
unsigned timeout)
{
+#if wxUSE_DYNLIB_CLASS
if ( effect == wxSHOW_EFFECT_NONE )
return Show(show);
}
return true;
+#else // wxUSE_DYNLIB_CLASS
+ return Show(show);
+#endif
}
// Raise the window to the top of the Z order
/* static */ wxWindow *wxWindowBase::GetCapture()
{
+ // When we receive WM_CAPTURECHANGED message, ::GetCapture() still returns
+ // the HWND that is losing the mouse capture. But as we must not release
+ // the capture for it (it's going to happen anyhow), pretend that there is
+ // no capture any more.
+ if ( gs_insideCaptureChanged )
+ return NULL;
+
HWND hwnd = ::GetCapture();
return hwnd ? wxFindWinFromHandle(hwnd) : NULL;
}
return true;
}
+
bool wxWindowMSW::SetCursor(const wxCursor& cursor)
{
if ( !wxWindowBase::SetCursor(cursor) )
}
// don't "overwrite" busy cursor
- if ( m_cursor.IsOk() && !wxIsBusy() )
+ if ( wxIsBusy() )
+ return true;
+
+ if ( m_cursor.IsOk() )
{
// normally we should change the cursor only if it's over this window
// but we should do it always if we capture the mouse currently
HWND hWnd = GetHwnd();
POINT point;
-#ifdef __WXWINCE__
- ::GetCursorPosWinCE(&point);
-#else
- ::GetCursorPos(&point);
-#endif
+ ::wxGetCursorPosMSW(&point);
RECT rect = wxGetWindowRect(hWnd);
}
//else: will be set later when the mouse enters this window
}
+ else // Invalid cursor: this means reset to the default one.
+ {
+ // To revert to the correct cursor we need to find the window currently
+ // under the cursor and ask it to set its cursor itself as only it
+ // knows what it is.
+ POINT pt;
+ wxGetCursorPosMSW(&pt);
+
+ const wxWindowMSW* win = wxFindWindowAtPoint(wxPoint(pt.x, pt.y));
+ if ( !win )
+ win = this;
+
+ ::SendMessage(GetHwndOf(win), WM_SETCURSOR,
+ (WPARAM)GetHwndOf(win),
+ MAKELPARAM(HTCLIENT, WM_MOUSEMOVE));
+ }
return true;
}
if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) )
{
wxSetWindowProc(hwnd, wxWndProc);
+
+ // If the window didn't use our window proc during its creation, the
+ // code in HandleCreate() hasn't been executed, so do it here.
+ if ( wxHasWindowExStyle(this, WS_EX_CONTROLPARENT) )
+ EnsureParentHasControlParentStyle(GetParent());
}
else
{
// 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
+ // regions), so avoid it altogether
if ( flags & wxVSCROLL )
{
// get the mouse position
POINT pt;
-#ifdef __WXWINCE__
- ::GetCursorPosWinCE(&pt);
-#else
- ::GetCursorPos(&pt);
-#endif
+ wxGetCursorPosMSW(&pt);
// find the window which currently has the cursor and go up the window
// chain until we find this window - or exhaust it
if ( y )
*y = rect.bottom;
}
+
+ // The size of the client window can't be negative but ::GetClientRect()
+ // can return negative size for an extremely small (1x1) window with
+ // borders so ensure that we correct it here as having negative sizes is
+ // completely unexpected.
+ if ( x && *x < 0 )
+ *x = 0;
+ if ( y && *y < 0 )
+ *y = 0;
}
void wxWindowMSW::DoGetPosition(int *x, int *y) const
int *externalLeading,
const wxFont *fontToUse) const
{
- wxASSERT_MSG( !fontToUse || fontToUse->IsOk(),
- wxT("invalid font in GetTextExtent()") );
-
- HFONT hfontToUse;
- if ( fontToUse )
- hfontToUse = GetHfontOf(*fontToUse);
+ // ensure we work with a valid font
+ wxFont font;
+ if ( !fontToUse || !fontToUse->IsOk() )
+ font = GetFont();
else
- hfontToUse = GetHfontOf(GetFont());
-
- WindowHDC hdc(GetHwnd());
- SelectInHDC selectFont(hdc, hfontToUse);
+ font = *fontToUse;
- SIZE sizeRect;
- TEXTMETRIC tm;
- ::GetTextExtentPoint32(hdc, string.wx_str(), string.length(), &sizeRect);
- GetTextMetrics(hdc, &tm);
+ wxCHECK_RET( font.IsOk(), wxT("invalid font in GetTextExtent()") );
- if ( x )
- *x = sizeRect.cx;
- if ( y )
- *y = sizeRect.cy;
- if ( descent )
- *descent = tm.tmDescent;
- if ( externalLeading )
- *externalLeading = tm.tmExternalLeading;
+ const wxWindow* win = static_cast<const wxWindow*>(this);
+ wxTextMeasure txm(win, &font);
+ txm.GetTextExtent(string, x, y, descent, externalLeading);
}
// ---------------------------------------------------------------------------
{
menu->UpdateUI();
+ wxPoint pt;
if ( x == wxDefaultCoord && y == wxDefaultCoord )
{
- wxPoint mouse = ScreenToClient(wxGetMousePosition());
- x = mouse.x; y = mouse.y;
+ pt = wxGetMousePosition();
+ }
+ else
+ {
+ pt = ClientToScreen(wxPoint(x, y));
}
- HWND hWnd = GetHwnd();
- HMENU hMenu = GetHmenuOf(menu);
- POINT point;
- point.x = x;
- point.y = y;
- ::ClientToScreen(hWnd, &point);
#if defined(__WXWINCE__)
static const UINT flags = 0;
#else // !__WXWINCE__
}
#endif // __WXWINCE__/!__WXWINCE__
- ::TrackPopupMenu(hMenu, flags, point.x, point.y, 0, hWnd, NULL);
+ ::TrackPopupMenu(GetHmenuOf(menu), flags, pt.x, pt.y, 0, GetHwnd(), NULL);
// we need to do it right now as otherwise the events are never going to be
// sent to wxCurrentPopupMenu from HandleCommand()
{
// wxUniversal implements tab traversal itself
#ifndef __WXUNIVERSAL__
- if ( m_hWnd != 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL) )
+ // Notice that we check for WS_EX_CONTROLPARENT and not wxTAB_TRAVERSAL
+ // here. While usually they are both set or both unset, doing it like this
+ // also works if there is ever a bug that results in wxTAB_TRAVERSAL being
+ // set but not WS_EX_CONTROLPARENT as we must not call IsDialogMessage() in
+ // this case, it would simply hang (see #15458).
+ if ( m_hWnd != 0 && (wxGetWindowExStyle(this) & WS_EX_CONTROLPARENT) )
{
// intercept dialog navigation keys
MSG *msg = (MSG *)pMsg;
// emulate the button click
btn = wxFindWinFromHandle(msg->hwnd);
}
-
- bProcess = false;
}
else // not a button itself, do we have default button?
{
return true;
}
+ // This "Return" key press won't be actually used for
+ // navigation so don't generate wxNavigationKeyEvent
+ // for it but still pass it to IsDialogMessage() as it
+ // may handle it in some other way (e.g. by playing the
+ // default error sound).
+ bProcess = false;
+
#endif // wxUSE_BUTTON
#ifdef __WXWINCE__
return rc;
}
-WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
+bool
+wxWindowMSW::MSWHandleMessage(WXLRESULT *result,
+ WXUINT message,
+ WXWPARAM wParam,
+ WXLPARAM lParam)
{
// did we process the message?
bool processed = false;
#if wxUSE_MOUSEWHEEL
case WM_MOUSEWHEEL:
- processed = HandleMouseWheel(wParam, lParam);
+ processed = HandleMouseWheel(wxMOUSE_WHEEL_VERTICAL, wParam, lParam);
break;
-#endif
+
+ case WM_MOUSEHWHEEL:
+ processed = HandleMouseWheel(wxMOUSE_WHEEL_HORIZONTAL, wParam, lParam);
+ break;
+#endif // wxUSE_MOUSEWHEEL
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case MM_JOY1BUTTONUP:
case MM_JOY2BUTTONUP:
processed = HandleJoystickEvent(message,
- GET_X_LPARAM(lParam),
- GET_Y_LPARAM(lParam),
+ LOWORD(lParam),
+ HIWORD(lParam),
wParam);
break;
#endif // __WXMICROWIN__
case VK_OEM_5:
case VK_OEM_6:
case VK_OEM_7:
+ case VK_OEM_102:
case VK_OEM_PLUS:
case VK_OEM_COMMA:
case VK_OEM_MINUS:
#if !defined(__WXWINCE__)
case WM_CONTEXTMENU:
{
- // we don't convert from screen to client coordinates as
- // the event may be handled by a parent window
- wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
-
- wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
-
- // we could have got an event from our child, reflect it back
- // to it if this is the case
- wxWindowMSW *win = NULL;
+ // Ignore the events that are propagated from a child window by
+ // DefWindowProc(): as wxContextMenuEvent is already propagated
+ // upwards the window hierarchy by us, not doing this would
+ // result in duplicate events being sent.
WXHWND hWnd = (WXHWND)wParam;
if ( hWnd != m_hWnd )
{
- win = FindItemByHWND(hWnd);
+ wxWindowMSW *win = FindItemByHWND(hWnd);
+ if ( win && IsDescendant(win) )
+ {
+ // We had already generated wxContextMenuEvent when we
+ // got WM_CONTEXTMENU for that window.
+ processed = true;
+ break;
+ }
}
- if ( !win )
- win = this;
+ // we don't convert from screen to client coordinates as
+ // the event may be handled by a parent window
+ wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+
+ wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
+ evtCtx.SetEventObject(this);
- evtCtx.SetEventObject(win);
- processed = win->HandleWindowEvent(evtCtx);
+ processed = HandleWindowEvent(evtCtx);
}
break;
#endif
}
if ( !processed )
+ return false;
+
+ *result = rc.result;
+
+ return true;
+}
+
+WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
+{
+ WXLRESULT result;
+ if ( !MSWHandleMessage(&result, message, wParam, lParam) )
{
#if wxDEBUG_LEVEL >= 2
wxLogTrace("winmsg", wxT("Forwarding %s to DefWindowProc."),
wxGetMessageName(message));
#endif // wxDEBUG_LEVEL >= 2
- rc.result = MSWDefWindowProc(message, wParam, lParam);
+ result = MSWDefWindowProc(message, wParam, lParam);
}
- return rc.result;
+ return result;
}
// ----------------------------------------------------------------------------
m_hWnd = (WXHWND)::CreateWindowEx
(
extendedStyle,
- className.wx_str(),
- title ? title : m_windowName.wx_str(),
+ className.t_str(),
+ title ? title : m_windowName.t_str(),
style,
x, y, w, h,
(HWND)MSWGetParent(),
(
CP_ACP,
0, // no flags
- ttip.wx_str(),
+ ttip.t_str(),
tipLength,
buf,
WXSIZEOF(buf) - 1
// first ask the user code - it may wish to set the cursor in some very
// specific way (for example, depending on the current position)
POINT pt;
-#ifdef __WXWINCE__
- if ( !::GetCursorPosWinCE(&pt))
-#else
- if ( !::GetCursorPos(&pt) )
-#endif
- {
- wxLogLastError(wxT("GetCursorPos"));
- }
+ wxGetCursorPosMSW(&pt);
int x = pt.x,
y = pt.y;
bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
{
+ // Ensure that wxWindow::GetCapture() returns NULL if called from the event
+ // handlers invoked below. This is necessary to avoid wrongly calling
+ // ReleaseMouse() when we're already losing the mouse capture anyhow.
+ gs_insideCaptureChanged = true;
+ wxON_BLOCK_EXIT_SET(gs_insideCaptureChanged, false);
+
// 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();
// be called from inside the event handlers called above)
m_updateRegion.Clear();
+ wxPaintDCImpl::EndPaint((wxWindow *)this);
+
return processed;
}
bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc)
{
+ if ( IsBeingDeleted() )
+ {
+ // We can get WM_ERASEBKGND after starting the destruction of our top
+ // level parent. Handling it in this case is unnecessary and can be
+ // actually harmful as e.g. wxStaticBox::GetClientSize() doesn't work
+ // without a valid TLW parent (because it uses dialog units internally
+ // which use the dialog font), so just don't do anything then.
+ return false;
+ }
+
switch ( GetBackgroundStyle() )
{
case wxBG_STYLE_ERASE:
::MapWindowPoints(NULL, GetHwnd(), (POINT *)&rc, 1);
- if ( !::SetBrushOrgEx((HDC)hDC, -rc.left, -rc.top, NULL) )
+ int x = rc.left,
+ y = rc.top;
+ MSWAdjustBrushOrg(&x, &y);
+
+ if ( !::SetBrushOrgEx((HDC)hDC, -x, -y, NULL) )
{
wxLogLastError(wxT("SetBrushOrgEx(bg brush)"));
}
return HandleWindowEvent(event);
}
-bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
+bool wxWindowMSW::BeginRepositioningChildren()
{
#if wxUSE_DEFERRED_SIZING
- // when we resize this window, its children are probably going to be
- // repositioned as well, prepare to use DeferWindowPos() for them
int numChildren = 0;
for ( HWND child = ::GetWindow(GetHwndOf(this), GW_CHILD);
child;
numChildren ++;
}
+ // Nothing is gained by deferring the repositioning of a single child.
+ if ( numChildren < 2 )
+ return false;
+
// Protect against valid m_hDWP being overwritten
- bool useDefer = false;
+ if ( m_hDWP )
+ return false;
- if ( numChildren > 1 )
+ m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
+ if ( !m_hDWP )
{
- if (!m_hDWP)
- {
- m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
- if ( !m_hDWP )
- {
- wxLogLastError(wxT("BeginDeferWindowPos"));
- }
- if (m_hDWP)
- useDefer = true;
- }
+ wxLogLastError(wxT("BeginDeferWindowPos"));
+ return false;
+ }
+
+ // Return true to indicate that EndDeferWindowPos() should be called.
+ return true;
+#endif // wxUSE_DEFERRED_SIZING
+}
+
+void wxWindowMSW::EndRepositioningChildren()
+{
+#if wxUSE_DEFERRED_SIZING
+ wxASSERT_MSG( m_hDWP, wxS("Shouldn't be called") );
+
+ // 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(wxT("EndDeferWindowPos"));
+ }
+
+ // Reset our children's pending pos/size values.
+ for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ wxWindowMSW * const child = node->GetData();
+ child->MSWEndDeferWindowPos();
}
#endif // wxUSE_DEFERRED_SIZING
+}
+
+bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
+{
+ // when we resize this window, its children are probably going to be
+ // repositioned as well, prepare to use DeferWindowPos() for them
+ ChildrenRepositioningGuard repositionGuard(this);
// update this window size
bool processed = false;
processed = HandleWindowEvent(event);
}
-#if wxUSE_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(wxT("EndDeferWindowPos"));
- }
-
- // Reset our children's pending pos/size values.
- for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
- node;
- node = node->GetNext() )
- {
- wxWindowMSW * const child = node->GetData();
- child->MSWEndDeferWindowPos();
- }
- }
-#endif // wxUSE_DEFERRED_SIZING
-
return processed;
}
// the messages sent from the in-place edit control used by the treectrl
// for label editing have id == 0, but they should _not_ be treated as menu
// messages (they are EN_XXX ones, in fact) so don't translate anything
- // coming from a control to wxEVT_COMMAND_MENU_SELECTED
+ // coming from a control to wxEVT_MENU
if ( !control )
{
- wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, id);
+ wxCommandEvent event(wxEVT_MENU, id);
event.SetEventObject(this);
event.SetInt(id);
};
#ifdef wxHAS_XBUTTON
- // the same messages are used for both auxillary mouse buttons so we need
+ // the same messages are used for both auxiliary mouse buttons so we need
// to adjust the index manually
switch ( msg )
{
}
-bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam)
+bool
+wxWindowMSW::HandleMouseWheel(wxMouseWheelAxis axis,
+ WXWPARAM wParam, WXLPARAM lParam)
{
#if wxUSE_MOUSEWHEEL
// notice that WM_MOUSEWHEEL position is in screen coords (as it's
InitMouseEvent(event, pt.x, pt.y, LOWORD(wParam));
event.m_wheelRotation = (short)HIWORD(wParam);
event.m_wheelDelta = WHEEL_DELTA;
+ event.m_wheelAxis = axis;
static int s_linesPerRotation = -1;
if ( s_linesPerRotation == -1 )
}
}
+ static int s_columnsPerRotation = -1;
+ if ( s_columnsPerRotation == -1 )
+ {
+ if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0,
+ &s_columnsPerRotation, 0))
+ {
+ // this setting is not supported on Windows 2000/XP, so use the value of 1
+ // http://msdn.microsoft.com/en-us/library/ms997498.aspx
+ s_columnsPerRotation = 1;
+ }
+ }
+
event.m_linesPerAction = s_linesPerRotation;
+ event.m_columnsPerAction = s_columnsPerRotation;
return HandleWindowEvent(event);
#else // !wxUSE_MOUSEWHEEL
state |= MK_RBUTTON;
POINT pt;
-#ifdef __WXWINCE__
- if ( !::GetCursorPosWinCE(&pt) )
-#else
- if ( !::GetCursorPos(&pt) )
-#endif
- {
- wxLogLastError(wxT("GetCursorPos"));
- }
+ wxGetCursorPosMSW(&pt);
// we need to have client coordinates here for symmetry with
// wxEVT_ENTER_WINDOW
#ifndef __WXWINCE__
event.SetTimestamp(::GetMessageTime());
#endif
-
- // Event coordinates must be in window client coordinates system which
- // doesn't make sense if there is no window.
- //
- // We could use screen coordinates for such events but this would make the
- // logic of the event handlers more complicated: you'd need to test for the
- // event object and interpret the coordinates differently according to
- // whether it's NULL or not so unless somebody really asks for this let's
- // just avoid the issue.
- if ( win )
- {
- const wxPoint mousePos = win->ScreenToClient(wxGetMousePosition());
- event.m_x = mousePos.x;
- event.m_y = mousePos.y;
- }
}
} // anonymous namespace
#ifndef __WXWINCE__
const HMENU hmenu = (HMENU)lParam;
- MENUITEMINFO mii;
- wxZeroMemory(mii);
- mii.cbSize = sizeof(MENUITEMINFO);
+ WinStruct<MENUITEMINFO> mii;
// 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
wxMenuItem *item = (wxMenuItem*)mii.dwItemData;
const wxString label(item->GetItemLabel());
- const wxChar *p = wxStrchr(label.wx_str(), wxT('&'));
+ const wxChar *p = wxStrchr(label.t_str(), wxT('&'));
while ( p++ )
{
if ( *p == wxT('&') )
bool wxWindowMSW::HandleClipboardEvent(WXUINT nMsg)
{
- const wxEventType type = nMsg == WM_CUT ? wxEVT_COMMAND_TEXT_CUT
- : nMsg == WM_COPY ? wxEVT_COMMAND_TEXT_COPY
- : /* nMsg == WM_PASTE */ wxEVT_COMMAND_TEXT_PASTE;
+ const wxEventType type = nMsg == WM_CUT ? wxEVT_TEXT_CUT
+ : nMsg == WM_COPY ? wxEVT_TEXT_COPY
+ : /* nMsg == WM_PASTE */ wxEVT_TEXT_PASTE;
wxClipboardTextEvent evt(type, GetId());
evt.SetEventObject(this);
}
wxJoystickEvent event(eventType, buttons, joystick, change);
- event.SetPosition(wxPoint(x, y));
+ if ( eventType == wxEVT_JOY_ZMOVE )
+ event.SetZPosition(x);
+ else
+ event.SetPosition(wxPoint(x, y));
event.SetEventObject(this);
return HandleWindowEvent(event);
case VK_OEM_5:
case VK_OEM_6:
case VK_OEM_7:
+ case VK_OEM_102:
// MapVirtualKey() returns 0 if it fails to convert the virtual
// key which nicely corresponds to our WXK_NONE.
wxk = ::MapVirtualKey(vk, MAPVK_VK_TO_CHAR);
case VK_DELETE:
wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DELETE, WXK_DELETE);
+
+ if ( uc )
+ *uc = WXK_DELETE;
break;
case VK_RETURN:
// don't use ChooseNormalOrExtended() here as the keys are reversed
// here: numpad enter is the extended one
wxk = HIWORD(lParam) & KF_EXTENDED ? WXK_NUMPAD_ENTER : WXK_RETURN;
+
+ if ( uc )
+ *uc = WXK_RETURN;
break;
default:
{
wxMouseState ms;
POINT pt;
- GetCursorPos( &pt );
+ wxGetCursorPosMSW(&pt);
ms.SetX(pt.x);
ms.SetY(pt.y);
DWORD hiWord = HIWORD(lParam);
if ( nCode != HC_NOREMOVE && ((hiWord & KF_UP) == 0) )
{
- wchar_t uc;
+ wchar_t uc = 0;
int id = wxMSWKeyboard::VKToWX(wParam, lParam, &uc);
// Don't intercept keyboard entry (notably Escape) if a modal window
#endif // wxUSE_UNICODE
)
{
- const wxWindow * const win = wxGetActiveWindow();
+ wxWindow const* win = wxWindow::DoFindFocus();
+ if ( !win )
+ {
+ // Even if the focus got lost somehow, still send the event
+ // to the top level parent to allow a wxDialog to always
+ // close on Escape.
+ win = wxGetActiveWindow();
+ }
wxKeyEvent event(wxEVT_CHAR_HOOK);
MSWInitAnyKeyEvent(event, wParam, lParam, win);
if ( handler && handler->ProcessEvent(event) )
{
- // processed
- return 1;
+ if ( !event.IsNextEventAllowed() )
+ {
+ // Stop processing of this event.
+ return 1;
+ }
}
}
}
pt2.y = pt.y;
HWND hWnd = ::WindowFromPoint(pt2);
+ if ( hWnd )
+ {
+ // WindowFromPoint() ignores the disabled children but we're supposed
+ // to take them into account, so check if we have a child at this
+ // coordinate using ChildWindowFromPointEx().
+ for ( ;; )
+ {
+ pt2.x = pt.x;
+ pt2.y = pt.y;
+ ::ScreenToClient(hWnd, &pt2);
+ HWND child = ::ChildWindowFromPointEx(hWnd, pt2, CWP_SKIPINVISIBLE);
+ if ( child == hWnd || !child )
+ break;
+
+ // ChildWindowFromPointEx() only examines the immediate children
+ // but we want to get the deepest (top in Z-order) one, so continue
+ // iterating for as long as it finds anything.
+ hWnd = child;
+ }
+ }
return wxGetWindowFromHWND((WXHWND)hWnd);
}
wxPoint wxGetMousePosition()
{
POINT pt;
-#ifdef __WXWINCE__
- GetCursorPosWinCE(&pt);
-#else
- GetCursorPos( & pt );
-#endif
+ wxGetCursorPosMSW(&pt);
return wxPoint(pt.x, pt.y);
}
return true;
}
-#if wxUSE_ACCEL
-
bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam)
{
int win_modifiers = LOWORD(lParam);
return HandleWindowEvent(event);
}
-#endif // wxUSE_ACCEL
-
#endif // wxUSE_HOTKEY
// Not tested under WinCE
#if wxUSE_STATBOX
static void wxAdjustZOrder(wxWindow* parent)
{
- if (parent->IsKindOf(CLASSINFO(wxStaticBox)))
+ if (wxDynamicCast(parent, wxStaticBox))
{
// Set the z-order correctly
SetWindowPos((HWND) parent->GetHWND(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);