[RSHELL]
authorDavid Quintana <gigaherz@gmail.com>
Sat, 22 Feb 2014 22:59:28 +0000 (22:59 +0000)
committerDavid Quintana <gigaherz@gmail.com>
Sat, 22 Feb 2014 22:59:28 +0000 (22:59 +0000)
* Take "DbgPrint" function from explorer-new.
* CMenuBand: Show placeholder if the band gets an empty IShellFolder. Added what I guess is a hack, to allow CMenuDeskBar to get the submenu popup from the band.
* CMenuDeskBar: Use WM_ACTIVATE and WM_ACTIVATEAPP to detect when the menu should be closed. Uses the hack above for the exception of showing a submenu.
CORE-7886

svn path=/branches/shell-experiments/; revision=62295

base/shell/rshell/CMenuBand.cpp
base/shell/rshell/CMenuDeskBar.cpp
base/shell/rshell/precomp.h

index 4e2c799..7641ad0 100644 (file)
@@ -332,6 +332,11 @@ private:
     }
 
 private:
+    CMenuBand * m_currentBand;
+    HWND m_currentFocus;
+    HHOOK m_hHook;
+    DWORD m_threadId;
+
     // TODO: make dynamic
 #define MAX_RECURSE 20
     CMenuBand* m_bandStack[MAX_RECURSE];
@@ -399,23 +404,16 @@ public:
     BEGIN_COM_MAP(CMenuFocusManager)
     END_COM_MAP()
 
-private:
-    CMenuBand * m_currentBand;
-    HWND m_currentFocus;
-    HHOOK m_hHook;
-    DWORD m_threadId;
-
     LRESULT GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam)
     {
         if (nCode < 0)
             return CallNextHookEx(m_hHook, nCode, wParam, lParam);
 
-        BOOL callNext = TRUE;
-        BOOL fRemoved = wParam;
-        MSG* msg = reinterpret_cast<MSG*>(lParam);
-
         if (nCode == HC_ACTION)
         {
+            BOOL callNext = TRUE;
+            MSG* msg = reinterpret_cast<MSG*>(lParam);
+
             // Do whatever is necessary here
 
             switch (msg->message)
@@ -452,9 +450,6 @@ private:
                 //    PostMessage(m_currentFocus, WM_SYSCHAR, wParam, lParam);
                 //}
                 break;
-            case WM_ACTIVATE:
-                break;
-
             }
 
             if (!callNext)
@@ -481,24 +476,26 @@ private:
     HRESULT UpdateFocus(CMenuBand * newBand)
     {
         HRESULT hr;
+        HWND newFocus;
 
-        hr = RemoveHooks(m_currentFocus);
-
-        if (FAILED(hr) || !newBand)
+        if (newBand == NULL)
         {
+            hr = RemoveHooks(m_currentFocus);
             m_currentFocus = NULL;
             m_currentBand = NULL;
             return S_OK;
         }
 
-        HWND newFocus;
         hr = newBand->_GetTopLevelWindow(&newFocus);
         if (FAILED(hr))
             return hr;
 
-        hr = PlaceHooks(m_currentFocus);
-        if (FAILED(hr))
-            return hr;
+        if (!m_currentBand)
+        {
+            hr = PlaceHooks(newFocus);
+            if (FAILED(hr))
+                return hr;
+        }
 
         m_currentFocus = newFocus;
         m_currentBand = newBand;
@@ -1147,6 +1144,22 @@ HRESULT CMenuSFToolbar::FillToolbar()
     }
     CoTaskMemFree(item);
 
+    // If no items were added, show the "empty" placeholder
+    if (i == 0)
+    {
+        TBBUTTON tbb = { 0 };
+        PWSTR MenuString = L"(Empty)";
+
+        tbb.fsState = 0/*TBSTATE_DISABLED*/;
+        tbb.fsStyle = 0;
+        tbb.iString = (INT_PTR) MenuString;
+        tbb.iBitmap = -1;
+
+        SendMessageW(m_hwnd, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
+
+        return S_OK;
+    }
+
     return hr;
 }
 
@@ -1829,7 +1842,15 @@ HRESULT STDMETHODCALLTYPE CMenuBand::SetClient(IUnknown *punkClient)
 
 HRESULT STDMETHODCALLTYPE CMenuBand::GetClient(IUnknown **ppunkClient)
 {
-    UNIMPLEMENTED;
+    // HACK, so I can test for a submenu in the DeskBar
+    //UNIMPLEMENTED;
+    if (ppunkClient)
+    {
+        if (m_subMenuChild)
+            *ppunkClient = m_subMenuChild;
+        else
+            *ppunkClient = NULL;
+    }
     return S_OK;
 }
 
@@ -2209,7 +2230,6 @@ HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType)
     return S_OK;
 }
 
