]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/treectrl.cpp
fixed LastRead() after Read(wxOutputStream&) (patch 1658301)
[wxWidgets.git] / src / msw / treectrl.cpp
index 5fa9112a5fb4dd413a529d075850b9b0e9d88d48..f314a7a873d8563cdc05a3070225477b06684d26 100644 (file)
 // private functions
 // ----------------------------------------------------------------------------
 
-// wrapper for TreeView_HitTest
-static HTREEITEM GetItemFromPoint(HWND hwndTV, int x, int y)
-{
-    TV_HITTESTINFO tvht;
-    tvht.pt.x = x;
-    tvht.pt.y = y;
-
-    return (HTREEITEM)TreeView_HitTest(hwndTV, &tvht);
-}
-
 // wrappers for TreeView_GetItem/TreeView_SetItem
 static bool IsItemSelected(HWND hwndTV, HTREEITEM hItem)
 {
@@ -659,7 +649,7 @@ bool wxTreeCtrl::Create(wxWindow *parent,
     if ( !CreateControl(parent, id, pos, size, style, validator, name) )
         return false;
 
-    DWORD exStyle = 0;
+    WXDWORD exStyle = 0;
     DWORD wstyle = MSWGetStyle(m_windowStyle, & exStyle);
     wstyle |= WS_TABSTOP | TVS_SHOWSELALWAYS;
 
@@ -1172,6 +1162,10 @@ void wxTreeCtrl::SetItemFont(const wxTreeItemId& item, const wxFont& font)
 
     attr->SetFont(font);
 
+    // Reset the item's text to ensure that the bounding rect will be adjusted
+    // for the new font.
+    SetItemText(item, GetItemText(item));
+
     RefreshItem(item);
 }
 
@@ -2005,31 +1999,46 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
     {
         int x = GET_X_LPARAM(lParam),
             y = GET_Y_LPARAM(lParam);
-        // Convert the screen point to a client point
-        wxPoint MenuPoint = ScreenToClient(wxPoint(x, y));
-
-        // can't use GetSelection() here as it would assert in multiselect mode
-        wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_MENU, this,
-                          wxTreeItemId(TreeView_GetSelection(GetHwnd())));
-
-        // Get the bounding rectangle for the item, including the non-text areas
-        wxRect ItemRect;
-        GetBoundingRect(event.m_item, ItemRect, false);
-        // If the point is inside the bounding rectangle, use it as the click position.
-        // This should be the case for WM_CONTEXTMENU as the result of a right-click
-        if (ItemRect.Contains(MenuPoint))
+
+        // the item for which the menu should be shown
+        wxTreeItemId item;
+
+        // the position where the menu should be shown in client coordinates
+        // (so that it can be passed directly to PopupMenu())
+        wxPoint pt;
+
+        if ( x == -1 || y == -1 )
         {
-            event.m_pointDrag = MenuPoint;
+            // this means that the event was generated from keyboard (e.g. with
+            // Shift-F10 or special Windows menu key)
+            //
+            // use the Explorer standard of putting the menu at the left edge
+            // of the text, in the vertical middle of the text
+            item = wxTreeItemId(TreeView_GetSelection(GetHwnd()));
+            if ( item.IsOk() )
+            {
+                // Use the bounding rectangle of only the text part
+                wxRect rect;
+                GetBoundingRect(item, rect, true);
+                pt = wxPoint(rect.GetX(), rect.GetY() + rect.GetHeight() / 2);
+            }
         }
-        // Use the Explorer standard of putting the menu at the left edge of the text,
-        // in the vertical middle of the text. Should be the case for the "menu" key
-        else
+        else // event from mouse, use mouse position
         {
-            // Use the bounding rectangle of only the text part
-            GetBoundingRect(event.m_item, ItemRect, true);
-            event.m_pointDrag = wxPoint(ItemRect.GetX(), ItemRect.GetY() + ItemRect.GetHeight() / 2);
+            pt = ScreenToClient(wxPoint(x, y));
+
+            TV_HITTESTINFO tvhti;
+            tvhti.pt.x = pt.x;
+            tvhti.pt.y = pt.y;
+            if ( TreeView_HitTest(GetHwnd(), &tvhti) )
+                item = wxTreeItemId(tvhti.hItem);
         }
 
+        // create the event
+        wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_MENU, this, item);
+
+        event.m_pointDrag = pt;
+
         if ( GetEventHandler()->ProcessEvent(event) )
             processed = true;
         //else: continue with generating wxEVT_CONTEXT_MENU in base class code
