]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
Added inline setters for wxTreeEvent so we don't need to add new
[wxWidgets.git] / src / msw / window.cpp
index 890bd089c33ddd80c7bfb7b70f7494565038000c..a3e8a8332931ead757f9f7068622100b97fb640f 100644 (file)
@@ -5,8 +5,8 @@
 // Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation
 // Created:     04/01/98
 // RCS-ID:      $Id$
-// Copyright:   (c) Julian Smart and Markus Holzem
-// Licence:     wxWindows license
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // ===========================================================================
     #include "wx/dnd.h"
 #endif
 
+#if wxUSE_ACCESSIBILITY
+    #include "wx/access.h"
+    #include <oleacc.h>
+    #ifndef WM_GETOBJECT
+        #define WM_GETOBJECT 0x003D
+    #endif
+    #ifndef OBJID_CLIENT
+        #define OBJID_CLIENT 0xFFFFFFFC
+    #endif
+#endif
+
 #include "wx/menuitem.h"
 #include "wx/log.h"
 
@@ -159,15 +170,25 @@ static bool gs_hasStdCmap = FALSE;
 // ---------------------------------------------------------------------------
 
 // the window proc for all our windows
+#ifdef __DIGITALMARS__
+extern "C" LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
+                                   WPARAM wParam, LPARAM lParam);
+#else
 LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
                                    WPARAM wParam, LPARAM lParam);
+#endif
+                                   
 
 #ifdef  __WXDEBUG__
     const char *wxGetMessageName(int message);
 #endif  //__WXDEBUG__
 
 void wxRemoveHandleAssociation(wxWindowMSW *win);
-void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
+#ifdef __DIGITALMARS__
+extern "C" void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
+#else
+extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
+#endif
 wxWindow *wxFindWinFromHandle(WXHWND hWnd);
 
 // this magical function is used to translate VK_APPS key presses to right