-
 HRESULT CMenuBand::_OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude)
 {
     if (m_subMenuChild)
index f5f92f7..2ffed5d 100644 (file)
@@ -56,6 +56,8 @@ private:
 
     INT m_Level;
 
+    BOOL m_Shown;
+
 public:
     CMenuDeskBar();
     ~CMenuDeskBar();
@@ -68,8 +70,9 @@ public:
     BEGIN_MSG_MAP(CMenuDeskBar)
         MESSAGE_HANDLER(WM_SIZE, _OnSize)
         MESSAGE_HANDLER(WM_NOTIFY, _OnNotify)
-        MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, _OnWindowPosChanged)
         MESSAGE_HANDLER(WM_PAINT, _OnPaint)
+        MESSAGE_HANDLER(WM_ACTIVATE, _OnActivate)
+        MESSAGE_HANDLER(WM_ACTIVATEAPP, _OnAppActivate)
     END_MSG_MAP()
 
     BEGIN_COM_MAP(CMenuDeskBar)
@@ -131,9 +134,11 @@ private:
     // message handlers
     LRESULT _OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
     LRESULT _OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
-    LRESULT _OnWindowPosChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
     LRESULT _OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+    LRESULT _OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+    LRESULT _OnAppActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
 
+    BOOL _IsSubMenuParent(HWND hwnd);
     HRESULT _CloseBar();
 };
 
@@ -160,7 +165,8 @@ INT deskBarCount=0;
 CMenuDeskBar::CMenuDeskBar() :
     m_Client(NULL),
     m_Banner(NULL),
-    m_Level(deskBarCount++)
+    m_Level(deskBarCount++),
+    m_Shown(FALSE)
 {
 }
 
@@ -169,6 +175,11 @@ CMenuDeskBar::~CMenuDeskBar()
     deskBarCount--;
 }
 
+HRESULT STDMETHODCALLTYPE CMenuDeskBar::Initialize(THIS)
+{
+    return S_OK;
+}
+
 HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetWindow(HWND *lphwnd)
 {
     if (lphwnd == NULL)
@@ -320,6 +331,7 @@ HRESULT STDMETHODCALLTYPE CMenuDeskBar::OnPosRectChangeDB(LPRECT prc)
 {
     if (prc == NULL)
         return E_POINTER;
+
     return S_OK;
 }
 
@@ -327,6 +339,9 @@ HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetSite(IUnknown *pUnkSite)
 {
     // Windows closes the bar if this is called when the bar is shown
 
+    if (m_Shown)
+        _CloseBar();
+
     m_Site = pUnkSite;
 
     IUnknown_QueryService(m_Site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup, &m_SubMenuParent));
@@ -342,88 +357,6 @@ HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetSite(REFIID riid, void **ppvSite)
     return m_Site->QueryInterface(riid, ppvSite);
 }
 
