+ // 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 )
+ {
+ case WM_CREATE:
+ {
+ bool mayCreate;
+ processed = HandleCreate((WXLPCREATESTRUCT)lParam, &mayCreate);
+ if ( processed )
+ {
+ // return 0 to allow window creation
+ rc.result = mayCreate ? 0 : -1;
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ // never set processed to TRUE and *always* pass WM_DESTROY to
+ // DefWindowProc() as Windows may do some internal cleanup when
+ // processing it and failing to pass the message along may cause
+ // memory and resource leaks!
+ (void)HandleDestroy();
+ break;
+
+ case WM_MOVE:
+ processed = HandleMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ break;
+
+ case WM_SIZE:
+ switch ( wParam )
+ {
+ case SIZE_MAXHIDE:
+ case SIZE_MAXSHOW:
+ // we're not interested in these messages at all
+ break;
+
+ case SIZE_MINIMIZED:
+ // we shouldn't send sizev events for these messages as the
+ // client size may be negative which breaks existing code
+ //
+ // OTOH we might send another (wxMinimizedEvent?) one or
+ // add an additional parameter to wxSizeEvent if this is
+ // useful to anybody
+ break;
+
+ default:
+ wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
+ // fall through nevertheless
+
+ case SIZE_MAXIMIZED:
+ case SIZE_RESTORED:
+ processed = HandleSize(LOWORD(lParam), HIWORD(lParam),
+ wParam);
+ }
+ break;
+
+#ifndef __WXMICROWIN__
+ case WM_ACTIVATEAPP:
+ wxTheApp->SetActive(wParam != 0, FindFocus());
+ break;
+#endif
+
+ case WM_ACTIVATE:
+ {
+ WXWORD state, minimized;
+ WXHWND hwnd;
+ UnpackActivate(wParam, lParam, &state, &minimized, &hwnd);
+
+ processed = HandleActivate(state, minimized != 0, (WXHWND)hwnd);
+ }
+ break;
+
+ case WM_SETFOCUS:
+ processed = HandleSetFocus((WXHWND)(HWND)wParam);
+ break;
+
+ case WM_KILLFOCUS:
+ processed = HandleKillFocus((WXHWND)(HWND)wParam);
+ break;
+
+ case WM_PAINT:
+ processed = HandlePaint();
+ break;
+
+ case WM_CLOSE:
+ // don't let the DefWindowProc() destroy our window - we'll do it
+ // ourselves in ~wxWindow
+ processed = TRUE;
+ rc.result = TRUE;
+ break;
+
+ case WM_SHOWWINDOW:
+ processed = HandleShow(wParam != 0, (int)lParam);
+ break;
+
+ case WM_MOUSEMOVE:
+ processed = HandleMouseMove(GET_X_LPARAM(lParam),
+ GET_Y_LPARAM(lParam),
+ wParam);
+ break;
+
+#if wxUSE_MOUSEWHEEL
+ case WM_MOUSEWHEEL:
+ processed = HandleMouseWheel(wParam, lParam);
+ break;
+#endif
+
+ 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:
+ {
+ processed = FALSE;
+#ifdef __WXMICROWIN__
+ // MicroWindows seems to ignore the fact that a window is
+ // disabled. So catch mouse events and throw them away if
+ // necessary.
+ wxWindowMSW* win = this;
+ while (win)
+ {
+ if (!win->IsEnabled())
+ {
+ processed = TRUE;
+ break;
+ }
+ win = win->GetParent();
+ if (win && win->IsTopLevel())
+ break;
+ }
+#endif // __WXMICROWIN__
+ if (!processed)
+ {
+ if (message == WM_LBUTTONDOWN && AcceptsFocus())
+ SetFocus();
+ processed = HandleMouseEvent(message,
+ GET_X_LPARAM(lParam),
+ GET_Y_LPARAM(lParam),
+ wParam);
+ }
+ break;
+ }
+
+#ifdef __WXMICROWIN__
+ case WM_NCLBUTTONDOWN:
+ case WM_NCLBUTTONUP:
+ case WM_NCLBUTTONDBLCLK:
+ case WM_NCRBUTTONDOWN:
+ case WM_NCRBUTTONUP:
+ case WM_NCRBUTTONDBLCLK:
+#if 0
+ case WM_NCMBUTTONDOWN:
+ case WM_NCMBUTTONUP:
+ case WM_NCMBUTTONDBLCLK:
+#endif
+ {
+ // MicroWindows seems to ignore the fact that a window
+ // is disabled. So catch mouse events and throw them away if necessary.
+ processed = FALSE;
+ wxWindowMSW* win = this;
+ while (win)
+ {
+ if (!win->IsEnabled())
+ {
+ processed = TRUE;
+ break;
+ }
+ win = win->GetParent();
+ if (win && win->IsTopLevel())
+ break;
+ }
+ break;
+ }
+#endif // __WXMICROWIN__
+
+#ifdef MM_JOY1MOVE
+ case MM_JOY1MOVE:
+ case MM_JOY2MOVE:
+ case MM_JOY1ZMOVE:
+ case MM_JOY2ZMOVE:
+ case MM_JOY1BUTTONDOWN:
+ case MM_JOY2BUTTONDOWN:
+ case MM_JOY1BUTTONUP:
+ case MM_JOY2BUTTONUP:
+ processed = HandleJoystickEvent(message,
+ GET_X_LPARAM(lParam),
+ GET_Y_LPARAM(lParam),
+ wParam);
+ break;
+#endif // __WXMICROWIN__
+
+ case WM_SYSCOMMAND:
+ processed = HandleSysCommand(wParam, lParam);
+ break;
+
+ case WM_COMMAND:
+ {
+ WORD id, cmd;
+ WXHWND hwnd;
+ UnpackCommand(wParam, lParam, &id, &hwnd, &cmd);
+
+ processed = HandleCommand(id, cmd, hwnd);
+ }
+ break;
+
+#ifdef __WIN95__
+ case WM_NOTIFY:
+ processed = HandleNotify((int)wParam, lParam, &rc.result);
+ break;
+#endif // Win95
+
+ // for these messages we must return TRUE if process the message
+#ifdef WM_DRAWITEM
+ 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);
+ }
+
+ if ( processed )
+ rc.result = TRUE;
+ }
+ break;
+#endif // defined(WM_DRAWITEM)
+
+ case WM_GETDLGCODE:
+ if ( m_lDlgCode )
+ {
+ rc.result = m_lDlgCode;
+ processed = TRUE;
+ }
+ //else: get the dlg code from the DefWindowProc()
+ break;
+
+ 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;
+
+ break;
+ }
+
+ // we consider these message "not interesting" to OnChar
+ if ( wParam == VK_SHIFT || wParam == VK_CONTROL )
+ {
+ processed = TRUE;
+
+ 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;
+
+ break;
+
+#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;
+
+ TranslateKbdEventToMouse(this, &x, &y, &flags);
+ processed = HandleMouseEvent(WM_RBUTTONDOWN, x, y, flags);
+ }
+ break;
+#endif // VK_APPS
+
+ case VK_LEFT:
+ case VK_RIGHT:
+ case VK_DOWN:
+ case VK_UP:
+ default:
+ processed = HandleChar((WORD)wParam, lParam);
+ }
+ break;
+
+ 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;
+
+ TranslateKbdEventToMouse(this, &x, &y, &flags);
+ processed = HandleMouseEvent(WM_RBUTTONUP, x, y, flags);
+ }
+ else
+#endif // VK_APPS
+ {
+ processed = HandleKeyUp((WORD) wParam, lParam);
+ }
+ break;
+
+ case WM_SYSCHAR:
+ case WM_CHAR: // Always an ASCII character
+ processed = HandleChar((WORD)wParam, lParam, TRUE);
+ break;
+
+ case WM_HSCROLL:
+ case WM_VSCROLL:
+ {
+ WXWORD code, pos;
+ WXHWND hwnd;
+ UnpackScroll(wParam, lParam, &code, &pos, &hwnd);
+
+ processed = MSWOnScroll(message == WM_HSCROLL ? wxHORIZONTAL
+ : wxVERTICAL,
+ code, pos, hwnd);
+ }
+ break;
+
+ // CTLCOLOR messages are sent by children to query the parent for their
+ // colors#ifndef __WXMICROWIN__
+#ifndef __WXMICROWIN__
+#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;
+#endif // !__WXMICROWIN__
+
+ // the return value for this message is ignored
+ case WM_SYSCOLORCHANGE:
+ processed = HandleSysColorChange();
+ break;
+
+ case WM_PALETTECHANGED:
+ processed = HandlePaletteChanged((WXHWND) (HWND) wParam);
+ break;
+
+ case WM_QUERYNEWPALETTE:
+ processed = HandleQueryNewPalette();
+ break;
+
+ case WM_ERASEBKGND:
+ processed = HandleEraseBkgnd((WXHDC)(HDC)wParam);
+ if ( processed )
+ {
+ // we processed the message, i.e. erased the background
+ rc.result = TRUE;
+ }
+ break;
+
+ case WM_DROPFILES:
+ processed = HandleDropFiles(wParam);
+ break;
+
+ case WM_INITDIALOG:
+ processed = HandleInitDialog((WXHWND)(HWND)wParam);
+
+ if ( processed )
+ {
+ // we never set focus from here
+ rc.result = FALSE;
+ }
+ break;
+
+ case WM_QUERYENDSESSION:
+ processed = HandleQueryEndSession(lParam, &rc.allow);
+ break;
+
+ case WM_ENDSESSION:
+ processed = HandleEndSession(wParam != 0, lParam);
+ break;
+
+ 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 )
+ {
+ // 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;
+
+#if defined(__WIN32__) && defined(WM_HELP)
+ case WM_HELP:
+ {
+ HELPINFO* info = (HELPINFO*) lParam;
+ // Don't yet process menu help events, just windows
+ if (info->iContextType == HELPINFO_WINDOW)
+ {
+ wxWindowMSW* subjectOfHelp = this;
+ bool eventProcessed = FALSE;
+ while (subjectOfHelp && !eventProcessed)
+ {
+ wxHelpEvent helpEvent(wxEVT_HELP,
+ subjectOfHelp->GetId(),
+ wxPoint(info->MousePos.x,
+ info->MousePos.y) );
+ helpEvent.SetEventObject(this);
+ eventProcessed =
+ GetEventHandler()->ProcessEvent(helpEvent);
+
+ // Go up the window hierarchy until the event is
+ // handled (or not)
+ subjectOfHelp = subjectOfHelp->GetParent();
+ }
+
+ processed = eventProcessed;
+ }
+ else if (info->iContextType == HELPINFO_MENUITEM)
+ {
+ wxHelpEvent helpEvent(wxEVT_HELP, info->iCtrlId);
+ helpEvent.SetEventObject(this);
+ processed = GetEventHandler()->ProcessEvent(helpEvent);
+
+ }
+ //else: processed is already FALSE
+ }
+ break;
+
+ case WM_CONTEXTMENU:
+ {
+ // we don't convert from screen to client coordinates as
+ // the event may be handled by a parent window
+ wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+
+ wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
+ processed = GetEventHandler()->ProcessEvent(evtCtx);
+ }
+ break;
+#endif // __WIN32__
+
+ // unfortunately this doesn't really work as then window which
+ // doesn't accept focus doesn't get any mouse events neither which
+ // means it can't get any input at all
+#if 0 //def __WXUNIVERSAL__
+ case WM_NCHITTEST:
+ // we shouldn't allow the windows which don't want to get focus to
+ // get it
+ if ( !AcceptsFocus() )
+ {
+ rc.result = HTTRANSPARENT;
+ processed = TRUE;
+ }
+ break;
+#endif // __WXUNIVERSAL__
+ }
+
+ if ( !processed )
+ {
+#ifdef __WXDEBUG__
+ wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."),
+ wxGetMessageName(message));
+#endif // __WXDEBUG__
+ rc.result = MSWDefWindowProc(message, wParam, lParam);
+ }
+
+ return rc.result;
+}
+
+// ----------------------------------------------------------------------------
+// wxWindow <-> HWND map
+// ----------------------------------------------------------------------------
+
+wxList *wxWinHandleList = NULL;
+
+wxWindow *wxFindWinFromHandle(WXHWND hWnd)
+{
+ wxNode *node = wxWinHandleList->Find((long)hWnd);
+ if ( !node )
+ return NULL;
+ return (wxWindow *)node->Data();
+}
+
+void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *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") );
+
+ wxWindow *oldWin = wxFindWinFromHandle((WXHWND) hWnd);
+#ifdef __WXDEBUG__
+ if ( oldWin && (oldWin != win) )
+ {
+ wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
+ hWnd, win->GetClassInfo()->GetClassName());
+ }
+ else
+#endif // __WXDEBUG__
+ if (!oldWin)
+ {
+ wxWinHandleList->Append((long)hWnd, win);
+ }
+}
+
+void wxRemoveHandleAssociation(wxWindowMSW *win)
+{
+ wxWinHandleList->DeleteObject(win);
+}
+
+// ----------------------------------------------------------------------------
+// various MSW speciic class dependent functions
+// ----------------------------------------------------------------------------
+
+// Default destroyer - override if you destroy it in some other way
+// (e.g. with MDI child windows)
+void wxWindowMSW::MSWDestroyWindow()
+{
+}
+
+void wxWindowMSW::MSWDetachWindowMenu()
+{
+#ifndef __WXUNIVERSAL__
+ if ( m_hMenu )
+ {
+ wxChar buf[1024];
+ HMENU hMenu = (HMENU)m_hMenu;
+
+ int N = ::GetMenuItemCount(hMenu);
+ for ( int i = 0; i < N; i++ )
+ {
+ if ( !::GetMenuString(hMenu, i, buf, WXSIZEOF(buf), MF_BYPOSITION) )
+ {
+ wxLogLastError(wxT("GetMenuString"));
+
+ continue;
+ }
+
+ if ( wxStrcmp(buf, _("&Window")) == 0 )
+ {
+ if ( !::RemoveMenu(hMenu, i, MF_BYPOSITION) )
+ {
+ wxLogLastError(wxT("RemoveMenu"));
+ }
+
+ break;
+ }
+ }
+ }
+#endif // __WXUNIVERSAL__
+}
+
+bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos,
+ const wxSize& size,
+ int& x, int& y,
+ int& w, int& h) const
+{
+ bool nonDefault = FALSE;
+
+ if ( pos.x == -1 )
+ {
+ // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
+ // just as well set it to CW_USEDEFAULT as well
+ x =
+ y = CW_USEDEFAULT;
+ }
+ else
+ {
+ x = pos.x;
+ y = pos.y == -1 ? CW_USEDEFAULT : pos.y;
+
+ nonDefault = TRUE;
+ }
+
+ /*
+ NB: there used to be some code here which set the initial size of the
+ window to the client size of the parent if no explicit size was
+ specified. This was wrong because wxWindows programs often assume
+ that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
+ it. To see why, you should understand that Windows sends WM_SIZE from
+ inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
+ from some base class ctor and so this WM_SIZE is not processed in the
+ real class' OnSize() (because it's not fully constructed yet and the
+ event goes to some base class OnSize() instead). So the WM_SIZE we
+ rely on is the one sent when the parent frame resizes its children
+ but here is the problem: if the child already has just the right
+ size, nothing will happen as both wxWindows and Windows check for
+ this and ignore any attempts to change the window size to the size it
+ already has - so no WM_SIZE would be sent.
+ */
+ if ( size.x == -1 )
+ {
+ // as abobe, h is not used at all in this case anyhow
+ w =
+ h = CW_USEDEFAULT;
+ }
+ else
+ {
+ w = size.x;
+ h = size.y == -1 ? CW_USEDEFAULT : size.y;
+
+ nonDefault = TRUE;
+ }
+
+ return nonDefault;
+}
+
+bool wxWindowMSW::MSWCreate(const wxChar *wclass,
+ const wxChar *title,
+ const wxPoint& pos,
+ const wxSize& size,
+ WXDWORD style,
+ WXDWORD extendedStyle)
+{
+ // choose the position/size for the new window
+ int x, y, w, h;
+ (void)MSWGetCreateWindowCoords(pos, size, x, y, w, h);
+
+ // find the correct parent HWND
+ wxWindow *parent = GetParent();
+ bool isChild = (style & WS_CHILD) != 0;
+ HWND hParent;
+ if ( GetWindowStyleFlag() & wxPOPUP_WINDOW )
+ {
+ // popup windows should have desktop as parent because they shouldn't
+ // be limited to the parents client area as child windows usually are
+ hParent = ::GetDesktopWindow();
+ }
+ else // !popup
+ {
+ if ( (isChild || HasFlag(wxFRAME_TOOL_WINDOW)) && parent )
+ {
+ // this is either a normal child window or a top level window with
+ // wxFRAME_TOOL_WINDOW style (see below)
+ hParent = GetHwndOf(parent);
+ }
+ else
+ {
+ // this is either a window for which no parent was specified (not
+ // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
+ // style: we should use NULL parent HWND for it or it would be
+ // always on top of its parent which is not what we usually want
+ // (in fact, we only want it for frames with the special
+ // wxFRAME_TOOL_WINDOW as above)
+ hParent = NULL;
+ }
+
+ }
+
+ // controlId is menu handle for the top level windows, so set it to 0
+ // unless we're creating a child window
+ int controlId;
+ if ( isChild )
+ {
+ controlId = GetId();
+
+ if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS )
+ {
+ style |= WS_CLIPSIBLINGS;
+ }
+ }
+ else // !child
+ {
+ controlId = 0;
+ }
+
+ // for each class "Foo" we have we also have "FooNR" ("no repaint") class
+ // which is the same but without CS_[HV]REDRAW class styles so using it
+ // ensures that the window is not fully repainted on each resize
+ wxString className(wclass);
+ if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE )
+ {
+ className += wxT("NR");
+ }
+
+ // do create the window
+ wxWindowCreationHook hook(this);
+
+ m_hWnd = (WXHWND)::CreateWindowEx
+ (
+ extendedStyle,
+ className,
+ title ? title : wxT(""),
+ style,
+ x, y, w, h,
+ hParent,
+ (HMENU)controlId,
+ wxGetInstance(),
+ NULL // no extra data
+ );
+
+ if ( !m_hWnd )
+ {
+ wxLogSysError(_("Can't create window of class %s"), wclass);
+
+ return FALSE;
+ }
+
+ SubclassWin(m_hWnd);
+
+ SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
+
+ return TRUE;
+}
+
+// ===========================================================================
+// MSW message handlers
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// WM_NOTIFY
+// ---------------------------------------------------------------------------
+
+#ifdef __WIN95__
+// FIXME: VZ: I'm not sure at all that the order of processing is correct
+bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
+{
+#ifndef __WXMICROWIN__
+ 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;
+ }
+
+ node = node->GetNext();
+ }
+
+ // finally try this window too (catches toolbar case)
+ return MSWOnNotify(idCtrl, lParam, result);
+#else // __WXMICROWIN__
+ return FALSE;
+#endif
+}
+
+bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl),
+ WXLPARAM lParam,
+ WXLPARAM* WXUNUSED(result))
+{
+#if wxUSE_TOOLTIPS
+ NMHDR* hdr = (NMHDR *)lParam;
+ if ( (int)hdr->code == TTN_NEEDTEXT && m_tooltip )
+ {
+ TOOLTIPTEXT *ttt = (TOOLTIPTEXT *)lParam;
+ ttt->lpszText = (wxChar *)m_tooltip->GetTip().c_str();
+
+ // processed
+ return TRUE;
+ }
+#endif // wxUSE_TOOLTIPS
+
+ return FALSE;
+}
+#endif // __WIN95__
+
+// ---------------------------------------------------------------------------
+// end session messages
+// ---------------------------------------------------------------------------
+
+bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd)
+{
+ 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 )
+ {
+ // we may end only if the app didn't veto session closing (double
+ // negation...)
+ *mayEnd = !event.GetVeto();
+ }
+
+ return rc;
+}
+
+bool wxWindowMSW::HandleEndSession(bool endSession, long logOff)
+{
+ // do nothing if the session isn't ending
+ if ( !endSession )
+ return FALSE;
+
+ // only send once
+ if ( (this != wxTheApp->GetTopWindow()) )
+ return FALSE;
+
+ wxCloseEvent event(wxEVT_END_SESSION, -1);
+ event.SetEventObject(wxTheApp);
+ event.SetCanVeto(FALSE);
+ event.SetLoggingOff( (logOff == (long)ENDSESSION_LOGOFF) );
+
+ return wxTheApp->ProcessEvent(event);
+}
+
+// ---------------------------------------------------------------------------
+// window creation/destruction
+// ---------------------------------------------------------------------------
+
+bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT WXUNUSED(cs), bool *mayCreate)
+{
+ // TODO: should generate this event from WM_NCCREATE
+ wxWindowCreateEvent event((wxWindow *)this);
+ (void)GetEventHandler()->ProcessEvent(event);
+
+ *mayCreate = TRUE;
+
+ return TRUE;
+}
+
+bool wxWindowMSW::HandleDestroy()
+{
+ wxWindowDestroyEvent event((wxWindow *)this);
+ (void)GetEventHandler()->ProcessEvent(event);
+
+ // delete our drop target if we've got one
+#if wxUSE_DRAG_AND_DROP
+ if ( m_dropTarget != NULL )
+ {
+ m_dropTarget->Revoke(m_hWnd);
+
+ delete m_dropTarget;
+ m_dropTarget = NULL;
+ }
+#endif // wxUSE_DRAG_AND_DROP
+
+ // WM_DESTROY handled
+ return TRUE;
+}
+
+// ---------------------------------------------------------------------------
+// activation/focus
+// ---------------------------------------------------------------------------
+
+bool wxWindowMSW::HandleActivate(int state,
+ bool WXUNUSED(minimized),
+ WXHWND WXUNUSED(activate))
+{
+ wxActivateEvent event(wxEVT_ACTIVATE,
+ (state == WA_ACTIVE) || (state == WA_CLICKACTIVE),
+ m_windowId);
+ event.SetEventObject(this);
+
+ return GetEventHandler()->ProcessEvent(event);
+}
+
+bool wxWindowMSW::HandleSetFocus(WXHWND hwnd)
+{
+ // notify the parent keeping track of focus for the kbd navigation
+ // purposes that we got it
+ wxChildFocusEvent eventFocus((wxWindow *)this);
+ (void)GetEventHandler()->ProcessEvent(eventFocus);
+
+#if wxUSE_CARET
+ // Deal with caret
+ if ( m_caret )
+ {
+ m_caret->OnSetFocus();
+ }
+#endif // wxUSE_CARET
+
+#if wxUSE_TEXTCTRL
+ // If it's a wxTextCtrl don't send the event as it will be done
+ // after the control gets to process it from EN_FOCUS handler
+ if ( wxDynamicCastThis(wxTextCtrl) )
+ {
+ return FALSE;
+ }
+#endif // wxUSE_TEXTCTRL
+
+ wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId);
+ event.SetEventObject(this);
+
+ // wxFindWinFromHandle() may return NULL, it is ok
+ event.SetWindow(wxFindWinFromHandle(hwnd));
+
+ return GetEventHandler()->ProcessEvent(event);
+}
+
+bool wxWindowMSW::HandleKillFocus(WXHWND hwnd)
+{
+#if wxUSE_CARET
+ // Deal with caret
+ if ( m_caret )
+ {
+ m_caret->OnKillFocus();
+ }
+#endif // wxUSE_CARET
+
+#if wxUSE_TEXTCTRL
+ // If it's a wxTextCtrl don't send the event as it will be done
+ // after the control gets to process it.
+ wxTextCtrl *ctrl = wxDynamicCastThis(wxTextCtrl);
+ if ( ctrl )
+ {
+ return FALSE;
+ }
+#endif
+
+ wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId);
+ event.SetEventObject(this);
+
+ // wxFindWinFromHandle() may return NULL, it is ok
+ event.SetWindow(wxFindWinFromHandle(hwnd));
+
+ return GetEventHandler()->ProcessEvent(event);
+}
+
+// ---------------------------------------------------------------------------
+// miscellaneous
+// ---------------------------------------------------------------------------
+
+bool wxWindowMSW::HandleShow(bool show, int WXUNUSED(status))
+{
+ wxShowEvent event(GetId(), show);
+ event.m_eventObject = this;
+
+ return GetEventHandler()->ProcessEvent(event);
+}
+
+bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus))
+{
+ wxInitDialogEvent event(GetId());
+ event.m_eventObject = this;
+
+ return GetEventHandler()->ProcessEvent(event);
+}
+
+bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
+{
+#ifndef __WXMICROWIN__
+ HDROP hFilesInfo = (HDROP) wParam;
+ POINT dropPoint;
+ DragQueryPoint(hFilesInfo, (LPPOINT) &dropPoint);
+
+ // Get the total number of files dropped
+ WORD gwFilesDropped = (WORD)::DragQueryFile
+ (
+ (HDROP)hFilesInfo,
+ (UINT)-1,
+ (LPTSTR)0,
+ (UINT)0
+ );
+
+ 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);
+
+ wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files);
+ event.m_eventObject = this;
+ event.m_pos.x = dropPoint.x;
+ event.m_pos.y = dropPoint.y;
+
+ bool rc = GetEventHandler()->ProcessEvent(event);
+
+ delete[] files;
+
+ return rc;
+#else // __WXMICROWIN__
+ return FALSE;
+#endif
+}
+
+bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd),
+ short nHitTest,
+ int WXUNUSED(mouseMsg))
+{
+#ifndef __WXMICROWIN__
+ // 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;
+ }
+
+ HCURSOR hcursor = 0;
+
+ // 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
+
+ int x = pt.x,
+ y = pt.y;
+ ScreenToClient(&x, &y);
+ wxSetCursorEvent event(x, y);
+
+ bool processedEvtSetCursor = GetEventHandler()->ProcessEvent(event);
+ if ( processedEvtSetCursor && event.HasCursor() )
+ {
+ hcursor = GetHcursorOf(event.GetCursor());
+ }
+
+ if ( !hcursor )
+ {
+ bool isBusy = wxIsBusy();
+
+ // 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() )