+ UpdateWindowUI();
+}
+
+// Set this window to be the child of 'parent'.
+bool wxWindowMSW::Reparent(wxWindowBase *parent)
+{
+ if ( !wxWindowBase::Reparent(parent) )
+ return FALSE;
+
+ HWND hWndChild = GetHwnd();
+ HWND hWndParent = GetParent() ? GetWinHwnd(GetParent()) : (HWND)0;
+
+ ::SetParent(hWndChild, hWndParent);
+
+ return TRUE;
+}
+
+void wxWindowMSW::Clear()
+{
+ wxClientDC dc((wxWindow *)this);
+ wxBrush brush(GetBackgroundColour(), wxSOLID);
+ dc.SetBackground(brush);
+ dc.Clear();
+}
+
+void wxWindowMSW::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);
+ }
+}
+
+void wxWindowMSW::Update()
+{
+ if ( !::UpdateWindow(GetHwnd()) )
+ {
+ wxLogLastError(_T("UpdateWindow"));
+ }
+
+#if defined(__WIN32__) && !defined(__WXMICROWIN__)
+ // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
+ // handler needs to be really drawn right now
+ (void)::GdiFlush();
+#endif // __WIN32__
+}
+
+// ---------------------------------------------------------------------------
+// drag and drop
+// ---------------------------------------------------------------------------
+
+#if wxUSE_DRAG_AND_DROP
+
+void wxWindowMSW::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 wxWindowMSW::DragAcceptFiles(bool accept)
+{
+ HWND hWnd = GetHwnd();
+ if ( hWnd )
+ ::DragAcceptFiles(hWnd, (BOOL)accept);
+}
+
+// ----------------------------------------------------------------------------
+// tooltips
+// ----------------------------------------------------------------------------
+
+#if wxUSE_TOOLTIPS
+
+void wxWindowMSW::DoSetToolTip(wxToolTip *tooltip)
+{
+ wxWindowBase::DoSetToolTip(tooltip);
+
+ if ( m_tooltip )
+ m_tooltip->SetWindow(this);
+}
+
+#endif // wxUSE_TOOLTIPS
+
+// ---------------------------------------------------------------------------
+// moving and resizing
+// ---------------------------------------------------------------------------
+
+// Get total size
+void wxWindowMSW::DoGetSize(int *x, int *y) const
+{
+ HWND hWnd = GetHwnd();
+ RECT rect;
+#ifdef __WIN16__
+ ::GetWindowRect(hWnd, &rect);
+#else
+ if ( !::GetWindowRect(hWnd, &rect) )
+ {
+ wxLogLastError(_T("GetWindowRect"));
+ }
+#endif
+ if ( x )
+ *x = rect.right - rect.left;
+ if ( y )
+ *y = rect.bottom - rect.top;
+}
+
+void wxWindowMSW::DoGetPosition(int *x, int *y) const
+{
+ HWND hWnd = GetHwnd();
+
+ RECT rect;
+ GetWindowRect(hWnd, &rect);
+
+ POINT point;
+ point.x = rect.left;
+ point.y = rect.top;
+
+ // 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);
+ }
+
+ if ( parent )
+ {
+ // We may be faking the client origin. So a window that's really at (0,
+ // 30) may appear (to wxWin apps) to be at (0, 0).
+ wxPoint pt(parent->GetClientAreaOrigin());
+ point.x -= pt.x;
+ point.y -= pt.y;
+ }
+ }
+
+ if ( x )
+ *x = point.x;
+ if ( y )
+ *y = point.y;
+}
+
+void wxWindowMSW::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 wxWindowMSW::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 wxWindowMSW::DoGetClientSize(int *x, int *y) const
+{
+ HWND hWnd = GetHwnd();
+ RECT rect;
+ ::GetClientRect(hWnd, &rect);
+ if ( x )
+ *x = rect.right;
+ if ( y )
+ *y = rect.bottom;
+}
+
+void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
+{
+ if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) )
+ {
+ 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 wxWindowMSW::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 )
+ {
+ size = DoGetBestSize();
+ }
+ //else: already called DoGetBestSize() above
+
+ height = size.y;
+ }
+ else
+ {
+ // just take the current one
+ height = currentH;
+ }
+ }
+
+ DoMoveWindow(x, y, width, height);
+}
+
+void wxWindowMSW::DoSetClientSize(int width, int height)
+{
+ 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
+
+ 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 wxWindowMSW::GetClientAreaOrigin() const
+{
+ return wxPoint(0, 0);
+}
+
+// Makes an adjustment to the window position (for example, a frame that has
+// a toolbar that it manages itself).
+void wxWindowMSW::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
+{
+ // don't do it for the dialogs/frames - they float independently of their
+ // parent
+ if ( !IsTopLevel() )
+ {
+ wxWindow *parent = GetParent();
+ if ( !(sizeFlags & wxSIZE_NO_ADJUSTMENTS) && parent )
+ {
+ wxPoint pt(parent->GetClientAreaOrigin());
+ x += pt.x;
+ y += pt.y;
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------
+// text metrics
+// ---------------------------------------------------------------------------
+
+int wxWindowMSW::GetCharHeight() const
+{
+ return wxGetTextMetrics(this).tmHeight;
+}
+
+int wxWindowMSW::GetCharWidth() const
+{
+ // +1 is needed because Windows apparently adds it when calculating the
+ // dialog units size in pixels
+#if wxDIALOG_UNIT_COMPATIBILITY
+ return wxGetTextMetrics(this).tmAveCharWidth;
+#else
+ return wxGetTextMetrics(this).tmAveCharWidth + 1;
+#endif
+}
+
+void wxWindowMSW::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;
+
+ HWND hWnd = GetHwnd();
+ HDC dc = ::GetDC(hWnd);
+
+ HFONT fnt = 0;
+ HFONT hfontOld = 0;
+ if ( fontToUse && fontToUse->Ok() )
+ {
+ fnt = (HFONT)((wxFont *)fontToUse)->GetResourceHandle(); // const_cast
+ if ( fnt )
+ hfontOld = (HFONT)SelectObject(dc,fnt);
+ }
+
+ 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 wxWindowMSW::CreateCaret(int w, int h)
+{
+ SetCaret(new wxCaret(this, w, h));
+}
+
+void wxWindowMSW::CreateCaret(const wxBitmap *WXUNUSED(bitmap))
+{
+ wxFAIL_MSG("not implemented");
+}
+
+void wxWindowMSW::ShowCaret(bool show)
+{
+ wxCHECK_RET( m_caret, "no caret to show" );
+
+ m_caret->Show(show);
+}
+
+void wxWindowMSW::DestroyCaret()
+{
+ SetCaret(NULL);
+}
+
+void wxWindowMSW::SetCaretPos(int x, int y)
+{
+ wxCHECK_RET( m_caret, "no caret to move" );
+
+ m_caret->Move(x, y);
+}
+
+void wxWindowMSW::GetCaretPos(int *x, int *y) const
+{
+ wxCHECK_RET( m_caret, "no caret to get position of" );
+
+ m_caret->GetPosition(x, y);
+}
+#endif // wxUSE_CARET
+
+// ---------------------------------------------------------------------------
+// popup menu
+// ---------------------------------------------------------------------------
+
+// yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
+// immediately, without waiting for the next event loop iteration
+//
+// NB: this function should probably be made public later as it can almost
+// surely replace wxYield() elsewhere as well
+static void wxYieldForCommandsOnly()
+{
+ // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
+ // want to process it here)
+ MSG msg;
+ while ( ::PeekMessage(&msg, (HWND)0, WM_COMMAND, WM_COMMAND, PM_REMOVE)
+ && msg.message != WM_QUIT )
+ {
+ wxTheApp->DoMessage((WXMSG *)&msg);
+ }
+}
+
+#if wxUSE_MENUS_NATIVE
+
+bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y)
+{
+ menu->SetInvokingWindow(this);
+ menu->UpdateUI();
+
+ 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);
+
+ // we need to do it righ now as otherwise the events are never going to be
+ // sent to wxCurrentPopupMenu from HandleCommand()
+ //
+ // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
+ // help and we'd still need wxYieldForCommandsOnly() as the menu may be
+ // destroyed as soon as we return (it can be a local variable in the caller
+ // for example) and so we do need to process the event immediately
+ wxYieldForCommandsOnly();
+
+ wxCurrentPopupMenu = NULL;
+
+ menu->SetInvokingWindow(NULL);
+
+ return TRUE;
+}
+
+#endif // wxUSE_MENUS_NATIVE
+
+// ===========================================================================
+// pre/post message processing
+// ===========================================================================
+
+long wxWindowMSW::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);
+}
+
+bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
+{
+ // wxUniversal implements tab traversal itself
+#ifndef __WXUNIVERSAL__
+ if ( m_hWnd != 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL) )
+ {
+ // intercept dialog navigation keys
+ MSG *msg = (MSG *)pMsg;
+
+ // 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;
+
+ 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 )
+ {
+ lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0);
+ }
+
+ bool bForward = TRUE,
+ bWindowChange = FALSE;
+
+ 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
+ bForward = FALSE;
+ break;
+
+ case VK_DOWN:
+ case VK_RIGHT:
+ if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown )
+ bProcess = FALSE;
+ break;
+
+ case VK_RETURN:
+ {
+ if ( (lDlgCode & DLGC_WANTMESSAGE) && !bCtrlDown )
+ {
+ // control wants to process Enter itself, don't
+ // call IsDialogMessage() which would interpret
+ // it
+ return FALSE;
+ }
+ else if ( lDlgCode & DLGC_BUTTON )
+ {
+ // let IsDialogMessage() handle this for all
+ // buttons except the owner-drawn ones which it
+ // just seems to ignore
+ long style = ::GetWindowLong(msg->hwnd, GWL_STYLE);
+ if ( (style & BS_OWNERDRAW) == BS_OWNERDRAW )
+ {
+ // emulate the button click
+ wxWindow *btn = wxFindWinFromHandle((WXHWND)msg->hwnd);
+ if ( btn )
+ btn->MSWCommand(BN_CLICKED, 0 /* unused */);
+ }
+
+ bProcess = FALSE;
+ }
+#if wxUSE_BUTTON
+ else
+ {
+ wxPanel *panel = wxDynamicThisCast(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.
+ }
+#endif // wxUSE_BUTTON
+ }
+ break;
+
+ default:
+ bProcess = FALSE;
+ }
+
+ if ( bProcess )
+ {
+ wxNavigationKeyEvent event;
+ event.SetDirection(bForward);
+ event.SetWindowChange(bWindowChange);
+ event.SetEventObject(this);
+
+ if ( GetEventHandler()->ProcessEvent(event) )
+ {
+#if wxUSE_BUTTON
+ wxButton *btn = wxDynamicCast(FindFocus(), wxButton);
+ if ( btn )
+ {
+ // the button which has focus should be default
+ btn->SetDefault();
+ }
+#endif // wxUSE_BUTTON
+
+ return TRUE;
+ }
+ }
+ }
+#else
+ // let ::IsDialogMessage() do almost everything and handle just the
+ // things it doesn't here: Ctrl-TAB for switching notebook pages
+ if ( msg->message == WM_KEYDOWN )
+ {
+ // don't process system keys here
+ if ( !(HIWORD(msg->lParam) & KF_ALTDOWN) )
+ {
+ if ( (msg->wParam == VK_TAB) && wxIsCtrlDown() )
+ {
+ // find the first notebook parent and change its page
+ wxWindow *win = this;
+ wxNotebook *nbook = NULL;
+ while ( win && !nbook )
+ {
+ nbook = wxDynamicCast(win, wxNotebook);
+ win = win->GetParent();
+ }
+
+ if ( nbook )
+ {
+ bool forward = !wxIsShiftDown();
+
+ nbook->AdvanceSelection(forward);
+ }
+ }
+ }
+ }
+#endif // 0
+
+ if ( ::IsDialogMessage(GetHwnd(), msg) )
+ {
+ // IsDialogMessage() did something...
+ return TRUE;
+ }
+ }
+#endif // __WXUNIVERSAL__
+
+#if wxUSE_TOOLTIPS
+ if ( m_tooltip )
+ {
+ // 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 FALSE;
+}
+
+bool wxWindowMSW::MSWTranslateMessage(WXMSG* pMsg)
+{
+#if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
+ return m_acceleratorTable.Translate(this, pMsg);
+#else
+ return FALSE;
+#endif // wxUSE_ACCEL
+}
+
+// ---------------------------------------------------------------------------
+// message params unpackers (different for Win16 and Win32)
+// ---------------------------------------------------------------------------
+
+#ifdef __WIN32__
+
+void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam,
+ WORD *id, WXHWND *hwnd, WORD *cmd)
+{
+ *id = LOWORD(wParam);
+ *hwnd = (WXHWND)lParam;
+ *cmd = HIWORD(wParam);
+}
+
+void wxWindowMSW::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam,
+ WXWORD *state, WXWORD *minimized, WXHWND *hwnd)
+{
+ *state = LOWORD(wParam);
+ *minimized = HIWORD(wParam);
+ *hwnd = (WXHWND)lParam;
+}
+
+void wxWindowMSW::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam,
+ WXWORD *code, WXWORD *pos, WXHWND *hwnd)
+{
+ *code = LOWORD(wParam);
+ *pos = HIWORD(wParam);
+ *hwnd = (WXHWND)lParam;
+}
+
+void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam,
+ WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd)
+{
+#ifndef __WXMICROWIN__
+ *nCtlColor = CTLCOLOR_BTN;
+ *hwnd = (WXHWND)lParam;
+ *hdc = (WXHDC)wParam;
+#endif
+}
+
+void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam,
+ WXWORD *item, WXWORD *flags, WXHMENU *hmenu)
+{
+ *item = (WXWORD)wParam;
+ *flags = HIWORD(wParam);
+ *hmenu = (WXHMENU)lParam;
+}
+
+#else // Win16
+
+void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam,
+ WXWORD *id, WXHWND *hwnd, WXWORD *cmd)
+{
+ *id = (WXWORD)wParam;
+ *hwnd = (WXHWND)LOWORD(lParam);
+ *cmd = HIWORD(lParam);
+}
+
+void wxWindowMSW::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam,
+ WXWORD *state, WXWORD *minimized, WXHWND *hwnd)
+{
+ *state = (WXWORD)wParam;
+ *minimized = LOWORD(lParam);
+ *hwnd = (WXHWND)HIWORD(lParam);
+}
+
+void wxWindowMSW::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam,
+ WXWORD *code, WXWORD *pos, WXHWND *hwnd)
+{
+ *code = (WXWORD)wParam;
+ *pos = LOWORD(lParam);
+ *hwnd = (WXHWND)HIWORD(lParam);
+}
+
+void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam,
+ WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd)
+{
+ *hwnd = (WXHWND)LOWORD(lParam);
+ *nCtlColor = (int)HIWORD(lParam);
+ *hdc = (WXHDC)wParam;
+}
+
+void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam,
+ WXWORD *item, WXWORD *flags, WXHMENU *hmenu)
+{
+ *item = (WXWORD)wParam;
+ *flags = LOWORD(lParam);
+ *hmenu = (WXHMENU)HIWORD(lParam);
+}
+
+#endif // Win32/16
+
+// ---------------------------------------------------------------------------
+// Main wxWindows window proc and the window proc for wxWindow
+// ---------------------------------------------------------------------------
+
+// Hook for new window just as it's being created, when the window isn't yet
+// associated with the handle
+wxWindowMSW *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__
+
+ wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd);
+
+ // when we get the first message for the HWND we just created, we associate
+ // it with wxWindow stored in wxWndHook
+ if ( !wnd && wxWndHook )
+ {
+#if 0 // def __WXDEBUG__
+ char buf[512];
+ ::GetClassNameA((HWND) hWnd, buf, 512);
+ wxString className(buf);
+#endif
+
+ wxAssociateWinWithHandle(hWnd, wxWndHook);
+ wnd = wxWndHook;
+ wxWndHook = NULL;
+ wnd->SetHWND((WXHWND)hWnd);
+ }
+
+ LRESULT rc;
+
+ // 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 );
+ }
+
+ return rc;
+}
+
+long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
+{
+ // did we process the message?
+ bool processed = FALSE;
+
+ // the return value
+ union
+ {
+ bool allow;
+ long result;
+ WXHICON hIcon;
+ WXHBRUSH hBrush;
+ } rc;
+
+ // for most messages we should return 0 when we do process the message
+ rc.result = 0;
+
+ switch ( message )
+ {