/////////////////////////////////////////////////////////////////////////////
-// Name: windows.cpp
+// Name: src/msw/windows.cpp
// Purpose: wxWindow
// Author: Julian Smart
// Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation
#include <string.h>
-#ifndef __GNUWIN32_OLD__
+#if !defined(__GNUWIN32_OLD__) || defined(__CYGWIN10__)
#include <shellapi.h>
#include <mmsystem.h>
#endif
#include <windowsx.h>
#endif
-#if !defined(__GNUWIN32_OLD__) && !defined(__TWIN32__)
+#if (!defined(__GNUWIN32_OLD__) && !defined(__TWIN32__)) || defined(__CYGWIN10__)
#ifdef __WIN95__
#include <commctrl.h>
#endif
// the last Windows message we got (MT-UNSAFE)
extern MSG s_currentMsg;
+#if wxUSE_MENUS_NATIVE
wxMenu *wxCurrentPopupMenu = NULL;
+#endif // wxUSE_MENUS_NATIVE
+
extern wxList WXDLLEXPORT wxPendingDelete;
extern const wxChar *wxCanvasClassName;
const char *wxGetMessageName(int message);
#endif //__WXDEBUG__
-void wxRemoveHandleAssociation(wxWindow *win);
-void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win);
+void wxRemoveHandleAssociation(wxWindowMSW *win);
+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(wxWindow *win, int *x, int *y, WPARAM *flags);
+static void TranslateKbdEventToMouse(wxWindowMSW *win,
+ int *x, int *y, WPARAM *flags);
// get the text metrics for the current font
-static TEXTMETRIC wxGetTextMetrics(const wxWindow *win);
+static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win);
+
+// check if the mouse is in the window or its child
+static bool IsMouseInWindow(HWND hwnd);
// ---------------------------------------------------------------------------
// event tables
// ---------------------------------------------------------------------------
-IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
-
-BEGIN_EVENT_TABLE(wxWindow, wxWindowBase)
- EVT_ERASE_BACKGROUND(wxWindow::OnEraseBackground)
- EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
- EVT_INIT_DIALOG(wxWindow::OnInitDialog)
- EVT_IDLE(wxWindow::OnIdle)
- EVT_SET_FOCUS(wxWindow::OnSetFocus)
+// in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
+// method
+#ifdef __WXUNIVERSAL__
+ IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW, wxWindowBase)
+#else // __WXMSW__
+ IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
+#endif // __WXUNIVERSAL__/__WXMSW__
+
+BEGIN_EVENT_TABLE(wxWindowMSW, wxWindowBase)
+ EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground)
+ EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged)
+ EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog)
+ EVT_IDLE(wxWindowMSW::OnIdle)
+ EVT_SET_FOCUS(wxWindowMSW::OnSetFocus)
END_EVENT_TABLE()
// ===========================================================================
// ---------------------------------------------------------------------------
// Find an item given the MS Windows id
-wxWindow *wxWindow::FindItem(long id) const
+wxWindow *wxWindowMSW::FindItem(long id) const
{
+#if wxUSE_CONTROLS
wxControl *item = wxDynamicThisCast(this, wxControl);
if ( item )
{
- // i it we or one of our "internal" children?
- if ( item->GetId() == id ||
- (item->GetSubcontrols().Index(id) != wxNOT_FOUND) )
+ // is it we or one of our "internal" children?
+ if ( item->GetId() == id
+#ifndef __WXUNIVERSAL__
+ || (item->GetSubcontrols().Index(id) != wxNOT_FOUND)
+#endif // __WXUNIVERSAL__
+ )
{
return item;
}
}
+#endif // wxUSE_CONTROLS
wxWindowList::Node *current = GetChildren().GetFirst();
while (current)
}
// Find an item given the MS Windows handle
-wxWindow *wxWindow::FindItemByHWND(WXHWND hWnd, bool controlOnly) const
+wxWindow *wxWindowMSW::FindItemByHWND(WXHWND hWnd, bool controlOnly) const
{
wxWindowList::Node *current = GetChildren().GetFirst();
while (current)
if ( wnd )
return wnd;
- if ( !controlOnly || parent->IsKindOf(CLASSINFO(wxControl)) )
+ if ( !controlOnly
+#if wxUSE_CONTROLS
+ || parent->IsKindOf(CLASSINFO(wxControl))
+#endif // wxUSE_CONTROLS
+ )
{
wxWindow *item = current->GetData();
if ( item->GetHWND() == hWnd )
}
// Default command handler
-bool wxWindow::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id))
+bool wxWindowMSW::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id))
{
return FALSE;
}
// constructors and such
// ----------------------------------------------------------------------------
-void wxWindow::Init()
+void wxWindowMSW::Init()
{
// generic
InitBase();
// MSW specific
m_doubleClickAllowed = 0;
- m_winCaptured = FALSE;
m_isBeingDeleted = FALSE;
m_oldWndProc = 0;
}
// Destructor
-wxWindow::~wxWindow()
+wxWindowMSW::~wxWindowMSW()
{
m_isBeingDeleted = TRUE;
MSWDetachWindowMenu();
-
+
// VS: make sure there's no wxFrame with last focus set to us:
for (wxWindow *win = GetParent(); win; win = win->GetParent())
{
}
}
+ // 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
+ // find their parent frame (see above).
+ DestroyChildren();
+
if ( m_parent )
m_parent->RemoveChild(this);
- DestroyChildren();
-
if ( m_hWnd )
{
// VZ: test temp removed to understand what really happens here
}
// real construction (Init() must have been called before!)
-bool wxWindow::Create(wxWindow *parent, wxWindowID id,
- const wxPoint& pos,
- const wxSize& size,
- long style,
- const wxString& name)
+bool wxWindowMSW::Create(wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxString& name)
{
wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") );
parent->AddChild(this);
- DWORD msflags = 0;
- if ( style & wxBORDER )
- msflags |= WS_BORDER;
-/* Not appropriate for non-frame/dialog windows, and
- may clash with other window styles.
- if ( style & wxTHICK_FRAME )
- msflags |= WS_THICKFRAME;
-*/
- //msflags |= WS_CHILD /* | WS_CLIPSIBLINGS */ | WS_VISIBLE;
- msflags |= WS_CHILD | WS_VISIBLE;
+ // all windows are created visible
+ DWORD msflags = WS_CHILD | WS_VISIBLE;
+
+#ifdef __WXUNIVERSAL__
+ // no 3d effects, we draw them ourselves
+ WXDWORD exStyle = 0;
+#else // !wxUniversal
if ( style & wxCLIP_CHILDREN )
msflags |= WS_CLIPCHILDREN;
if ( style & wxCLIP_SIBLINGS )
// Even with extended styles, need to combine with WS_BORDER
// for them to look right.
- if ( want3D || (m_windowStyle & wxSIMPLE_BORDER) || (m_windowStyle & wxRAISED_BORDER ) ||
- (m_windowStyle & wxSUNKEN_BORDER) || (m_windowStyle & wxDOUBLE_BORDER))
+ if ( want3D ||
+ (m_windowStyle & (wxBORDER |
+ wxSIMPLE_BORDER |
+ wxRAISED_BORDER |
+ wxSUNKEN_BORDER |
+ wxDOUBLE_BORDER)) )
{
msflags |= WS_BORDER;
}
m_lDlgCode = DLGC_WANTARROWS | DLGC_WANTCHARS |
DLGC_WANTTAB | DLGC_WANTMESSAGE;
}
+#endif // wxUniversal/!wxUniversal
+
+ if ( style & wxPOPUP_WINDOW )
+ {
+ // a popup window floats on top of everything
+ exStyle |= WS_EX_TOPMOST | WS_EX_TOOLWINDOW;
+
+ // it is also created hidden as other top level windows
+ msflags &= ~WS_VISIBLE;
+ m_isShown = FALSE;
+ }
- return MSWCreate(m_windowId, parent, wxCanvasClassName, this, NULL,
+ return MSWCreate(m_windowId, parent, wxCanvasClassName,
+ (wxWindow *)this, NULL,
pos.x, pos.y,
WidthDefault(size.x), HeightDefault(size.y),
msflags, NULL, exStyle);
// basic operations
// ---------------------------------------------------------------------------
-void wxWindow::SetFocus()
+void wxWindowMSW::SetFocus()
{
HWND hWnd = GetHwnd();
- if ( hWnd )
- ::SetFocus(hWnd);
+ wxCHECK_RET( hWnd, _T("can't set focus to invalid window") );
+
+ ::SetLastError(0);
+
+ if ( !::SetFocus(hWnd) )
+ {
+ // was there really an error?
+ DWORD dwRes = ::GetLastError();
+ if ( dwRes )
+ {
+ wxLogApiError(_T("SetFocus"), dwRes);
+ }
+
+ // VZ: just why does this happen sometimes?? any idea?
+#if 0
+ HWND hwndFocus = ::GetFocus();
+ wxASSERT_MSG( hwndFocus == hWnd, _T("SetFocus() didn't work?") );
+#endif // 0
+ }
}
// Get the window with the focus
return NULL;
}
-bool wxWindow::Enable(bool enable)
+bool wxWindowMSW::Enable(bool enable)
{
if ( !wxWindowBase::Enable(enable) )
return FALSE;
return TRUE;
}
-bool wxWindow::Show(bool show)
+bool wxWindowMSW::Show(bool show)
{
if ( !wxWindowBase::Show(show) )
return FALSE;
}
// Raise the window to the top of the Z order
-void wxWindow::Raise()
+void wxWindowMSW::Raise()
{
+#ifdef __WIN16__
::BringWindowToTop(GetHwnd());
+#else // Win32
+ ::SetForegroundWindow(GetHwnd());
+#endif
}
// Lower the window to the bottom of the Z order
-void wxWindow::Lower()
+void wxWindowMSW::Lower()
{
::SetWindowPos(GetHwnd(), HWND_BOTTOM, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
-void wxWindow::SetTitle( const wxString& title)
+void wxWindowMSW::SetTitle( const wxString& title)
{
SetWindowText(GetHwnd(), title.c_str());
}
-wxString wxWindow::GetTitle() const
+wxString wxWindowMSW::GetTitle() const
{
return wxGetWindowText(GetHWND());
}
-void wxWindow::CaptureMouse()
+void wxWindowMSW::CaptureMouse()
{
HWND hWnd = GetHwnd();
- if ( hWnd && !m_winCaptured )
+ if ( hWnd )
{
- SetCapture(hWnd);
- m_winCaptured = TRUE;
+ ::SetCapture(hWnd);
}
}
-void wxWindow::ReleaseMouse()
+void wxWindowMSW::ReleaseMouse()
{
- if ( m_winCaptured )
+ if ( !::ReleaseCapture() )
{
- ReleaseCapture();
- m_winCaptured = FALSE;
+ wxLogLastError(_T("ReleaseCapture"));
}
}
-bool wxWindow::SetFont(const wxFont& font)
+/* static */ wxWindow *wxWindowBase::GetCapture()
+{
+ HWND hwnd = ::GetCapture();
+ return hwnd ? wxFindWinFromHandle((WXHWND)hwnd) : (wxWindow *)NULL;
+}
+
+bool wxWindowMSW::SetFont(const wxFont& font)
{
if ( !wxWindowBase::SetFont(font) )
{
return TRUE;
}
-bool wxWindow::SetCursor(const wxCursor& cursor)
+bool wxWindowMSW::SetCursor(const wxCursor& cursor)
{
if ( !wxWindowBase::SetCursor(cursor) )
{
return TRUE;
}
-void wxWindow::WarpPointer (int x_pos, int y_pos)
+void wxWindowMSW::WarpPointer (int x, int y)
{
- // Move the pointer to (x_pos,y_pos) coordinates. They are expressed in
- // pixel coordinates, relatives to the canvas -- So, we first need to
- // substract origin of the window, then convert to screen position
-
- int x = x_pos; int y = y_pos;
- RECT rect;
- GetWindowRect (GetHwnd(), &rect);
-
- x += rect.left;
- y += rect.top;
+ ClientToScreen(&x, &y);
- SetCursorPos (x, y);
+ if ( !::SetCursorPos(x, y) )
+ {
+ wxLogLastError(_T("SetCursorPos"));
+ }
}
#if WXWIN_COMPATIBILITY
-void wxWindow::MSWDeviceToLogical (float *x, float *y) const
+void wxWindowMSW::MSWDeviceToLogical (float *x, float *y) const
{
}
#endif // WXWIN_COMPATIBILITY
// ---------------------------------------------------------------------------
#if WXWIN_COMPATIBILITY
-void wxWindow::SetScrollRange(int orient, int range, bool refresh)
+void wxWindowMSW::SetScrollRange(int orient, int range, bool refresh)
{
#if defined(__WIN95__)
#endif
}
-void wxWindow::SetScrollPage(int orient, int page, bool refresh)
+void wxWindowMSW::SetScrollPage(int orient, int page, bool refresh)
{
#if defined(__WIN95__)
SCROLLINFO info;
#endif
}
-int wxWindow::OldGetScrollRange(int orient) const
+int wxWindowMSW::OldGetScrollRange(int orient) const
{
int wOrient;
if ( orient == wxHORIZONTAL )
return 0;
}
-int wxWindow::GetScrollPage(int orient) const
+int wxWindowMSW::GetScrollPage(int orient) const
{
if ( orient == wxHORIZONTAL )
return m_xThumbSize;
#endif // WXWIN_COMPATIBILITY
-int wxWindow::GetScrollPos(int orient) const
+int wxWindowMSW::GetScrollPos(int orient) const
{
int wOrient;
if ( orient == wxHORIZONTAL )
// This now returns the whole range, not just the number
// of positions that we can scroll.
-int wxWindow::GetScrollRange(int orient) const
+int wxWindowMSW::GetScrollRange(int orient) const
{
int wOrient;
if ( orient == wxHORIZONTAL )
return 0;
}
-int wxWindow::GetScrollThumb(int orient) const
+int wxWindowMSW::GetScrollThumb(int orient) const
{
if ( orient == wxHORIZONTAL )
return m_xThumbSize;
return m_yThumbSize;
}
-void wxWindow::SetScrollPos(int orient, int pos, bool refresh)
+void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh)
{
#if defined(__WIN95__)
SCROLLINFO info;
}
// New function that will replace some of the above.
-void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible,
+void wxWindowMSW::SetScrollbar(int orient, int pos, int thumbVisible,
int range, bool refresh)
{
#if defined(__WIN95__)
}
}
-void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
+void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect)
{
- RECT rect2;
- if ( rect )
+ RECT rect;
+ if ( prect )
{
- rect2.left = rect->x;
- rect2.top = rect->y;
- rect2.right = rect->x + rect->width;
- rect2.bottom = rect->y + rect->height;
+ rect.left = prect->x;
+ rect.top = prect->y;
+ rect.right = prect->x + prect->width;
+ rect.bottom = prect->y + prect->height;
}
- if ( rect )
- ::ScrollWindow(GetHwnd(), dx, dy, &rect2, NULL);
- else
- ::ScrollWindow(GetHwnd(), dx, dy, NULL, NULL);
+ ::ScrollWindow(GetHwnd(), dx, dy, prect ? &rect : NULL, NULL);
}
// ---------------------------------------------------------------------------
// subclassing
// ---------------------------------------------------------------------------
-void wxWindow::SubclassWin(WXHWND hWnd)
+void wxWindowMSW::SubclassWin(WXHWND hWnd)
{
wxASSERT_MSG( !m_oldWndProc, wxT("subclassing window twice?") );
SetWindowLong(hwnd, GWL_WNDPROC, (LONG) wxWndProc);
}
-void wxWindow::UnsubclassWin()
+void wxWindowMSW::UnsubclassWin()
{
wxRemoveHandleAssociation(this);
}
// Make a Windows extended style from the given wxWindows window style
-WXDWORD wxWindow::MakeExtendedStyle(long style, bool eliminateBorders)
+WXDWORD wxWindowMSW::MakeExtendedStyle(long style, bool eliminateBorders)
{
WXDWORD exStyle = 0;
if ( style & wxTRANSPARENT_WINDOW )
// 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 wxWindow::Determine3DEffects(WXDWORD defaultBorderStyle,
+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() || !IsKindOf(CLASSINFO(wxControl)) || (m_windowStyle & wxNO_BORDER) )
+ if ( !GetParent()
+#if wxUSE_CONTROLS
+ || !IsKindOf(CLASSINFO(wxControl))
+#endif // wxUSE_CONTROLS
+ || (m_windowStyle & wxNO_BORDER) )
{
*want3D = FALSE;
return MakeExtendedStyle(m_windowStyle, FALSE);
// 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 wxWindow::OnCommand(wxWindow& win, wxCommandEvent& event)
+void wxWindowMSW::OnCommand(wxWindow& win, wxCommandEvent& event)
{
if ( GetEventHandler()->ProcessEvent(event) )
return;
#endif // WXWIN_COMPATIBILITY_2
#if WXWIN_COMPATIBILITY
-wxObject* wxWindow::GetChild(int number) const
+wxObject* wxWindowMSW::GetChild(int number) const
{
// Return a pointer to the Nth object in the Panel
wxNode *node = GetChildren().First();
#endif // WXWIN_COMPATIBILITY
// Setup background and foreground colours correctly
-void wxWindow::SetupColours()
+void wxWindowMSW::SetupColours()
{
if ( GetParent() )
SetBackgroundColour(GetParent()->GetBackgroundColour());
}
-void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event))
+bool wxWindowMSW::IsMouseInWindow() const
+{
+ // get the mouse position
+ POINT pt;
+ ::GetCursorPos(&pt);
+
+ // find the window which currently has the cursor and go up the window
+ // chain until we find this window - or exhaust it
+ HWND hwnd = ::WindowFromPoint(pt);
+ while ( hwnd && (hwnd != GetHwnd()) )
+ hwnd = ::GetParent(hwnd);
+
+ return hwnd != NULL;
+}
+
+void wxWindowMSW::OnIdle(wxIdleEvent& WXUNUSED(event))
{
// Check if we need to send a LEAVE event
if ( m_mouseInWindow )
{
- POINT pt;
- ::GetCursorPos(&pt);
- if ( ::WindowFromPoint(pt) != GetHwnd() )
+ 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.
+ // 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 ( GetKeyState( VK_RBUTTON ) )
state |= MK_RBUTTON;
- wxMouseEvent event(wxEVT_LEAVE_WINDOW);
- InitMouseEvent(event, pt.x, pt.y, state);
+ POINT pt;
+ if ( !::GetCursorPos(&pt) )
+ {
+ wxLogLastError(_T("GetCursorPos"));
+ }
- (void)GetEventHandler()->ProcessEvent(event);
+ // we need to have client coordinates here for symmetry with
+ // wxEVT_ENTER_WINDOW
+ RECT rect;
+ if ( !::GetWindowRect(GetHwnd(), &rect) )
+ {
+ wxLogLastError(_T("GetWindowRect"));
+ }
+ pt.x -= rect.left;
+ pt.y -= rect.top;
+
+ wxMouseEvent event2(wxEVT_LEAVE_WINDOW);
+ InitMouseEvent(event2, pt.x, pt.y, state);
+
+ (void)GetEventHandler()->ProcessEvent(event2);
}
}
}
// Set this window to be the child of 'parent'.
-bool wxWindow::Reparent(wxWindowBase *parent)
+bool wxWindowMSW::Reparent(wxWindowBase *parent)
{
if ( !wxWindowBase::Reparent(parent) )
return FALSE;
return TRUE;
}
-void wxWindow::Clear()
+void wxWindowMSW::Clear()
{
- wxClientDC dc(this);
+ wxClientDC dc((wxWindow *)this);
wxBrush brush(GetBackgroundColour(), wxSOLID);
dc.SetBackground(brush);
dc.Clear();
}
-void wxWindow::Refresh(bool eraseBack, const wxRect *rect)
+void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
{
HWND hWnd = GetHwnd();
if ( hWnd )
}
}
+void wxWindowMSW::Update()
+{
+ if ( !::UpdateWindow(GetHwnd()) )
+ {
+ wxLogLastError(_T("UpdateWindow"));
+ }
+
+#ifdef __WIN32__
+ // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
+ // handler needs to be really drawn right now
+ (void)::GdiFlush();
+#endif // __WIN32__
+}
+
// ---------------------------------------------------------------------------
// drag and drop
// ---------------------------------------------------------------------------
#if wxUSE_DRAG_AND_DROP
-void wxWindow::SetDropTarget(wxDropTarget *pDropTarget)
+void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
{
if ( m_dropTarget != 0 ) {
m_dropTarget->Revoke(m_hWnd);
// old style file-manager drag&drop support: we retain the old-style
// DragAcceptFiles in parallel with SetDropTarget.
-void wxWindow::DragAcceptFiles(bool accept)
+void wxWindowMSW::DragAcceptFiles(bool accept)
{
HWND hWnd = GetHwnd();
if ( hWnd )
#if wxUSE_TOOLTIPS
-void wxWindow::DoSetToolTip(wxToolTip *tooltip)
+void wxWindowMSW::DoSetToolTip(wxToolTip *tooltip)
{
wxWindowBase::DoSetToolTip(tooltip);
// ---------------------------------------------------------------------------
// Get total size
-void wxWindow::DoGetSize(int *x, int *y) const
+void wxWindowMSW::DoGetSize(int *x, int *y) const
{
HWND hWnd = GetHwnd();
RECT rect;
*y = rect.bottom - rect.top;
}
-void wxWindow::DoGetPosition(int *x, int *y) const
+void wxWindowMSW::DoGetPosition(int *x, int *y) const
{
HWND hWnd = GetHwnd();
*y = point.y;
}
-void wxWindow::DoScreenToClient(int *x, int *y) const
+void wxWindowMSW::DoScreenToClient(int *x, int *y) const
{
POINT pt;
if ( x )
*y = pt.y;
}
-void wxWindow::DoClientToScreen(int *x, int *y) const
+void wxWindowMSW::DoClientToScreen(int *x, int *y) const
{
POINT pt;
if ( x )
}
// Get size *available for subwindows* i.e. excluding menu bar etc.
-void wxWindow::DoGetClientSize(int *x, int *y) const
+void wxWindowMSW::DoGetClientSize(int *x, int *y) const
{
HWND hWnd = GetHwnd();
RECT rect;
*y = rect.bottom;
}
-void wxWindow::DoMoveWindow(int x, int y, int width, int height)
+void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
{
if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) )
{
// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
// the width/height to best suit our contents, otherwise we reuse the current
// width/height
-void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags)
+void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags)
{
// get the current size and position...
int currentX, currentY;
DoMoveWindow(x, y, width, height);
}
-void wxWindow::DoSetClientSize(int width, int height)
+void wxWindowMSW::DoSetClientSize(int width, int height)
{
wxWindow *parent = GetParent();
HWND hWnd = GetHwnd();
// For implementation purposes - sometimes decorations make the client area
// smaller
-wxPoint wxWindow::GetClientAreaOrigin() const
+wxPoint wxWindowMSW::GetClientAreaOrigin() const
{
return wxPoint(0, 0);
}
// Makes an adjustment to the window position (for example, a frame that has
// a toolbar that it manages itself).
-void wxWindow::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
+void wxWindowMSW::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
{
// don't do it for the dialogs/frames - they float independently of their
// parent
if ( !(sizeFlags & wxSIZE_NO_ADJUSTMENTS) && parent )
{
wxPoint pt(parent->GetClientAreaOrigin());
- x += pt.x; y += pt.y;
+ x += pt.x;
+ y += pt.y;
}
}
}
// text metrics
// ---------------------------------------------------------------------------
-int wxWindow::GetCharHeight() const
+int wxWindowMSW::GetCharHeight() const
{
return wxGetTextMetrics(this).tmHeight;
}
-int wxWindow::GetCharWidth() const
+int wxWindowMSW::GetCharWidth() const
{
// +1 is needed because Windows apparently adds it when calculating the
// dialog units size in pixels
#if wxDIALOG_UNIT_COMPATIBILITY
- return wxGetTextMetrics(this).tmAveCharWidth ;
+ return wxGetTextMetrics(this).tmAveCharWidth;
#else
return wxGetTextMetrics(this).tmAveCharWidth + 1;
#endif
}
-void wxWindow::GetTextExtent(const wxString& string,
+void wxWindowMSW::GetTextExtent(const wxString& string,
int *x, int *y,
int *descent, int *externalLeading,
const wxFont *theFont) const
// Caret manipulation
// ---------------------------------------------------------------------------
-void wxWindow::CreateCaret(int w, int h)
+void wxWindowMSW::CreateCaret(int w, int h)
{
SetCaret(new wxCaret(this, w, h));
}
-void wxWindow::CreateCaret(const wxBitmap *WXUNUSED(bitmap))
+void wxWindowMSW::CreateCaret(const wxBitmap *WXUNUSED(bitmap))
{
wxFAIL_MSG("not implemented");
}
-void wxWindow::ShowCaret(bool show)
+void wxWindowMSW::ShowCaret(bool show)
{
wxCHECK_RET( m_caret, "no caret to show" );
m_caret->Show(show);
}
-void wxWindow::DestroyCaret()
+void wxWindowMSW::DestroyCaret()
{
SetCaret(NULL);
}
-void wxWindow::SetCaretPos(int x, int y)
+void wxWindowMSW::SetCaretPos(int x, int y)
{
wxCHECK_RET( m_caret, "no caret to move" );
m_caret->Move(x, y);
}
-void wxWindow::GetCaretPos(int *x, int *y) const
+void wxWindowMSW::GetCaretPos(int *x, int *y) const
{
wxCHECK_RET( m_caret, "no caret to get position of" );
// popup menu
// ---------------------------------------------------------------------------
-bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
+// yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
+// immediately, without waiting for the next event loop iteration
+//
+// NB: this function should probably be made public later as it can almost
+// surely replace wxYield() elsewhere as well
+static void wxYieldForCommandsOnly()
+{
+ // 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 )
+ {
+ wxTheApp->DoMessage((WXMSG *)&msg);
+ }
+}
+
+#if wxUSE_MENUS_NATIVE
+
+bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y)
{
menu->SetInvokingWindow(this);
menu->UpdateUI();
::ClientToScreen(hWnd, &point);
wxCurrentPopupMenu = menu;
::TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL);
- wxYieldIfNeeded();
+
+ // we need to do it righ now as otherwise the events are never going to be
+ // sent to wxCurrentPopupMenu from HandleCommand()
+ //
+ // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
+ // help and we'd still need wxYieldForCommandsOnly() as the menu may be
+ // destroyed as soon as we return (it can be a local variable in the caller
+ // for example) and so we do need to process the event immediately
+ wxYieldForCommandsOnly();
+
wxCurrentPopupMenu = NULL;
menu->SetInvokingWindow(NULL);
return TRUE;
}
+#endif // wxUSE_MENUS_NATIVE
+
// ===========================================================================
// pre/post message processing
// ===========================================================================
-long wxWindow::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
+long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{
if ( m_oldWndProc )
return ::CallWindowProc(CASTWNDPROC m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
return ::DefWindowProc(GetHwnd(), nMsg, wParam, lParam);
}
-bool wxWindow::MSWProcessMessage(WXMSG* pMsg)
+bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
{
+ // wxUniversal implements tab traversal itself
+#ifndef __WXUNIVERSAL__
if ( m_hWnd != 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL) )
{
// intercept dialog navigation keys
bProcess = FALSE;
}
+#if wxUSE_BUTTON
else
{
wxPanel *panel = wxDynamicThisCast(this, wxPanel);
// it work like a TAB - and that's what we do.
// Note that Ctrl-Enter always works this way.
}
+#endif // wxUSE_BUTTON
}
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;
}
return TRUE;
}
}
+#endif // __WXUNIVERSAL__
#if wxUSE_TOOLTIPS
if ( m_tooltip )
return FALSE;
}
-bool wxWindow::MSWTranslateMessage(WXMSG* pMsg)
+bool wxWindowMSW::MSWTranslateMessage(WXMSG* pMsg)
{
+#if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
return m_acceleratorTable.Translate(this, pMsg);
+#else
+ return FALSE;
+#endif // wxUSE_ACCEL
}
// ---------------------------------------------------------------------------
#ifdef __WIN32__
-void wxWindow::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam,
+void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam,
WORD *id, WXHWND *hwnd, WORD *cmd)
{
*id = LOWORD(wParam);
*cmd = HIWORD(wParam);
}
-void wxWindow::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam,
+void wxWindowMSW::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam,
WXWORD *state, WXWORD *minimized, WXHWND *hwnd)
{
*state = LOWORD(wParam);
*hwnd = (WXHWND)lParam;
}
-void wxWindow::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam,
+void wxWindowMSW::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam,
WXWORD *code, WXWORD *pos, WXHWND *hwnd)
{
*code = LOWORD(wParam);
*hwnd = (WXHWND)lParam;
}
-void wxWindow::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam,
+void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam,
WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd)
{
*nCtlColor = CTLCOLOR_BTN;
*hdc = (WXHDC)wParam;
}
-void wxWindow::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam,
+void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam,
WXWORD *item, WXWORD *flags, WXHMENU *hmenu)
{
*item = (WXWORD)wParam;
#else // Win16
-void wxWindow::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam,
+void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam,
WXWORD *id, WXHWND *hwnd, WXWORD *cmd)
{
*id = (WXWORD)wParam;
*cmd = HIWORD(lParam);
}
-void wxWindow::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam,
+void wxWindowMSW::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam,
WXWORD *state, WXWORD *minimized, WXHWND *hwnd)
{
*state = (WXWORD)wParam;
*hwnd = (WXHWND)HIWORD(lParam);
}
-void wxWindow::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam,
+void wxWindowMSW::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam,
WXWORD *code, WXWORD *pos, WXHWND *hwnd)
{
*code = (WXWORD)wParam;
*hwnd = (WXHWND)HIWORD(lParam);
}
-void wxWindow::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam,
+void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam,
WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd)
{
*hwnd = (WXHWND)LOWORD(lParam);
*hdc = (WXHDC)wParam;
}
-void wxWindow::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam,
+void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam,
WXWORD *item, WXWORD *flags, WXHMENU *hmenu)
{
*item = (WXWORD)wParam;
// Hook for new window just as it's being created, when the window isn't yet
// associated with the handle
-wxWindow *wxWndHook = NULL;
+wxWindowMSW *wxWndHook = NULL;
// Main window proc
LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
wxGetMessageName(message), wParam, lParam);
#endif // __WXDEBUG__
- wxWindow *wnd = wxFindWinFromHandle((WXHWND) hWnd);
+ wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd);
// when we get the first message for the HWND we just created, we associate
// it with wxWindow stored in wxWndHook
return rc;
}
-long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
+long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
// did we process the message?
bool processed = FALSE;
break;
case WM_SIZE:
- processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
+ switch ( wParam )
+ {
+ 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
+
+ case SIZE_MAXIMIZED:
+ case SIZE_RESTORED:
+ processed = HandleSize(LOWORD(lParam), HIWORD(lParam),
+ wParam);
+ }
break;
+#ifdef __WXUNIVERSAL__
+ case WM_ACTIVATEAPP:
+ wxTheApp->SetActive(wParam != 0, FindFocus());
+ break;
+
+ case WM_NCHITTEST:
+ // we shouldn't allow the windows which don't want to get focus to
+ // get it
+ if ( !AcceptsFocus() )
+ {
+ rc.result = HTTRANSPARENT;
+ processed = TRUE;
+ }
+ break;
+#endif // __WXUNIVERSAL__
+
case WM_ACTIVATE:
{
WXWORD state, minimized;
wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
- GetEventHandler()->ProcessEvent(evtCtx);
-
- // set processed to true even if the event is not handled
- // because if we don't windows will propogate the
- // WM_CONTEXTMENU up the parent window chain, which we have
- // already done ourselves.
- processed = true;
+ processed = GetEventHandler()->ProcessEvent(evtCtx);
}
break;
#endif // __WIN32__
static int gs_AssociationCount = 0;
#endif
-void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win)
+void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win)
{
// adding NULL hWnd is (first) surely a result of an error and
// (secondly) breaks menu command processing
}
}
-void wxRemoveHandleAssociation(wxWindow *win)
+void wxRemoveHandleAssociation(wxWindowMSW *win)
{
#if 0 // def __WXDEBUG__
if (wxWinHandleList->Member(win))
// Default destroyer - override if you destroy it in some other way
// (e.g. with MDI child windows)
-void wxWindow::MSWDestroyWindow()
+void wxWindowMSW::MSWDestroyWindow()
{
}
-void wxWindow::MSWDetachWindowMenu()
+void wxWindowMSW::MSWDetachWindowMenu()
{
if ( m_hMenu )
{
}
}
-bool wxWindow::MSWCreate(int id,
- wxWindow *parent,
- const wxChar *wclass,
- wxWindow *WXUNUSED(wx_win),
- const wxChar *title,
- int x,
- int y,
- int width,
- int height,
- WXDWORD style,
- const wxChar *dialog_template,
- WXDWORD extendedStyle)
+bool wxWindowMSW::MSWCreate(int id,
+ wxWindow *parent,
+ const wxChar *wclass,
+ wxWindow * WXUNUSED(wx_win),
+ const wxChar *title,
+ int x,
+ int y,
+ int width,
+ int height,
+ WXDWORD style,
+ const wxChar *dialog_template,
+ WXDWORD extendedStyle)
{
int x1 = CW_USEDEFAULT;
int y1 = 0;
// Find parent's size, if it exists, to set up a possible default
// panel size the size of the parent window
- RECT parent_rect;
+ RECT rectParent;
if ( parent )
{
- ::GetClientRect((HWND) parent->GetHWND(), &parent_rect);
+ ::GetClientRect(GetHwndOf(parent), &rectParent);
- width1 = parent_rect.right - parent_rect.left;
- height1 = parent_rect.bottom - parent_rect.top;
+ width1 = rectParent.right - rectParent.left;
+ height1 = rectParent.bottom - rectParent.top;
}
if ( x != -1 )
}
#endif // 0
- HWND hParent = parent ? GetHwndOf(parent) : NULL;
+ HWND hParent;
+ if ( GetWindowStyleFlag() & wxPOPUP_WINDOW )
+ {
+ // popup windows should have desktop as parent because they shouldn't
+ // be limited to the parents client area as child windows usually are
+ hParent = ::GetDesktopWindow();
+ }
+ else if ( parent )
+ {
+ hParent = GetHwndOf(parent);
+ }
+ else
+ {
+ // top level window
+ hParent = NULL;
+ }
wxWndHook = this;
{
int controlId = 0;
if ( style & WS_CHILD )
+ {
controlId = id;
- if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS )
- style |= WS_CLIPSIBLINGS;
+ if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS )
+ {
+ style |= WS_CLIPSIBLINGS;
+ }
+ }
wxString className(wclass);
if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE )
#ifdef __WIN95__
// FIXME: VZ: I'm not sure at all that the order of processing is correct
-bool wxWindow::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
+bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
{
LPNMHDR hdr = (LPNMHDR)lParam;
HWND hWnd = hdr->hwndFrom;
return MSWOnNotify(idCtrl, lParam, result);
}
-bool wxWindow::MSWOnNotify(int WXUNUSED(idCtrl),
+bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl),
WXLPARAM lParam,
WXLPARAM* WXUNUSED(result))
{
// end session messages
// ---------------------------------------------------------------------------
-bool wxWindow::HandleQueryEndSession(long logOff, bool *mayEnd)
+bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd)
{
wxCloseEvent event(wxEVT_QUERY_END_SESSION, -1);
event.SetEventObject(wxTheApp);
return rc;
}
-bool wxWindow::HandleEndSession(bool endSession, long logOff)
+bool wxWindowMSW::HandleEndSession(bool endSession, long logOff)
{
// do nothing if the session isn't ending
if ( !endSession )
// window creation/destruction
// ---------------------------------------------------------------------------
-bool wxWindow::HandleCreate(WXLPCREATESTRUCT WXUNUSED(cs), bool *mayCreate)
+bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT WXUNUSED(cs), bool *mayCreate)
{
// TODO: should generate this event from WM_NCCREATE
- wxWindowCreateEvent event(this);
+ wxWindowCreateEvent event((wxWindow *)this);
(void)GetEventHandler()->ProcessEvent(event);
*mayCreate = TRUE;
return TRUE;
}
-bool wxWindow::HandleDestroy()
+bool wxWindowMSW::HandleDestroy()
{
- wxWindowDestroyEvent event(this);
+ wxWindowDestroyEvent event((wxWindow *)this);
(void)GetEventHandler()->ProcessEvent(event);
// delete our drop target if we've got one
// activation/focus
// ---------------------------------------------------------------------------
-void wxWindow::OnSetFocus(wxFocusEvent& event)
+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 = this;
+ wxWindow *win = (wxWindow *)this;
while ( win )
{
wxWindow *parent = win->GetParent();
event.Skip();
}
-bool wxWindow::HandleActivate(int state,
+bool wxWindowMSW::HandleActivate(int state,
bool WXUNUSED(minimized),
WXHWND WXUNUSED(activate))
{
return GetEventHandler()->ProcessEvent(event);
}
-bool wxWindow::HandleSetFocus(WXHWND WXUNUSED(hwnd))
+bool wxWindowMSW::HandleSetFocus(WXHWND hwnd)
{
#if wxUSE_CARET
// Deal with caret
wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId);
event.SetEventObject(this);
+ // wxFindWinFromHandle() may return NULL, it is ok
+ event.SetWindow(wxFindWinFromHandle(hwnd));
+
return GetEventHandler()->ProcessEvent(event);
}
-bool wxWindow::HandleKillFocus(WXHWND WXUNUSED(hwnd))
+bool wxWindowMSW::HandleKillFocus(WXHWND hwnd)
{
#if wxUSE_CARET
// Deal with caret
wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId);
event.SetEventObject(this);
+ // wxFindWinFromHandle() may return NULL, it is ok
+ event.SetWindow(wxFindWinFromHandle(hwnd));
+
return GetEventHandler()->ProcessEvent(event);
}
// miscellaneous
// ---------------------------------------------------------------------------
-bool wxWindow::HandleShow(bool show, int WXUNUSED(status))
+bool wxWindowMSW::HandleShow(bool show, int WXUNUSED(status))
{
wxShowEvent event(GetId(), show);
event.m_eventObject = this;
return GetEventHandler()->ProcessEvent(event);
}
-bool wxWindow::HandleInitDialog(WXHWND WXUNUSED(hWndFocus))
+bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus))
{
wxInitDialogEvent event(GetId());
event.m_eventObject = this;
return GetEventHandler()->ProcessEvent(event);
}
-bool wxWindow::HandleDropFiles(WXWPARAM wParam)
+bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
{
HDROP hFilesInfo = (HDROP) wParam;
POINT dropPoint;
return rc;
}
-bool wxWindow::HandleSetCursor(WXHWND WXUNUSED(hWnd),
- short nHitTest,
- int WXUNUSED(mouseMsg))
+bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd),
+ short nHitTest,
+ int WXUNUSED(mouseMsg))
{
// the logic is as follows:
// -1. don't set cursor for non client area, including but not limited to
// owner drawn stuff
// ---------------------------------------------------------------------------
-bool wxWindow::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct)
+bool wxWindowMSW::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct)
{
#if wxUSE_OWNER_DRAWN
+
+#if wxUSE_MENUS_NATIVE
// is it a menu item?
if ( id == 0 )
{
(wxOwnerDrawn::wxODStatus)pDrawStruct->itemState
);
}
+#endif // wxUSE_MENUS_NATIVE
+#if wxUSE_CONTROLS
wxWindow *item = FindItem(id);
if ( item && item->IsKindOf(CLASSINFO(wxControl)) )
{
return ((wxControl *)item)->MSWOnDraw(itemStruct);
}
+#endif // wxUSE_CONTROLS
+
#endif // USE_OWNER_DRAWN
return FALSE;
}
-bool wxWindow::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct)
+bool wxWindowMSW::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct)
{
#if wxUSE_OWNER_DRAWN
// is it a menu item?
// colours and palettes
// ---------------------------------------------------------------------------
-bool wxWindow::HandleSysColorChange()
+bool wxWindowMSW::HandleSysColorChange()
{
wxSysColourChangedEvent event;
event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
}
-bool wxWindow::HandleCtlColor(WXHBRUSH *brush,
+bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush,
WXHDC pDC,
WXHWND pWnd,
WXUINT nCtlColor,
{
hBrush = OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam);
}
+#if wxUSE_CONTROLS
else
{
wxControl *item = (wxControl *)FindItemByHWND(pWnd, TRUE);
if ( item )
hBrush = item->OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam);
}
+#endif // wxUSE_CONTROLS
if ( hBrush )
*brush = hBrush;
}
// Define for each class of dialog and control
-WXHBRUSH wxWindow::OnCtlColor(WXHDC WXUNUSED(hDC),
- WXHWND WXUNUSED(hWnd),
- WXUINT WXUNUSED(nCtlColor),
- WXUINT WXUNUSED(message),
- WXWPARAM WXUNUSED(wParam),
- WXLPARAM WXUNUSED(lParam))
+WXHBRUSH wxWindowMSW::OnCtlColor(WXHDC WXUNUSED(hDC),
+ WXHWND WXUNUSED(hWnd),
+ WXUINT WXUNUSED(nCtlColor),
+ WXUINT WXUNUSED(message),
+ WXWPARAM WXUNUSED(wParam),
+ WXLPARAM WXUNUSED(lParam))
{
return (WXHBRUSH)0;
}
-bool wxWindow::HandlePaletteChanged(WXHWND hWndPalChange)
+bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
{
wxPaletteChangedEvent event(GetId());
event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
}
-bool wxWindow::HandleQueryNewPalette()
+bool wxWindowMSW::HandleQueryNewPalette()
{
wxQueryNewPaletteEvent event(GetId());
event.SetEventObject(this);
}
// Responds to colour changes: passes event on to children.
-void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event)
+void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& event)
{
wxNode *node = GetChildren().First();
while ( node )
// painting
// ---------------------------------------------------------------------------
-bool wxWindow::HandlePaint()
+bool wxWindowMSW::HandlePaint()
{
#ifdef __WIN32__
HRGN hRegion = ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
wxLogLastError(wxT("GetUpdateRgn"));
m_updateRegion = wxRegion((WXHRGN) hRegion);
-#else
+#else // Win16
RECT updateRect;
- ::GetUpdateRect(GetHwnd(), & updateRect, FALSE);
+ ::GetUpdateRect(GetHwnd(), &updateRect, FALSE);
m_updateRegion = wxRegion(updateRect.left, updateRect.top,
updateRect.right - updateRect.left,
updateRect.bottom - updateRect.top);
-#endif
+#endif // Win32/16
wxPaintEvent event(m_windowId);
event.SetEventObject(this);
- return GetEventHandler()->ProcessEvent(event);
+ bool processed = GetEventHandler()->ProcessEvent(event);
+
+ // note that we must generate NC event after the normal one as otherwise
+ // BeginPaint() will happily overwrite our decorations with the background
+ // colour
+ wxNcPaintEvent eventNc(m_windowId);
+ eventNc.SetEventObject(this);
+ GetEventHandler()->ProcessEvent(eventNc);
+
+ return processed;
}
// Can be called from an application's OnPaint handler
-void wxWindow::OnPaint(wxPaintEvent& event)
+void wxWindowMSW::OnPaint(wxPaintEvent& event)
{
+#ifdef __WXUNIVERSAL__
+ event.Skip();
+#else
HDC hDC = (HDC) wxPaintDC::FindDCInCache((wxWindow*) event.GetEventObject());
if (hDC != 0)
{
MSWDefWindowProc(WM_PAINT, (WPARAM) hDC, 0);
}
+#endif
}
-bool wxWindow::HandleEraseBkgnd(WXHDC hdc)
+bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc)
{
// Prevents flicker when dragging
if ( ::IsIconic(GetHwnd()) )
wxDCTemp dc(hdc);
- dc.SetWindow(this);
+ dc.SetHDC(hdc);
+ dc.SetWindow((wxWindow *)this);
dc.BeginDrawing();
wxEraseEvent event(m_windowId, &dc);
return rc;
}
-void wxWindow::OnEraseBackground(wxEraseEvent& event)
+void wxWindowMSW::OnEraseBackground(wxEraseEvent& event)
{
RECT rect;
::GetClientRect(GetHwnd(), &rect);
// moving and resizing
// ---------------------------------------------------------------------------
-bool wxWindow::HandleMinimize()
+bool wxWindowMSW::HandleMinimize()
{
wxIconizeEvent event(m_windowId);
event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
}
-bool wxWindow::HandleMaximize()
+bool wxWindowMSW::HandleMaximize()
{
wxMaximizeEvent event(m_windowId);
event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
}
-bool wxWindow::HandleMove(int x, int y)
+bool wxWindowMSW::HandleMove(int x, int y)
{
wxMoveEvent event(wxPoint(x, y), m_windowId);
event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
}
-bool wxWindow::HandleSize(int w, int h, WXUINT WXUNUSED(flag))
+bool wxWindowMSW::HandleSize(int w, int h, WXUINT WXUNUSED(flag))
{
wxSizeEvent event(wxSize(w, h), m_windowId);
event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
}
-bool wxWindow::HandleGetMinMaxInfo(void *mmInfo)
+bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo)
{
MINMAXINFO *info = (MINMAXINFO *)mmInfo;
return rc;
}
-// generate an artificial resize event
-/* FUNCTION IS NOW A MEMBER OF wxFrame - gt
-void wxWindow::SendSizeEvent()
-{
- RECT r;
-#ifdef __WIN16__
- ::GetWindowRect(GetHwnd(), &r);
-#else
- if ( !::GetWindowRect(GetHwnd(), &r) )
- {
- wxLogLastError(_T("GetWindowRect"));
- }
-#endif
-
- (void)::PostMessage(GetHwnd(), WM_SIZE, SIZE_RESTORED,
- MAKELPARAM(r.right - r.left, r.bottom - r.top));
-}
-*/
-
// ---------------------------------------------------------------------------
// command messages
// ---------------------------------------------------------------------------
-bool wxWindow::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control)
+bool wxWindowMSW::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control)
{
+#if wxUSE_MENUS_NATIVE
if ( wxCurrentPopupMenu )
{
wxMenu *popupMenu = wxCurrentPopupMenu;
return popupMenu->MSWCommand(cmd, id);
}
+#endif // wxUSE_MENUS_NATIVE
wxWindow *win = (wxWindow*) NULL;
if ( cmd == 0 || cmd == 1 ) // menu or accel - use id
return FALSE;
}
-bool wxWindow::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam))
+bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam))
{
// 4 bits are reserved
switch ( wParam & 0xFFFFFFF0 )
// mouse events
// ---------------------------------------------------------------------------
-void wxWindow::InitMouseEvent(wxMouseEvent& event, int x, int y, WXUINT flags)
+void wxWindowMSW::InitMouseEvent(wxMouseEvent& event,
+ int x, int y,
+ WXUINT flags)
{
- event.m_x = x;
- event.m_y = y;
- event.m_shiftDown = ((flags & MK_SHIFT) != 0);
- event.m_controlDown = ((flags & MK_CONTROL) != 0);
- event.m_leftDown = ((flags & MK_LBUTTON) != 0);
- event.m_middleDown = ((flags & MK_MBUTTON) != 0);
- event.m_rightDown = ((flags & MK_RBUTTON) != 0);
+ // our client coords are not quite the same as Windows ones
+ wxPoint pt = GetClientAreaOrigin();
+ event.m_x = x - pt.x;
+ event.m_y = y - pt.y;
+
+ event.m_shiftDown = (flags & MK_SHIFT) != 0;
+ event.m_controlDown = (flags & MK_CONTROL) != 0;
+ 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.SetTimestamp(s_currentMsg.time);
event.m_eventObject = this;
m_lastMouseY = y;
m_lastMouseEvent = event.GetEventType();
#endif // wxUSE_MOUSEEVENT_HACK
-
}
-bool wxWindow::HandleMouseEvent(WXUINT msg, int x, int y, WXUINT flags)
+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
return GetEventHandler()->ProcessEvent(event);
}
-bool wxWindow::HandleMouseMove(int x, int y, WXUINT flags)
+bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags)
{
if ( !m_mouseInWindow )
{
- // Generate an ENTER event
- m_mouseInWindow = TRUE;
+ // it would be wrong to assume that just because we get a mouse move
+ // event that the mouse is inside the window: although this is usually
+ // true, it is not if we had captured the mouse, so we need to check
+ // the mouse coordinates here
+ if ( !HasCapture() || IsMouseInWindow() )
+ {
+ // Generate an ENTER event
+ m_mouseInWindow = TRUE;
- wxMouseEvent event(wxEVT_ENTER_WINDOW);
- InitMouseEvent(event, x, y, flags);
+ wxMouseEvent event(wxEVT_ENTER_WINDOW);
+ InitMouseEvent(event, x, y, flags);
- (void)GetEventHandler()->ProcessEvent(event);
+ (void)GetEventHandler()->ProcessEvent(event);
+ }
}
#if wxUSE_MOUSEEVENT_HACK
return GetEventHandler()->ProcessEvent(event);
#else
+ (void) wParam;
+ (void) lParam;
+
return FALSE;
#endif
}
// create the key event of the given type for the given key - used by
// HandleChar and HandleKeyDown/Up
-wxKeyEvent wxWindow::CreateKeyEvent(wxEventType evType,
+wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType,
int id,
WXLPARAM lParam) const
{
// isASCII is TRUE only when we're called from WM_CHAR handler and not from
// WM_KEYDOWN one
-bool wxWindow::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII)
+bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII)
{
bool ctrlDown = FALSE;
return FALSE;
}
-bool wxWindow::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam)
+bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam)
{
int id = wxCharCodeMSWToWX(wParam);
return FALSE;
}
-bool wxWindow::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
+bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
{
int id = wxCharCodeMSWToWX(wParam);
// joystick
// ---------------------------------------------------------------------------
-bool wxWindow::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags)
+bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags)
{
int change = 0;
if ( flags & JOY_BUTTON1CHG )
// scrolling
// ---------------------------------------------------------------------------
-bool wxWindow::MSWOnScroll(int orientation, WXWORD wParam,
+bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam,
WXWORD pos, WXHWND control)
{
if ( control )
}
#endif //__WXDEBUG__
-static void TranslateKbdEventToMouse(wxWindow *win, int *x, int *y, WPARAM *flags)
+static void TranslateKbdEventToMouse(wxWindowMSW *win,
+ int *x, int *y, WPARAM *flags)
{
// construct the key mask
WPARAM& fwKeys = *flags;
win->ScreenToClient(x, y);
}
-static TEXTMETRIC wxGetTextMetrics(const wxWindow *win)
+static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win)
{
// prepare the DC
TEXTMETRIC tm;