@@ -394,17 +415,6 @@ bool wxWindowMSW::Create(wxWindow *parent,
 {
     wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") );
 
-#if wxUSE_STATBOX
-    // wxGTK doesn't allow to create controls with static box as the parent so
-    // this will result in a crash when the program is ported to wxGTK - warn
-    // about it
-    //
-    // the correct solution is to create the controls as siblings of the
-    // static box
-    wxASSERT_MSG( !wxDynamicCast(parent, wxStaticBox),
-                  _T("wxStaticBox can't be used as a window parent!") );
-#endif // wxUSE_STATBOX
-
     if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
         return FALSE;
 
@@ -1155,9 +1165,22 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
         style |= WS_CLIPSIBLINGS;
 
     wxBorder border = (wxBorder)(flags & wxBORDER_MASK);
-    if ( border != wxBORDER_NONE && border != wxBORDER_DEFAULT )
-        style |= WS_BORDER;
+    
+    // Check if we want to automatically give it a sunken style.
+    // Note than because 'sunken' actually maps to WS_EX_CLIENTEDGE, which
+    // is a more neutral term, we don't necessarily get a sunken effect in
+    // Windows XP. Instead we get the appropriate style for the theme.
 
+    if (border == wxBORDER_DEFAULT && wxTheApp->GetAuto3D() && GetParent() &&
+        ((GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS) != wxUSER_COLOURS))
+    {
+        border = (wxBorder)((flags & wxBORDER_MASK) | wxBORDER_SUNKEN);
+    }   
+    
+    // Only give it WS_BORDER for wxBORDER_SIMPLE
+    if (border & wxBORDER_SIMPLE)
+        style |= WS_BORDER;
+    
     // now deal with ext style if the caller wants it
     if ( exstyle )
     {
@@ -1166,7 +1189,7 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
         if ( flags & wxTRANSPARENT_WINDOW )
             *exstyle |= WS_EX_TRANSPARENT;
 
-        switch ( flags & wxBORDER_MASK )
+        switch ( border )
         {
             default:
                 wxFAIL_MSG( _T("unknown border style") );
@@ -1187,6 +1210,7 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
 
             case wxBORDER_SUNKEN:
                 *exstyle |= WS_EX_CLIENTEDGE;
+                style &= ~WS_BORDER;
                 break;
 
             case wxBORDER_DOUBLE:
@@ -1208,94 +1232,6 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
     return style;
 }
 
-// Make a Windows extended style from the given wxWindows window style
-WXDWORD wxWindowMSW::MakeExtendedStyle(long style, bool eliminateBorders)
-{
-    WXDWORD exStyle = 0;
-    if ( style & wxTRANSPARENT_WINDOW )
-        exStyle |= WS_EX_TRANSPARENT;
-
-    if ( !eliminateBorders )
-    {
-        if ( style & wxSUNKEN_BORDER )
-            exStyle |= WS_EX_CLIENTEDGE;
-        if ( style & wxDOUBLE_BORDER )
-            exStyle |= WS_EX_DLGMODALFRAME;
-#if defined(__WIN95__)
-        if ( style & wxRAISED_BORDER )
-            // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
-            exStyle |= WS_EX_DLGMODALFRAME; /* WS_EX_WINDOWEDGE */;
-        if ( style & wxSTATIC_BORDER )
-            exStyle |= WS_EX_STATICEDGE;
-#endif
-    }
-
-    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 wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle,
-                                        bool *want3D) const
-{
-    // If matches certain criteria, then assume no 3D effects
-    // unless specifically requested (dealt with in MakeExtendedStyle)
-    if ( !GetParent()
-#if wxUSE_CONTROLS
-            || !IsKindOf(CLASSINFO(wxControl))
-#endif // wxUSE_CONTROLS
-            || (m_windowStyle & wxNO_BORDER) )
-    {
-        *want3D = FALSE;
-        return MakeExtendedStyle(m_windowStyle);
-    }
-
-    // Determine whether we should be using 3D effects or not.
-    bool nativeBorder = FALSE; // by default, we don't want a Win95 effect
-
-    // 1) App can specify global 3D effects
-    *want3D = wxTheApp->GetAuto3D();
-
-    // 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;
-
-    // 3) Control can override this global setting by defining
-    // a border style, e.g. wxSUNKEN_BORDER
-    if ( m_windowStyle & wxSUNKEN_BORDER  )
-        *want3D = TRUE;
-
-    // 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;
-    }
-
-    // 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;
-}
-
 #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
@@ -1463,14 +1399,10 @@ void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
 
 void wxWindowMSW::Update()
 {
-#ifdef __WXWINE__
-    ::UpdateWindow(GetHwnd());
-#else
     if ( !::UpdateWindow(GetHwnd()) )
     {
         wxLogLastError(_T("UpdateWindow"));
     }
-#endif
 
 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
     // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
@@ -1483,10 +1415,12 @@ void wxWindowMSW::Update()
 // drag and drop
 // ---------------------------------------------------------------------------
 
-#if wxUSE_DRAG_AND_DROP
+//FIXME __DIGITALMARS__ does not honor drag drop in setup.h
 
+#if wxUSE_DRAG_AND_DROP
 void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
 {
+#ifndef __DIGITALMARS__
     if ( m_dropTarget != 0 ) {
         m_dropTarget->Revoke(m_hWnd);
         delete m_dropTarget;
@@ -1495,17 +1429,19 @@ void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
     m_dropTarget = pDropTarget;
     if ( m_dropTarget != 0 )
         m_dropTarget->Register(m_hWnd);
+#endif //  __DIGITALMARS__
 }
-
 #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)
 {
+#ifndef __DIGITALMARS__
     HWND hWnd = GetHwnd();
     if ( hWnd )
         ::DragAcceptFiles(hWnd, (BOOL)accept);
+#endif
 }
 
 // ----------------------------------------------------------------------------
@@ -1519,7 +1455,7 @@ void wxWindowMSW::DoSetToolTip(wxToolTip *tooltip)
     wxWindowBase::DoSetToolTip(tooltip);
 
     if ( m_tooltip )
-        m_tooltip->SetWindow(this);
+        m_tooltip->SetWindow((wxWindow *)this);
 }
 
 #endif // wxUSE_TOOLTIPS
@@ -1891,7 +1827,7 @@ static void wxYieldForCommandsOnly()
     {
         wxTheApp->DoMessage((WXMSG *)&msg);
     }
-    
+
     // If we retrieved a WM_QUIT, insert back into the message queue.
     if (msg.message == WM_QUIT)
         ::PostQuitMessage(0);
@@ -1936,7 +1872,11 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y)
 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
 {
     if ( m_oldWndProc )
+#ifdef __DIGITALMARS__
+        return ::CallWindowProc( (FARPROC) m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
+#else
         return ::CallWindowProc(CASTWNDPROC m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
+#endif
     else
         return ::DefWindowProc(GetHwnd(), nMsg, wParam, lParam);
 }
@@ -2313,8 +2253,10 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM w
 {
     // trace all messages - useful for the debugging
 #ifdef __WXDEBUG__
+#if wxUSE_LOG
     wxLogTrace(wxTraceMessages, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
                wxGetMessageName(message), (long) wParam, lParam);
+#endif // wxUSE_LOG
 #endif // __WXDEBUG__
 
     wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd);
@@ -2840,6 +2782,20 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
             }
             break;
 
+#if wxUSE_ACCESSIBILITY
+        case WM_GETOBJECT:
+            {
+                //WPARAM dwFlags = (WPARAM) (DWORD) wParam;
+                LPARAM dwObjId = (LPARAM) (DWORD) lParam;
+
+                if (dwObjId == OBJID_CLIENT && GetOrCreateAccessible())
+                {
+                    return LresultFromObject(IID_IAccessible, wParam, (IUnknown*) GetAccessible()->GetIAccessible());
+                }
+                break;
+            }
+#endif
+
 #if defined(__WIN32__) && defined(WM_HELP)
         case WM_HELP:
             {
@@ -2887,14 +2843,30 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
                 processed = GetEventHandler()->ProcessEvent(evtCtx);
             }
             break;
+
+        case WM_MENUCHAR:
+            // we're only interested in our own menus, not MF_SYSMENU
+            if ( HIWORD(wParam) == MF_POPUP )
+            {
+                // handle menu chars for ownerdrawn menu items
+                int i = HandleMenuChar(toupper(LOWORD(wParam)), lParam);
+                if ( i != wxNOT_FOUND )
+                {
+                    rc.result = MAKELRESULT(i, MNC_EXECUTE);
+                    processed = TRUE;
+                }
+            }
+            break;
 #endif // __WIN32__
     }
 
     if ( !processed )
     {
 #ifdef __WXDEBUG__
+#if wxUSE_LOG
         wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."),
                    wxGetMessageName(message));
+#endif // wxUSE_LOG
 #endif // __WXDEBUG__
         rc.result = MSWDefWindowProc(message, wParam, lParam);
     }
@@ -3155,36 +3127,9 @@ bool wxWindowMSW::HandleTooltipNotify(WXUINT code,
         // in Unicode mode this is just what we need
         ttText->lpszText = (wxChar *)ttip.c_str();
 #else // !Unicode
-        // in ANSI mode we have to convert the string and put it into the
-        // provided buffer: be careful not to overrun it
-        const size_t lenAnsi = ttip.length();
-
-        // some compilers (MetroWerks and Cygwin) don't like calling mbstowcs
-        // with NULL argument
-        #if defined( __MWERKS__ ) || defined( __CYGWIN__ )
-            size_t lenUnicode = 2*lenAnsi;
-        #else
-            size_t lenUnicode = mbstowcs(NULL, ttip, lenAnsi);
-        #endif
-
-        // using the pointer of right type avoids us doing all sorts of
-        // pointer arithmetics ourselves
-        wchar_t *dst = (wchar_t *)ttText->szText,
-                *pwz = new wchar_t[lenUnicode + 1];
-        mbstowcs(pwz, ttip, lenAnsi + 1);
-
-        // stay inside the buffer (-1 because it must be NUL-terminated)
-        if ( lenUnicode > WXSIZEOF(ttText->szText) - 1 )
-        {
-            lenUnicode = WXSIZEOF(ttText->szText) - 1;
-        }
-
-        memcpy(dst, pwz, lenUnicode*sizeof(wchar_t));
-
-        // put the terminating wide NUL
-        dst[lenUnicode] = L'\0';
-
-        delete [] pwz;
+        MultiByteToWideChar(CP_ACP, 0, ttip, ttip.length()+1,
+                            (wchar_t *)ttText->szText,
+                            sizeof(ttText->szText) / sizeof(wchar_t));
 #endif // Unicode/!Unicode
     }
 
@@ -3297,11 +3242,11 @@ bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate)
 
 bool wxWindowMSW::HandleDestroy()
 {
-    wxWindowDestroyEvent event((wxWindow *)this);
-    (void)GetEventHandler()->ProcessEvent(event);
+    SendDestroyEvent();
 
     // delete our drop target if we've got one
 #if wxUSE_DRAG_AND_DROP
+#ifndef __DIGITALMARS__    
     if ( m_dropTarget != NULL )
     {
         m_dropTarget->Revoke(m_hWnd);
@@ -3309,6 +3254,7 @@ bool wxWindowMSW::HandleDestroy()
         delete m_dropTarget;
         m_dropTarget = NULL;
     }
+#endif  //#ifndef __DIGITALMARS__
 #endif // wxUSE_DRAG_AND_DROP
 
     // WM_DESTROY handled
@@ -3422,7 +3368,10 @@ bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus))
 
 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
 {
-#ifndef __WXMICROWIN__
+//FIX ME  __DIGITALMARS__   
+#if defined (__WXMICROWIN__) || defined (__DIGITALMARS__)
+    return FALSE;
+#else // __WXMICROWIN__
     HDROP hFilesInfo = (HDROP) wParam;
 
     // Get the total number of files dropped
@@ -3457,11 +3406,13 @@ bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
     event.m_pos.y = dropPoint.y;
 
     return GetEventHandler()->ProcessEvent(event);
-#else // __WXMICROWIN__
-    return FALSE;
 #endif
 }
 