@@ -2040,31 +2049,15 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
         // same meaning for all of them
         int x = GET_X_LPARAM(lParam),
             y = GET_Y_LPARAM(lParam);
-        HTREEITEM htItem = GetItemFromPoint(GetHwnd(), x, y);
 
         TV_HITTESTINFO tvht;
         tvht.pt.x = x;
         tvht.pt.y = y;
 
-        (void) TreeView_HitTest(GetHwnd(), &tvht);
+        HTREEITEM htItem = TreeView_HitTest(GetHwnd(), &tvht);
 
         switch ( nMsg )
         {
-            case WM_RBUTTONDOWN:
-                // if the item we are about to right click on is not already
-                // selected or if we click outside of any item, remove the
-                // entire previous selection
-                if ( !htItem || !::IsItemSelected(GetHwnd(), htItem) )
-                {
-                    UnselectAll();
-                }
-
-                // select item and set the focus to the
-                // newly selected item
-                ::SelectItem(GetHwnd(), htItem);
-                ::SetFocus(GetHwnd(), htItem);
-                break;
-
             case WM_LBUTTONDOWN:
                 if ( htItem && isMultiple && (tvht.flags & TVHT_ONITEM) != 0 )
                 {
@@ -2231,6 +2224,8 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
 
                     // generate the drag end event
                     wxTreeEvent event(wxEVT_COMMAND_TREE_END_DRAG, this, htItem);
+                    event.m_pointDrag = wxPoint(x, y);
+
                     (void)GetEventHandler()->ProcessEvent(event);
 
                     // if we don't do it, the tree seems to think that 2 items
@@ -2367,32 +2362,9 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
 WXLRESULT
 wxTreeCtrl::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
 {
-    // default WM_RBUTTONDOWN handler enters modal loop inside DefWindowProc()
-    // waiting for WM_RBUTTONUP and then sends the resulting WM_CONTEXTMENU to
-    // the parent window, not us, which completely breaks everything so simply
-    // don't let it see this message at all
-    if ( nMsg == WM_RBUTTONDOWN )
-        return 0;
-
-    // but because of the above we don't get NM_RCLICK which is normally
-    // generated by tree window proc when the modal loop mentioned above ends
-    // because the mouse is released -- synthesize it ourselves instead
-    if ( nMsg == WM_RBUTTONUP )
-    {
-        NMHDR hdr;
-        hdr.hwndFrom = GetHwnd();
-        hdr.idFrom = GetId();
-        hdr.code = NM_RCLICK;
-
-        WXLPARAM rc;
-        MSWOnNotify(GetId(), (LPARAM)&hdr, &rc);
-
-        // continue as usual
-    }
-
     if ( nMsg == WM_CHAR )
     {
-        // also don't let the control process Space and Return keys because it
+        // don't let the control process Space and Return keys because it
         // doesn't do anything useful with them anyhow but always beeps
         // annoyingly when it receives them and there is no way to turn it off
         // simply if you just process TREEITEM_ACTIVATED event to which Space
@@ -2503,8 +2475,8 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
 
                 break;
             }
-#endif
-#endif
+#endif // TVN_GETINFOTIP
+#endif // !__WXWINCE__
 
         case TVN_GETDISPINFO:
             eventType = wxEVT_COMMAND_TREE_GET_INFO;
@@ -2775,6 +2747,17 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
             *result = false;
             break;
 
+        case NM_RCLICK:
+            // prevent tree control from sending WM_CONTEXTMENU to our parent
+            // (which it does if NM_RCLICK is not handled) because we want to
+            // send it to the control itself
+            *result =
+            processed = true;
+
+            ::SendMessage(GetHwnd(), WM_CONTEXTMENU,
+                          (WPARAM)GetHwnd(), ::GetMessagePos());
+            break;
+
         case TVN_BEGINDRAG:
         case TVN_BEGINRDRAG:
             if ( event.IsAllowed() )