X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a23fd0e1d1329a4a258b4defb3e0b0001b700c6e..28be2e8a170979d476a5ea4f585505b8a2f5af27:/src/msw/window.cpp?ds=inline diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 3a7107fbba..b19210ce93 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -29,6 +29,10 @@ #endif #ifndef WX_PRECOMP + #include + #include "wx/msw/winundef.h" + #include "wx/window.h" + #include "wx/accel.h" #include "wx/setup.h" #include "wx/menu.h" #include "wx/dc.h" @@ -46,31 +50,36 @@ #include #endif -#if wxUSE_OWNER_DRAWN +#if wxUSE_OWNER_DRAWN #include "wx/ownerdrw.h" #endif -#if wxUSE_DRAG_AND_DROP - #include "wx/msw/ole/droptgt.h" +#if wxUSE_DRAG_AND_DROP + #include "wx/dnd.h" #endif #include "wx/menuitem.h" #include "wx/log.h" +#include "wx/msw/private.h" + #if wxUSE_TOOLTIPS -#include "wx/tooltip.h" + #include "wx/tooltip.h" #endif +#if wxUSE_CARET + #include "wx/caret.h" +#endif // wxUSE_CARET + #include "wx/intl.h" #include "wx/log.h" -#include "wx/msw/private.h" - #include "wx/textctrl.h" +#include "wx/notebook.h" #include -#ifndef __GNUWIN32__ +#ifndef __GNUWIN32_OLD__ #include #include #endif @@ -79,126 +88,123 @@ #include #endif -#if ( defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__ ) -#include -#endif - -#ifndef __TWIN32__ - #ifdef __GNUWIN32__ - #include +#if !defined(__GNUWIN32_OLD__) && !defined(__TWIN32__) + #ifdef __WIN95__ + #include + #endif +#else // broken compiler + #ifndef __TWIN32__ + #include "wx/msw/gnuwin32/extra.h" #endif #endif -#ifdef GetCharWidth -#undef GetCharWidth +// This didn't appear in mingw until 2.95.2 +#ifndef SIF_TRACKPOS +#define SIF_TRACKPOS 16 #endif -#ifdef FindWindow -#undef FindWindow -#endif +// --------------------------------------------------------------------------- +// global variables +// --------------------------------------------------------------------------- -#ifdef GetClassName -#undef GetClassName -#endif +// the last Windows message we got (MT-UNSAFE) +extern MSG s_currentMsg; -#ifdef GetClassInfo -#undef GetClassInfo -#endif +wxMenu *wxCurrentPopupMenu = NULL; +extern wxList WXDLLEXPORT wxPendingDelete; +extern const wxChar *wxCanvasClassName; // --------------------------------------------------------------------------- -// macros +// private functions // --------------------------------------------------------------------------- -// standard macros missing from some compilers headers -#ifndef GET_X_LPARAM - #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) - #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp)) -#endif // GET_X_LPARAM +// the window proc for all our windows +LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam); -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- #ifdef __WXDEBUG__ const char *wxGetMessageName(int message); #endif //__WXDEBUG__ -#define WINDOW_MARGIN 3 // This defines sensitivity of Leave events - -wxMenu *wxCurrentPopupMenu = NULL; -extern wxList WXDLLEXPORT wxPendingDelete; - void wxRemoveHandleAssociation(wxWindow *win); void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win); wxWindow *wxFindWinFromHandle(WXHWND hWnd); -#if !USE_SHARED_LIBRARY - IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase) -#endif +// 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); + +// get the text metrics for the current font +static TEXTMETRIC wxGetTextMetrics(const wxWindow *win); // --------------------------------------------------------------------------- // 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) END_EVENT_TABLE() // =========================================================================== // implementation // =========================================================================== +// --------------------------------------------------------------------------- +// wxWindow utility functions +// --------------------------------------------------------------------------- + // Find an item given the MS Windows id -wxWindow *wxWindow::FindItem(int id) const +wxWindow *wxWindow::FindItem(long id) const { -// if ( !GetChildren() ) -// return NULL; - wxNode *current = GetChildren().First(); + wxControl *item = wxDynamicCast(this, wxControl); + if ( item ) + { + // i it we or one of our "internal" children? + if ( item->GetId() == id || + (item->GetSubcontrols().Index(id) != wxNOT_FOUND) ) + { + return item; + } + } + + wxWindowList::Node *current = GetChildren().GetFirst(); while (current) { - wxWindow *childWin = (wxWindow *)current->Data(); + wxWindow *childWin = current->GetData(); - wxWindow *wnd = childWin->FindItem(id) ; + wxWindow *wnd = childWin->FindItem(id); if ( wnd ) - return wnd ; + return wnd; - if ( childWin->IsKindOf(CLASSINFO(wxControl)) ) - { - wxControl *item = (wxControl *)childWin; - if ( item->GetId() == id ) - return item; - else - { - // In case it's a 'virtual' control (e.g. radiobox) - if ( item->GetSubcontrols().Member((wxObject *)id) ) - return item; - } - } - current = current->Next(); + current = current->GetNext(); } + return NULL; } // Find an item given the MS Windows handle wxWindow *wxWindow::FindItemByHWND(WXHWND hWnd, bool controlOnly) const { -// if ( !GetChildren() ) -// return NULL; - wxNode *current = GetChildren().First(); + wxWindowList::Node *current = GetChildren().GetFirst(); while (current) { - wxObject *obj = (wxObject *)current->Data() ; + wxWindow *parent = current->GetData(); + // Do a recursive search. - wxWindow *parent = (wxWindow *)obj ; - wxWindow *wnd = parent->FindItemByHWND(hWnd) ; + wxWindow *wnd = parent->FindItemByHWND(hWnd); if ( wnd ) - return wnd ; + return wnd; - if ( (!controlOnly) || obj->IsKindOf(CLASSINFO(wxControl)) ) + if ( !controlOnly || parent->IsKindOf(CLASSINFO(wxControl)) ) { - wxWindow *item = (wxWindow *)current->Data(); - if ( (HWND)(item->GetHWND()) == (HWND) hWnd ) + wxWindow *item = current->GetData(); + if ( item->GetHWND() == hWnd ) return item; else { @@ -206,7 +212,8 @@ wxWindow *wxWindow::FindItemByHWND(WXHWND hWnd, bool controlOnly) const return item; } } - current = current->Next(); + + current = current->GetNext(); } return NULL; } @@ -217,63 +224,6 @@ bool wxWindow::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id)) return FALSE; } -#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) -{ - LPNMHDR hdr = (LPNMHDR)lParam; - HWND hWnd = hdr->hwndFrom; - wxWindow *win = wxFindWinFromHandle((WXHWND)hWnd); - - // is this one of our windows? - if ( win ) - { - return win->MSWOnNotify(idCtrl, lParam, result); - } - - // try all our children - wxWindowList::Node *node = GetChildren().GetFirst(); - while ( node ) - { - wxWindow *child = node->GetData(); - if ( child->MSWOnNotify(idCtrl, lParam, result) ) - { - return TRUE; - - break; - } - - node = node->GetNext(); - } - - // finally try this window too (catches toolbar case) - return MSWOnNotify(idCtrl, lParam, result); -} - -bool wxWindow::MSWOnNotify(int WXUNUSED(idCtrl), - WXLPARAM lParam, - WXLPARAM* WXUNUSED(result)) -{ -#if wxUSE_TOOLTIPS - NMHDR* hdr = (NMHDR *)lParam; - if ( hdr->code == TTN_NEEDTEXT && m_tooltip ) - { - TOOLTIPTEXT *ttt = (TOOLTIPTEXT *)lParam; - ttt->lpszText = (char *)m_tooltip->GetTip().c_str(); - - // processed - return TRUE; - } -#endif // wxUSE_TOOLTIPS - - return FALSE; -} -#endif // __WIN95__ - -void wxWindow::PreDelete(WXHDC WXUNUSED(dc)) -{ -} - // ---------------------------------------------------------------------------- // constructors and such // ---------------------------------------------------------------------------- @@ -284,17 +234,9 @@ void wxWindow::Init() InitBase(); // MSW specific - m_doubleClickAllowed = 0 ; + m_doubleClickAllowed = 0; m_winCaptured = FALSE; - // caret stuff: initially there is no caret at all - m_caretWidth = - m_caretHeight = 0; - m_caretEnabled = - m_caretShown = FALSE; - - m_inOnSize = FALSE; - m_isBeingDeleted = FALSE; m_oldWndProc = 0; m_useCtl3D = FALSE; @@ -303,10 +245,18 @@ void wxWindow::Init() // wxWnd m_hMenu = 0; + m_hWnd = 0; + + // pass WM_GETDLGCODE to DefWindowProc() + m_lDlgCode = 0; + m_xThumbSize = 0; m_yThumbSize = 0; m_backgroundTransparent = FALSE; + // as all windows are created with WS_VISIBLE style... + m_isShown = TRUE; + #if wxUSE_MOUSEEVENT_HACK m_lastMouseX = m_lastMouseY = -1; @@ -327,18 +277,19 @@ wxWindow::~wxWindow() DestroyChildren(); if ( m_hWnd ) - ::DestroyWindow((HWND)m_hWnd); - - wxRemoveHandleAssociation(this); - m_hWnd = 0; + { + // VZ: test temp removed to understand what really happens here + //if (::IsWindow(GetHwnd())) + { + if ( !::DestroyWindow(GetHwnd()) ) + wxLogLastError(wxT("DestroyWindow")); + } - // Restore old Window proc, if required and remove hWnd <-> wxWindow - // association - UnsubclassWin(); + // remove hWnd <-> wxWindow association + wxRemoveHandleAssociation(this); + } } -extern char wxCanvasClassName[]; - // real construction (Init() must have been called before!) bool wxWindow::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, @@ -346,22 +297,30 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, long style, const wxString& name) { - wxCHECK_MSG( parent, FALSE, "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; 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; if ( style & wxCLIP_CHILDREN ) msflags |= WS_CLIPCHILDREN; + if ( style & wxCLIP_SIBLINGS ) + msflags |= WS_CLIPSIBLINGS; bool want3D; - WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ; + WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D); // Even with extended styles, need to combine with WS_BORDER // for them to look right. @@ -371,6 +330,14 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, msflags |= WS_BORDER; } + // calculate the value to return from WM_GETDLGCODE handler + if ( GetWindowStyleFlag() & wxWANTS_CHARS ) + { + // want everything: i.e. all keys and WM_CHAR message + m_lDlgCode = DLGC_WANTARROWS | DLGC_WANTCHARS | + DLGC_WANTTAB | DLGC_WANTMESSAGE; + } + MSWCreate(m_windowId, parent, wxCanvasClassName, this, NULL, pos.x, pos.y, WidthDefault(size.x), HeightDefault(size.y), @@ -379,6 +346,10 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, return TRUE; } +// --------------------------------------------------------------------------- +// basic operations +// --------------------------------------------------------------------------- + void wxWindow::SetFocus() { HWND hWnd = GetHwnd(); @@ -386,6 +357,18 @@ void wxWindow::SetFocus() ::SetFocus(hWnd); } +// Get the window with the focus +wxWindow *wxWindowBase::FindFocus() +{ + HWND hWnd = ::GetFocus(); + if ( hWnd ) + { + return wxFindWinFromHandle((WXHWND) hWnd); + } + + return NULL; +} + bool wxWindow::Enable(bool enable) { if ( !wxWindowBase::Enable(enable) ) @@ -395,9 +378,63 @@ bool wxWindow::Enable(bool enable) if ( hWnd ) ::EnableWindow(hWnd, (BOOL)enable); + // VZ: no, this is a bad idea: imagine that you have a dialog with some + // disabled controls and disable it - you really wouldn't like the + // disabled controls eb reenabled too when you reenable the dialog! +#if 0 + wxWindowList::Node *node = GetChildren().GetFirst(); + while ( node ) + { + wxWindow *child = node->GetData(); + child->Enable(enable); + + node = node->GetNext(); + } +#endif // 0 + + return TRUE; +} + +bool wxWindow::Show(bool show) +{ + if ( !wxWindowBase::Show(show) ) + return FALSE; + + HWND hWnd = GetHwnd(); + int cshow = show ? SW_SHOW : SW_HIDE; + ::ShowWindow(hWnd, cshow); + + if ( show ) + { + BringWindowToTop(hWnd); + } + return TRUE; } +// Raise the window to the top of the Z order +void wxWindow::Raise() +{ + ::BringWindowToTop(GetHwnd()); +} + +// Lower the window to the bottom of the Z order +void wxWindow::Lower() +{ + ::SetWindowPos(GetHwnd(), HWND_BOTTOM, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); +} + +void wxWindow::SetTitle( const wxString& title) +{ + SetWindowText(GetHwnd(), title.c_str()); +} + +wxString wxWindow::GetTitle() const +{ + return wxGetWindowText(GetHWND()); +} + void wxWindow::CaptureMouse() { HWND hWnd = GetHwnd(); @@ -417,3348 +454,3989 @@ void wxWindow::ReleaseMouse() } } -#if wxUSE_DRAG_AND_DROP - -void wxWindow::SetDropTarget(wxDropTarget *pDropTarget) +bool wxWindow::SetFont(const wxFont& font) { - if ( m_dropTarget != 0 ) { - m_dropTarget->Revoke(m_hWnd); - delete m_dropTarget; + if ( !wxWindowBase::SetFont(font) ) + { + // nothing to do + return FALSE; } - m_dropTarget = pDropTarget; - if ( m_dropTarget != 0 ) - m_dropTarget->Register(m_hWnd); -} + HWND hWnd = GetHwnd(); + if ( hWnd != 0 ) + { + WXHANDLE hFont = m_font.GetResourceHandle(); -#endif // wxUSE_DRAG_AND_DROP + wxASSERT_MSG( hFont, wxT("should have valid font") ); + ::SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0)); + } -//old style file-manager drag&drop support -// I think we should retain the old-style -// DragAcceptFiles in parallel with SetDropTarget. -// JACS -void wxWindow::DragAcceptFiles(bool accept) -{ - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::DragAcceptFiles(hWnd, (BOOL)accept); + return TRUE; } +bool wxWindow::SetCursor(const wxCursor& cursor) +{ + if ( !wxWindowBase::SetCursor(cursor) ) + { + // no change + return FALSE; + } -// ---------------------------------------------------------------------------- -// tooltips -// ---------------------------------------------------------------------------- + if ( m_cursor.Ok() ) + { + HWND hWnd = GetHwnd(); -#if wxUSE_TOOLTIPS + // Change the cursor NOW if we're within the correct window + POINT point; + ::GetCursorPos(&point); -void wxWindow::DoSetToolTip(wxToolTip *tooltip) -{ - wxWindowBase::DoSetToolTip(tooltip); + RECT rect; + ::GetWindowRect(hWnd, &rect); - if ( m_tooltip ) - m_tooltip->SetWindow(this); -} + if ( ::PtInRect(&rect, point) && !wxIsBusy() ) + ::SetCursor(GetHcursorOf(m_cursor)); + } -#endif // wxUSE_TOOLTIPS + return TRUE; +} -// Get total size -void wxWindow::DoGetSize(int *x, int *y) const +void wxWindow::WarpPointer (int x_pos, int y_pos) { - HWND hWnd = GetHwnd(); + // 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(hWnd, &rect); + GetWindowRect (GetHwnd(), &rect); - if ( x ) - *x = rect.right - rect.left; - if ( y ) - *y = rect.bottom - rect.top; + x += rect.left; + y += rect.top; + + SetCursorPos (x, y); } -void wxWindow::DoGetPosition(int *x, int *y) const +#if WXWIN_COMPATIBILITY +void wxWindow::MSWDeviceToLogical (float *x, float *y) const { - HWND hWnd = GetHwnd(); - HWND hParentWnd = 0; - if ( GetParent() ) - hParentWnd = (HWND) GetParent()->GetHWND(); +} +#endif // WXWIN_COMPATIBILITY - RECT rect; - GetWindowRect(hWnd, &rect); +// --------------------------------------------------------------------------- +// scrolling stuff +// --------------------------------------------------------------------------- - // Since we now have the absolute screen coords, if there's a parent we - // must subtract its top left corner - POINT point; - point.x = rect.left; - point.y = rect.top; - if ( hParentWnd ) - { - ::ScreenToClient(hParentWnd, &point); - } - - // 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). - if ( GetParent() ) - { - wxPoint pt(GetParent()->GetClientAreaOrigin()); - point.x -= pt.x; - point.y -= pt.y; - } - - if ( x ) - *x = point.x; - if ( y ) - *y = point.y; -} - -void wxWindow::ScreenToClient(int *x, int *y) const -{ - POINT pt; - if ( x ) - pt.x = *x; - if ( y ) - pt.y = *y; - - HWND hWnd = GetHwnd(); - ::ScreenToClient(hWnd, &pt); - - if ( x ) - *x = pt.x; - if ( y ) - *y = pt.y; -} - -void wxWindow::ClientToScreen(int *x, int *y) const +#if WXWIN_COMPATIBILITY +void wxWindow::SetScrollRange(int orient, int range, bool refresh) { - POINT pt; - if ( x ) - pt.x = *x; - if ( y ) - pt.y = *y; - - HWND hWnd = GetHwnd(); - ::ClientToScreen(hWnd, &pt); +#if defined(__WIN95__) - if ( x ) - *x = pt.x; - if ( y ) - *y = pt.y; -} + int range1 = range; -bool wxWindow::SetCursor(const wxCursor& cursor) -{ - if ( !wxWindowBase::SetCursor(cursor) ) + // Try to adjust the range to cope with page size > 1 + // - a Windows API quirk + int pageSize = GetScrollPage(orient); + if ( pageSize > 1 && range > 0) { - // no change - return FALSE; + range1 += (pageSize - 1); } - wxASSERT_MSG( m_cursor.Ok(), - _T("cursor must be valid after call to the base version")); - - HWND hWnd = GetHwnd(); - - // Change the cursor NOW if we're within the correct window - POINT point; - ::GetCursorPos(&point); + SCROLLINFO info; + int dir; - RECT rect; - ::GetWindowRect(hWnd, &rect); + if ( orient == wxHORIZONTAL ) { + dir = SB_HORZ; + } else { + dir = SB_VERT; + } - if ( ::PtInRect(&rect, point) && !wxIsBusy() ) - ::SetCursor((HCURSOR)m_cursor.GetHCURSOR()); + 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; - return TRUE; -} + HWND hWnd = GetHwnd(); + if ( hWnd ) + ::SetScrollInfo(hWnd, dir, &info, refresh); +#else + int wOrient; + if ( orient == wxHORIZONTAL ) + wOrient = SB_HORZ; + else + wOrient = SB_VERT; -// Get size *available for subwindows* i.e. excluding menu bar etc. -void wxWindow::DoGetClientSize(int *x, int *y) const -{ HWND hWnd = GetHwnd(); - RECT rect; - ::GetClientRect(hWnd, &rect); - if ( x ) - *x = rect.right; - if ( y ) - *y = rect.bottom; + if ( hWnd ) + ::SetScrollRange(hWnd, wOrient, 0, range, refresh); +#endif } -void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags) +void wxWindow::SetScrollPage(int orient, int page, bool refresh) { - int currentX, currentY; - GetPosition(¤tX, ¤tY); - int currentW,currentH; - GetSize(¤tW, ¤tH); - - if ( x == currentX && y == currentY && width == currentW && height == currentH ) - return; - - int actualWidth = width; - int actualHeight = height; - int actualX = x; - int actualY = y; - if ( x == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE) ) - actualX = currentX; - if ( y == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE) ) - actualY = currentY; +#if defined(__WIN95__) + SCROLLINFO info; + int dir; - AdjustForParentClientOrigin(actualX, actualY, sizeFlags); + if ( orient == wxHORIZONTAL ) { + dir = SB_HORZ; + m_xThumbSize = page; + } else { + dir = SB_VERT; + m_yThumbSize = page; + } - if ( width == -1 ) - actualWidth = currentW ; - if ( height == -1 ) - actualHeight = currentH ; + info.cbSize = sizeof(SCROLLINFO); + info.nPage = page; + info.nMin = 0; + info.fMask = SIF_PAGE; HWND hWnd = GetHwnd(); if ( hWnd ) - MoveWindow(hWnd, actualX, actualY, actualWidth, actualHeight, (BOOL)TRUE); + ::SetScrollInfo(hWnd, dir, &info, refresh); +#else + if ( orient == wxHORIZONTAL ) + m_xThumbSize = page; + else + m_yThumbSize = page; +#endif } -void wxWindow::DoSetClientSize(int width, int height) +int wxWindow::OldGetScrollRange(int orient) const { - wxWindow *parent = GetParent(); - HWND hWnd = GetHwnd(); - HWND hParentWnd = (HWND) 0; - if ( parent ) - hParentWnd = (HWND) parent->GetHWND(); - - RECT rect; - ::GetClientRect(hWnd, &rect); - - RECT rect2; - GetWindowRect(hWnd, &rect2); - - // 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 - int actual_width = rect2.right - rect2.left - rect.right + width; - int actual_height = rect2.bottom - rect2.top - rect.bottom + height; - - // If there's a parent, must subtract the parent's top left corner - // since MoveWindow moves relative to the parent + int wOrient; + if ( orient == wxHORIZONTAL ) + wOrient = SB_HORZ; + else + wOrient = SB_VERT; - POINT point; - point.x = rect2.left; - point.y = rect2.top; - if ( parent ) +#if __WATCOMC__ && defined(__WINDOWS_386__) + short minPos, maxPos; +#else + int minPos, maxPos; +#endif + HWND hWnd = GetHwnd(); + if ( hWnd ) { - ::ScreenToClient(hParentWnd, &point); + ::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; } - - MoveWindow(hWnd, point.x, point.y, actual_width, actual_height, (BOOL)TRUE); - - wxSizeEvent event(wxSize(width, height), m_windowId); - event.SetEventObject(this); - GetEventHandler()->ProcessEvent(event); + else + return 0; } -// For implementation purposes - sometimes decorations make the client area -// smaller -wxPoint wxWindow::GetClientAreaOrigin() const +int wxWindow::GetScrollPage(int orient) const { - return wxPoint(0, 0); + if ( orient == wxHORIZONTAL ) + return m_xThumbSize; + else + return m_yThumbSize; } -// 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) +#endif // WXWIN_COMPATIBILITY + +int wxWindow::GetScrollPos(int orient) const { - if ( ((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent() ) + int wOrient; + if ( orient == wxHORIZONTAL ) + wOrient = SB_HORZ; + else + wOrient = SB_VERT; + HWND hWnd = GetHwnd(); + if ( hWnd ) { - wxPoint pt(GetParent()->GetClientAreaOrigin()); - x += pt.x; y += pt.y; + return ::GetScrollPos(hWnd, wOrient); } + else + return 0; } -bool wxWindow::Show(bool show) +// This now returns the whole range, not just the number +// of positions that we can scroll. +int wxWindow::GetScrollRange(int orient) const { - if ( !wxWindowBase::Show(show) ) - return FALSE; + 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(); - int cshow = show ? SW_SHOW : SW_HIDE; - ::ShowWindow(hWnd, cshow); - - if ( show ) + if ( hWnd ) { - BringWindowToTop(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; +#endif - return TRUE; + return maxPos; + } + else + return 0; } -int wxWindow::GetCharHeight(void) const +int wxWindow::GetScrollThumb(int orient) const { - TEXTMETRIC lpTextMetric; - HWND hWnd = GetHwnd(); - HDC dc = ::GetDC(hWnd); - - GetTextMetrics(dc, &lpTextMetric); - ::ReleaseDC(hWnd, dc); - - return lpTextMetric.tmHeight; + if ( orient == wxHORIZONTAL ) + return m_xThumbSize; + else + return m_yThumbSize; } -int wxWindow::GetCharWidth(void) const +void wxWindow::SetScrollPos(int orient, int pos, bool refresh) { - TEXTMETRIC lpTextMetric; - HWND hWnd = GetHwnd(); - HDC dc = ::GetDC(hWnd); +#if defined(__WIN95__) + SCROLLINFO info; + int dir; + + if ( orient == wxHORIZONTAL ) { + dir = SB_HORZ; + } else { + dir = SB_VERT; + } - GetTextMetrics(dc, &lpTextMetric); - ::ReleaseDC(hWnd, dc); + info.cbSize = sizeof(SCROLLINFO); + info.nPage = 0; + info.nMin = 0; + info.nPos = pos; + info.fMask = 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; - return lpTextMetric.tmAveCharWidth; + HWND hWnd = GetHwnd(); + if ( hWnd ) + ::SetScrollPos(hWnd, wOrient, pos, refresh); +#endif } -void wxWindow::GetTextExtent(const wxString& string, int *x, int *y, - int *descent, int *externalLeading, const wxFont *theFont) const +// New function that will replace some of the above. +void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible, + int range, bool refresh) { - wxFont *fontToUse = (wxFont *)theFont; - if ( !fontToUse ) - fontToUse = (wxFont *) & m_font; +#if defined(__WIN95__) + int oldRange = range - thumbVisible; - HWND hWnd = GetHwnd(); - HDC dc = ::GetDC(hWnd); + int range1 = oldRange; - HFONT fnt = 0; - HFONT was = 0; - if ( fontToUse && fontToUse->Ok() ) + // Try to adjust the range to cope with page size > 1 + // - a Windows API quirk + int pageSize = thumbVisible; + if ( pageSize > 1 && range > 0) { - fnt = (HFONT)fontToUse->GetResourceHandle(); - if ( fnt ) - was = (HFONT) SelectObject(dc,fnt) ; + range1 += (pageSize - 1); } - SIZE sizeRect; - TEXTMETRIC tm; - GetTextExtentPoint(dc, (const char *)string, (int)string.Length(), &sizeRect); - GetTextMetrics(dc, &tm); - - if ( fontToUse && fnt && was ) - SelectObject(dc,was) ; + SCROLLINFO info; + int dir; - ReleaseDC(hWnd, dc); + if ( orient == wxHORIZONTAL ) { + dir = SB_HORZ; + } else { + dir = SB_VERT; + } - *x = sizeRect.cx; - *y = sizeRect.cy; - if ( descent ) *descent = tm.tmDescent; - if ( externalLeading ) *externalLeading = tm.tmExternalLeading; + info.cbSize = sizeof(SCROLLINFO); + info.nPage = pageSize; // Have to set this, or scrollbar goes awry + info.nMin = 0; + info.nMax = range1; + info.nPos = pos; + info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; - // if ( fontToUse ) - // fontToUse->ReleaseResource(); -} + HWND hWnd = GetHwnd(); + if ( hWnd ) + ::SetScrollInfo(hWnd, dir, &info, refresh); +#else + int wOrient; + if ( orient == wxHORIZONTAL ) + wOrient = SB_HORZ; + else + wOrient = SB_VERT; -void wxWindow::Refresh(bool eraseBack, const wxRect *rect) -{ HWND hWnd = GetHwnd(); if ( hWnd ) { - if ( rect ) - { - RECT mswRect; - mswRect.left = rect->x; - mswRect.top = rect->y; - mswRect.right = rect->x + rect->width; - mswRect.bottom = rect->y + rect->height; + ::SetScrollRange(hWnd, wOrient, 0, range, FALSE); + ::SetScrollPos(hWnd, wOrient, pos, refresh); + } +#endif + if ( orient == wxHORIZONTAL ) { + m_xThumbSize = thumbVisible; + } else { + m_yThumbSize = thumbVisible; + } +} - ::InvalidateRect(hWnd, &mswRect, eraseBack); - } - else - ::InvalidateRect(hWnd, NULL, eraseBack); +void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect) +{ + RECT rect2; + if ( rect ) + { + rect2.left = rect->x; + rect2.top = rect->y; + rect2.right = rect->x + rect->width; + rect2.bottom = rect->y + rect->height; } + + if ( rect ) + ::ScrollWindow(GetHwnd(), dx, dy, &rect2, NULL); + else + ::ScrollWindow(GetHwnd(), dx, dy, NULL, NULL); } // --------------------------------------------------------------------------- -// Main wxWindows window proc and the window proc for wxWindow +// subclassing // --------------------------------------------------------------------------- -// Hook for new window just as it's being created, when the window isn't yet -// associated with the handle -wxWindow *wxWndHook = NULL; - -// Main window proc -LRESULT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +void wxWindow::SubclassWin(WXHWND hWnd) { - // trace all messages - useful for the debugging -#ifdef __WXDEBUG__ - wxLogTrace(wxTraceMessages, "Processing %s(wParam=%8lx, lParam=%8lx)", - wxGetMessageName(message), wParam, lParam); -#endif // __WXDEBUG__ - - wxWindow *wnd = wxFindWinFromHandle((WXHWND) hWnd); - - // when we get the first message for the HWND we just created, we associate - // it with wxWindow stored in wxWndHook - if ( !wnd && wxWndHook ) - { - wxAssociateWinWithHandle(hWnd, wxWndHook); - wnd = wxWndHook; - wxWndHook = NULL; - wnd->SetHWND((WXHWND)hWnd); - } + wxASSERT_MSG( !m_oldWndProc, wxT("subclassing window twice?") ); - LRESULT rc; + HWND hwnd = (HWND)hWnd; + wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in SubclassWin") ); - // Stop right here if we don't have a valid handle in our wxWindow object. - if ( wnd && !wnd->GetHWND() ) - { - // FIXME: why do we do this? - wnd->SetHWND((WXHWND) hWnd); - rc = wnd->MSWDefWindowProc(message, wParam, lParam ); - wnd->SetHWND(0); - } - else - { - if ( wnd ) - rc = wnd->MSWWindowProc(message, wParam, lParam); - else - rc = DefWindowProc( hWnd, message, wParam, lParam ); - } + wxAssociateWinWithHandle(hwnd, this); - return rc; + m_oldWndProc = (WXFARPROC) GetWindowLong(hwnd, GWL_WNDPROC); + SetWindowLong(hwnd, GWL_WNDPROC, (LONG) wxWndProc); } -long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) +void wxWindow::UnsubclassWin() { - // did we process the message? - bool processed = FALSE; + wxRemoveHandleAssociation(this); - // the return value - union + // Restore old Window proc + HWND hwnd = GetHwnd(); + if ( hwnd ) { - bool allow; - long result; - WXHICON hIcon; - WXHBRUSH hBrush; - } rc; + m_hWnd = 0; - // for most messages we should return 0 when we do process the message - rc.result = 0; + wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in UnsubclassWin") ); - HWND hWnd = GetHwnd(); + FARPROC farProc = (FARPROC) GetWindowLong(hwnd, GWL_WNDPROC); + if ( (m_oldWndProc != 0) && (farProc != (FARPROC) m_oldWndProc) ) + { + SetWindowLong(hwnd, GWL_WNDPROC, (LONG) m_oldWndProc); + m_oldWndProc = 0; + } + } +} - switch ( message ) +// Make a Windows extended style from the given wxWindows window style +WXDWORD wxWindow::MakeExtendedStyle(long style, bool eliminateBorders) +{ + WXDWORD exStyle = 0; + if ( style & wxTRANSPARENT_WINDOW ) + exStyle |= WS_EX_TRANSPARENT; + + if ( !eliminateBorders ) { - case WM_ACTIVATE: - { -#ifdef __WIN32__ - WORD state = LOWORD(wParam); - WORD minimized = HIWORD(wParam); - HWND hwnd = (HWND)lParam; -#else - WORD state = (WORD)wParam; - WORD minimized = LOWORD(lParam); - HWND hwnd = (HWND)HIWORD(lParam); + if ( style & wxSUNKEN_BORDER ) + exStyle |= WS_EX_CLIENTEDGE; + if ( style & wxDOUBLE_BORDER ) + exStyle |= WS_EX_DLGMODALFRAME; +#if defined(__WIN95__) + if ( style & wxRAISED_BORDER ) + exStyle |= WS_EX_WINDOWEDGE; + if ( style & wxSTATIC_BORDER ) + exStyle |= WS_EX_STATICEDGE; #endif - processed = MSWOnActivate(state, minimized != 0, (WXHWND)hwnd); - } - break; - - case WM_CLOSE: - // process this message for any toplevel window - if ( !GetParent() ) - { - // if we can't close, tell the system that we processed the - // message - otherwise it would close us - processed = !Close(); - } - break; + } + return exStyle; +} - case WM_SETFOCUS: - processed = MSWOnSetFocus((WXHWND)(HWND)wParam); - break; +// 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, + 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) ) + { + *want3D = FALSE; + return MakeExtendedStyle(m_windowStyle, FALSE); + } - case WM_KILLFOCUS: - processed = MSWOnKillFocus((WXHWND)(HWND)wParam); - break; + // Determine whether we should be using 3D effects or not. + bool nativeBorder = FALSE; // by default, we don't want a Win95 effect - case WM_CREATE: - { - bool allow; - processed = MSWOnCreate((WXLPCREATESTRUCT)lParam, &allow); + // 1) App can specify global 3D effects + *want3D = wxTheApp->GetAuto3D(); - // we should return 0 to allow window creation - rc.result = !allow; - } - break; + // 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; - case WM_SHOWWINDOW: - processed = MSWOnShow(wParam != 0, (int)lParam); - break; + // 3) Control can override this global setting by defining + // a border style, e.g. wxSUNKEN_BORDER + if ( m_windowStyle & wxSUNKEN_BORDER ) + *want3D = TRUE; - case WM_PAINT: - processed = MSWOnPaint(); - break; + // 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; + } - case WM_QUERYDRAGICON: - processed = MSWOnQueryDragIcon(&rc.hIcon); - break; + // 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 - case WM_SIZE: - processed = MSWOnSize(LOWORD(lParam), HIWORD(lParam), wParam); - break; + DWORD exStyle = MakeExtendedStyle(m_windowStyle, !nativeBorder); - case WM_MOVE: - processed = HandleMove(LOWORD(lParam), HIWORD(lParam)); - break; + // 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 - case WM_WINDOWPOSCHANGING: - processed = MSWOnWindowPosChanging((void *)lParam); - break; + return exStyle; +} - case WM_MOUSEMOVE: - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_LBUTTONDBLCLK: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_RBUTTONDBLCLK: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_MBUTTONDBLCLK: - { - int x = LOWORD(lParam); - int y = HIWORD(lParam); +#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 wxWindow::OnCommand(wxWindow& win, wxCommandEvent& event) +{ + if ( GetEventHandler()->ProcessEvent(event) ) + return; + if ( m_parent ) + m_parent->GetEventHandler()->OnCommand(win, event); +} +#endif // WXWIN_COMPATIBILITY_2 - processed = MSWOnMouseEvent(message, x, y, wParam); - } - break; +#if WXWIN_COMPATIBILITY +wxObject* wxWindow::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 - case MM_JOY1MOVE: - case MM_JOY2MOVE: - case MM_JOY1ZMOVE: - case MM_JOY2ZMOVE: - case MM_JOY1BUTTONDOWN: - case MM_JOY2BUTTONDOWN: - case MM_JOY1BUTTONUP: - case MM_JOY2BUTTONUP: - { - int x = LOWORD(lParam); - int y = HIWORD(lParam); +// Setup background and foreground colours correctly +void wxWindow::SetupColours() +{ + if ( GetParent() ) + SetBackgroundColour(GetParent()->GetBackgroundColour()); +} - processed = HandleJoystickEvent(message, x, y, wParam); - } - break; +void wxWindow::OnIdle(wxIdleEvent& event) +{ + // Check if we need to send a LEAVE event + if ( m_mouseInWindow ) + { + POINT pt; + ::GetCursorPos(&pt); + if ( ::WindowFromPoint(pt) != GetHwnd() ) + { + // Generate a LEAVE event + m_mouseInWindow = FALSE; - case WM_DESTROY: - processed = MSWOnDestroy(); - break; + // 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; + + wxMouseEvent event(wxEVT_LEAVE_WINDOW); + InitMouseEvent(event, pt.x, pt.y, state); - case WM_SYSCOMMAND: - processed = MSWOnSysCommand(wParam, lParam); - break; + (void)GetEventHandler()->ProcessEvent(event); + } + } - case WM_COMMAND: - { -#ifdef __WIN32__ - WORD id = LOWORD(wParam); - HWND hwnd = (HWND)lParam; - WORD cmd = HIWORD(wParam); + UpdateWindowUI(); +} + +// Set this window to be the child of 'parent'. +bool wxWindow::Reparent(wxWindow *parent) +{ + if ( !wxWindowBase::Reparent(parent) ) + return FALSE; + + HWND hWndChild = GetHwnd(); + HWND hWndParent = GetParent() ? GetWinHwnd(GetParent()) : (HWND)0; + + ::SetParent(hWndChild, hWndParent); + + return TRUE; +} + +void wxWindow::Clear() +{ + wxClientDC dc(this); + wxBrush brush(GetBackgroundColour(), wxSOLID); + dc.SetBackground(brush); + dc.Clear(); +} + +void wxWindow::Refresh(bool eraseBack, const wxRect *rect) +{ + HWND hWnd = GetHwnd(); + if ( hWnd ) + { + 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); + } + else + ::InvalidateRect(hWnd, NULL, eraseBack); + } +} + +// --------------------------------------------------------------------------- +// drag and drop +// --------------------------------------------------------------------------- + +#if wxUSE_DRAG_AND_DROP + +void wxWindow::SetDropTarget(wxDropTarget *pDropTarget) +{ + if ( m_dropTarget != 0 ) { + m_dropTarget->Revoke(m_hWnd); + delete m_dropTarget; + } + + m_dropTarget = pDropTarget; + if ( m_dropTarget != 0 ) + m_dropTarget->Register(m_hWnd); +} + +#endif // wxUSE_DRAG_AND_DROP + +// old style file-manager drag&drop support: we retain the old-style +// DragAcceptFiles in parallel with SetDropTarget. +void wxWindow::DragAcceptFiles(bool accept) +{ + HWND hWnd = GetHwnd(); + if ( hWnd ) + ::DragAcceptFiles(hWnd, (BOOL)accept); +} + +// ---------------------------------------------------------------------------- +// tooltips +// ---------------------------------------------------------------------------- + +#if wxUSE_TOOLTIPS + +void wxWindow::DoSetToolTip(wxToolTip *tooltip) +{ + wxWindowBase::DoSetToolTip(tooltip); + + if ( m_tooltip ) + m_tooltip->SetWindow(this); +} + +#endif // wxUSE_TOOLTIPS + +// --------------------------------------------------------------------------- +// moving and resizing +// --------------------------------------------------------------------------- + +// Get total size +void wxWindow::DoGetSize(int *x, int *y) const +{ + HWND hWnd = GetHwnd(); + RECT rect; +#ifdef __WIN16__ + ::GetWindowRect(hWnd, &rect); #else - WORD id = (WORD)wParam; - HWND hwnd = (HWND)LOWORD(lParam) ; - WORD cmd = HIWORD(lParam); + if ( !::GetWindowRect(hWnd, &rect) ) + { + wxLogLastError(_T("GetWindowRect")); + } #endif - processed = MSWOnCommand(id, cmd, (WXHWND)hwnd); - } - break; + if ( x ) + *x = rect.right - rect.left; + if ( y ) + *y = rect.bottom - rect.top; +} -#ifdef __WIN95__ - case WM_NOTIFY: - processed = HandleNotify((int)wParam, lParam, &rc.result); - break; -#endif // Win95 +void wxWindow::DoGetPosition(int *x, int *y) const +{ + HWND hWnd = GetHwnd(); - // for these messages we must return TRUE if process the message - case WM_DRAWITEM: - case WM_MEASUREITEM: - { - int idCtrl = (UINT)wParam; - if ( message == WM_DRAWITEM ) - { - processed = MSWOnDrawItem(idCtrl, - (WXDRAWITEMSTRUCT *)lParam); - } - else - { - processed = MSWOnMeasureItem(idCtrl, - (WXMEASUREITEMSTRUCT *)lParam); - } + RECT rect; + GetWindowRect(hWnd, &rect); - if ( processed ) - rc.result = TRUE; - } - break; + POINT point; + point.x = rect.left; + point.y = rect.top; - case WM_KEYDOWN: - // If this has been processed by an event handler, - // return 0 now (we've handled it). - if ( MSWOnKeyDown((WORD) wParam, lParam) ) - { - processed = TRUE; + // we do the adjustments with respect to the parent only for the "real" + // children, not for the dialogs/frames + if ( !IsTopLevel() ) + { + HWND hParentWnd = 0; + wxWindow *parent = GetParent(); + if ( parent ) + hParentWnd = GetWinHwnd(parent); + + // 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); + } - break; - } + // 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; + } - // we consider these message "not interesting" to OnChar - if ( wParam == VK_SHIFT || wParam == VK_CONTROL ) + if ( x ) + *x = point.x; + if ( y ) + *y = point.y; +} + +void wxWindow::DoScreenToClient(int *x, int *y) const +{ + POINT pt; + if ( x ) + pt.x = *x; + if ( y ) + pt.y = *y; + + HWND hWnd = GetHwnd(); + ::ScreenToClient(hWnd, &pt); + + if ( x ) + *x = pt.x; + if ( y ) + *y = pt.y; +} + +void wxWindow::DoClientToScreen(int *x, int *y) const +{ + POINT pt; + if ( x ) + pt.x = *x; + if ( y ) + pt.y = *y; + + HWND hWnd = GetHwnd(); + ::ClientToScreen(hWnd, &pt); + + if ( x ) + *x = pt.x; + if ( y ) + *y = pt.y; +} + +// Get size *available for subwindows* i.e. excluding menu bar etc. +void wxWindow::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 wxWindow::DoMoveWindow(int x, int y, int width, int height) +{ + if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) ) + { + wxLogLastError(wxT("MoveWindow")); + } +} + +// set the size of the window: if the dimensions are positive, just use them, +// but if any of them is equal to -1, it means that we must find the value for +// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in +// which case -1 is a valid value for x and y) +// +// 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) +{ + // get the current size and position... + int currentX, currentY; + GetPosition(¤tX, ¤tY); + int currentW,currentH; + GetSize(¤tW, ¤tH); + + // ... and don't do anything (avoiding flicker) if it's already ok + if ( x == currentX && y == currentY && + width == currentW && height == currentH ) + { + return; + } + + if ( x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) ) + x = currentX; + if ( y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) ) + y = currentY; + + AdjustForParentClientOrigin(x, y, sizeFlags); + + wxSize size(-1, -1); + if ( width == -1 ) + { + if ( sizeFlags & wxSIZE_AUTO_WIDTH ) + { + size = DoGetBestSize(); + width = size.x; + } + else + { + // just take the current one + width = currentW; + } + } + + if ( height == -1 ) + { + if ( sizeFlags & wxSIZE_AUTO_HEIGHT ) + { + if ( size.x == -1 ) { - break; + size = DoGetBestSize(); } + //else: already called DoGetBestSize() above - switch ( wParam ) - { - // avoid duplicate messages to OnChar for these ASCII keys: they - // will be translated by TranslateMessage() and received in WM_CHAR - case VK_ESCAPE: - case VK_SPACE: - case VK_RETURN: - case VK_BACK: - case VK_TAB: - break; + height = size.y; + } + else + { + // just take the current one + height = currentH; + } + } -#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: - { - // construct the key mask - WPARAM fwKeys = MK_RBUTTON; - if ( (::GetKeyState(VK_CONTROL) & 0x100) != 0 ) - fwKeys |= MK_CONTROL; - if ( (::GetKeyState(VK_SHIFT) & 0x100) != 0 ) - fwKeys |= MK_SHIFT; - - // simulate right mouse button click - DWORD dwPos = ::GetMessagePos(); - int x = GET_X_LPARAM(dwPos), - y = GET_Y_LPARAM(dwPos); - - ScreenToClient(&x, &y); - processed = MSWOnMouseEvent(WM_RBUTTONDOWN, x, y, fwKeys); - } - break; -#endif // VK_APPS + DoMoveWindow(x, y, width, height); +} - case VK_LEFT: - case VK_RIGHT: - case VK_DOWN: - case VK_UP: - default: - processed = MSWOnChar((WORD)wParam, lParam); - } - break; +void wxWindow::DoSetClientSize(int width, int height) +{ + wxWindow *parent = GetParent(); + HWND hWnd = GetHwnd(); + HWND hParentWnd = (HWND) 0; + if ( parent ) + hParentWnd = (HWND) parent->GetHWND(); - case WM_KEYUP: - processed = MSWOnKeyUp((WORD) wParam, lParam); - break; + RECT rect; + ::GetClientRect(hWnd, &rect); - case WM_CHAR: // Always an ASCII character - processed = MSWOnChar((WORD)wParam, lParam, TRUE); - break; + RECT rect2; + GetWindowRect(hWnd, &rect2); - case WM_HSCROLL: - case WM_VSCROLL: - { -#ifdef __WIN32__ - WORD code = LOWORD(wParam); - WORD pos = HIWORD(wParam); - HWND control = (HWND)lParam; + // 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 + int actual_width = rect2.right - rect2.left - rect.right + width; + int actual_height = rect2.bottom - rect2.top - rect.bottom + height; + + // If there's a parent, must subtract the parent's top left corner + // since MoveWindow moves relative to the parent + + POINT point; + point.x = rect2.left; + point.y = rect2.top; + if ( parent ) + { + ::ScreenToClient(hParentWnd, &point); + } + + DoMoveWindow(point.x, point.y, actual_width, actual_height); + + wxSizeEvent event(wxSize(width, height), m_windowId); + event.SetEventObject(this); + GetEventHandler()->ProcessEvent(event); +} + +// For implementation purposes - sometimes decorations make the client area +// smaller +wxPoint wxWindow::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) +{ + // 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 +// --------------------------------------------------------------------------- + +int wxWindow::GetCharHeight() const +{ + return wxGetTextMetrics(this).tmHeight; +} + +int wxWindow::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 ; #else - WORD code = (WORD)wParam; - WORD pos = LOWORD(lParam); - HWND control = (HWND)HIWORD(lParam); + return wxGetTextMetrics(this).tmAveCharWidth + 1; #endif - processed = MSWOnScroll(message == WM_HSCROLL ? wxHORIZONTAL - : wxVERTICAL, - code, pos, (WXHWND)control); - } - break; +} - // CTLCOLOR messages are sent by children to query the parent for their - // colors -#ifdef __WIN32__ - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORBTN: - case WM_CTLCOLORDLG: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORSTATIC: - { - int nCtlColor = CTLCOLOR_BTN; - HWND control = (HWND)lParam; - HDC hdc = (HDC)wParam; +void wxWindow::GetTextExtent(const wxString& string, + int *x, int *y, + int *descent, int *externalLeading, + const wxFont *theFont) const +{ + const wxFont *fontToUse = theFont; + if ( !fontToUse ) + fontToUse = &m_font; - processed = MSWOnCtlColor(&rc.hBrush, (WXHDC)hdc, (WXHWND)control, - nCtlColor, message, wParam, lParam); - break; - } -#else // Win16 - case WM_CTLCOLOR: - { - HWND control = (HWND)LOWORD(lParam); - int nCtlColor = (int)HIWORD(lParam); - HDC hdc = (HDC)wParam; + HWND hWnd = GetHwnd(); + HDC dc = ::GetDC(hWnd); - processed = MSWOnCtlColor(&rc.hBrush, (WXHDC)hdc, (WXHWND)control, - nCtlColor, message, wParam, lParam); - } - break; -#endif // Win32/16 + HFONT fnt = 0; + HFONT hfontOld = 0; + if ( fontToUse && fontToUse->Ok() ) + { + fnt = (HFONT)((wxFont *)fontToUse)->GetResourceHandle(); // const_cast + if ( fnt ) + hfontOld = (HFONT)SelectObject(dc,fnt); + } - // the return value for this message is ignored - case WM_SYSCOLORCHANGE: - { - wxSysColourChangedEvent event; - event.SetEventObject(this); + SIZE sizeRect; + TEXTMETRIC tm; + GetTextExtentPoint(dc, string, (int)string.Length(), &sizeRect); + GetTextMetrics(dc, &tm); + + if ( fontToUse && fnt && hfontOld ) + SelectObject(dc, hfontOld); + + ReleaseDC(hWnd, dc); + + if ( x ) + *x = sizeRect.cx; + if ( y ) + *y = sizeRect.cy; + if ( descent ) + *descent = tm.tmDescent; + if ( externalLeading ) + *externalLeading = tm.tmExternalLeading; +} + +#if wxUSE_CARET && WXWIN_COMPATIBILITY +// --------------------------------------------------------------------------- +// Caret manipulation +// --------------------------------------------------------------------------- + +void wxWindow::CreateCaret(int w, int h) +{ + SetCaret(new wxCaret(this, w, h)); +} + +void wxWindow::CreateCaret(const wxBitmap *WXUNUSED(bitmap)) +{ + wxFAIL_MSG("not implemented"); +} + +void wxWindow::ShowCaret(bool show) +{ + wxCHECK_RET( m_caret, "no caret to show" ); + + m_caret->Show(show); +} + +void wxWindow::DestroyCaret() +{ + SetCaret(NULL); +} + +void wxWindow::SetCaretPos(int x, int y) +{ + wxCHECK_RET( m_caret, "no caret to move" ); - processed = GetEventHandler()->ProcessEvent(event); - } - break; + m_caret->Move(x, y); +} - case WM_PALETTECHANGED: - processed = MSWOnPaletteChanged((WXHWND) (HWND) wParam); - break; +void wxWindow::GetCaretPos(int *x, int *y) const +{ + wxCHECK_RET( m_caret, "no caret to get position of" ); - case WM_QUERYNEWPALETTE: - processed = MSWOnQueryNewPalette(); - break; + m_caret->GetPosition(x, y); +} +#endif // wxUSE_CARET - // return TRUE if we erase the background - case WM_ERASEBKGND: - // Prevents flicker when dragging - if ( IsIconic(hWnd) ) return 1; +// --------------------------------------------------------------------------- +// popup menu +// --------------------------------------------------------------------------- - if ( !MSWOnEraseBkgnd((WXHDC) (HDC)wParam) ) - return 0; - else return 1; - break; +bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y) +{ + menu->SetInvokingWindow(this); + menu->UpdateUI(); - case WM_MDIACTIVATE: - { -#ifdef __WIN32__ - HWND hWndActivate = GET_WM_MDIACTIVATE_HWNDACTIVATE(wParam,lParam); - HWND hWndDeactivate = GET_WM_MDIACTIVATE_HWNDDEACT(wParam,lParam); - BOOL activate = GET_WM_MDIACTIVATE_FACTIVATE(hWnd,wParam,lParam); - processed = MSWOnMDIActivate((long)activate, - (WXHWND)hWndActivate, - (WXHWND)hWndDeactivate); -#else - processed = MSWOnMDIActivate((BOOL)wParam, - (HWND)LOWORD(lParam), - (HWND)HIWORD(lParam)); -#endif - } - break; + HWND hWnd = GetHwnd(); + HMENU hMenu = GetHmenuOf(menu); + POINT point; + point.x = x; + point.y = y; + ::ClientToScreen(hWnd, &point); + wxCurrentPopupMenu = menu; + ::TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL); + wxYield(); + wxCurrentPopupMenu = NULL; - case WM_DROPFILES: - processed = MSWOnDropFiles(wParam); - break; + menu->SetInvokingWindow(NULL); - case WM_INITDIALOG: - wxFAIL_MSG("to fix"); + return TRUE; +} - return 0; // MSWOnInitDialog((WXHWND)(HWND)wParam); +// =========================================================================== +// pre/post message processing +// =========================================================================== - // we never set focus from here - rc.result = FALSE; - break; +long wxWindow::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) +{ + if ( m_oldWndProc ) + return ::CallWindowProc(CASTWNDPROC m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam); + else + return ::DefWindowProc(GetHwnd(), nMsg, wParam, lParam); +} - case WM_QUERYENDSESSION: - processed = MSWOnQueryEndSession(lParam, &rc.allow); - break; +bool wxWindow::MSWProcessMessage(WXMSG* pMsg) +{ + if ( m_hWnd != 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL) ) + { + // intercept dialog navigation keys + MSG *msg = (MSG *)pMsg; - case WM_ENDSESSION: - processed = MSWOnEndSession(wParam != 0, lParam); - break; + // here we try to do all the job which ::IsDialogMessage() usually does + // internally +#if 1 + bool bProcess = TRUE; + if ( msg->message != WM_KEYDOWN ) + bProcess = FALSE; - case WM_GETMINMAXINFO: + if ( bProcess && (HIWORD(msg->lParam) & KF_ALTDOWN) == KF_ALTDOWN ) + bProcess = FALSE; + + if ( bProcess ) + { + bool bCtrlDown = wxIsCtrlDown(); + bool bShiftDown = wxIsShiftDown(); + + // 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 ) { - MINMAXINFO *info = (MINMAXINFO *)lParam; - if ( m_minWidth != -1 ) - info->ptMinTrackSize.x = m_minWidth; - if ( m_minHeight != -1 ) - info->ptMinTrackSize.y = m_minHeight; - if ( m_maxWidth != -1 ) - info->ptMaxTrackSize.x = m_maxWidth; - if ( m_maxHeight != -1 ) - info->ptMaxTrackSize.y = m_maxHeight; + lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0); } - break; - case WM_SETCURSOR: - // don't set cursor for other windows, only for this one: this - // prevents children of this window from getting the same cursor as - // the parent has (don't forget that this message is propagated by - // default up the window parent-child hierarchy) - if ( (HWND)wParam == hWnd ) - { - // don't set cursor when the mouse is not in the client part - short nHitTest = LOWORD(lParam); - if ( nHitTest == HTCLIENT || nHitTest == HTERROR ) - { - HCURSOR hcursor = 0; - if ( wxIsBusy() ) - { - // from msw\utils.cpp - extern HCURSOR gs_wxBusyCursor; + bool bForward = TRUE, + bWindowChange = FALSE; - hcursor = gs_wxBusyCursor; + 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; + } + else { + // Ctrl-Tab cycles thru notebook pages + bWindowChange = bCtrlDown; + bForward = !bShiftDown; } + break; + + case VK_UP: + case VK_LEFT: + if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown ) + bProcess = FALSE; else - { - wxCursor *cursor = NULL; + bForward = FALSE; + break; + + case VK_DOWN: + case VK_RIGHT: + if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown ) + bProcess = FALSE; + break; - if ( m_cursor.Ok() ) + case VK_RETURN: + { + if ( (lDlgCode & DLGC_WANTMESSAGE) && !bCtrlDown ) + { + // control wants to process Enter itself, don't + // call IsDialogMessage() which would interpret + // it + return FALSE; + } + else if ( lDlgCode & DLGC_BUTTON ) { - cursor = &m_cursor; + // buttons want process Enter themselevs + bProcess = FALSE; } else { - // from msw\data.cpp - extern wxCursor *g_globalCursor; - - if ( g_globalCursor && g_globalCursor->Ok() ) - cursor = g_globalCursor; + wxPanel *panel = wxDynamicCast(this, wxPanel); + wxButton *btn = NULL; + if ( panel ) + { + // panel may have a default button which should + // be activated by Enter + btn = panel->GetDefaultItem(); + } + + if ( btn && btn->IsEnabled() ) + { + // if we do have a default button, do press it + btn->MSWCommand(BN_CLICKED, 0 /* unused */); + + 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. } + } + break; + + default: + bProcess = FALSE; + } + + if ( bProcess ) + { + wxNavigationKeyEvent event; + event.SetDirection(bForward); + event.SetWindowChange(bWindowChange); + event.SetEventObject(this); + + if ( GetEventHandler()->ProcessEvent(event) ) + { + wxButton *btn = wxDynamicCast(FindFocus(), wxButton); + if ( btn ) + { + // the button which has focus should be default + btn->SetDefault(); + } - if ( cursor ) - hcursor = (HCURSOR)cursor->GetHCURSOR(); + return TRUE; + } + } + } +#else + // 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 ( hcursor ) + if ( nbook ) { - ::SetCursor(hcursor); + bool forward = !wxIsShiftDown(); - // returning TRUE stops the DefWindowProc() from - // further processing this message - exactly what we - // need because we've just set the cursor. - rc.result = TRUE; - processed = TRUE; + nbook->AdvanceSelection(forward); } } } + } +#endif // 0 + + if ( ::IsDialogMessage(GetHwnd(), msg) ) + { + // IsDialogMessage() did something... + return TRUE; + } } - if ( !processed ) +#if wxUSE_TOOLTIPS + if ( m_tooltip ) { -#ifdef __WXDEBUG__ - wxLogTrace(wxTraceMessages, "Forwarding %s to DefWindowProc.", - wxGetMessageName(message)); -#endif // __WXDEBUG__ - rc.result = MSWDefWindowProc(message, wParam, lParam); + // relay mouse move events to the tooltip control + MSG *msg = (MSG *)pMsg; + if ( msg->message == WM_MOUSEMOVE ) + m_tooltip->RelayEvent(pMsg); } +#endif // wxUSE_TOOLTIPS - return rc.result; + return FALSE; } -// Dialog window proc -LONG APIENTRY _EXPORT -wxDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +bool wxWindow::MSWTranslateMessage(WXMSG* pMsg) { - return 0; + return m_acceleratorTable.Translate(this, pMsg); } -wxList *wxWinHandleList = NULL; -wxWindow *wxFindWinFromHandle(WXHWND hWnd) +// --------------------------------------------------------------------------- +// message params unpackers (different for Win16 and Win32) +// --------------------------------------------------------------------------- + +#ifdef __WIN32__ + +void wxWindow::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam, + WORD *id, WXHWND *hwnd, WORD *cmd) { - wxNode *node = wxWinHandleList->Find((long)hWnd); - if ( !node ) - return NULL; - return (wxWindow *)node->Data(); + *id = LOWORD(wParam); + *hwnd = (WXHWND)lParam; + *cmd = HIWORD(wParam); } -void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win) +void wxWindow::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam, + WXWORD *state, WXWORD *minimized, WXHWND *hwnd) { - // adding NULL hWnd is (first) surely a result of an error and - // (secondly) breaks menu command processing - wxCHECK_RET( hWnd != (HWND) NULL, "attempt to add a NULL hWnd to window list" ); + *state = LOWORD(wParam); + *minimized = HIWORD(wParam); + *hwnd = (WXHWND)lParam; +} - if ( !wxWinHandleList->Find((long)hWnd) ) - wxWinHandleList->Append((long)hWnd, win); +void wxWindow::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam, + WXWORD *code, WXWORD *pos, WXHWND *hwnd) +{ + *code = LOWORD(wParam); + *pos = HIWORD(wParam); + *hwnd = (WXHWND)lParam; } -void wxRemoveHandleAssociation(wxWindow *win) +void wxWindow::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam, + WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd) { - wxWinHandleList->DeleteObject(win); + *nCtlColor = CTLCOLOR_BTN; + *hwnd = (WXHWND)lParam; + *hdc = (WXHDC)wParam; } -// Default destroyer - override if you destroy it in some other way -// (e.g. with MDI child windows) -void wxWindow::MSWDestroyWindow() +void wxWindow::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam, + WXWORD *item, WXWORD *flags, WXHMENU *hmenu) { + *item = (WXWORD)wParam; + *flags = HIWORD(wParam); + *hmenu = (WXHMENU)lParam; } -bool wxWindow::MSWCreate(int id, - wxWindow *parent, - const char *wclass, - wxWindow *wx_win, - const char *title, - int x, - int y, - int width, - int height, - WXDWORD style, - const char *dialog_template, - WXDWORD extendedStyle) +#else // Win16 + +void wxWindow::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam, + WXWORD *id, WXHWND *hwnd, WXWORD *cmd) { - int x1 = CW_USEDEFAULT; - int y1 = 0; - int width1 = CW_USEDEFAULT; - int height1 = 100; + *id = (WXWORD)wParam; + *hwnd = (WXHWND)LOWORD(lParam); + *cmd = HIWORD(lParam); +} - // Find parent's size, if it exists, to set up a possible default - // panel size the size of the parent window - RECT parent_rect; - if ( parent ) - { - ::GetClientRect((HWND) parent->GetHWND(), &parent_rect); +void wxWindow::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam, + WXWORD *state, WXWORD *minimized, WXHWND *hwnd) +{ + *state = (WXWORD)wParam; + *minimized = LOWORD(lParam); + *hwnd = (WXHWND)HIWORD(lParam); +} - width1 = parent_rect.right - parent_rect.left; - height1 = parent_rect.bottom - parent_rect.top; - } +void wxWindow::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam, + WXWORD *code, WXWORD *pos, WXHWND *hwnd) +{ + *code = (WXWORD)wParam; + *pos = LOWORD(lParam); + *hwnd = (WXHWND)HIWORD(lParam); +} - if ( x > -1 ) x1 = x; - if ( y > -1 ) y1 = y; - if ( width > -1 ) width1 = width; - if ( height > -1 ) height1 = height; +void wxWindow::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam, + WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd) +{ + *hwnd = (WXHWND)LOWORD(lParam); + *nCtlColor = (int)HIWORD(lParam); + *hdc = (WXHDC)wParam; +} - HWND hParent = NULL; - if ( parent ) - hParent = (HWND) parent->GetHWND(); +void wxWindow::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam, + WXWORD *item, WXWORD *flags, WXHMENU *hmenu) +{ + *item = (WXWORD)wParam; + *flags = LOWORD(lParam); + *hmenu = (WXHMENU)HIWORD(lParam); +} - wxWndHook = this; +#endif // Win32/16 - if ( dialog_template ) +// --------------------------------------------------------------------------- +// Main wxWindows window proc and the window proc for wxWindow +// --------------------------------------------------------------------------- + +// Hook for new window just as it's being created, when the window isn't yet +// associated with the handle +wxWindow *wxWndHook = NULL; + +// Main window proc +LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + // trace all messages - useful for the debugging +#ifdef __WXDEBUG__ + wxLogTrace(wxTraceMessages, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"), + wxGetMessageName(message), wParam, lParam); +#endif // __WXDEBUG__ + + wxWindow *wnd = wxFindWinFromHandle((WXHWND) hWnd); + + // when we get the first message for the HWND we just created, we associate + // it with wxWindow stored in wxWndHook + if ( !wnd && wxWndHook ) { - m_hWnd = (WXHWND)::CreateDialog(wxGetInstance(), - dialog_template, - hParent, - (DLGPROC)wxDlgProc); +#if 0 // def __WXDEBUG__ + char buf[512]; + ::GetClassNameA((HWND) hWnd, buf, 512); + wxString className(buf); +#endif - if ( m_hWnd == 0 ) - { - wxLogError(_("Can't find dummy dialog template!\n" - "Check resource include path for finding wx.rc.")); + wxAssociateWinWithHandle(hWnd, wxWndHook); + wnd = wxWndHook; + wxWndHook = NULL; + wnd->SetHWND((WXHWND)hWnd); + } - return FALSE; - } + LRESULT rc; - ::MoveWindow(GetHwnd(), x1, y1, width1, height1, FALSE); + // Stop right here if we don't have a valid handle in our wxWindow object. + if ( wnd && !wnd->GetHWND() ) + { + // FIXME: why do we do this? + wnd->SetHWND((WXHWND) hWnd); + rc = wnd->MSWDefWindowProc(message, wParam, lParam ); + wnd->SetHWND(0); } else { - int controlId = 0; - if ( style & WS_CHILD ) - controlId = id; + if ( wnd ) + rc = wnd->MSWWindowProc(message, wParam, lParam); + else + rc = DefWindowProc( hWnd, message, wParam, lParam ); + } - m_hWnd = (WXHWND)CreateWindowEx(extendedStyle, - wclass, - title ? title : "", - style, - x1, y1, - width1, height1, - hParent, (HMENU)controlId, - wxGetInstance(), - NULL); + return rc; +} - if ( !m_hWnd ) - { - wxLogError(_("Can't create window of class %s!\n" - "Possible Windows 3.x compatibility problem?"), - wclass); +long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) +{ + // did we process the message? + bool processed = FALSE; - return FALSE; - } - } + // the return value + union + { + bool allow; + long result; + WXHICON hIcon; + WXHBRUSH hBrush; + } rc; - wxWndHook = NULL; - wxWinHandleList->Append((long)m_hWnd, this); + // for most messages we should return 0 when we do process the message + rc.result = 0; - return TRUE; -} + switch ( message ) + { + case WM_CREATE: + { + bool mayCreate; + processed = HandleCreate((WXLPCREATESTRUCT)lParam, &mayCreate); + if ( processed ) + { + // return 0 to allow window creation + rc.result = mayCreate ? 0 : -1; + } + } + break; -bool wxWindow::MSWOnCreate(WXLPCREATESTRUCT WXUNUSED(cs), bool *mayCreate) -{ - *mayCreate = TRUE; + case WM_DESTROY: + processed = HandleDestroy(); + break; - return TRUE; -} + case WM_MOVE: + processed = HandleMove(LOWORD(lParam), HIWORD(lParam)); + break; -bool wxWindow::MSWOnQueryEndSession(long logOff, bool *mayEnd) -{ - wxCloseEvent event(wxEVT_QUERY_END_SESSION, -1); - event.SetEventObject(wxTheApp); - event.SetCanVeto(TRUE); - event.SetLoggingOff(logOff == ENDSESSION_LOGOFF); + case WM_SIZE: + processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam); + break; - bool rc = wxTheApp->ProcessEvent(event); + case WM_ACTIVATE: + { + WXWORD state, minimized; + WXHWND hwnd; + UnpackActivate(wParam, lParam, &state, &minimized, &hwnd); - if ( rc ) - { - // we may end only if the app didn't veto session closing (double - // negation...) - *mayEnd = !event.GetVeto(); - } + processed = HandleActivate(state, minimized != 0, (WXHWND)hwnd); + } + break; - return rc; -} + case WM_SETFOCUS: + processed = HandleSetFocus((WXHWND)(HWND)wParam); + break; -bool wxWindow::MSWOnEndSession(bool endSession, long logOff) -{ - // do nothing if the session isn't ending - if ( !endSession ) - return FALSE; + case WM_KILLFOCUS: + processed = HandleKillFocus((WXHWND)(HWND)wParam); + break; - wxCloseEvent event(wxEVT_END_SESSION, -1); - event.SetEventObject(wxTheApp); - event.SetCanVeto(FALSE); - event.SetLoggingOff( (logOff == ENDSESSION_LOGOFF) ); - if ( (this == wxTheApp->GetTopWindow()) && // Only send once - wxTheApp->ProcessEvent(event)) - { - } - return TRUE; -} + case WM_PAINT: + processed = HandlePaint(); + break; -bool wxWindow::MSWOnDestroy() -{ - // delete our drop target if we've got one -#if wxUSE_DRAG_AND_DROP - if ( m_dropTarget != NULL ) { - m_dropTarget->Revoke(m_hWnd); + case WM_CLOSE: + // don't let the DefWindowProc() destroy our window - we'll do it + // ourselves in ~wxWindow + processed = TRUE; + rc.result = TRUE; + break; - delete m_dropTarget; - m_dropTarget = NULL; - } -#endif + case WM_SHOWWINDOW: + processed = HandleShow(wParam != 0, (int)lParam); + break; - return TRUE; -} + case WM_MOUSEMOVE: + { + short x = LOWORD(lParam); + short y = HIWORD(lParam); -bool wxWindow::MSWOnMDIActivate(long WXUNUSED(flag), - WXHWND WXUNUSED(activate), - WXHWND WXUNUSED(deactivate)) -{ - return FALSE; -} + processed = HandleMouseMove(x, y, wParam); + } + break; -bool wxWindow::MSWOnActivate(int state, bool WXUNUSED(minimized), WXHWND WXUNUSED(activate)) -{ - wxActivateEvent event(wxEVT_ACTIVATE, - (state == WA_ACTIVE) || (state == WA_CLICKACTIVE), - m_windowId); - event.SetEventObject(this); + case WM_LBUTTONDOWN: + // set focus to this window + if (AcceptsFocus()) + SetFocus(); - return GetEventHandler()->ProcessEvent(event); -} + // fall through -bool wxWindow::MSWOnSetFocus(WXHWND WXUNUSED(hwnd)) -{ - // Deal with caret - if ( m_caretEnabled && (m_caretWidth > 0) && (m_caretHeight > 0) ) - { - ::CreateCaret(GetHwnd(), NULL, m_caretWidth, m_caretHeight); - if ( m_caretShown ) - ::ShowCaret(GetHwnd()); - } + case WM_LBUTTONUP: + case WM_LBUTTONDBLCLK: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_RBUTTONDBLCLK: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MBUTTONDBLCLK: + { + short x = LOWORD(lParam); + short y = HIWORD(lParam); - // panel wants to track the window which was the last to have focus in it - wxWindow *parent = GetParent(); - if ( parent && parent->IsKindOf(CLASSINFO(wxPanel)) ) - { - ((wxPanel *)parent)->SetLastFocus(GetId()); - } + processed = HandleMouseEvent(message, x, y, wParam); + } + break; - wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId); - event.SetEventObject(this); - return GetEventHandler()->ProcessEvent(event); -} + case MM_JOY1MOVE: + case MM_JOY2MOVE: + case MM_JOY1ZMOVE: + case MM_JOY2ZMOVE: + case MM_JOY1BUTTONDOWN: + case MM_JOY2BUTTONDOWN: + case MM_JOY1BUTTONUP: + case MM_JOY2BUTTONUP: + { + int x = LOWORD(lParam); + int y = HIWORD(lParam); -bool wxWindow::MSWOnKillFocus(WXHWND WXUNUSED(hwnd)) -{ - // Deal with caret - if ( m_caretEnabled ) - { - ::DestroyCaret(); - } + processed = HandleJoystickEvent(message, x, y, wParam); + } + break; - wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId); - event.SetEventObject(this); - return GetEventHandler()->ProcessEvent(event); -} + case WM_SYSCOMMAND: + processed = HandleSysCommand(wParam, lParam); + break; -bool wxWindow::MSWOnDropFiles(WXWPARAM wParam) -{ + case WM_COMMAND: + { + WORD id, cmd; + WXHWND hwnd; + UnpackCommand(wParam, lParam, &id, &hwnd, &cmd); - HDROP hFilesInfo = (HDROP) wParam; - POINT dropPoint; - DragQueryPoint(hFilesInfo, (LPPOINT) &dropPoint); + processed = HandleCommand(id, cmd, hwnd); + } + break; - // Get the total number of files dropped - WORD gwFilesDropped = (WORD)DragQueryFile ((HDROP)hFilesInfo, - (UINT)-1, - (LPSTR)0, - (UINT)0); +#ifdef __WIN95__ + case WM_NOTIFY: + processed = HandleNotify((int)wParam, lParam, &rc.result); + break; +#endif // Win95 - wxString *files = new wxString[gwFilesDropped]; - int wIndex; - for (wIndex=0; wIndex < (int)gwFilesDropped; wIndex++) - { - DragQueryFile (hFilesInfo, wIndex, (LPSTR) wxBuffer, 1000); - files[wIndex] = wxBuffer; - } - DragFinish (hFilesInfo); + // for these messages we must return TRUE if process the message + case WM_DRAWITEM: + case WM_MEASUREITEM: + { + int idCtrl = (UINT)wParam; + if ( message == WM_DRAWITEM ) + { + processed = MSWOnDrawItem(idCtrl, + (WXDRAWITEMSTRUCT *)lParam); + } + else + { + processed = MSWOnMeasureItem(idCtrl, + (WXMEASUREITEMSTRUCT *)lParam); + } - wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files); - event.m_eventObject = this; - event.m_pos.x = dropPoint.x; event.m_pos.x = dropPoint.y; + if ( processed ) + rc.result = TRUE; + } + break; - bool rc = GetEventHandler()->ProcessEvent(event); + case WM_GETDLGCODE: + if ( m_lDlgCode ) + { + rc.result = m_lDlgCode; + processed = TRUE; + } + //else: get the dlg code from the DefWindowProc() + break; - delete[] files; + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + // If this has been processed by an event handler, + // return 0 now (we've handled it). + if ( HandleKeyDown((WORD) wParam, lParam) ) + { + processed = TRUE; - return rc; -} + break; + } -bool wxWindow::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct) -{ -#if wxUSE_OWNER_DRAWN - if ( id == 0 ) { // is it a menu item? - DRAWITEMSTRUCT *pDrawStruct = (DRAWITEMSTRUCT *)itemStruct; - wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData); - wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE ); + // we consider these message "not interesting" to OnChar + if ( wParam == VK_SHIFT || wParam == VK_CONTROL ) + { + processed = TRUE; - // prepare to call OnDrawItem() - wxDC dc; - dc.SetHDC((WXHDC)pDrawStruct->hDC, FALSE); - wxRect rect(pDrawStruct->rcItem.left, pDrawStruct->rcItem.top, - pDrawStruct->rcItem.right - pDrawStruct->rcItem.left, - pDrawStruct->rcItem.bottom - pDrawStruct->rcItem.top); - return pMenuItem->OnDrawItem( - dc, rect, - (wxOwnerDrawn::wxODAction)pDrawStruct->itemAction, - (wxOwnerDrawn::wxODStatus)pDrawStruct->itemState - ); - } -#endif // owner-drawn menus + break; + } + + switch ( wParam ) + { + // avoid duplicate messages to OnChar for these ASCII keys: they + // will be translated by TranslateMessage() and received in WM_CHAR + case VK_ESCAPE: + case VK_SPACE: + case VK_RETURN: + case VK_BACK: + case VK_TAB: + case VK_ADD: + case VK_SUBTRACT: + // 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; - wxWindow *item = FindItem(id); -#if wxUSE_DYNAMIC_CLASSES - if ( item && item->IsKindOf(CLASSINFO(wxControl)) ) - { - return ((wxControl *)item)->MSWOnDraw(itemStruct); - } - else -#endif - return FALSE; -} + break; -bool wxWindow::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct) -{ -#if wxUSE_OWNER_DRAWN - if ( id == 0 ) { // is it a menu item? - MEASUREITEMSTRUCT *pMeasureStruct = (MEASUREITEMSTRUCT *)itemStruct; - wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData); - wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE ); +#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; - return pMenuItem->OnMeasureItem(&pMeasureStruct->itemWidth, - &pMeasureStruct->itemHeight); - } -#endif // owner-drawn menus + TranslateKbdEventToMouse(this, &x, &y, &flags); + processed = HandleMouseEvent(WM_RBUTTONDOWN, x, y, flags); + } + break; +#endif // VK_APPS - wxWindow *item = FindItem(id); -#if wxUSE_DYNAMIC_CLASSES - if ( item && item->IsKindOf(CLASSINFO(wxControl)) ) - { - return ((wxControl *)item)->MSWOnMeasure(itemStruct); - } - else -#endif - return FALSE; -} + case VK_LEFT: + case VK_RIGHT: + case VK_DOWN: + case VK_UP: + default: + processed = HandleChar((WORD)wParam, lParam); + } + break; -bool wxWindow::MSWOnCtlColor(WXHBRUSH *brush, - WXHDC pDC, - WXHWND pWnd, - WXUINT nCtlColor, - WXUINT message, - WXWPARAM wParam, - WXLPARAM lParam) -{ - WXHBRUSH hBrush = 0; + case WM_SYSKEYUP: + case WM_KEYUP: +#ifdef VK_APPS + // special case of VK_APPS: treat it the same as right mouse button + if ( wParam == VK_APPS ) + { + WPARAM flags; + int x, y; - if ( nCtlColor == CTLCOLOR_DLG ) - { - hBrush = OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam); - } - else - { - wxControl *item = (wxControl *)FindItemByHWND(pWnd, TRUE); - if ( item ) - hBrush = item->OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam); - } + TranslateKbdEventToMouse(this, &x, &y, &flags); + processed = HandleMouseEvent(WM_RBUTTONUP, x, y, flags); + } + else +#endif // VK_APPS + { + processed = HandleKeyUp((WORD) wParam, lParam); + } + break; - if ( hBrush ) - *brush = hBrush; + case WM_SYSCHAR: + case WM_CHAR: // Always an ASCII character + processed = HandleChar((WORD)wParam, lParam, TRUE); + break; - return hBrush != 0; -} + case WM_HSCROLL: + case WM_VSCROLL: + { + WXWORD code, pos; + WXHWND hwnd; + UnpackScroll(wParam, lParam, &code, &pos, &hwnd); -// Define for each class of dialog and control -WXHBRUSH wxWindow::OnCtlColor(WXHDC hDC, - WXHWND hWnd, - WXUINT nCtlColor, - WXUINT message, - WXWPARAM wParam, - WXLPARAM lParam) -{ - return (WXHBRUSH)0; -} + processed = MSWOnScroll(message == WM_HSCROLL ? wxHORIZONTAL + : wxVERTICAL, + code, pos, hwnd); + } + break; -bool wxWindow::MSWOnPaletteChanged(WXHWND hWndPalChange) -{ - wxPaletteChangedEvent event(GetId()); - event.SetEventObject(this); - event.SetChangedWindow(wxFindWinFromHandle(hWndPalChange)); + // CTLCOLOR messages are sent by children to query the parent for their + // colors +#ifdef __WIN32__ + case WM_CTLCOLORMSGBOX: + case WM_CTLCOLOREDIT: + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLORBTN: + 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); + } + break; - return GetEventHandler()->ProcessEvent(event); -} + // the return value for this message is ignored + case WM_SYSCOLORCHANGE: + processed = HandleSysColorChange(); + break; -bool wxWindow::MSWOnQueryNewPalette() -{ - wxQueryNewPaletteEvent event(GetId()); - event.SetEventObject(this); + case WM_PALETTECHANGED: + processed = HandlePaletteChanged((WXHWND) (HWND) wParam); + break; - return GetEventHandler()->ProcessEvent(event) && event.GetPaletteRealized(); -} + case WM_QUERYNEWPALETTE: + processed = HandleQueryNewPalette(); + break; -// Responds to colour changes: passes event on to children. -void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event) -{ - wxNode *node = GetChildren().First(); - while ( node ) - { - // Only propagate to non-top-level windows - wxWindow *win = (wxWindow *)node->Data(); - if ( win->GetParent() ) - { - wxSysColourChangedEvent event2; - event.m_eventObject = win; - win->GetEventHandler()->ProcessEvent(event2); - } + case WM_ERASEBKGND: + processed = HandleEraseBkgnd((WXHDC)(HDC)wParam); + if ( processed ) + { + // we processed the message, i.e. erased the background + rc.result = TRUE; + } + break; - node = node->Next(); - } -} + case WM_DROPFILES: + processed = HandleDropFiles(wParam); + break; -long wxWindow::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) -{ - if ( m_oldWndProc ) - return ::CallWindowProc(CASTWNDPROC m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam); - else - return ::DefWindowProc(GetHwnd(), nMsg, wParam, lParam); -} + case WM_INITDIALOG: + processed = HandleInitDialog((WXHWND)(HWND)wParam); -bool wxWindow::MSWProcessMessage(WXMSG* pMsg) -{ - if ( m_hWnd != 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL) ) - { - // intercept dialog navigation keys - MSG *msg = (MSG *)pMsg; - bool bProcess = TRUE; - if ( msg->message != WM_KEYDOWN ) - bProcess = FALSE; + if ( processed ) + { + // we never set focus from here + rc.result = FALSE; + } + break; - if ( bProcess && (HIWORD(msg->lParam) & KF_ALTDOWN) == KF_ALTDOWN ) - bProcess = FALSE; + case WM_QUERYENDSESSION: + processed = HandleQueryEndSession(lParam, &rc.allow); + break; - if ( bProcess ) - { - bool bCtrlDown = (::GetKeyState(VK_CONTROL) & 0x100) != 0; + case WM_ENDSESSION: + processed = HandleEndSession(wParam != 0, lParam); + break; - // 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 ) + case WM_GETMINMAXINFO: + processed = HandleGetMinMaxInfo((MINMAXINFO*)lParam); + break; + + case WM_SETCURSOR: + processed = HandleSetCursor((WXHWND)(HWND)wParam, + LOWORD(lParam), // hit test + HIWORD(lParam)); // mouse msg + + if ( processed ) { - lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0); + // returning TRUE stops the DefWindowProc() from further + // processing this message - exactly what we need because we've + // just set the cursor. + rc.result = TRUE; } + break; +#ifdef __WIN32__ + case WM_HELP: + { + HELPINFO* info = (HELPINFO*) lParam; + // Don't yet process menu help events, just windows + if (info->iContextType == HELPINFO_WINDOW) + { + wxWindow* subjectOfHelp = this; + bool eventProcessed = FALSE; + while (subjectOfHelp && !eventProcessed) + { + wxHelpEvent helpEvent(wxEVT_HELP, subjectOfHelp->GetId(), wxPoint(info->MousePos.x, info->MousePos.y) ) ; // info->iCtrlId); + helpEvent.SetEventObject(this); + eventProcessed = GetEventHandler()->ProcessEvent(helpEvent); - bool bForward = TRUE, - bWindowChange = FALSE; - - switch ( msg->wParam ) + // Go up the window hierarchy until the event is handled (or not) + subjectOfHelp = subjectOfHelp->GetParent(); + } + processed = eventProcessed; + } + else if (info->iContextType == HELPINFO_MENUITEM) { - case VK_TAB: - if ( lDlgCode & DLGC_WANTTAB ) { - bProcess = FALSE; - } - else { - // Ctrl-Tab cycles thru notebook pages - bWindowChange = bCtrlDown; - bForward = !(::GetKeyState(VK_SHIFT) & 0x100); - } - break; + wxHelpEvent helpEvent(wxEVT_HELP, info->iCtrlId) ; + helpEvent.SetEventObject(this); + processed = GetEventHandler()->ProcessEvent(helpEvent); + } + else processed = FALSE; + break; + } +#endif + } - case VK_UP: - case VK_LEFT: - if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown ) - bProcess = FALSE; - else - bForward = FALSE; - break; + if ( !processed ) + { +#ifdef __WXDEBUG__ + wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."), + wxGetMessageName(message)); +#endif // __WXDEBUG__ + rc.result = MSWDefWindowProc(message, wParam, lParam); + } - case VK_DOWN: - case VK_RIGHT: - if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown ) - bProcess = FALSE; - break; + return rc.result; +} - case VK_RETURN: - { - if ( lDlgCode & DLGC_WANTMESSAGE ) - { - // control wants to process Enter itself, don't - // call IsDialogMessage() which would interpret - // it - return FALSE; - } -#ifndef __WIN16__ - wxButton *btnDefault = GetDefaultItem(); - if ( btnDefault && !bCtrlDown ) - { - // if there is a default button, Enter should - // press it - (void)::SendMessage((HWND)btnDefault->GetHWND(), - BM_CLICK, 0, 0); - return TRUE; - } - // else: but if there is 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. -#endif - } - break; +// Dialog window proc +LONG APIENTRY _EXPORT +wxDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if ( message == WM_INITDIALOG ) + { + // for this message, returning TRUE tells system to set focus to the + // first control in the dialog box + return TRUE; + } + else + { + // for all the other ones, FALSE means that we didn't process the + // message + return 0; + } +} - default: - bProcess = FALSE; - } +wxList *wxWinHandleList = NULL; +wxWindow *wxFindWinFromHandle(WXHWND hWnd) +{ + wxNode *node = wxWinHandleList->Find((long)hWnd); + if ( !node ) + return NULL; + return (wxWindow *)node->Data(); +} - if ( bProcess ) - { - wxNavigationKeyEvent event; - event.SetDirection(bForward); - event.SetWindowChange(bWindowChange); - event.SetEventObject(this); +#if 0 // def __WXDEBUG__ +static int gs_AssociationCount = 0; +#endif - if ( GetEventHandler()->ProcessEvent(event) ) - return TRUE; - } - } +void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win) +{ + // adding NULL hWnd is (first) surely a result of an error and + // (secondly) breaks menu command processing + wxCHECK_RET( hWnd != (HWND)NULL, + wxT("attempt to add a NULL hWnd to window list ignored") ); - if ( ::IsDialogMessage(GetHwnd(), msg) ) - return TRUE; - } -#if wxUSE_TOOLTIPS - if ( m_tooltip ) + wxWindow *oldWin = wxFindWinFromHandle((WXHWND) hWnd); + if ( oldWin && (oldWin != win) ) { - // relay mouse move events to the tooltip control - MSG *msg = (MSG *)pMsg; - if ( msg->message == WM_MOUSEMOVE ) - m_tooltip->RelayEvent(pMsg); + wxString str(win->GetClassInfo()->GetClassName()); + wxLogError(wxT("Bug! Found existing HWND %X for new window of class %s"), (int) hWnd, (const wxChar*) str); } -#endif // wxUSE_TOOLTIPS + else if (!oldWin) + { +#if 0 // def __WXDEBUG__ + gs_AssociationCount ++; + wxLogDebug("+ Association %d", gs_AssociationCount); +#endif -/* This code manages to disable character input completely. Nice one! - * Probably because the dialog is requesting all char input. Or, - * it gets called by non-dialog windows. + wxWinHandleList->Append((long)hWnd, win); + } +} - // In case we don't have wxTAB_TRAVERSAL style on. - // If we don't call this, we may never process Enter correctly. - if ( m_hWnd != 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL) == 0 ) +void wxRemoveHandleAssociation(wxWindow *win) +{ +#if 0 // def __WXDEBUG__ + if (wxWinHandleList->Member(win)) { - MSG *msg = (MSG *)pMsg; - if ( ::IsDialogMessage(GetHwnd(), msg) ) - return TRUE; + wxLogDebug("- Association %d", gs_AssociationCount); + gs_AssociationCount --; } -*/ - return FALSE; +#endif + wxWinHandleList->DeleteObject(win); } -bool wxWindow::MSWTranslateMessage(WXMSG* pMsg) +// Default destroyer - override if you destroy it in some other way +// (e.g. with MDI child windows) +void wxWindow::MSWDestroyWindow() { - if ( m_acceleratorTable.Ok( ) && - ::TranslateAccelerator(GetHwnd(), (HACCEL) m_acceleratorTable.GetHACCEL(), (MSG *)pMsg)) - return TRUE; - else - return FALSE; } void wxWindow::MSWDetachWindowMenu() { if ( m_hMenu ) { - int N = GetMenuItemCount((HMENU) m_hMenu); + HMENU hMenu = (HMENU)m_hMenu; + + int N = ::GetMenuItemCount(hMenu); int i; for (i = 0; i < N; i++) { - char buf[100]; - int chars = GetMenuString((HMENU) m_hMenu, i, buf, 100, MF_BYPOSITION); - if ( (chars > 0) && (strcmp(buf, "&Window") == 0) ) + wxChar buf[100]; + int chars = GetMenuString(hMenu, i, buf, 100, MF_BYPOSITION); + if ( !chars ) + { + wxLogLastError(wxT("GetMenuString")); + + continue; + } + + if ( wxStrcmp(buf, wxT("&Window")) == 0 ) { - RemoveMenu((HMENU) m_hMenu, i, MF_BYPOSITION); + RemoveMenu(hMenu, i, MF_BYPOSITION); + break; } } } } -bool wxWindow::MSWOnPaint() +bool wxWindow::MSWCreate(int id, + wxWindow *parent, + const wxChar *wclass, + wxWindow *wx_win, + const wxChar *title, + int x, + int y, + int width, + int height, + WXDWORD style, + const wxChar *dialog_template, + WXDWORD extendedStyle) { -#ifdef __WIN32__ - HRGN hRegion = ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle - ::GetUpdateRgn(GetHwnd(), hRegion, FALSE); + int x1 = CW_USEDEFAULT; + int y1 = 0; + int width1 = CW_USEDEFAULT; + int height1 = 100; - m_updateRegion = wxRegion((WXHRGN) hRegion); -#else - RECT updateRect; - ::GetUpdateRect(GetHwnd(), & updateRect, FALSE); + // Find parent's size, if it exists, to set up a possible default + // panel size the size of the parent window + RECT parent_rect; + if ( parent ) + { + ::GetClientRect((HWND) parent->GetHWND(), &parent_rect); - m_updateRegion = wxRegion(updateRect.left, updateRect.top, - updateRect.right - updateRect.left, updateRect.bottom - updateRect.top); -#endif + width1 = parent_rect.right - parent_rect.left; + height1 = parent_rect.bottom - parent_rect.top; + } - wxPaintEvent event(m_windowId); - event.SetEventObject(this); - return GetEventHandler()->ProcessEvent(event); -} + if ( x > -1 ) x1 = x; + if ( y > -1 ) y1 = y; + if ( width > -1 ) width1 = width; + if ( height > -1 ) height1 = height; -bool wxWindow::HandleMove(int x, int y) -{ - wxMoveEvent event(wxPoint(x, y), m_windowId); - event.SetEventObject(this); + // unfortunately, setting WS_EX_CONTROLPARENT only for some windows in the + // hierarchy with several embedded panels (and not all of them) causes the + // program to hang during the next call to IsDialogMessage() due to the bug + // in this function (at least in Windows NT 4.0, it seems to work ok in + // Win2K) +#if 0 + // if we have wxTAB_TRAVERSAL style, we want WS_EX_CONTROLPARENT or + // IsDialogMessage() won't work for us + if ( GetWindowStyleFlag() & wxTAB_TRAVERSAL ) + { + extendedStyle |= WS_EX_CONTROLPARENT; + } +#endif // 0 - return GetEventHandler()->ProcessEvent(event); -} + HWND hParent = parent ? GetHwndOf(parent) : NULL; -bool wxWindow::MSWOnSize(int w, int h, WXUINT WXUNUSED(flag)) -{ - wxSizeEvent event(wxSize(w, h), m_windowId); - event.SetEventObject(this); + wxWndHook = this; - return GetEventHandler()->ProcessEvent(event); -} + if ( dialog_template ) + { + // for the dialogs without wxDIALOG_NO_PARENT style, use the top level + // app window as parent - this avoids creating modal dialogs without + // parent + if ( !hParent && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT) ) + { + wxWindow *winTop = wxTheApp->GetTopWindow(); + if ( winTop ) + hParent = GetHwndOf(winTop); + } -bool wxWindow::MSWOnWindowPosChanging(void *WXUNUSED(lpPos)) -{ - return FALSE; -} + m_hWnd = (WXHWND)::CreateDialog(wxGetInstance(), + dialog_template, + hParent, + (DLGPROC)wxDlgProc); -// Deal with child commands from buttons etc. -bool wxWindow::MSWOnCommand(WXWORD id, WXWORD cmd, WXHWND control) -{ - if ( wxCurrentPopupMenu ) - { - wxMenu *popupMenu = wxCurrentPopupMenu; - wxCurrentPopupMenu = NULL; - bool succ = popupMenu->MSWCommand(cmd, id); - return succ; - } + if ( m_hWnd == 0 ) + { + wxLogError(_("Can't find dialog template '%s'!\nCheck resource include path for finding wx.rc."), + dialog_template); - wxWindow *item = FindItem(id); - if ( item ) - { - bool value = item->MSWCommand(cmd, id); - return value; - } - else - { - wxWindow *win = wxFindWinFromHandle(control); - if ( win ) - return win->MSWCommand(cmd, id); - } - return FALSE; -} + return FALSE; + } -bool wxWindow::MSWOnSysCommand(WXWPARAM wParam, WXLPARAM lParam) -{ - // 4 bits are reserved - switch (wParam & 0xFFFFFFF0) - { - case SC_MAXIMIZE: - { - wxMaximizeEvent event(m_windowId); - event.SetEventObject(this); + if ( extendedStyle != 0 ) + { + ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, extendedStyle); + ::SetWindowPos(GetHwnd(), NULL, 0, 0, 0, 0, + SWP_NOSIZE | + SWP_NOMOVE | + SWP_NOZORDER | + SWP_NOACTIVATE); + } - return GetEventHandler()->ProcessEvent(event); +#if defined(__WIN95__) + // For some reason, the system menu is activated when we use the + // WS_EX_CONTEXTHELP style, so let's set a reasonable icon + if (extendedStyle & WS_EX_CONTEXTHELP) + { + wxFrame *winTop = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame); + if ( winTop ) + { + wxIcon icon = winTop->GetIcon(); + if ( icon.Ok() ) + { + ::SendMessage(GetHwnd(), WM_SETICON, + (WPARAM)TRUE, + (LPARAM)GetHiconOf(icon)); + } } + } +#endif // __WIN95__ - case SC_MINIMIZE: - { - wxIconizeEvent event(m_windowId); - event.SetEventObject(this); - return GetEventHandler()->ProcessEvent(event); + // JACS: is the following still necessary? The above seems to work. + + // ::SetWindowLong(GWL_EXSTYLE) doesn't work for the dialogs, so try + // to take care of (at least some) extended style flags ourselves + if ( extendedStyle & WS_EX_TOPMOST ) + { + if ( !::SetWindowPos(GetHwnd(), HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE) ) + { + wxLogLastError(wxT("SetWindowPos")); } + } + + // move the dialog to its initial position without forcing repainting + if ( !::MoveWindow(GetHwnd(), x1, y1, width1, height1, FALSE) ) + { + wxLogLastError(wxT("MoveWindow")); + } } + else // creating a normal window, not a dialog + { + int controlId = 0; + if ( style & WS_CHILD ) + { + controlId = id; + // all child windows should clip their siblings + // style |= /* WS_CLIPSIBLINGS */ ; + } - return FALSE; + wxString className(wclass); + if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE ) + { + className += wxT("NR"); + } + + m_hWnd = (WXHWND)CreateWindowEx(extendedStyle, + className, + title ? title : wxT(""), + style, + x1, y1, + width1, height1, + hParent, (HMENU)controlId, + wxGetInstance(), + NULL); + + if ( !m_hWnd ) + { + wxLogError(_("Can't create window of class %s!\nPossible Windows 3.x compatibility problem?"), + wclass); + + return FALSE; + } + } + + wxWndHook = NULL; + +#ifdef __WXDEBUG__ + wxNode* node = wxWinHandleList->Member(this); + if (node) + { + HWND hWnd = (HWND) node->GetKeyInteger(); + if (hWnd != (HWND) m_hWnd) + { + wxLogError(wxT("A second HWND association is being added for the same window!")); + } + } +#endif // Debug + + wxAssociateWinWithHandle((HWND) m_hWnd, this); + + return TRUE; } +// =========================================================================== +// MSW message handlers +// =========================================================================== + // --------------------------------------------------------------------------- -// mouse events +// WM_NOTIFY // --------------------------------------------------------------------------- -void wxWindow::InitMouseEvent(wxMouseEvent& event, int x, int y, WXUINT flags) +#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) { - 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); - event.SetTimestamp(wxApp::sm_lastMessageTime); - event.m_eventObject = this; - -#if wxUSE_MOUSEEVENT_HACK - m_lastMouseX = x; - m_lastMouseY = y; - m_lastMouseEvent = event.GetEventType(); -#endif // wxUSE_MOUSEEVENT_HACK + LPNMHDR hdr = (LPNMHDR)lParam; + HWND hWnd = hdr->hwndFrom; + wxWindow *win = wxFindWinFromHandle((WXHWND)hWnd); -} + // is this one of our windows? + if ( win ) + { + return win->MSWOnNotify(idCtrl, lParam, result); + } -bool wxWindow::MSWOnMouseEvent(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 - // from the message id and take the value in the table to get wxWin event - // id - static const wxEventType eventsMouse[] = + // try all our children + wxWindowList::Node *node = GetChildren().GetFirst(); + while ( node ) { - wxEVT_MOTION, - wxEVT_LEFT_DOWN, - wxEVT_LEFT_UP, - wxEVT_LEFT_DCLICK, - wxEVT_RIGHT_DOWN, - wxEVT_RIGHT_UP, - wxEVT_RIGHT_DCLICK, - wxEVT_MIDDLE_DOWN, - wxEVT_MIDDLE_UP, - wxEVT_MIDDLE_DCLICK - }; + wxWindow *child = node->GetData(); + if ( child->MSWOnNotify(idCtrl, lParam, result) ) + { + return TRUE; + } - wxMouseEvent event(eventsMouse[msg - WM_MOUSEMOVE]); - InitMouseEvent(event, x, y, flags); + node = node->GetNext(); + } - return GetEventHandler()->ProcessEvent(event); + // finally try this window too (catches toolbar case) + return MSWOnNotify(idCtrl, lParam, result); } -bool wxWindow::MSWOnMouseMove(int x, int y, WXUINT flags) +bool wxWindow::MSWOnNotify(int WXUNUSED(idCtrl), + WXLPARAM lParam, + WXLPARAM* WXUNUSED(result)) { - if ( !m_mouseInWindow ) - { - // Generate an ENTER event - m_mouseInWindow = TRUE; - - wxMouseEvent event(wxEVT_ENTER_WINDOW); - InitMouseEvent(event, x, y, flags); - - (void)GetEventHandler()->ProcessEvent(event); - } - -#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 == event.m_x && m_lastMouseY == event.m_y) ) +#if wxUSE_TOOLTIPS + NMHDR* hdr = (NMHDR *)lParam; + if ( (int)hdr->code == TTN_NEEDTEXT && m_tooltip ) { - m_lastMouseEvent = wxEVT_MOTION; + TOOLTIPTEXT *ttt = (TOOLTIPTEXT *)lParam; + ttt->lpszText = (wxChar *)m_tooltip->GetTip().c_str(); - return FALSE; + // processed + return TRUE; } -#endif // wxUSE_MOUSEEVENT_HACK +#endif // wxUSE_TOOLTIPS - return MSWOnMouseEvent(WM_MOUSEMOVE, x, y, flags); + return FALSE; } +#endif // __WIN95__ // --------------------------------------------------------------------------- -// keyboard handling +// end session messages // --------------------------------------------------------------------------- -// isASCII is TRUE only when we're called from WM_CHAR handler and not from -// WM_KEYDOWN one -bool wxWindow::MSWOnChar(WXWORD wParam, WXLPARAM lParam, bool isASCII) +bool wxWindow::HandleQueryEndSession(long logOff, bool *mayEnd) { - int id; - bool tempControlDown = FALSE; - if ( isASCII ) + wxCloseEvent event(wxEVT_QUERY_END_SESSION, -1); + event.SetEventObject(wxTheApp); + event.SetCanVeto(TRUE); + event.SetLoggingOff(logOff == (long)ENDSESSION_LOGOFF); + + bool rc = wxTheApp->ProcessEvent(event); + + if ( rc ) { - // If 1 -> 26, translate to CTRL plus a letter. - 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: - { - tempControlDown = TRUE; - id = id + 96; - } - } - } - } - else if ( (id = wxCharCodeMSWToWX(wParam)) == 0 ) { - // it's ASCII and will be processed here only when called from - // WM_CHAR (i.e. when isASCII = TRUE) - id = -1; + // we may end only if the app didn't veto session closing (double + // negation...) + *mayEnd = !event.GetVeto(); } - if ( id != -1 ) + return rc; +} + +bool wxWindow::HandleEndSession(bool endSession, long logOff) +{ + // do nothing if the session isn't ending + if ( !endSession ) + 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)) { - wxKeyEvent event(wxEVT_CHAR); - event.m_shiftDown = (::GetKeyState(VK_SHIFT)&0x100?TRUE:FALSE); - event.m_controlDown = (::GetKeyState(VK_CONTROL)&0x100?TRUE:FALSE); - if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN ) - event.m_altDown = TRUE; + } + return TRUE; +} - event.m_eventObject = this; - event.m_keyCode = id; - event.SetTimestamp(wxApp::sm_lastMessageTime); +// --------------------------------------------------------------------------- +// window creation/destruction +// --------------------------------------------------------------------------- - POINT pt ; - GetCursorPos(&pt) ; - RECT rect ; - GetWindowRect(GetHwnd(),&rect) ; - pt.x -= rect.left ; - pt.y -= rect.top ; +bool wxWindow::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate) +{ + // TODO: should generate this event from WM_NCCREATE + wxWindowCreateEvent event(this); + (void)GetEventHandler()->ProcessEvent(event); - event.m_x = pt.x; event.m_y = pt.y; + *mayCreate = TRUE; - if ( GetEventHandler()->ProcessEvent(event) ) - return TRUE; - else - return FALSE; - } - else - return FALSE; + return TRUE; } -bool wxWindow::MSWOnKeyDown(WXWORD wParam, WXLPARAM lParam) +bool wxWindow::HandleDestroy() { - int id; + wxWindowDestroyEvent event(this); + (void)GetEventHandler()->ProcessEvent(event); - if ( (id = wxCharCodeMSWToWX(wParam)) == 0 ) { - id = wParam; - } - - if ( id != -1 ) + // delete our drop target if we've got one +#if wxUSE_DRAG_AND_DROP + if ( m_dropTarget != NULL ) { - wxKeyEvent event(wxEVT_KEY_DOWN); - event.m_shiftDown = (::GetKeyState(VK_SHIFT)&0x100?TRUE:FALSE); - event.m_controlDown = (::GetKeyState(VK_CONTROL)&0x100?TRUE:FALSE); - if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN ) - event.m_altDown = TRUE; + m_dropTarget->Revoke(m_hWnd); - event.m_eventObject = this; - event.m_keyCode = id; - event.SetTimestamp(wxApp::sm_lastMessageTime); + delete m_dropTarget; + m_dropTarget = NULL; + } +#endif // wxUSE_DRAG_AND_DROP - POINT pt ; - GetCursorPos(&pt) ; - RECT rect ; - GetWindowRect(GetHwnd(),&rect) ; - pt.x -= rect.left ; - pt.y -= rect.top ; + // WM_DESTROY handled + return TRUE; +} - event.m_x = pt.x; event.m_y = pt.y; +// --------------------------------------------------------------------------- +// activation/focus +// --------------------------------------------------------------------------- - if ( GetEventHandler()->ProcessEvent(event) ) +void wxWindow::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; + while ( win ) + { + wxWindow *parent = win->GetParent(); + wxPanel *panel = wxDynamicCast(parent, wxPanel); + if ( panel ) { - return TRUE; + panel->SetLastFocus(win); } - else return FALSE; - } - else - { - return FALSE; + + win = parent; } + + wxLogTrace(_T("focus"), _T("%s (0x%08x) gets focus"), + GetClassInfo()->GetClassName(), GetHandle()); + + event.Skip(); } -bool wxWindow::MSWOnKeyUp(WXWORD wParam, WXLPARAM lParam) +bool wxWindow::HandleActivate(int state, + bool WXUNUSED(minimized), + WXHWND WXUNUSED(activate)) { - int id; + wxActivateEvent event(wxEVT_ACTIVATE, + (state == WA_ACTIVE) || (state == WA_CLICKACTIVE), + m_windowId); + event.SetEventObject(this); - if ( (id = wxCharCodeMSWToWX(wParam)) == 0 ) { - id = wParam; - } + return GetEventHandler()->ProcessEvent(event); +} - if ( id != -1 ) +bool wxWindow::HandleSetFocus(WXHWND WXUNUSED(hwnd)) +{ +#if wxUSE_CARET + // Deal with caret + if ( m_caret ) { - wxKeyEvent event(wxEVT_KEY_UP); - event.m_shiftDown = (::GetKeyState(VK_SHIFT)&0x100?TRUE:FALSE); - event.m_controlDown = (::GetKeyState(VK_CONTROL)&0x100?TRUE:FALSE); - if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN ) - event.m_altDown = TRUE; - - event.m_eventObject = this; - event.m_keyCode = id; - event.SetTimestamp(wxApp::sm_lastMessageTime); + m_caret->OnSetFocus(); + } +#endif // wxUSE_CARET - POINT pt ; - GetCursorPos(&pt) ; - RECT rect ; - GetWindowRect(GetHwnd(),&rect) ; - pt.x -= rect.left ; - pt.y -= rect.top ; + wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId); + event.SetEventObject(this); - event.m_x = pt.x; event.m_y = pt.y; + return GetEventHandler()->ProcessEvent(event); +} - if ( GetEventHandler()->ProcessEvent(event) ) - return TRUE; - else - return FALSE; +bool wxWindow::HandleKillFocus(WXHWND WXUNUSED(hwnd)) +{ +#if wxUSE_CARET + // Deal with caret + if ( m_caret ) + { + m_caret->OnKillFocus(); } - else - return FALSE; +#endif // wxUSE_CARET + + wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId); + event.SetEventObject(this); + + return GetEventHandler()->ProcessEvent(event); } // --------------------------------------------------------------------------- -// joystick +// miscellaneous // --------------------------------------------------------------------------- -bool wxWindow::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) +bool wxWindow::HandleShow(bool show, int status) { - int change = 0; - if ( flags & JOY_BUTTON1CHG ) - change = wxJOY_BUTTON1; - if ( flags & JOY_BUTTON2CHG ) - change = wxJOY_BUTTON2; - if ( flags & JOY_BUTTON3CHG ) - change = wxJOY_BUTTON3; - if ( flags & JOY_BUTTON4CHG ) - change = wxJOY_BUTTON4; + wxShowEvent event(GetId(), show); + event.m_eventObject = this; - int buttons = 0; - if ( flags & JOY_BUTTON1 ) - buttons |= wxJOY_BUTTON1; - if ( flags & JOY_BUTTON2 ) - buttons |= wxJOY_BUTTON2; - if ( flags & JOY_BUTTON3 ) - buttons |= wxJOY_BUTTON3; - if ( flags & JOY_BUTTON4 ) - buttons |= wxJOY_BUTTON4; + return GetEventHandler()->ProcessEvent(event); +} - // the event ids aren't consecutive so we can't use table based lookup - int joystick; - wxEventType eventType; - switch ( msg ) - { - case MM_JOY1MOVE: - joystick = 1; - eventType = wxEVT_JOY_MOVE; - break; +bool wxWindow::HandleInitDialog(WXHWND WXUNUSED(hWndFocus)) +{ + wxInitDialogEvent event(GetId()); + event.m_eventObject = this; - case MM_JOY2MOVE: - joystick = 2; - eventType = wxEVT_JOY_MOVE; - break; + return GetEventHandler()->ProcessEvent(event); +} - case MM_JOY1ZMOVE: - joystick = 1; - eventType = wxEVT_JOY_ZMOVE; - break; +bool wxWindow::HandleDropFiles(WXWPARAM wParam) +{ + HDROP hFilesInfo = (HDROP) wParam; + POINT dropPoint; + DragQueryPoint(hFilesInfo, (LPPOINT) &dropPoint); - case MM_JOY2ZMOVE: - joystick = 2; - eventType = wxEVT_JOY_ZMOVE; - break; + // Get the total number of files dropped + WORD gwFilesDropped = (WORD)::DragQueryFile + ( + (HDROP)hFilesInfo, + (UINT)-1, + (LPTSTR)0, + (UINT)0 + ); - case MM_JOY1BUTTONDOWN: - joystick = 1; - eventType = wxEVT_JOY_BUTTON_DOWN; - break; + wxString *files = new wxString[gwFilesDropped]; + int wIndex; + for (wIndex=0; wIndex < (int)gwFilesDropped; wIndex++) + { + DragQueryFile (hFilesInfo, wIndex, (LPTSTR) wxBuffer, 1000); + files[wIndex] = wxBuffer; + } + DragFinish (hFilesInfo); - case MM_JOY2BUTTONDOWN: - joystick = 2; - eventType = wxEVT_JOY_BUTTON_DOWN; - break; + wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files); + event.m_eventObject = this; + event.m_pos.x = dropPoint.x; event.m_pos.x = dropPoint.y; - case MM_JOY1BUTTONUP: - joystick = 1; - eventType = wxEVT_JOY_BUTTON_UP; - break; + bool rc = GetEventHandler()->ProcessEvent(event); - case MM_JOY2BUTTONUP: - joystick = 2; - eventType = wxEVT_JOY_BUTTON_UP; - break; + delete[] files; - default: - wxFAIL_MSG("no such joystick event"); + return rc; +} - return FALSE; +bool wxWindow::HandleSetCursor(WXHWND 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 + // the title bar, scrollbars, &c + // 0. allow the user to override default behaviour by using EVT_SET_CURSOR + // 1. if we have the cursor set it unless wxIsBusy() + // 2. if we're a top level window, set some cursor anyhow + // 3. if wxIsBusy(), set the busy cursor, otherwise the global one + + if ( nHitTest != HTCLIENT ) + { + return FALSE; } - wxJoystickEvent event(eventType, buttons, joystick, change); - event.SetPosition(wxPoint(x, y)); - event.SetEventObject(this); + HCURSOR hcursor = 0; - return GetEventHandler()->ProcessEvent(event); -} + // first ask the user code - it may wish to set the cursor in some very + // specific way (for example, depending on the current position) + POINT pt; +#ifdef __WIN32__ + if ( !::GetCursorPos(&pt) ) + { + wxLogLastError(wxT("GetCursorPos")); + } +#else + // In WIN16 it doesn't return a value. + ::GetCursorPos(&pt); +#endif -bool wxWindow::MSWOnScroll(int orientation, WXWORD wParam, - WXWORD pos, WXHWND control) -{ - if ( control ) + int x = pt.x, + y = pt.y; + ScreenToClient(&x, &y); + wxSetCursorEvent event(x, y); + + bool processedEvtSetCursor = GetEventHandler()->ProcessEvent(event); + if ( processedEvtSetCursor && event.HasCursor() ) { - wxWindow *child = wxFindWinFromHandle(control); - if ( child ) - return child->MSWOnScroll(orientation, wParam, pos, control); + hcursor = GetHcursorOf(event.GetCursor()); } - wxScrollEvent event; - event.SetPosition(pos); - event.SetOrientation(orientation); - event.m_eventObject = this; + if ( !hcursor ) + { + bool isBusy = wxIsBusy(); - switch ( wParam ) + // the test for processedEvtSetCursor is here to prevent using m_cursor + // if the user code caught EVT_SET_CURSOR() and returned nothing from + // it - this is a way to say that our cursor shouldn't be used for this + // point + if ( !processedEvtSetCursor && m_cursor.Ok() ) + { + hcursor = GetHcursorOf(m_cursor); + } + + if ( !GetParent() ) + { + if ( isBusy ) + { + hcursor = wxGetCurrentBusyCursor(); + } + else if ( !hcursor ) + { + const wxCursor *cursor = wxGetGlobalCursor(); + if ( cursor && cursor->Ok() ) + { + hcursor = GetHcursorOf(*cursor); + } + } + } + } + + if ( hcursor ) { - case SB_TOP: - event.m_eventType = wxEVT_SCROLL_TOP; - break; + ::SetCursor(hcursor); - case SB_BOTTOM: - event.m_eventType = wxEVT_SCROLL_BOTTOM; - break; + // cursor set, stop here + return TRUE; + } - case SB_LINEUP: - event.m_eventType = wxEVT_SCROLL_LINEUP; - break; + // pass up the window chain + return FALSE; +} - case SB_LINEDOWN: - event.m_eventType = wxEVT_SCROLL_LINEDOWN; - break; +// --------------------------------------------------------------------------- +// owner drawn stuff +// --------------------------------------------------------------------------- - case SB_PAGEUP: - event.m_eventType = wxEVT_SCROLL_PAGEUP; - break; +bool wxWindow::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct) +{ +#if wxUSE_OWNER_DRAWN + // is it a menu item? + if ( id == 0 ) + { + DRAWITEMSTRUCT *pDrawStruct = (DRAWITEMSTRUCT *)itemStruct; + wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData); - case SB_PAGEDOWN: - event.m_eventType = wxEVT_SCROLL_PAGEDOWN; - break; + wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE ); - case SB_THUMBTRACK: - case SB_THUMBPOSITION: - event.m_eventType = wxEVT_SCROLL_THUMBTRACK; - break; + // prepare to call OnDrawItem() + wxDC dc; + dc.SetHDC((WXHDC)pDrawStruct->hDC, FALSE); + wxRect rect(pDrawStruct->rcItem.left, pDrawStruct->rcItem.top, + pDrawStruct->rcItem.right - pDrawStruct->rcItem.left, + pDrawStruct->rcItem.bottom - pDrawStruct->rcItem.top); + + return pMenuItem->OnDrawItem + ( + dc, rect, + (wxOwnerDrawn::wxODAction)pDrawStruct->itemAction, + (wxOwnerDrawn::wxODStatus)pDrawStruct->itemState + ); + } - default: - return FALSE; + wxWindow *item = FindItem(id); + if ( item && item->IsKindOf(CLASSINFO(wxControl)) ) + { + return ((wxControl *)item)->MSWOnDraw(itemStruct); } +#endif // USE_OWNER_DRAWN - return GetEventHandler()->ProcessEvent(event); + return FALSE; } -bool wxWindow::MSWOnShow(bool show, int status) +bool wxWindow::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct) { - wxShowEvent event(GetId(), show); - event.m_eventObject = this; +#if wxUSE_OWNER_DRAWN + // is it a menu item? + if ( id == 0 ) + { + MEASUREITEMSTRUCT *pMeasureStruct = (MEASUREITEMSTRUCT *)itemStruct; + wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData); - return GetEventHandler()->ProcessEvent(event); + wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE ); + + return pMenuItem->OnMeasureItem(&pMeasureStruct->itemWidth, + &pMeasureStruct->itemHeight); + } + + wxWindow *item = FindItem(id); + if ( item && item->IsKindOf(CLASSINFO(wxControl)) ) + { + return ((wxControl *)item)->MSWOnMeasure(itemStruct); + } +#endif // owner-drawn menus + return FALSE; } -bool wxWindow::MSWOnInitDialog(WXHWND WXUNUSED(hWndFocus)) +// --------------------------------------------------------------------------- +// colours and palettes +// --------------------------------------------------------------------------- + +bool wxWindow::HandleSysColorChange() { - wxInitDialogEvent event(GetId()); - event.m_eventObject = this; + wxSysColourChangedEvent event; + event.SetEventObject(this); return GetEventHandler()->ProcessEvent(event); } -void wxGetCharSize(WXHWND wnd, int *x, int *y,wxFont *the_font) +bool wxWindow::HandleCtlColor(WXHBRUSH *brush, + WXHDC pDC, + WXHWND pWnd, + WXUINT nCtlColor, + WXUINT message, + WXWPARAM wParam, + WXLPARAM lParam) { - TEXTMETRIC tm; - HDC dc = ::GetDC((HWND) wnd); - HFONT fnt =0; - HFONT was = 0; - if ( the_font ) + WXHBRUSH hBrush = 0; + + if ( nCtlColor == CTLCOLOR_DLG ) { - // the_font->UseResource(); - // the_font->RealizeResource(); - fnt = (HFONT)the_font->GetResourceHandle(); - if ( fnt ) - was = (HFONT) SelectObject(dc,fnt) ; + hBrush = OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam); } - GetTextMetrics(dc, &tm); - if ( the_font && fnt && was ) + else { - SelectObject(dc,was) ; + wxControl *item = (wxControl *)FindItemByHWND(pWnd, TRUE); + if ( item ) + hBrush = item->OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam); } - ReleaseDC((HWND)wnd, dc); - *x = tm.tmAveCharWidth; - *y = tm.tmHeight + tm.tmExternalLeading; - // if ( the_font ) - // the_font->ReleaseResource(); + if ( hBrush ) + *brush = hBrush; + + return hBrush != 0; } -// 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) +// Define for each class of dialog and control +WXHBRUSH wxWindow::OnCtlColor(WXHDC hDC, + WXHWND hWnd, + WXUINT nCtlColor, + WXUINT message, + WXWPARAM wParam, + WXLPARAM lParam) { - int id = 0; - switch (keySym) + return (WXHBRUSH)0; +} + +bool wxWindow::HandlePaletteChanged(WXHWND hWndPalChange) +{ + wxPaletteChangedEvent event(GetId()); + event.SetEventObject(this); + event.SetChangedWindow(wxFindWinFromHandle(hWndPalChange)); + + return GetEventHandler()->ProcessEvent(event); +} + +bool wxWindow::HandleQueryNewPalette() +{ + wxQueryNewPaletteEvent event(GetId()); + event.SetEventObject(this); + + return GetEventHandler()->ProcessEvent(event) && event.GetPaletteRealized(); +} + +// Responds to colour changes: passes event on to children. +void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event) +{ + wxNode *node = GetChildren().First(); + while ( node ) { - 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_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_MULTIPLY; break; - case VK_ADD: id = WXK_ADD; break; - case VK_SUBTRACT: id = WXK_SUBTRACT; break; - case VK_DECIMAL: id = WXK_DECIMAL; break; - case VK_DIVIDE: id = WXK_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; - default: + // Only propagate to non-top-level windows + wxWindow *win = (wxWindow *)node->Data(); + if ( win->GetParent() ) { - return 0; + wxSysColourChangedEvent event2; + event.m_eventObject = win; + win->GetEventHandler()->ProcessEvent(event2); } + + node = node->Next(); } - return id; } -int wxCharCodeWXToMSW(int id, bool *isVirtual) +// --------------------------------------------------------------------------- +// painting +// --------------------------------------------------------------------------- + +bool wxWindow::HandlePaint() { - *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_MULTIPLY: keySym = VK_MULTIPLY; break; - case WXK_ADD: keySym = VK_ADD; break; - case WXK_SUBTRACT: keySym = VK_SUBTRACT; break; - case WXK_DECIMAL: keySym = VK_DECIMAL; break; - case WXK_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; - break; - } +#ifdef __WIN32__ + HRGN hRegion = ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle + if ( !hRegion ) + wxLogLastError(wxT("CreateRectRgn")); + if ( ::GetUpdateRgn(GetHwnd(), hRegion, FALSE) == ERROR ) + wxLogLastError(wxT("GetUpdateRgn")); + + m_updateRegion = wxRegion((WXHRGN) hRegion); +#else + RECT updateRect; + ::GetUpdateRect(GetHwnd(), & updateRect, FALSE); + + m_updateRegion = wxRegion(updateRect.left, updateRect.top, + updateRect.right - updateRect.left, + updateRect.bottom - updateRect.top); +#endif + + wxPaintEvent event(m_windowId); + event.SetEventObject(this); + + return GetEventHandler()->ProcessEvent(event); +} + +// Can be called from an application's OnPaint handler +void wxWindow::OnPaint(wxPaintEvent& event) +{ + HDC hDC = (HDC) wxPaintDC::FindDCInCache((wxWindow*) event.GetEventObject()); + if (hDC != 0) + { + MSWDefWindowProc(WM_PAINT, (WPARAM) hDC, 0); } - return keySym; } -// Caret manipulation -void wxWindow::CreateCaret(int w, int h) +bool wxWindow::HandleEraseBkgnd(WXHDC hdc) { - m_caretWidth = w; - m_caretHeight = h; - m_caretEnabled = TRUE; + // Prevents flicker when dragging + if ( ::IsIconic(GetHwnd()) ) + return TRUE; + + wxDC dc; + + dc.SetHDC(hdc); + dc.SetWindow(this); + dc.BeginDrawing(); + + wxEraseEvent event(m_windowId, &dc); + event.SetEventObject(this); + bool rc = GetEventHandler()->ProcessEvent(event); + + dc.EndDrawing(); + dc.SelectOldObjects(hdc); + dc.SetHDC((WXHDC) NULL); + + return rc; } -void wxWindow::CreateCaret(const wxBitmap *WXUNUSED(bitmap)) +void wxWindow::OnEraseBackground(wxEraseEvent& event) { - // Not implemented + RECT rect; + ::GetClientRect(GetHwnd(), &rect); + + COLORREF ref = PALETTERGB(m_backgroundColour.Red(), + m_backgroundColour.Green(), + m_backgroundColour.Blue()); + HBRUSH hBrush = ::CreateSolidBrush(ref); + if ( !hBrush ) + wxLogLastError(wxT("CreateSolidBrush")); + + HDC hdc = (HDC)event.GetDC()->GetHDC(); + + int mode = ::SetMapMode(hdc, MM_TEXT); + + ::FillRect(hdc, &rect, hBrush); + ::DeleteObject(hBrush); + ::SetMapMode(hdc, mode); } -void wxWindow::ShowCaret(bool show) +// --------------------------------------------------------------------------- +// moving and resizing +// --------------------------------------------------------------------------- + +bool wxWindow::HandleMinimize() { - if ( m_caretEnabled ) - { - if ( show ) - ::ShowCaret(GetHwnd()); - else - ::HideCaret(GetHwnd()); - m_caretShown = show; - } + wxIconizeEvent event(m_windowId); + event.SetEventObject(this); + + return GetEventHandler()->ProcessEvent(event); } -void wxWindow::DestroyCaret() +bool wxWindow::HandleMaximize() { - m_caretEnabled = FALSE; + wxMaximizeEvent event(m_windowId); + event.SetEventObject(this); + + return GetEventHandler()->ProcessEvent(event); } -void wxWindow::SetCaretPos(int x, int y) +bool wxWindow::HandleMove(int x, int y) { - ::SetCaretPos(x, y); + wxMoveEvent event(wxPoint(x, y), m_windowId); + event.SetEventObject(this); + + return GetEventHandler()->ProcessEvent(event); } -void wxWindow::GetCaretPos(int *x, int *y) const +bool wxWindow::HandleSize(int w, int h, WXUINT WXUNUSED(flag)) { - POINT point; - ::GetCaretPos(&point); - *x = point.x; - *y = point.y; + wxSizeEvent event(wxSize(w, h), m_windowId); + event.SetEventObject(this); + + return GetEventHandler()->ProcessEvent(event); } -wxWindow *wxGetActiveWindow() +bool wxWindow::HandleGetMinMaxInfo(void *mmInfo) { - HWND hWnd = GetActiveWindow(); - if ( hWnd != 0 ) + MINMAXINFO *info = (MINMAXINFO *)mmInfo; + + bool rc = FALSE; + + if ( m_minWidth != -1 ) { - return wxFindWinFromHandle((WXHWND) hWnd); + info->ptMinTrackSize.x = m_minWidth; + rc = TRUE; } - return NULL; -} -// Windows keyboard hook. Allows interception of e.g. F1, ESCAPE -// in active frames and dialogs, regardless of where the focus is. -static HHOOK wxTheKeyboardHook = 0; -static FARPROC wxTheKeyboardHookProc = 0; -int APIENTRY _EXPORT -wxKeyboardHook(int nCode, WORD wParam, DWORD lParam); + if ( m_minHeight != -1 ) + { + info->ptMinTrackSize.y = m_minHeight; + rc = TRUE; + } -void wxSetKeyboardHook(bool doIt) -{ - if ( doIt ) + if ( m_maxWidth != -1 ) { - 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 + info->ptMaxTrackSize.x = m_maxWidth; + rc = TRUE; } - else + + if ( m_maxHeight != -1 ) { - UnhookWindowsHookEx(wxTheKeyboardHook); - FreeProcInstance(wxTheKeyboardHookProc); + info->ptMaxTrackSize.y = m_maxHeight; + rc = TRUE; } + + return rc; } -int APIENTRY _EXPORT -wxKeyboardHook(int nCode, WORD wParam, DWORD lParam) +// generate an artificial resize event +void wxWindow::SendSizeEvent() { - DWORD hiWord = HIWORD(lParam); - if ( nCode != HC_NOREMOVE && ((hiWord & KF_UP) == 0) ) + RECT r; +#ifdef __WIN16__ + ::GetWindowRect(GetHwnd(), &r); +#else + if ( !::GetWindowRect(GetHwnd(), &r) ) { - int id; - if ( (id = wxCharCodeMSWToWX(wParam)) != 0 ) - { - wxKeyEvent event(wxEVT_CHAR_HOOK); - if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN ) - event.m_altDown = TRUE; + wxLogLastError(_T("GetWindowRect")); + } +#endif - event.m_eventObject = NULL; - event.m_keyCode = id; - /* begin Albert's fix for control and shift key 26.5 */ - event.m_shiftDown = (::GetKeyState(VK_SHIFT)&0x100?TRUE:FALSE); - event.m_controlDown = (::GetKeyState(VK_CONTROL)&0x100?TRUE:FALSE); - /* end Albert's fix for control and shift key 26.5 */ - event.SetTimestamp(wxApp::sm_lastMessageTime); + (void)::PostMessage(GetHwnd(), WM_SIZE, SIZE_RESTORED, + MAKELPARAM(r.right - r.left, r.bottom - r.top)); +} - wxWindow *win = wxGetActiveWindow(); - if ( win ) - { - if ( win->GetEventHandler()->ProcessEvent(event) ) - return 1; - } - else - { - if ( wxTheApp && wxTheApp->ProcessEvent(event) ) - return 1; - } - } +// --------------------------------------------------------------------------- +// command messages +// --------------------------------------------------------------------------- + +bool wxWindow::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control) +{ + if ( wxCurrentPopupMenu ) + { + wxMenu *popupMenu = wxCurrentPopupMenu; + wxCurrentPopupMenu = NULL; + + return popupMenu->MSWCommand(cmd, id); } - return (int)CallNextHookEx(wxTheKeyboardHook, nCode, wParam, lParam); + + wxWindow *win = (wxWindow*) NULL; + if ( cmd == 0 || cmd == 1 ) // menu or accel - use id + { + // must cast to a signed type before comparing with other ids! + win = FindItem((signed short)id); + } + + if (!win && control) + { + // find it from HWND - this works even with the broken programs using + // the same ids for different controls + win = wxFindWinFromHandle(control); + } + + if ( win ) + { + return win->MSWCommand(cmd, id); + } + + // 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 + if ( !control ) + { + // If no child window, it may be an accelerator, e.g. for a popup menu + // command + + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED); + event.SetEventObject(this); + event.SetId(id); + event.SetInt(id); + + return GetEventHandler()->ProcessEvent(event); + } + + return FALSE; } -void wxWindow::WarpPointer (int x_pos, int y_pos) +bool wxWindow::HandleSysCommand(WXWPARAM wParam, WXLPARAM lParam) { - // 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); + // 4 bits are reserved + switch ( wParam & 0xFFFFFFF0 ) + { + case SC_MAXIMIZE: + return HandleMaximize(); - x += rect.left; - y += rect.top; + case SC_MINIMIZE: + return HandleMinimize(); + } - SetCursorPos (x, y); + return FALSE; } -void wxWindow::MSWDeviceToLogical (float *x, float *y) const +// --------------------------------------------------------------------------- +// mouse events +// --------------------------------------------------------------------------- + +void wxWindow::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); + event.m_altDown = (::GetKeyState(VK_MENU) & 0x80000000) != 0; + event.SetTimestamp(s_currentMsg.time); + event.m_eventObject = this; + +#if wxUSE_MOUSEEVENT_HACK + m_lastMouseX = x; + m_lastMouseY = y; + m_lastMouseEvent = event.GetEventType(); +#endif // wxUSE_MOUSEEVENT_HACK + } -bool wxWindow::MSWOnQueryDragIcon(WXHICON * WXUNUSED(hIcon)) +bool wxWindow::HandleMouseEvent(WXUINT msg, int x, int y, WXUINT flags) { - return FALSE; + // the mouse events take consecutive IDs from WM_MOUSEFIRST to + // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST + // from the message id and take the value in the table to get wxWin event + // id + static const wxEventType eventsMouse[] = + { + wxEVT_MOTION, + wxEVT_LEFT_DOWN, + wxEVT_LEFT_UP, + wxEVT_LEFT_DCLICK, + wxEVT_RIGHT_DOWN, + wxEVT_RIGHT_UP, + wxEVT_RIGHT_DCLICK, + wxEVT_MIDDLE_DOWN, + wxEVT_MIDDLE_UP, + wxEVT_MIDDLE_DCLICK + }; + + wxMouseEvent event(eventsMouse[msg - WM_MOUSEMOVE]); + InitMouseEvent(event, x, y, flags); + + return GetEventHandler()->ProcessEvent(event); } -bool wxWindow::MSWOnEraseBkgnd(WXHDC hdc) +bool wxWindow::HandleMouseMove(int x, int y, WXUINT flags) { - wxDC dc; + if ( !m_mouseInWindow ) + { + // Generate an ENTER event + m_mouseInWindow = TRUE; - dc.SetHDC(hdc); - dc.SetWindow(this); - dc.BeginDrawing(); + wxMouseEvent event(wxEVT_ENTER_WINDOW); + InitMouseEvent(event, x, y, flags); - wxEraseEvent event(m_windowId, &dc); - event.m_eventObject = this; - bool rc = GetEventHandler()->ProcessEvent(event); + (void)GetEventHandler()->ProcessEvent(event); + } - dc.EndDrawing(); - dc.SelectOldObjects(hdc); - dc.SetHDC((WXHDC) NULL); +#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 == event.m_x && m_lastMouseY == event.m_y) ) + { + m_lastMouseEvent = wxEVT_MOTION; - return rc; + return FALSE; + } +#endif // wxUSE_MOUSEEVENT_HACK + + return HandleMouseEvent(WM_MOUSEMOVE, x, y, flags); } -void wxWindow::OnEraseBackground(wxEraseEvent& event) +// --------------------------------------------------------------------------- +// keyboard handling +// --------------------------------------------------------------------------- + +// create the key event of the given type for the given key - used by +// HandleChar and HandleKeyDown/Up +wxKeyEvent wxWindow::CreateKeyEvent(wxEventType evType, + int id, + WXLPARAM lParam) const { - if ( !GetHWND() ) - return; + wxKeyEvent event(evType); + event.SetId(GetId()); + event.m_shiftDown = wxIsShiftDown(); + event.m_controlDown = wxIsCtrlDown(); + event.m_altDown = (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN; + + event.m_eventObject = (wxWindow *)this; // const_cast + event.m_keyCode = id; + event.SetTimestamp(s_currentMsg.time); + // translate the position to client coords + POINT pt; + GetCursorPos(&pt); RECT rect; - ::GetClientRect(GetHwnd(), &rect); - - COLORREF ref = PALETTERGB(m_backgroundColour.Red(), m_backgroundColour.Green(), m_backgroundColour.Blue()) ; - HBRUSH hBrush = ::CreateSolidBrush(ref); - int mode = ::SetMapMode((HDC) event.GetDC()->GetHDC(), MM_TEXT); + GetWindowRect(GetHwnd(),&rect); + pt.x -= rect.left; + pt.y -= rect.top; - // ::GetClipBox((HDC) event.GetDC()->GetHDC(), &rect); - ::FillRect ((HDC) event.GetDC()->GetHDC(), &rect, hBrush); - ::DeleteObject(hBrush); - ::SetMapMode((HDC) event.GetDC()->GetHDC(), mode); - /* - // Less efficient version (and doesn't account for scrolling) - int w, h; - GetClientSize(& w, & h); - wxBrush *brush = wxTheBrushList->FindOrCreateBrush(& GetBackgroundColour(), wxSOLID); - event.GetDC()->SetBrush(brush); - event.GetDC()->SetPen(wxTRANSPARENT_PEN); + event.m_x = pt.x; + event.m_y = pt.y; - event.GetDC()->DrawRectangle(0, 0, w+1, h+1); - */ + return event; } -#if WXWIN_COMPATIBILITY -void wxWindow::SetScrollRange(int orient, int range, bool refresh) +// isASCII is TRUE only when we're called from WM_CHAR handler and not from +// WM_KEYDOWN one +bool wxWindow::HandleChar(WXWORD wParam, WXLPARAM lParam, bool isASCII) { -#if defined(__WIN95__) - - int range1 = range; + bool ctrlDown = FALSE; - // Try to adjust the range to cope with page size > 1 - // - a Windows API quirk - int pageSize = GetScrollPage(orient); - if ( pageSize > 1 && range > 0) + int id; + if ( isASCII ) { - range1 += (pageSize - 1); - } + // If 1 -> 26, translate to CTRL plus a letter. + id = wParam; + if ( (id > 0) && (id < 27) ) + { + switch (id) + { + case 13: + id = WXK_RETURN; + break; - SCROLLINFO info; - int dir; + case 8: + id = WXK_BACK; + break; - if ( orient == wxHORIZONTAL ) { - dir = SB_HORZ; - } else { - dir = SB_VERT; + case 9: + id = WXK_TAB; + break; + + default: + ctrlDown = TRUE; + id = id + 96; + } + } + } + else if ( (id = wxCharCodeMSWToWX(wParam)) == 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 + id = -1; } - 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; + if ( id != -1 ) + { + wxKeyEvent event(CreateKeyEvent(wxEVT_CHAR, id, lParam)); + if ( ctrlDown ) + { + event.m_controlDown = TRUE; + } - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::SetScrollInfo(hWnd, dir, &info, refresh); -#else - int wOrient ; - if ( orient == wxHORIZONTAL ) - wOrient = SB_HORZ; - else - wOrient = SB_VERT; + if ( GetEventHandler()->ProcessEvent(event) ) + return TRUE; + } - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::SetScrollRange(hWnd, wOrient, 0, range, refresh); -#endif + return FALSE; } -void wxWindow::SetScrollPage(int orient, int page, bool refresh) +bool wxWindow::HandleKeyDown(WXWORD wParam, WXLPARAM lParam) { -#if defined(__WIN95__) - SCROLLINFO info; - int dir; + int id = wxCharCodeMSWToWX(wParam); - if ( orient == wxHORIZONTAL ) { - dir = SB_HORZ; - m_xThumbSize = page; - } else { - dir = SB_VERT; - m_yThumbSize = page; + if ( !id ) + { + // normal ASCII char + id = wParam; } - 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 wxWindow::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 ( id != -1 ) // VZ: does this ever happen (FIXME)? { - ::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 ) + wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam)); + if ( GetEventHandler()->ProcessEvent(event) ) { - maxPos -= (pageSize - 1); + return TRUE; } -#endif - return maxPos; } - else - return 0; -} -int wxWindow::GetScrollPage(int orient) const -{ - if ( orient == wxHORIZONTAL ) - return m_xThumbSize; - else - return m_yThumbSize; + return FALSE; } -#endif -int wxWindow::GetScrollPos(int orient) const +bool wxWindow::HandleKeyUp(WXWORD wParam, WXLPARAM lParam) { - int wOrient ; - if ( orient == wxHORIZONTAL ) - wOrient = SB_HORZ; - else - wOrient = SB_VERT; - HWND hWnd = GetHwnd(); - if ( hWnd ) + int id = wxCharCodeMSWToWX(wParam); + + if ( !id ) { - return ::GetScrollPos(hWnd, wOrient); + // normal ASCII char + id = wParam; } - else - return 0; -} - -// This now returns the whole range, not just the number -// of positions that we can scroll. -int wxWindow::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 - HWND hWnd = GetHwnd(); - if ( hWnd ) + if ( id != -1 ) // VZ: does this ever happen (FIXME)? { - ::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; -#endif - - return maxPos; + wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam)); + if ( GetEventHandler()->ProcessEvent(event) ) + return TRUE; } - else - return 0; -} -int wxWindow::GetScrollThumb(int orient) const -{ - if ( orient == wxHORIZONTAL ) - return m_xThumbSize; - else - return m_yThumbSize; + return FALSE; } -void wxWindow::SetScrollPos(int orient, int pos, bool refresh) +// --------------------------------------------------------------------------- +// joystick +// --------------------------------------------------------------------------- + +bool wxWindow::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) { -#if defined(__WIN95__) - SCROLLINFO info; - int dir; + int change = 0; + if ( flags & JOY_BUTTON1CHG ) + change = wxJOY_BUTTON1; + if ( flags & JOY_BUTTON2CHG ) + change = wxJOY_BUTTON2; + if ( flags & JOY_BUTTON3CHG ) + change = wxJOY_BUTTON3; + if ( flags & JOY_BUTTON4CHG ) + change = wxJOY_BUTTON4; - if ( orient == wxHORIZONTAL ) { - dir = SB_HORZ; - } else { - dir = SB_VERT; - } + int buttons = 0; + if ( flags & JOY_BUTTON1 ) + buttons |= wxJOY_BUTTON1; + if ( flags & JOY_BUTTON2 ) + buttons |= wxJOY_BUTTON2; + if ( flags & JOY_BUTTON3 ) + buttons |= wxJOY_BUTTON3; + if ( flags & JOY_BUTTON4 ) + buttons |= wxJOY_BUTTON4; - info.cbSize = sizeof(SCROLLINFO); - info.nPage = 0; - info.nMin = 0; - info.nPos = pos; - info.fMask = SIF_POS ; + // the event ids aren't consecutive so we can't use table based lookup + int joystick; + wxEventType eventType; + switch ( msg ) + { + case MM_JOY1MOVE: + joystick = 1; + eventType = wxEVT_JOY_MOVE; + break; - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::SetScrollInfo(hWnd, dir, &info, refresh); -#else - int wOrient ; - if ( orient == wxHORIZONTAL ) - wOrient = SB_HORZ; - else - wOrient = SB_VERT; + case MM_JOY2MOVE: + joystick = 2; + eventType = wxEVT_JOY_MOVE; + break; - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::SetScrollPos(hWnd, wOrient, pos, refresh); -#endif -} + case MM_JOY1ZMOVE: + joystick = 1; + eventType = wxEVT_JOY_ZMOVE; + break; -// New function that will replace some of the above. -void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible, - int range, bool refresh) -{ -/* -SetScrollPage(orient, thumbVisible, FALSE); + case MM_JOY2ZMOVE: + joystick = 2; + eventType = wxEVT_JOY_ZMOVE; + break; - int oldRange = range - thumbVisible ; - SetScrollRange(orient, oldRange, FALSE); + case MM_JOY1BUTTONDOWN: + joystick = 1; + eventType = wxEVT_JOY_BUTTON_DOWN; + break; - SetScrollPos(orient, pos, refresh); - */ -#if defined(__WIN95__) - int oldRange = range - thumbVisible ; + case MM_JOY2BUTTONDOWN: + joystick = 2; + eventType = wxEVT_JOY_BUTTON_DOWN; + break; - int range1 = oldRange; + case MM_JOY1BUTTONUP: + joystick = 1; + eventType = wxEVT_JOY_BUTTON_UP; + break; - // Try to adjust the range to cope with page size > 1 - // - a Windows API quirk - int pageSize = thumbVisible; - if ( pageSize > 1 && range > 0) - { - range1 += (pageSize - 1); - } + case MM_JOY2BUTTONUP: + joystick = 2; + eventType = wxEVT_JOY_BUTTON_UP; + break; - SCROLLINFO info; - int dir; + default: + wxFAIL_MSG(wxT("no such joystick event")); - if ( orient == wxHORIZONTAL ) { - dir = SB_HORZ; - } else { - dir = SB_VERT; + return FALSE; } - info.cbSize = sizeof(SCROLLINFO); - info.nPage = pageSize; // Have to set this, or scrollbar goes awry - info.nMin = 0; - info.nMax = range1; - 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; + wxJoystickEvent event(eventType, buttons, joystick, change); + event.SetPosition(wxPoint(x, y)); + event.SetEventObject(this); - 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; - } + return GetEventHandler()->ProcessEvent(event); } -void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect) +// --------------------------------------------------------------------------- +// scrolling +// --------------------------------------------------------------------------- + +bool wxWindow::MSWOnScroll(int orientation, WXWORD wParam, + WXWORD pos, WXHWND control) { - RECT rect2; - if ( rect ) + if ( control ) { - rect2.left = rect->x; - rect2.top = rect->y; - rect2.right = rect->x + rect->width; - rect2.bottom = rect->y + rect->height; + wxWindow *child = wxFindWinFromHandle(control); + if ( child ) + return child->MSWOnScroll(orientation, wParam, pos, control); } - if ( rect ) - ::ScrollWindow(GetHwnd(), dx, dy, &rect2, NULL); - else - ::ScrollWindow(GetHwnd(), dx, dy, NULL, NULL); -} + wxScrollWinEvent event; + event.SetPosition(pos); + event.SetOrientation(orientation); + event.m_eventObject = this; -bool wxWindow::SetFont(const wxFont& font) -{ - if ( !wxWindowBase::SetFont(font) ) + switch ( wParam ) { - // nothing to do - return FALSE; - } + case SB_TOP: + event.m_eventType = wxEVT_SCROLLWIN_TOP; + break; - HWND hWnd = GetHwnd(); - if ( hWnd != 0 ) - { - WXHANDLE hFont = m_font.GetResourceHandle(); + case SB_BOTTOM: + event.m_eventType = wxEVT_SCROLLWIN_BOTTOM; + break; - wxASSERT_MSG( hFont, _T("should have valid font") ); + case SB_LINEUP: + event.m_eventType = wxEVT_SCROLLWIN_LINEUP; + break; - ::SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, TRUE); - } + case SB_LINEDOWN: + event.m_eventType = wxEVT_SCROLLWIN_LINEDOWN; + break; - return TRUE; -} + case SB_PAGEUP: + event.m_eventType = wxEVT_SCROLLWIN_PAGEUP; + break; -void wxWindow::SubclassWin(WXHWND hWnd) -{ - wxASSERT_MSG( !m_oldWndProc, "subclassing window twice?" ); + case SB_PAGEDOWN: + event.m_eventType = wxEVT_SCROLLWIN_PAGEDOWN; + break; - wxAssociateWinWithHandle((HWND)hWnd, this); + 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); + scrollInfo.fMask = SIF_TRACKPOS; + + if ( !::GetScrollInfo(GetHwnd(), + orientation == wxHORIZONTAL ? SB_HORZ + : SB_VERT, + &scrollInfo) ) + { + wxLogLastError(_T("GetScrollInfo")); + } - m_oldWndProc = (WXFARPROC) GetWindowLong((HWND) hWnd, GWL_WNDPROC); - SetWindowLong((HWND) hWnd, GWL_WNDPROC, (LONG) wxWndProc); -} + event.SetPosition(scrollInfo.nTrackPos); + } +#endif // Win32 -void wxWindow::UnsubclassWin() -{ - wxRemoveHandleAssociation(this); + event.m_eventType = wParam == SB_THUMBPOSITION + ? wxEVT_SCROLLWIN_THUMBRELEASE + : wxEVT_SCROLLWIN_THUMBTRACK; + break; - // Restore old Window proc - if ( GetHwnd() ) - { - FARPROC farProc = (FARPROC) GetWindowLong(GetHwnd(), GWL_WNDPROC); - if ( (m_oldWndProc != 0) && (farProc != (FARPROC) m_oldWndProc) ) - { - SetWindowLong(GetHwnd(), GWL_WNDPROC, (LONG) m_oldWndProc); - m_oldWndProc = 0; - } + default: + return FALSE; } + + return GetEventHandler()->ProcessEvent(event); } -// Make a Windows extended style from the given wxWindows window style -WXDWORD wxWindow::MakeExtendedStyle(long style, bool eliminateBorders) -{ - WXDWORD exStyle = 0; - if ( style & wxTRANSPARENT_WINDOW ) - exStyle |= WS_EX_TRANSPARENT ; +// =========================================================================== +// global functions +// =========================================================================== - if ( !eliminateBorders ) +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 ) { - if ( style & wxSUNKEN_BORDER ) - exStyle |= WS_EX_CLIENTEDGE ; - if ( style & wxDOUBLE_BORDER ) - exStyle |= WS_EX_DLGMODALFRAME ; -#if defined(__WIN95__) - if ( style & wxRAISED_BORDER ) - exStyle |= WS_EX_WINDOWEDGE ; - if ( style & wxSTATIC_BORDER ) - exStyle |= WS_EX_STATICEDGE ; -#endif + // the_font->UseResource(); + // the_font->RealizeResource(); + fnt = (HFONT)((wxFont *)the_font)->GetResourceHandle(); // const_cast + if ( fnt ) + was = (HFONT) SelectObject(dc,fnt); } - 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 wxWindow::Determine3DEffects(WXDWORD defaultBorderStyle, bool *want3D) -{ - // 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) ) + GetTextMetrics(dc, &tm); + if ( the_font && fnt && was ) { - *want3D = FALSE; - return MakeExtendedStyle(m_windowStyle, FALSE); + SelectObject(dc,was); } + ReleaseDC((HWND)wnd, dc); - // Determine whether we should be using 3D effects or not. - bool nativeBorder = FALSE; // by default, we don't want a Win95 effect + if ( x ) + *x = tm.tmAveCharWidth; + if ( y ) + *y = tm.tmHeight + tm.tmExternalLeading; - // 1) App can specify global 3D effects - *want3D = wxTheApp->GetAuto3D(); + // if ( the_font ) + // the_font->ReleaseResource(); +} - // 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; +// 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 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_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_MULTIPLY; break; + case 0xBB: // VK_OEM_PLUS + case VK_ADD: id = WXK_ADD; break; + case 0xBD: // VK_OEM_MINUS + case VK_SUBTRACT: id = WXK_SUBTRACT; break; + case 0xBE: // VK_OEM_PERIOD + case VK_DECIMAL: id = WXK_DECIMAL; break; + case VK_DIVIDE: id = WXK_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; + default: + id = 0; + } - // 3) Control can override this global setting by defining - // a border style, e.g. wxSUNKEN_BORDER - if ( m_windowStyle & wxSUNKEN_BORDER ) - *want3D = TRUE; + return id; +} - // 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) ) +int wxCharCodeWXToMSW(int id, bool *isVirtual) +{ + *isVirtual = TRUE; + int keySym = 0; + switch (id) { - *want3D = TRUE; - nativeBorder = TRUE; + 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_MULTIPLY: keySym = VK_MULTIPLY; break; + case WXK_ADD: keySym = VK_ADD; break; + case WXK_SUBTRACT: keySym = VK_SUBTRACT; break; + case WXK_DECIMAL: keySym = VK_DECIMAL; break; + case WXK_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; + break; + } } - - // 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; + return keySym; } -// Get the window with the focus -wxWindow *wxWindowBase::FindFocus() +wxWindow *wxGetActiveWindow() { - HWND hWnd = ::GetFocus(); - if ( hWnd ) + HWND hWnd = GetActiveWindow(); + if ( hWnd != 0 ) { return wxFindWinFromHandle((WXHWND) hWnd); } return NULL; } -// 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) +extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd) { - if ( GetEventHandler()->ProcessEvent(event) ) - return; - if ( m_parent ) - m_parent->GetEventHandler()->OnCommand(win, event); -} + HWND hwnd = (HWND)hWnd; -wxObject* wxWindow::GetChild(int number) const -{ - // Return a pointer to the Nth object in the Panel -// if ( !GetChildren() ) -// return(NULL) ; - wxNode *node = GetChildren().First(); - int n = number; - while (node && n--) - node = node->Next() ; - if ( node ) + // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set + // by code in msw/radiobox.cpp), for all the others we just search up the + // window hierarchy + wxWindow *win = (wxWindow *)NULL; + if ( hwnd ) { - wxObject *obj = (wxObject *)node->Data(); - return(obj) ; + win = wxFindWinFromHandle((WXHWND)hwnd); + if ( !win ) + { + // the radiobox pointer is stored in GWL_USERDATA only under Win32 +#ifdef __WIN32__ + // 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)hwnd, WM_GETDLGCODE, + 0, 0) & DLGC_RADIOBUTTON ) + { + win = (wxWindow *)::GetWindowLong(hwnd, GWL_USERDATA); + } + else +#endif // Win32 + { + // hwnd is not a wxWindow, try its parent next below + hwnd = ::GetParent(hwnd); + } + } + //else: it's a wxRadioButton, not a radiobutton from wxRadioBox } - else - return NULL ; -} -void wxWindow::OnDefaultAction(wxControl *initiatingItem) -{ -/* This is obsolete now; if we wish to intercept listbox double-clicks, -* we explicitly intercept the wxEVT_COMMAND_LISTBOX_DOUBLECLICKED -* event. - - if ( initiatingItem->IsKindOf(CLASSINFO(wxListBox)) ) - { - wxListBox *lbox = (wxListBox *)initiatingItem; - wxCommandEvent event(wxEVT_COMMAND_LEFT_DCLICK); - event.m_commandInt = -1; - if ( (lbox->GetWindowStyleFlag() & wxLB_MULTIPLE) == 0 ) - { - event.m_commandString = copystring(lbox->GetStringSelection()); - event.m_commandInt = lbox->GetSelection(); - event.m_clientData = lbox->wxListBox::GetClientData(event.m_commandInt); - } - event.m_eventObject = lbox; - - lbox->ProcessCommand(event); - - if ( event.m_commandString ) - delete[] event.m_commandString; - return; - } + while ( hwnd && !win ) + { + win = wxFindWinFromHandle((WXHWND)hwnd); + hwnd = ::GetParent(hwnd); + } - wxButton *but = GetDefaultItem(); - if ( but ) - { - wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED); - event.SetEventObject(but); - but->Command(event); - } - */ + return win; } -void wxWindow::Clear() -{ - wxClientDC dc(this); - wxBrush brush(GetBackgroundColour(), wxSOLID); - dc.SetBackground(brush); - dc.Clear(); -} +// Windows keyboard hook. Allows interception of e.g. F1, ESCAPE +// in active frames and dialogs, regardless of where the focus is. +static HHOOK wxTheKeyboardHook = 0; +static FARPROC wxTheKeyboardHookProc = 0; +int APIENTRY _EXPORT +wxKeyboardHook(int nCode, WORD wParam, DWORD lParam); -/* TODO -// Default input behaviour for a scrolling canvas should be to scroll -// according to the cursor keys pressed -void wxWindow::OnChar(wxKeyEvent& event) -{ -int x_page = 0; -int y_page = 0; -int start_x = 0; -int start_y = 0; -// Bugfix Begin -int v_width = 0; -int v_height = 0; -int y_pages = 0; -// Bugfix End - - GetScrollUnitsPerPage(&x_page, &y_page); - // Bugfix Begin - GetVirtualSize(&v_width,&v_height); - // Bugfix End - ViewStart(&start_x, &start_y); - // Bugfix begin - if ( vert_units ) - y_pages = (int)(v_height/vert_units) - y_page; - - #ifdef __WXMSW__ - int y = 0; - #else - int y = y_page-1; - #endif - // Bugfix End - switch (event.keyCode) - { - case WXK_PRIOR: - { - // BugFix Begin - if ( y_page > 0 ) +void wxSetKeyboardHook(bool doIt) +{ + if ( doIt ) { - if ( start_y - y_page > 0 ) - Scroll(start_x, start_y - y_page); - else - Scroll(start_x, 0); - } - // Bugfix End - break; + 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 + ); } - case WXK_NEXT: - { - // Bugfix Begin - if ( (y_page > 0) && (start_y <= y_pages-y-1) ) - { - if ( y_pages + y < start_y + y_page ) - Scroll(start_x, y_pages + y); else - Scroll(start_x, start_y + y_page); - } - // Bugfix End - break; - } - case WXK_UP: - { - if ( (y_page > 0) && (start_y >= 1) ) - Scroll(start_x, start_y - 1); - break; - } - case WXK_DOWN: - { - // Bugfix Begin - if ( (y_page > 0) && (start_y <= y_pages-y-1) ) - // Bugfix End - { - Scroll(start_x, start_y + 1); - } - break; - } - case WXK_LEFT: - { - if ( (x_page > 0) && (start_x >= 1) ) - Scroll(start_x - 1, start_y); - break; - } - case WXK_RIGHT: - { - if ( x_page > 0 ) - Scroll(start_x + 1, start_y); - break; - } - case WXK_HOME: - { - Scroll(0, 0); - break; - } - // This is new - case WXK_END: { - Scroll(start_x, y_pages+y); - break; - } - // end - } + UnhookWindowsHookEx(wxTheKeyboardHook); + // avoids mingw warning about statement with no effect (FreeProcInstance + // doesn't do anything under Win32) +#ifndef __GNUC__ + FreeProcInstance(wxTheKeyboardHookProc); +#endif } -*/ - -// Setup background and foreground colours correctly -void wxWindow::SetupColours() -{ - if ( GetParent() ) - SetBackgroundColour(GetParent()->GetBackgroundColour()); } -void wxWindow::OnIdle(wxIdleEvent& event) +int APIENTRY _EXPORT +wxKeyboardHook(int nCode, WORD wParam, DWORD lParam) { - // Check if we need to send a LEAVE event - if ( m_mouseInWindow ) + DWORD hiWord = HIWORD(lParam); + if ( nCode != HC_NOREMOVE && ((hiWord & KF_UP) == 0) ) { - POINT pt; - ::GetCursorPos(&pt); - if ( ::WindowFromPoint(pt) != GetHwnd() ) + int id = wxCharCodeMSWToWX(wParam); + if ( id != 0 ) { - // Generate a LEAVE event - m_mouseInWindow = FALSE; + wxKeyEvent event(wxEVT_CHAR_HOOK); + if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN ) + event.m_altDown = TRUE; - // 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 ( ::GetKeyState(VK_SHIFT) != 0 ) - state |= MK_SHIFT; - if ( ::GetKeyState(VK_CONTROL) != 0 ) - state |= MK_CONTROL; + event.m_eventObject = NULL; + event.m_keyCode = id; + event.m_shiftDown = wxIsShiftDown(); + event.m_controlDown = wxIsCtrlDown(); + event.SetTimestamp(s_currentMsg.time); - wxMouseEvent event(wxEVT_LEAVE_WINDOW); - InitMouseEvent(event, pt.x, pt.y, state); + wxWindow *win = wxGetActiveWindow(); + wxEvtHandler *handler; + if ( win ) + { + handler = win->GetEventHandler(); + event.SetId(win->GetId()); + } + else + { + handler = wxTheApp; + event.SetId(-1); + } - (void)GetEventHandler()->ProcessEvent(event); + if ( handler && handler->ProcessEvent(event) ) + { + // processed + return 1; + } } } - UpdateWindowUI(); -} - -// Raise the window to the top of the Z order -void wxWindow::Raise() -{ - ::BringWindowToTop(GetHwnd()); -} - -// Lower the window to the bottom of the Z order -void wxWindow::Lower() -{ - ::SetWindowPos(GetHwnd(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); -} - -// Set this window to be the child of 'parent'. -bool wxWindow::Reparent(wxWindow *parent) -{ - if ( !wxWindowBase::Reparent(parent) ) - return FALSE; - - HWND hWndChild = GetHwnd(); - HWND hWndParent = GetParent() ? GetWinHwnd(GetParent()) : (HWND)0; - - ::SetParent(hWndChild, hWndParent); - - return TRUE; + return (int)CallNextHookEx(wxTheKeyboardHook, nCode, wParam, lParam); } #ifdef __WXDEBUG__ const char *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"; + 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"; + 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"; + 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"; + 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 0x0210: return "WM_PARENTNOTIFY"; - case 0x0211: return "WM_ENTERMENULOOP"; - case 0x0212: return "WM_EXITMENULOOP"; + 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 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"; + 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"; + 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"; + 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 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"; #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 "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"; // 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 "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"; // 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 "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"; // 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 "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"; // 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"; + 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 - default: - static char s_szBuf[128]; - sprintf(s_szBuf, "", message); - return s_szBuf; - } + default: + static char s_szBuf[128]; + sprintf(s_szBuf, "", message); + return s_szBuf; + } } #endif //__WXDEBUG__ + +static void TranslateKbdEventToMouse(wxWindow *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 wxWindow *win) +{ + // prepare the DC + TEXTMETRIC tm; + HWND hwnd = GetHwndOf(win); + HDC hdc = ::GetDC(hwnd); + +#if !wxDIALOG_UNIT_COMPATIBILITY + // and select the current font into it + HFONT hfont = GetHfontOf(win->GetFont()); + if ( hfont ) + { + hfont = (HFONT)::SelectObject(hdc, hfont); + } +#endif + + // finally retrieve the text metrics from it + GetTextMetrics(hdc, &tm); + +#if !wxDIALOG_UNIT_COMPATIBILITY + // and clean up + if ( hfont ) + { + (void)::SelectObject(hdc, hfont); + } +#endif + + ::ReleaseDC(hwnd, hdc); + + return tm; +} + +// Find the wxWindow at the current mouse position, returning the mouse +// position. +wxWindow* wxFindWindowAtPointer(wxPoint& pt) +{ + return wxFindWindowAtPoint(wxGetMousePosition()); +} + +wxWindow* wxFindWindowAtPoint(const wxPoint& pt) +{ + POINT pt2; + pt2.x = pt.x; + pt2.y = pt.y; + HWND hWndHit = ::WindowFromPoint(pt2); + + wxWindow* win = wxFindWinFromHandle((WXHWND) hWndHit) ; + HWND hWnd = hWndHit; + + // Try to find a window with a wxWindow associated with it + while (!win && (hWnd != 0)) + { + hWnd = ::GetParent(hWnd); + win = wxFindWinFromHandle((WXHWND) hWnd) ; + } + return win; +} + +// Get the current mouse position. +wxPoint wxGetMousePosition() +{ + POINT pt; + GetCursorPos( & pt ); + return wxPoint(pt.x, pt.y); +} +