+#ifdef __DIGITALMARS__
+extern "C" HCURSOR wxGetCurrentBusyCursor();
+#endif
+
 bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd),
                                   short nHitTest,
                                   int WXUNUSED(mouseMsg))
@@ -4478,6 +4429,69 @@ bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
     return FALSE;
 }
 
+#ifdef __WIN32__
+
+int wxWindowMSW::HandleMenuChar(int chAccel, WXLPARAM lParam)
+{
+    const HMENU hmenu = (HMENU)lParam;
+
+    MENUITEMINFO mii;
+    wxZeroMemory(mii);
+    mii.cbSize = sizeof(MENUITEMINFO);
+    mii.fMask = MIIM_TYPE | MIIM_DATA;
+
+    // find if we have this letter in any owner drawn item
+    const int count = ::GetMenuItemCount(hmenu);
+    for ( int i = 0; i < count; i++ )
+    {
+        if ( ::GetMenuItemInfo(hmenu, i, TRUE, &mii) )
+        {
+            if ( mii.fType == MFT_OWNERDRAW )
+            {
+                //  dwItemData member of the MENUITEMINFO is a
+                //  pointer to the associated wxMenuItem -- see the
+                //  menu creation code
+                wxMenuItem *item = (wxMenuItem*)mii.dwItemData;
+
+                const wxChar *p = wxStrchr(item->GetText(), _T('&'));
+                while ( p++ )
+                {
+                    if ( *p == _T('&') )
+                    {
+                        // this is not the accel char, find the real one
+                        p = wxStrchr(p + 1, _T('&'));
+                    }
+                    else // got the accel char
+                    {
+                        // FIXME-UNICODE: this comparison doesn't risk to work
+                        // for non ASCII accelerator characters I'm afraid, but
+                        // what can we do?
+                        if ( wxToupper(*p) == chAccel )
+                        {
+                            return i;
+                        }
+                        else
+                        {
+                            // this one doesn't match
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        else // failed ot get the menu text?
+        {
+            // it's not fatal, so don't show error, but still log
+            // it
+            wxLogLastError(_T("GetMenuItemInfo"));
+        }
+    }
+
+    return wxNOT_FOUND;
+}
+
+#endif // __WIN32__
+
 // ---------------------------------------------------------------------------
 // joystick
 // ---------------------------------------------------------------------------
@@ -4770,6 +4784,12 @@ int wxCharCodeMSWToWX(int keySym)
         case VK_OEM_6:      id = ']'; break;
         case VK_OEM_7:      id = '\''; break;
 
+#ifdef VK_APPS
+        case VK_LWIN:       id = WXK_WINDOWS_LEFT; break;
+        case VK_RWIN:       id = WXK_WINDOWS_RIGHT; break;
+        case VK_APPS:       id = WXK_WINDOWS_MENU; break;
+#endif // VK_APPS defined
+
         default:
             id = 0;
     }
@@ -4959,7 +4979,7 @@ void wxSetKeyboardHook(bool doIt)
 
         // avoids warning about statement with no effect (FreeProcInstance
         // doesn't do anything under Win32)
-#if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
+#if !defined(__WIN32__) && !defined(__NT__)
         FreeProcInstance(wxTheKeyboardHookProc);
 #endif
     }