-LRESULT CMenuDeskBar::_OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
-{
-    if (m_Client)
-    {
-        RECT rc;
-
-        GetClientRect(&rc);
-
-        if (m_Banner != NULL)
-        {
-            BITMAP bm;
-            ::GetObject(m_Banner, sizeof(bm), &bm);
-            rc.left += bm.bmWidth;
-        }
-
-        ::SetWindowPos(m_ClientWindow, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 0);
-    }
-
-    return 0;
-}
-
-LRESULT CMenuDeskBar::_OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
-{
-    CComPtr<IWinEventHandler>               winEventHandler;
-    LRESULT                                 result;
-    HRESULT                                 hr;
-
-    result = 0;
-    if (m_Client.p != NULL)
-    {
-        hr = m_Client->QueryInterface(IID_PPV_ARG(IWinEventHandler, &winEventHandler));
-        if (SUCCEEDED(hr) && winEventHandler.p != NULL)
-            hr = winEventHandler->OnWinEvent(NULL, uMsg, wParam, lParam, &result);
-    }
-    return result;
-}
-
-LRESULT CMenuDeskBar::_OnWindowPosChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
-{
-    return 0;
-}
-
-LRESULT CMenuDeskBar::_OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
-{
-    bHandled = FALSE;
-
-    if (m_Banner && !m_IconSize)
-    {
-        BITMAP bm;
-        PAINTSTRUCT ps;
-        HDC hdc = BeginPaint(&ps);
-
-        HDC hdcMem = ::CreateCompatibleDC(hdc);
-        HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_Banner);
-
-        ::GetObject(m_Banner, sizeof(bm), &bm);
-
-        RECT rc;
-        if (!GetClientRect(&rc))
-            WARN("GetClientRect failed\n");
-
-        const int bx = bm.bmWidth;
-        const int by = bm.bmHeight;
-        const int cy = rc.bottom;
-
-        TRACE("Painting banner: %d by %d\n", bm.bmWidth, bm.bmHeight);
-
-        if (!::StretchBlt(hdc, 0, 0, bx, cy - by, hdcMem, 0, 0, bx, 1, SRCCOPY))
-            WARN("StretchBlt failed\n");
-
-        if (!::BitBlt(hdc, 0, cy - by, bx, by, hdcMem, 0, 0, SRCCOPY))
-            WARN("BitBlt failed\n");
-
-        ::SelectObject(hdcMem, hbmOld);
-        ::DeleteDC(hdcMem);
-
-        EndPaint(&ps);
-    }
-
-    return TRUE;
-}
-
 HRESULT STDMETHODCALLTYPE CMenuDeskBar::Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags)
 {
     HRESULT hr;
@@ -502,6 +435,8 @@ HRESULT STDMETHODCALLTYPE CMenuDeskBar::Popup(POINTL *ppt, RECTL *prcExclude, MP
 
     this->SetWindowPos(HWND_TOPMOST, x, y, cx, cy, SWP_SHOWWINDOW);
 
+    m_Shown = true;
+
     // HACK: The bar needs to be notified of the size AFTER it is shown.
     // Quick & dirty way of getting it done.
     BOOL bHandled;
@@ -509,6 +444,7 @@ HRESULT STDMETHODCALLTYPE CMenuDeskBar::Popup(POINTL *ppt, RECTL *prcExclude, MP
 
     UIActivateIO(TRUE, NULL);
 
+
     return S_OK;
 }
 
@@ -555,8 +491,28 @@ HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetBitmap(THIS_ HBITMAP* phBitmap)
     return S_OK;
 }
 
-HRESULT STDMETHODCALLTYPE CMenuDeskBar::OnSelect(
-    DWORD dwSelectType)
+HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetSubMenu(IMenuPopup *pmp, BOOL fSet)
+{
+    // Called by the MenuBand to assign itself as the logical child of the DeskBar
+
+    if (fSet)
+    {
+        m_SubMenuChild = pmp;
+    }
+    else
+    {
+        if (m_SubMenuChild)
+        {
+            if (SHIsSameObject(pmp, m_SubMenuChild))
+            {
+                m_SubMenuChild = NULL;
+            }
+        }
+    }
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE CMenuDeskBar::OnSelect(DWORD dwSelectType)
 {
     /* As far as I can tell, the submenu hierarchy looks like this:
 
@@ -604,6 +560,8 @@ HRESULT CMenuDeskBar::_CloseBar()
     CComPtr<IDeskBarClient> dbc;
     HRESULT hr;
 
+    m_Shown = false;
+
     if (m_SubMenuChild)
     {
         hr = m_SubMenuChild->OnSelect(MPOS_CANCELLEVEL);
@@ -624,29 +582,150 @@ HRESULT CMenuDeskBar::_CloseBar()
     return UIActivateIO(FALSE, NULL);
 }
 
-HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetSubMenu(IMenuPopup *pmp, BOOL fSet)
+BOOL CMenuDeskBar::_IsSubMenuParent(HWND hwnd)
 {
-    // Called by the CHILD to notify the parent of the submenu object
+    CComPtr<IMenuPopup> popup = m_SubMenuParent;
 
-    if (fSet)
+    while (popup)
     {
-        m_SubMenuChild = pmp;
+        HRESULT hr;
+        CComPtr<IOleWindow> window;
+
+        hr = popup->QueryInterface(IID_PPV_ARG(IOleWindow, &window));
+        if (FAILED(hr))
+            return FALSE;
+
+        HWND parent;
+
+        hr = window->GetWindow(&parent);
+        if (SUCCEEDED(hr) && hwnd == parent)
+            return TRUE;
+
+        popup = NULL;
+        hr = IUnknown_GetSite(window, IID_PPV_ARG(IMenuPopup, &popup));
+        if (FAILED(hr))
+            return FALSE;
     }
-    else
+
+    return FALSE;
+}
+
+LRESULT CMenuDeskBar::_OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
+{
+    if (m_Client)
     {
-        if (m_SubMenuChild)
+        RECT rc;
+
+        GetClientRect(&rc);
+
+        if (m_Banner != NULL)
         {
-            if (SHIsSameObject(pmp, m_SubMenuChild))
-            {
-                m_SubMenuChild = NULL;
-            }
+            BITMAP bm;
+            ::GetObject(m_Banner, sizeof(bm), &bm);
+            rc.left += bm.bmWidth;
         }
+
+        ::SetWindowPos(m_ClientWindow, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 0);
     }
-    return S_OK;
+
+    return 0;
 }
 
+LRESULT CMenuDeskBar::_OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
+{
+    if (!m_Client)
+        return 0;
 
-HRESULT STDMETHODCALLTYPE CMenuDeskBar::Initialize(THIS)
+    CComPtr<IWinEventHandler> winEventHandler;
+    HRESULT hr = m_Client->QueryInterface(IID_PPV_ARG(IWinEventHandler, &winEventHandler));
+    if (FAILED(hr))
+        return 0;
+
+    if (winEventHandler)
+    {
+        LRESULT result;
+        hr = winEventHandler->OnWinEvent(NULL, uMsg, wParam, lParam, &result);
+        if (FAILED(hr))
+            return 0;
+        return result;
+    }
+
+    return 0;
+}
+
+LRESULT CMenuDeskBar::_OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
-    return S_OK;
+    bHandled = FALSE;
+
+    if (m_Banner && !m_IconSize)
+    {
+        BITMAP bm;
+        PAINTSTRUCT ps;
+        HDC hdc = BeginPaint(&ps);
+
+        HDC hdcMem = ::CreateCompatibleDC(hdc);
+        HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_Banner);
+
+        ::GetObject(m_Banner, sizeof(bm), &bm);
+
+        RECT rc;
+        if (!GetClientRect(&rc))
+            WARN("GetClientRect failed\n");
+
+        const int bx = bm.bmWidth;
+        const int by = bm.bmHeight;
+        const int cy = rc.bottom;
+
+        TRACE("Painting banner: %d by %d\n", bm.bmWidth, bm.bmHeight);
+
+        if (!::StretchBlt(hdc, 0, 0, bx, cy - by, hdcMem, 0, 0, bx, 1, SRCCOPY))
+            WARN("StretchBlt failed\n");
+
+        if (!::BitBlt(hdc, 0, cy - by, bx, by, hdcMem, 0, 0, SRCCOPY))
+            WARN("BitBlt failed\n");
+
+        ::SelectObject(hdcMem, hbmOld);
+        ::DeleteDC(hdcMem);
+
+        EndPaint(&ps);
+    }
+
+    return TRUE;
+}
+
+LRESULT CMenuDeskBar::_OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
+{
+    if (wParam != 0)
+        return 0;
+
+    // HACK! I just want it to work !!!
+    CComPtr<IDeskBar> db;
+    HRESULT hr = IUnknown_QueryService(m_Client, SID_SMenuBandChild, IID_PPV_ARG(IDeskBar, &db));
+    if (FAILED(hr))
+        return 0;
+
+    CComPtr<IUnknown> punk;
+
+    hr = db->GetClient(&punk);
+    if (FAILED(hr))
+        return 0;
+
+    if (!punk && m_Shown)
+    {
+        if (!_IsSubMenuParent(reinterpret_cast<HWND>(lParam)))
+        {
+            OnSelect(MPOS_FULLCANCEL);
+        }
+    }
+
+    return 0;
+}
+
+LRESULT CMenuDeskBar::_OnAppActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
+{
+    if (wParam == 0)
+    {
+        OnSelect(MPOS_FULLCANCEL);
+    }
+    return 0;
 }
index 5715aaa..4b1652f 100644 (file)
@@ -3,9 +3,9 @@
 #define USE_SYSTEM_MENUSITE 0
 #define USE_SYSTEM_MENUBAND 0
 
-#define WRAP_MENUDESKBAR 1
-#define WRAP_MENUSITE 1
-#define WRAP_MENUBAND 1
+#define WRAP_MENUDESKBAR 0
+#define WRAP_MENUSITE 0
+#define WRAP_MENUBAND 0
 
 #include <stdio.h>
 #include <tchar.h>
@@ -44,3 +44,39 @@ extern "C" HRESULT CMenuBand_Constructor(REFIID riid, LPVOID *ppv);
 extern "C" HRESULT CMenuDeskBar_Wrapper(IDeskBar * db, REFIID riid, LPVOID *ppv);
 extern "C" HRESULT CMenuSite_Wrapper(IBandSite * bs, REFIID riid, LPVOID *ppv);
 extern "C" HRESULT CMenuBand_Wrapper(IShellMenu * sm, REFIID riid, LPVOID *ppv);
+
+static __inline ULONG
+Win32DbgPrint(const char *filename, int line, const char *lpFormat, ...)
+{
+    char szMsg[512];
+    char *szMsgStart;
+    const char *fname;
+    va_list vl;
+    ULONG uRet;
+
+    fname = strrchr(filename, '\\');
+    if (fname == NULL)
+    {
+        fname = strrchr(filename, '/');
+        if (fname != NULL)
+            fname++;
+    }
+    else
+        fname++;
+
+    if (fname == NULL)
+        fname = filename;
+
+    szMsgStart = szMsg + sprintf(szMsg, "%s:%d: ", fname, line);
+
+    va_start(vl, lpFormat);
+    uRet = (ULONG) vsprintf(szMsgStart, lpFormat, vl);
+    va_end(vl);
+
+    OutputDebugStringA(szMsg);
+
+    return uRet;
+}
+
+#define DbgPrint(fmt, ...) \
+    Win32DbgPrint(__FILE__, __LINE__, fmt, ##__VA_ARGS__)