+#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;
+}
+
+// Dialog window proc
+LONG APIENTRY _EXPORT
+wxDlgProc(HWND WXUNUSED(hWnd), UINT message, WPARAM WXUNUSED(wParam), LPARAM WXUNUSED(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;
+ }
+}
+
+wxList *wxWinHandleList = NULL;
+wxWindow *wxFindWinFromHandle(WXHWND hWnd)
+{
+ wxNode *node = wxWinHandleList->Find((long)hWnd);
+ if ( !node )
+ return NULL;
+ return (wxWindow *)node->Data();
+}
+
+#if 0 // def __WXDEBUG__
+static int gs_AssociationCount = 0;
+#endif
+
+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);
+ if ( oldWin && (oldWin != win) )
+ {
+ wxString str(win->GetClassInfo()->GetClassName());
+ wxLogError(wxT("Bug! Found existing HWND %X for new window of class %s"), (int) hWnd, (const wxChar*) str);
+ }
+ else if (!oldWin)
+ {
+#if 0 // def __WXDEBUG__
+ gs_AssociationCount ++;
+ wxLogDebug("+ Association %d", gs_AssociationCount);
+#endif
+
+ wxWinHandleList->Append((long)hWnd, win);
+ }
+}
+
+void wxRemoveHandleAssociation(wxWindowMSW *win)
+{
+#if 0 // def __WXDEBUG__
+ if (wxWinHandleList->Member(win))
+ {
+ wxLogDebug("- Association %d", gs_AssociationCount);
+ gs_AssociationCount --;
+ }
+#endif
+ wxWinHandleList->DeleteObject(win);
+}
+
+// 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
+}
+
+bool wxWindowMSW::MSWCreate(int id,
+ wxWindow *parent,
+ const wxChar *wclass,
+ wxWindow * WXUNUSED(wx_win),
+ const wxChar *title,
+ int x,
+ int y,
+ int width,
+ int height,
+ WXDWORD style,
+ const wxChar *dialog_template,
+ WXDWORD extendedStyle)
+{
+ int x1 = CW_USEDEFAULT;
+ int y1 = 0;
+ int width1 = CW_USEDEFAULT;
+ int height1 = 100;
+
+ // Find parent's size, if it exists, to set up a possible default
+ // panel size the size of the parent window
+ RECT rectParent;
+ if ( parent )
+ {
+ ::GetClientRect(GetHwndOf(parent), &rectParent);
+
+ width1 = rectParent.right - rectParent.left;
+ height1 = rectParent.bottom - rectParent.top;
+ }
+
+ if ( x != -1 )
+ x1 = x;
+ if ( y != -1 )
+ y1 = y;
+ if ( width != -1 )
+ width1 = width;
+ if ( height != -1 )
+ height1 = height;
+
+ // 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
+
+ HWND hParent;
+ if ( GetWindowStyleFlag() & wxPOPUP_WINDOW )
+ {
+ // popup windows should have desktop as parent because they shouldn't
+ // be limited to the parents client area as child windows usually are
+ hParent = ::GetDesktopWindow();
+ }
+ else if ( parent )
+ {
+ hParent = GetHwndOf(parent);
+ }
+ else
+ {
+ // top level window
+ hParent = NULL;
+ }
+
+ wxWndHook = this;
+
+#ifndef __WXMICROWIN__
+ 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);
+ }
+
+ m_hWnd = (WXHWND)::CreateDialog(wxGetInstance(),
+ dialog_template,
+ hParent,
+ (DLGPROC)wxDlgProc);
+
+ if ( m_hWnd == 0 )
+ {
+ wxLogError(_("Can't find dialog template '%s'!\nCheck resource include path for finding wx.rc."),
+ dialog_template);
+
+ return FALSE;
+ }
+
+ if ( extendedStyle != 0 )
+ {
+ ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, extendedStyle);
+ ::SetWindowPos(GetHwnd(), NULL, 0, 0, 0, 0,
+ SWP_NOSIZE |
+ SWP_NOMOVE |
+ SWP_NOZORDER |
+ SWP_NOACTIVATE);
+ }
+
+#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__
+
+
+ // 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
+#endif // !__WXMICROWIN__
+ {
+ int controlId = 0;
+ if ( style & WS_CHILD )
+ {
+ controlId = id;
+
+ if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS )
+ {
+ style |= WS_CLIPSIBLINGS;
+ }
+ }
+
+ 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);
+
+ 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;
+
+ wxCloseEvent event(wxEVT_END_SESSION, -1);
+ event.SetEventObject(wxTheApp);
+ event.SetCanVeto(FALSE);
+ event.SetLoggingOff( (logOff == (long)ENDSESSION_LOGOFF) );
+ if ( (this == wxTheApp->GetTopWindow()) && // Only send once
+ wxTheApp->ProcessEvent(event))
+ {
+ }
+ return TRUE;
+}
+
+// ---------------------------------------------------------------------------
+// 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(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);
+}