#include "wx/dcclient.h"
#include "wx/utils.h"
#include "wx/app.h"
- #include "wx/panel.h"
#include "wx/layout.h"
#include "wx/dialog.h"
#include "wx/frame.h"
wxMenu *wxCurrentPopupMenu = NULL;
#endif // wxUSE_MENUS_NATIVE
-extern wxList WXDLLEXPORT wxPendingDelete;
extern const wxChar *wxCanvasClassName;
// ---------------------------------------------------------------------------
// get the text metrics for the current font
static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win);
-// check if the mouse is in the window or its child
-//static bool IsMouseInWindow(HWND hwnd);
+// wrapper around BringWindowToTop() API
+static inline void wxBringWindowToTop(HWND hwnd)
+{
+#ifdef __WXMICROWIN__
+ // It seems that MicroWindows brings the _parent_ of the window to the top,
+ // which can be the wrong one.
+
+ // activate (set focus to) specified window
+ ::SetFocus(hwnd);
+
+ // 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) )
+ {
+ wxLogLastError(_T("BringWindowToTop"));
+ }
+#endif // __WXMICROWIN__/!__WXMICROWIN__
+}
// ---------------------------------------------------------------------------
// event tables
EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged)
EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog)
EVT_IDLE(wxWindowMSW::OnIdle)
- EVT_SET_FOCUS(wxWindowMSW::OnSetFocus)
END_EVENT_TABLE()
// ===========================================================================
MSWDetachWindowMenu();
+#ifndef __WXUNIVERSAL__
// VS: make sure there's no wxFrame with last focus set to us:
- for (wxWindow *win = GetParent(); win; win = win->GetParent())
+ for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
{
wxFrame *frame = wxDynamicCast(win, wxFrame);
if ( frame )
{
if ( frame->GetLastFocus() == this )
+ {
frame->SetLastFocus((wxWindow*)NULL);
+ }
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 ( show )
{
-#ifdef __WXMICROWIN__
- // It seems that MicroWindows brings the _parent_ of the
- // window to the top, which can be the wrong one.
-
- // activate (set focus to) specified window
- ::SetFocus(hWnd);
-
- // raise top level parent to top of z order
- ::SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0,
- SWP_NOMOVE|SWP_NOSIZE);
-#else
- BringWindowToTop(hWnd);
-#endif
+ wxBringWindowToTop(hWnd);
}
return TRUE;
// Raise the window to the top of the Z order
void wxWindowMSW::Raise()
{
-#ifdef __WIN16__
- ::BringWindowToTop(GetHwnd());
-#else // Win32
-#ifdef __WXMICROWIN__
- // It seems that MicroWindows brings the _parent_ of the
- // window to the top, which can be the wrong one.
-
- // activate (set focus to) specified window
- ::SetFocus(GetHwnd());
-
- // raise top level parent to top of z order
- ::SetWindowPos(GetHwnd(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
-#else
- ::SetForegroundWindow(GetHwnd());
-#endif
-#endif
+ wxBringWindowToTop(GetHwnd());
}
// Lower the window to the bottom of the Z order
POINT point;
::GetCursorPos(&point);
- RECT rect;
- ::GetWindowRect(hWnd, &rect);
+ RECT rect = wxGetWindowRect(hWnd);
if ( ::PtInRect(&rect, point) && !wxIsBusy() )
::SetCursor(GetHcursorOf(m_cursor));
#endif // WXWIN_COMPATIBILITY
+inline int GetScrollPosition(HWND hWnd, int wOrient)
+{
+#ifdef __WXMICROWIN__
+ return ::GetScrollPosWX(hWnd, wOrient);
+#else
+ return ::GetScrollPos(hWnd, wOrient);
+#endif
+}
+
int wxWindowMSW::GetScrollPos(int orient) const
{
int wOrient;
wOrient = SB_HORZ;
else
wOrient = SB_VERT;
+
HWND hWnd = GetHwnd();
- if ( hWnd )
- {
-#ifdef __WXMICROWIN__
- return ::GetScrollPosWX(hWnd, wOrient);
-#else
- return ::GetScrollPos(hWnd, wOrient);
-#endif
- }
- else
- return 0;
+ wxCHECK_MSG( hWnd, 0, _T("no HWND in GetScrollPos") );
+
+ return GetScrollPosition(hWnd, wOrient);
}
// This now returns the whole range, not just the number
::ScrollWindow(GetHwnd(), dx, dy, prect ? &rect : NULL, NULL);
}
-static void ScrollVertically(int kind, int count)
+static bool ScrollVertically(HWND hwnd, int kind, int count)
{
+ int posStart = GetScrollPosition(hwnd, SB_VERT);
+
+ int pos = posStart;
+ for ( int n = 0; n < count; n++ )
+ {
+ ::SendMessage(hwnd, WM_VSCROLL, kind, 0);
+
+ int posNew = GetScrollPosition(hwnd, SB_VERT);
+ if ( posNew == pos )
+ {
+ // don't bother to continue, we're already at top/bottom
+ break;
+ }
+
+ pos = posNew;
+ }
+
+ return pos != posStart;
}
-void wxWindowMSW::ScrollLines(int lines)
+bool wxWindowMSW::ScrollLines(int lines)
{
bool down = lines > 0;
- ScrollVertically(down ? SB_LINEDOWN : SB_LINEUP, down ? lines : -lines);
+ return ScrollVertically(GetHwnd(),
+ down ? SB_LINEDOWN : SB_LINEUP,
+ down ? lines : -lines);
}
-void wxWindowMSW::ScrollPages(int pages)
+bool wxWindowMSW::ScrollPages(int pages)
{
bool down = pages > 0;
- ScrollVertically(down ? SB_PAGEDOWN : SB_PAGEUP, down ? pages : -pages);
+ return ScrollVertically(GetHwnd(),
+ down ? SB_PAGEDOWN : SB_PAGEUP,
+ down ? pages : -pages);
}
// ---------------------------------------------------------------------------
// we need to have client coordinates here for symmetry with
// wxEVT_ENTER_WINDOW
- RECT rect;
- if ( !::GetWindowRect(GetHwnd(), &rect) )
- {
- wxLogLastError(_T("GetWindowRect"));
- }
+ RECT rect = wxGetWindowRect(GetHwnd());
pt.x -= rect.left;
pt.y -= rect.top;
void wxWindowMSW::Thaw()
{
SendSetRedraw(GetHwnd(), TRUE);
+
+ // we need to refresh everything or otherwise he invalidated area is not
+ // repainted
+ Refresh();
}
void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
// Get total size
void wxWindowMSW::DoGetSize(int *x, int *y) const
{
- HWND hWnd = GetHwnd();
- RECT rect;
-#ifdef __WIN16__
- ::GetWindowRect(hWnd, &rect);
-#else
- if ( !::GetWindowRect(hWnd, &rect) )
- {
- wxLogLastError(_T("GetWindowRect"));
- }
-#endif
+ RECT rect = wxGetWindowRect(GetHwnd());
+
if ( x )
*x = rect.right - rect.left;
if ( y )
*y = rect.bottom - rect.top;
}
-void wxWindowMSW::DoGetPosition(int *x, int *y) const
+// Get size *available for subwindows* i.e. excluding menu bar etc.
+void wxWindowMSW::DoGetClientSize(int *x, int *y) const
{
- HWND hWnd = GetHwnd();
+ RECT rect = wxGetClientRect(GetHwnd());
- RECT rect;
- GetWindowRect(hWnd, &rect);
+ 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;
if ( y )
pt.y = *y;
- HWND hWnd = GetHwnd();
- ::ScreenToClient(hWnd, &pt);
+ ::ScreenToClient(GetHwnd(), &pt);
if ( x )
*x = pt.x;
if ( y )
pt.y = *y;
- HWND hWnd = GetHwnd();
- ::ClientToScreen(hWnd, &pt);
+ ::ClientToScreen(GetHwnd(), &pt);
if ( x )
*x = pt.x;
*y = pt.y;
}
-// Get size *available for subwindows* i.e. excluding menu bar etc.
-void wxWindowMSW::DoGetClientSize(int *x, int *y) const
-{
- HWND hWnd = GetHwnd();
- RECT rect;
- ::GetClientRect(hWnd, &rect);
- if ( x )
- *x = rect.right;
- if ( y )
- *y = rect.bottom;
-}
-
void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
{
if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) )
return wxPoint(0, 0);
}
-// Makes an adjustment to the window position (for example, a frame that has
-// a toolbar that it manages itself).
-void wxWindowMSW::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
-{
- // don't do it for the dialogs/frames - they float independently of their
- // parent
- if ( !IsTopLevel() )
- {
- wxWindow *parent = GetParent();
- if ( !(sizeFlags & wxSIZE_NO_ADJUSTMENTS) && parent )
- {
- wxPoint pt(parent->GetClientAreaOrigin());
- x += pt.x;
- y += pt.y;
- }
- }
-}
-
// ---------------------------------------------------------------------------
// text metrics
// ---------------------------------------------------------------------------
// popup menu
// ---------------------------------------------------------------------------
+#if wxUSE_MENUS_NATIVE
+
// yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
// immediately, without waiting for the next event loop iteration
//
}
}
-#if wxUSE_MENUS_NATIVE
-
bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y)
{
menu->SetInvokingWindow(this);
bProcess = FALSE;
}
-#if wxUSE_BUTTON
+ // FIXME: this should be handled by
+ // wxNavigationKeyEvent handler and not here!!
else
{
- wxPanel *panel = wxDynamicCastThis(wxPanel);
- wxButton *btn = NULL;
- if ( panel )
- {
- // panel may have a default button which should
- // be activated by Enter
- btn = panel->GetDefaultItem();
- }
-
+#if wxUSE_BUTTON
+ wxButton *btn = wxDynamicCast(GetDefaultItem(),
+ wxButton);
if ( btn && btn->IsEnabled() )
{
// if we do have a default button, do press it
return TRUE;
}
- // else: but if it does not it makes sense to make
- // it work like a TAB - and that's what we do.
- // Note that Ctrl-Enter always works this way.
- }
+ else // no default button
#endif // wxUSE_BUTTON
+ {
+ // no special function for enter and don't even
+ // let IsDialogMessage() have it: it seems to
+ // do something really strange with it
+ return FALSE;
+ }
+ }
}
break;
if ( GetEventHandler()->ProcessEvent(event) )
{
-#if wxUSE_BUTTON
- wxButton *btn = wxDynamicCast(FindFocus(), wxButton);
- if ( btn )
- {
- // the button which has focus should be default
- btn->SetDefault();
- }
-#endif // wxUSE_BUTTON
-
return TRUE;
}
}
}
-#else
+#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 )
}
}
}
-#endif // 0
+#endif // 1/0
if ( ::IsDialogMessage(GetHwnd(), msg) )
{
#endif // wxUSE_ACCEL
}
+bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG* pMsg)
+{
+ // preprocess all messages by default
+ return TRUE;
+}
+
// ---------------------------------------------------------------------------
// message params unpackers (different for Win16 and Win32)
// ---------------------------------------------------------------------------
break;
case WM_DESTROY:
- processed = HandleDestroy();
+ // 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_MOVE:
if ( !m_hWnd )
{
- wxLogError(_("Can't create window of class %s!\nPossible Windows 3.x compatibility problem?"),
- wclass);
+ wxLogSysError(_("Can't create window of class %s"), wclass);
return FALSE;
}
if ( !endSession )
return FALSE;
+ // only send once
+ if ( (this != wxTheApp->GetTopWindow()) )
+ return FALSE;
+
wxCloseEvent event(wxEVT_END_SESSION, -1);
event.SetEventObject(wxTheApp);
event.SetCanVeto(FALSE);
event.SetLoggingOff( (logOff == (long)ENDSESSION_LOGOFF) );
- if ( (this == wxTheApp->GetTopWindow()) && // Only send once
- wxTheApp->ProcessEvent(event))
- {
- }
- return TRUE;
+
+ return wxTheApp->ProcessEvent(event);
}
// ---------------------------------------------------------------------------
// activation/focus
// ---------------------------------------------------------------------------
-void wxWindowMSW::OnSetFocus(wxFocusEvent& event)
-{
- // panel wants to track the window which was the last to have focus in it,
- // so we want to set ourselves as the window which last had focus
- //
- // notice that it's also important to do it upwards the tree becaus
- // otherwise when the top level panel gets focus, it won't set it back to
- // us, but to some other sibling
- wxWindow *win = (wxWindow *)this;
- while ( win )
- {
- wxWindow *parent = win->GetParent();
- wxPanel *panel = wxDynamicCast(parent, wxPanel);
- if ( panel )
- {
- panel->SetLastFocus(win);
- }
-
- win = parent;
- }
-
- wxLogTrace(_T("focus"), _T("%s (0x%08x) gets focus"),
- GetClassInfo()->GetClassName(), GetHandle());
-
- event.Skip();
-}
-
bool wxWindowMSW::HandleActivate(int state,
bool WXUNUSED(minimized),
WXHWND WXUNUSED(activate))
bool wxWindowMSW::HandleSetFocus(WXHWND hwnd)
{
+ // notify the parent keeping track of focus for the kbd navigation
+ // purposes that we got it
+ wxChildFocusEvent eventFocus((wxWindow *)this);
+ (void)GetEventHandler()->ProcessEvent(eventFocus);
+
#if wxUSE_CARET
// Deal with caret
if ( m_caret )
}
#endif // wxUSE_CARET
+#if wxUSE_TEXTCTRL
+ // If it's a wxTextCtrl don't send the event as it will be done
+ // after the control gets to process it from EN_FOCUS handler
+ if ( wxDynamicCastThis(wxTextCtrl) )
+ {
+ return FALSE;
+ }
+#endif // wxUSE_TEXTCTRL
+
wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId);
event.SetEventObject(this);
}
#endif // wxUSE_CARET
+#if wxUSE_TEXTCTRL
+ // If it's a wxTextCtrl don't send the event as it will be done
+ // after the control gets to process it.
+ wxTextCtrl *ctrl = wxDynamicCastThis(wxTextCtrl);
+ if ( ctrl )
+ {
+ return FALSE;
+ }
+#endif
+
wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId);
event.SetEventObject(this);
wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files);
event.m_eventObject = this;
- event.m_pos.x = dropPoint.x; event.m_pos.x = dropPoint.y;
+ event.m_pos.x = dropPoint.x;
+ event.m_pos.y = dropPoint.y;
bool rc = GetEventHandler()->ProcessEvent(event);
#if wxUSE_MENUS_NATIVE
// is it a menu item?
- if ( id == 0 )
+ DRAWITEMSTRUCT *pDrawStruct = (DRAWITEMSTRUCT *)itemStruct;
+ if ( id == 0 && pDrawStruct->CtlType == ODT_MENU )
{
- DRAWITEMSTRUCT *pDrawStruct = (DRAWITEMSTRUCT *)itemStruct;
wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData);
wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
{
#if wxUSE_OWNER_DRAWN
// is it a menu item?
- if ( id == 0 )
+ MEASUREITEMSTRUCT *pMeasureStruct = (MEASUREITEMSTRUCT *)itemStruct;
+ if ( id == 0 && pMeasureStruct->CtlType == ODT_MENU )
{
- MEASUREITEMSTRUCT *pMeasureStruct = (MEASUREITEMSTRUCT *)itemStruct;
wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData);
wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
// create the key event of the given type for the given key - used by
// HandleChar and HandleKeyDown/Up
wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType,
- int id,
- WXLPARAM lParam) const
+ int id,
+ WXLPARAM lParam) const
{
wxKeyEvent event(evType);
event.SetId(GetId());
#endif // wxUSE_SPINCTRL
#endif // Win32
-
- if ( !win )
- {
- // hwnd is not a wxWindow, try its parent next below
- hwnd = ::GetParent(hwnd);
- }
}
}
while ( hwnd && !win )
{
- win = wxFindWinFromHandle((WXHWND)hwnd);
+ // this is a really ugly hack needed to avoid mistakenly returning the
+ // parent frame wxWindow for the find/replace modeless dialog HWND -
+ // this, in turn, is needed to call IsDialogMessage() from
+ // wxApp::ProcessMessage() as for this we must return NULL from here
+ //
+ // FIXME: this is clearly not the best way to do it but I think we'll
+ // need to change HWND <-> wxWindow code more heavily than I can
+ // do it now to fix it
+ if ( ::GetWindow(hwnd, GW_OWNER) )
+ {
+ // it's a dialog box, don't go upwards
+ break;
+ }
+
hwnd = ::GetParent(hwnd);
+ win = wxFindWinFromHandle((WXHWND)hwnd);
}
return win;