From 2ca6b95aeba635d2c7f3eefa71411436c52ce615 Mon Sep 17 00:00:00 2001 From: David Quintana Date: Fri, 7 Mar 2014 22:28:55 +0000 Subject: [PATCH] [BROWSEUI] * Load and use rshell for the menubar. * Properly forward WM_NOTIFY and WM_COMMAND messages to the toolbars. [RSHELL] * Improve behaviour of horizontal menubands. * Clicking on submenu items does not work yet. CORE-7586 svn path=/branches/shell-experiments/; revision=62448 --- base/shell/rshell/CMakeLists.txt | 6 + base/shell/rshell/CMenuBand.cpp | 39 +++++-- base/shell/rshell/CMenuBand.h | 2 +- base/shell/rshell/CMenuDeskBar.cpp | 2 +- base/shell/rshell/CMenuToolbars.cpp | 121 +++++++++++++++------ base/shell/rshell/CMenuToolbars.h | 4 +- dll/win32/browseui/CMakeLists.txt | 6 + dll/win32/browseui/internettoolbar.cpp | 145 ++++++++++++++++++++----- dll/win32/browseui/internettoolbar.h | 3 +- dll/win32/browseui/precomp.h | 37 +++++++ media/fonts/Marlett.ttf | Bin 28340 -> 4096 bytes 11 files changed, 288 insertions(+), 77 deletions(-) diff --git a/base/shell/rshell/CMakeLists.txt b/base/shell/rshell/CMakeLists.txt index ae88c160fd8..46d23a74312 100644 --- a/base/shell/rshell/CMakeLists.txt +++ b/base/shell/rshell/CMakeLists.txt @@ -49,3 +49,9 @@ add_custom_command(TARGET rshell POST_BUILD "$" "$/$" COMMENT "Copying to output directory") + +add_custom_command(TARGET rshell POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy + "$" + "$/$" + COMMENT "Copying to output directory") diff --git a/base/shell/rshell/CMenuBand.cpp b/base/shell/rshell/CMenuBand.cpp index 272c13049b4..23222fe608d 100644 --- a/base/shell/rshell/CMenuBand.cpp +++ b/base/shell/rshell/CMenuBand.cpp @@ -52,7 +52,10 @@ CMenuBand::CMenuBand() : m_site(NULL), m_psmc(NULL), m_subMenuChild(NULL), + m_hmenu(NULL), + m_menuOwner(NULL), m_useBigIcons(FALSE), + m_topLevelWindow(NULL), m_hotBar(NULL), m_hotItem(-1) { @@ -123,7 +126,7 @@ HRESULT STDMETHODCALLTYPE CMenuBand::SetMenu( m_staticToolbar = new CMenuStaticToolbar(this); } m_hmenu = hmenu; - m_menuOwner; + m_menuOwner = hwnd; HRESULT hr = m_staticToolbar->SetMenu(hmenu, hwnd, dwFlags); if (FAILED_UNEXPECTEDLY(hr)) @@ -203,7 +206,7 @@ HRESULT STDMETHODCALLTYPE CMenuBand::SetSite(IUnknown *pUnkSite) } hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup, &m_subMenuParent)); - if (FAILED_UNEXPECTEDLY(hr)) + if (FAILED(hr) && hr != E_NOINTERFACE) return hr; CComPtr pTopLevelWindow; @@ -326,10 +329,13 @@ HRESULT STDMETHODCALLTYPE CMenuBand::ShowDW(BOOL fShow) return hr; } - if (fShow) - hr = m_focusManager->PushMenu(this); - else - hr = m_focusManager->PopMenu(this); + if (m_dwFlags & SMINIT_VERTICAL) + { + if (fShow) + hr = m_focusManager->PushMenu(this); + else + hr = m_focusManager->PopMenu(this); + } return S_OK; } @@ -401,6 +407,8 @@ HRESULT STDMETHODCALLTYPE CMenuBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdI { return S_FALSE; } + + return S_FALSE; } UNIMPLEMENTED; @@ -610,9 +618,24 @@ HRESULT CMenuBand::_CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam, UINT id, LPI return hr; } -HRESULT CMenuBand::_TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y) +HRESULT CMenuBand::_TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y, RECT& rcExclude) { - ::TrackPopupMenu(popup, 0, x, y, 0, m_menuOwner, NULL); + HWND sendTo = m_menuOwner; + + // FIXME: use? + //TPMPARAMS params = { sizeof(TPMPARAMS), rcExclude }; + + if (sendTo) + { + ::TrackPopupMenuEx(popup, 0, x, y, sendTo, NULL); // ¶ms); + } + else + { + GetWindow(&sendTo); + ::TrackPopupMenuEx(popup, TPM_RETURNCMD, x, y, sendTo, NULL); // ¶ms); + // TODO: use the result somehow + } + return S_OK; } diff --git a/base/shell/rshell/CMenuBand.h b/base/shell/rshell/CMenuBand.h index 1e6fec1beeb..b487d6e711a 100644 --- a/base/shell/rshell/CMenuBand.h +++ b/base/shell/rshell/CMenuBand.h @@ -171,7 +171,7 @@ public: HRESULT _CallCBWithItemId(UINT Id, UINT uMsg, WPARAM wParam, LPARAM lParam); HRESULT _CallCBWithItemPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam); - HRESULT _TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y); + HRESULT _TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y, RECT& rcExclude); HRESULT _GetTopLevelWindow(HWND*topLevel); HRESULT _OnHotItemChanged(CMenuToolbarBase * tb, INT id); HRESULT _MenuItemHotTrack(DWORD changeType); diff --git a/base/shell/rshell/CMenuDeskBar.cpp b/base/shell/rshell/CMenuDeskBar.cpp index 5feed659677..6e310bc83a3 100644 --- a/base/shell/rshell/CMenuDeskBar.cpp +++ b/base/shell/rshell/CMenuDeskBar.cpp @@ -417,7 +417,7 @@ HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetSubMenu(IMenuPopup *pmp, BOOL fSet) { if (m_SubMenuChild) { - if (SHIsSameObject(pmp, m_SubMenuChild)) + if (pmp == m_SubMenuChild) { m_SubMenuChild = NULL; } diff --git a/base/shell/rshell/CMenuToolbars.cpp b/base/shell/rshell/CMenuToolbars.cpp index 4d79750831b..526f722c408 100644 --- a/base/shell/rshell/CMenuToolbars.cpp +++ b/base/shell/rshell/CMenuToolbars.cpp @@ -67,6 +67,10 @@ HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM hdr = reinterpret_cast(lParam); switch (hdr->code) { + case TTN_GETDISPINFOA: + case TTN_GETDISPINFOW: + return S_OK; + case PGN_CALCSIZE: csize = reinterpret_cast(hdr); @@ -99,7 +103,8 @@ HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM switch (cdraw->nmcd.dwDrawStage) { case CDDS_PREPAINT: - *theResult = CDRF_NOTIFYITEMDRAW; + if (m_toolbarFlags & SMINIT_VERTICAL) + *theResult = CDRF_NOTIFYITEMDRAW; return S_OK; case CDDS_ITEMPREPAINT: @@ -160,6 +165,10 @@ HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM return S_OK; } return S_OK; + case RBN_CHILDSIZE: + return S_OK; + default: + DbgPrint("WM_NOTIFY unknown code %d, %d\n", hdr->code, hdr->idFrom); } return S_OK; } @@ -214,6 +223,13 @@ HRESULT CMenuToolbarBase::ShowWindow(BOOL fShow) HRESULT CMenuToolbarBase::UpdateImageLists() { + if ((m_toolbarFlags & (SMINIT_TOPLEVEL| SMINIT_VERTICAL)) == SMINIT_TOPLEVEL) // not vertical. + { + /* Hide the placeholders for the button images */ + SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, 0); + return S_OK; + } + int shiml; if (m_menuBand->UseBigIcons()) { @@ -266,6 +282,8 @@ HRESULT CMenuToolbarBase::CreateToolbar(HWND hwndParent, DWORD dwFlags) #endif } + m_toolbarFlags = dwFlags; + RECT rc; if (!::GetClientRect(hwndParent, &rc) || (rc.left == rc.right) || (rc.top == rc.bottom)) @@ -311,13 +329,6 @@ HRESULT CMenuToolbarBase::CreateToolbar(HWND hwndParent, DWORD dwFlags) /* Identify the version of the used Common Controls DLL by sending the size of the TBBUTTON structure */ SendMessageW(hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); - //if (dwFlags & SMINIT_TOPLEVEL) - //{ - // /* Hide the placeholders for the button images */ - // SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, 0); - //} - //else - SetWindowLongPtr(hwndToolbar, GWLP_USERDATA, reinterpret_cast(this)); m_SubclassOld = (WNDPROC) SetWindowLongPtr(hwndToolbar, GWLP_WNDPROC, reinterpret_cast(CMenuToolbarBase::s_SubclassProc)); @@ -349,8 +360,11 @@ HRESULT CMenuToolbarBase::SetPosSize(int x, int y, int cx, int cy) SetWindowPos(m_hwndToolbar, NULL, x, y, cx, m_idealSize.cy, 0); } SetWindowPos(m_hwnd, NULL, x, y, cx, cy, 0); - DWORD btnSize = SendMessage(m_hwndToolbar, TB_GETBUTTONSIZE, 0, 0); - SendMessage(m_hwndToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(cx, HIWORD(btnSize))); + if (m_toolbarFlags & SMINIT_VERTICAL) + { + DWORD btnSize = SendMessage(m_hwndToolbar, TB_GETBUTTONSIZE, 0, 0); + SendMessage(m_hwndToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(cx, HIWORD(btnSize))); + } return S_OK; } @@ -372,8 +386,16 @@ LRESULT CALLBACK CMenuToolbarBase::s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM w LRESULT CMenuToolbarBase::SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + LRESULT lr; + switch (uMsg) { + case WM_COMMAND: + OnWinEvent(hWnd, uMsg, wParam, lParam, &lr); + break; + case WM_NOTIFY: + OnWinEvent(hWnd, uMsg, wParam, lParam, &lr); + break; case WM_TIMER: if (wParam == TIMERID_HOTTRACK) { @@ -402,9 +424,12 @@ HRESULT CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM * hot) } else if (m_hotItem != hot->idNew) { - DWORD elapsed = 0; - SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &elapsed, 0); - SetTimer(m_hwndToolbar, TIMERID_HOTTRACK, elapsed, NULL); + if (m_toolbarFlags & SMINIT_VERTICAL) + { + DWORD elapsed = 0; + SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &elapsed, 0); + SetTimer(m_hwndToolbar, TIMERID_HOTTRACK, elapsed, NULL); + } m_hotItem = hot->idNew; m_menuBand->_OnHotItemChanged(this, m_hotItem); @@ -415,8 +440,18 @@ HRESULT CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM * hot) HRESULT CMenuToolbarBase::OnHotItemChanged(CMenuToolbarBase * toolbar, INT item) { + BOOL wasChecked = FALSE; + if (m_hotBar == this && !(m_toolbarFlags & SMINIT_VERTICAL)) + { + wasChecked = SendMessage(m_hwndToolbar, TB_ISBUTTONCHECKED, m_hotItem, 0); + SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_hotItem, FALSE); + } m_hotBar = toolbar; m_hotItem = item; + if (wasChecked && m_hotBar == this && !(m_toolbarFlags & SMINIT_VERTICAL)) + { + SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_hotItem, TRUE); + } InvalidateDraw(); return S_OK; } @@ -436,18 +471,25 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, IShellMenu* child HRESULT hr = 0; RECT rc = { 0 }; + RECT rcx = { 0 }; if (!SendMessage(m_hwndToolbar, TB_GETITEMRECT, index, reinterpret_cast(&rc))) return E_FAIL; + GetWindowRect(m_hwnd, &rcx); + POINT a = { rc.left, rc.top }; POINT b = { rc.right, rc.bottom }; + POINT c = { rcx.left, rcx.top }; + POINT d = { rcx.right, rcx.bottom }; ClientToScreen(m_hwndToolbar, &a); ClientToScreen(m_hwndToolbar, &b); + ClientToScreen(m_hwnd, &c); + ClientToScreen(m_hwnd, &d); POINTL pt = { b.x - 3, a.y - 3 }; - RECTL rcl = { a.x, a.y, b.x, b.y }; // maybe-TODO: fetch client area of deskbar? + RECTL rcl = { c.x, c.y, d.x, d.y }; #if USE_SYSTEM_MENUSITE hr = CoCreateInstance(CLSID_MenuBandSite, @@ -499,20 +541,40 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, IShellMenu* child return S_OK; } -HRESULT CMenuToolbarBase::PopupSubMenu(UINT index, HMENU menu) +HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, HMENU menu) { RECT rc = { 0 }; + RECT rcx = { 0 }; if (!SendMessage(m_hwndToolbar, TB_GETITEMRECT, index, reinterpret_cast(&rc))) return E_FAIL; - POINT b = { rc.right, rc.bottom }; + GetWindowRect(m_hwnd, &rcx); + POINT a = { rc.left, rc.top }; + POINT b = { rc.right, rc.bottom }; + POINT c = { rcx.left, rcx.top }; + POINT d = { rcx.right, rcx.bottom }; + + ClientToScreen(m_hwndToolbar, &a); ClientToScreen(m_hwndToolbar, &b); + ClientToScreen(m_hwnd, &c); + ClientToScreen(m_hwnd, &d); + + POINT pt = { a.x, b.y }; + RECT rcl = { c.x, c.y, d.x, d.y }; + + if (m_toolbarFlags & SMINIT_VERTICAL) + { + pt.x = b.x; + pt.y = a.y; + } HMENU popup = GetSubMenu(menu, index); - m_menuBand->_TrackSubMenuUsingTrackPopupMenu(popup, b.x, b.y); + m_menuBand->_TrackSubMenuUsingTrackPopupMenu(popup, pt.x, pt.y, rcl); + + SendMessage(m_hwndToolbar, TB_CHECKBUTTON, uItem, FALSE); return S_OK; } @@ -653,22 +715,23 @@ HRESULT CMenuToolbarBase::AddButton(DWORD commandId, LPCWSTR caption, BOOL hasSu tbb.fsState = TBSTATE_ENABLED; #ifndef TBSTYLE_EX_VERTICAL - if (!last) + if (!last && (m_toolbarFlags & SMINIT_VERTICAL)) tbb.fsState |= TBSTATE_WRAP; #endif tbb.fsStyle = 0; - if (hasSubMenu) + if (hasSubMenu && (m_toolbarFlags & SMINIT_VERTICAL)) tbb.fsStyle |= BTNS_DROPDOWN; + if (!(m_toolbarFlags & SMINIT_VERTICAL)) + tbb.fsStyle |= BTNS_AUTOSIZE | BTNS_CHECKGROUP; + tbb.iString = (INT_PTR) caption; tbb.idCommand = commandId; tbb.iBitmap = iconId; tbb.dwData = buttonData; - DbgPrint("Trying to add a new button with id %d and caption '%S'...\n", commandId, caption); - if (!SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast(&tbb))) return HRESULT_FROM_WIN32(GetLastError()); @@ -681,14 +744,12 @@ HRESULT CMenuToolbarBase::AddSeparator(BOOL last) tbb.fsState = TBSTATE_ENABLED; #ifndef TBSTYLE_EX_VERTICAL - if (!last) + if (!last && (m_toolbarFlags & SMINIT_VERTICAL)) tbb.fsState |= TBSTATE_WRAP; #endif tbb.fsStyle = BTNS_SEP; tbb.iBitmap = 0; - DbgPrint("Trying to add a new separator...\n"); - if (!SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast(&tbb))) return HRESULT_FROM_WIN32(GetLastError()); @@ -705,8 +766,6 @@ HRESULT CMenuToolbarBase::AddPlaceholder() tbb.iString = (INT_PTR) MenuString; tbb.iBitmap = -1; - DbgPrint("Trying to add a new placeholder...\n"); - if (!SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast(&tbb))) return HRESULT_FROM_WIN32(GetLastError()); @@ -810,8 +869,6 @@ HRESULT CMenuStaticToolbar::FillToolbar() count++; - DbgPrint("Found item with fType=%x, cmdId=%d\n", info.fType, info.wID); - if (info.fType & MFT_SEPARATOR) { AddSeparator(last); @@ -839,8 +896,6 @@ HRESULT CMenuStaticToolbar::FillToolbar() } } - DbgPrint("Created toolbar with %d buttons.\n", count); - return S_OK; } @@ -876,7 +931,7 @@ HRESULT CMenuStaticToolbar::InternalPopupItem(INT uItem, INT index, DWORD_PTR dw if (nfo->dwFlags&SMIF_TRACKPOPUP) { - return PopupSubMenu(index, m_hmenu); + return PopupSubMenu(uItem, index, m_hmenu); } else { @@ -951,13 +1006,9 @@ HRESULT CMenuSFToolbar::FillToolbar() // If no items were added, show the "empty" placeholder if (i == 0) { - DbgPrint("The toolbar is empty, adding placeholder.\n"); - return AddPlaceholder(); } - DbgPrint("Created toolbar with %d buttons.\n", i); - return hr; } diff --git a/base/shell/rshell/CMenuToolbars.h b/base/shell/rshell/CMenuToolbars.h index 5fcd2fc1524..984e4bca563 100644 --- a/base/shell/rshell/CMenuToolbars.h +++ b/base/shell/rshell/CMenuToolbars.h @@ -42,6 +42,8 @@ protected: CMenuToolbarBase * m_popupBar; INT m_popupItem; + DWORD m_toolbarFlags; + private: static LRESULT CALLBACK s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -61,7 +63,7 @@ public: HRESULT OnPopupItemChanged(CMenuToolbarBase * toolbar, INT item); HRESULT PopupSubMenu(UINT itemId, UINT index, IShellMenu* childShellMenu); - HRESULT PopupSubMenu(UINT index, HMENU menu); + HRESULT PopupSubMenu(UINT itemId, UINT index, HMENU menu); HRESULT DoContextMenu(IContextMenu* contextMenu); HRESULT ChangeHotItem(DWORD changeType); diff --git a/dll/win32/browseui/CMakeLists.txt b/dll/win32/browseui/CMakeLists.txt index 8305bd8b37d..b242d01028a 100644 --- a/dll/win32/browseui/CMakeLists.txt +++ b/dll/win32/browseui/CMakeLists.txt @@ -59,3 +59,9 @@ add_importlibs(browseui add_pch(browseui precomp.h SOURCE) add_cd_file(TARGET browseui DESTINATION reactos/system32 FOR all) + +add_custom_command(TARGET browseui POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy + "$" + "$/$" + COMMENT "Copying to output directory") diff --git a/dll/win32/browseui/internettoolbar.cpp b/dll/win32/browseui/internettoolbar.cpp index adfd6ef98b4..3541c56b64b 100644 --- a/dll/win32/browseui/internettoolbar.cpp +++ b/dll/win32/browseui/internettoolbar.cpp @@ -67,6 +67,8 @@ extern HRESULT CreateBrandBand(REFIID riid, void **ppv); extern HRESULT CreateBandProxy(REFIID riid, void **ppv); extern HRESULT CreateAddressBand(REFIID riid, void **ppv); +typedef HRESULT(*PMENUBAND_CONSTRUCTOR)(REFIID riid, void **ppv); + class CInternetToolbar; class CDockSite : @@ -372,8 +374,23 @@ HRESULT STDMETHODCALLTYPE CMenuCallback::GetObject(LPSMDATA psmd, REFIID riid, v favoritesHMenu = GetSubMenu(parentHMenu, 3); if (favoritesHMenu == NULL) return E_FAIL; +#if 1 + HMODULE hrs = LoadLibrary(L"rshell.dll"); + + PMENUBAND_CONSTRUCTOR func = (PMENUBAND_CONSTRUCTOR) GetProcAddress(hrs, "CMenuBand_Constructor"); + if (func) + { + hResult = func(IID_PPV_ARG(IShellMenu, &newMenu)); + } + else + { + hResult = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER, + IID_IShellMenu, reinterpret_cast(&newMenu)); + } +#else hResult = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER, IID_IShellMenu, reinterpret_cast(&newMenu)); +#endif if (FAILED(hResult)) return hResult; hResult = newMenu->Initialize(this, FCIDM_MENU_FAVORITES, -1, SMINIT_VERTICAL | SMINIT_CACHED); @@ -536,8 +553,35 @@ HRESULT CInternetToolbar::CreateMenuBar(IShellMenu **menuBar) HWND ownerWindow; HRESULT hResult; +#if 1 + HMODULE hrs = LoadLibraryW(L"rshell.dll"); + + if (!hrs) + { + DbgPrint("Failed: %d\n", GetLastError()); + return E_FAIL; + } + + PMENUBAND_CONSTRUCTOR func = (PMENUBAND_CONSTRUCTOR) GetProcAddress(hrs, "CMenuBand_Constructor"); + if (func) + { + hResult = func(IID_PPV_ARG(IShellMenu, menuBar)); + } + else + { + DbgPrint("Failed: %d\n", GetLastError()); + hResult = E_FAIL; + } + + if (FAILED(hResult)) + { + hResult = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER, + IID_IShellMenu, reinterpret_cast(menuBar)); + } +#else hResult = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER, IID_IShellMenu, reinterpret_cast(menuBar)); +#endif if (FAILED(hResult)) return hResult; hResult = fMenuCallback.QueryInterface(IID_IShellMenuCallback, reinterpret_cast(&callback)); @@ -1137,12 +1181,16 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::OnWinEvent( CComPtr menuWinEventHandler; HRESULT hResult; - if (fMenuBar.p != NULL) + if (fMenuBar) { hResult = fMenuBar->QueryInterface(IID_IWinEventHandler, reinterpret_cast(&menuWinEventHandler)); - return menuWinEventHandler->OnWinEvent(fMenuBandWindow, uMsg, wParam, lParam, theResult); + if (menuWinEventHandler->IsWindowOwner(hWnd)) + { + return menuWinEventHandler->OnWinEvent(fMenuBandWindow, uMsg, wParam, lParam, theResult); + } } - return E_FAIL; + + return S_FALSE; } HRESULT STDMETHODCALLTYPE CInternetToolbar::IsWindowOwner(HWND hWnd) @@ -1410,20 +1458,6 @@ LRESULT CInternetToolbar::OnQueryDelete(UINT idControl, NMHDR *pNMHDR, BOOL &bHa return 1; } -LRESULT CInternetToolbar::OnNavigateCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) -{ - CComPtr winEventHandler; - LRESULT theResult; - HRESULT hResult; - - hResult = fNavigationBar->QueryInterface(IID_IWinEventHandler, reinterpret_cast(&winEventHandler)); - hResult = winEventHandler->OnWinEvent(m_hWnd, uMsg, wParam, lParam, &theResult); - if (SUCCEEDED(hResult)) - return theResult; - bHandled = FALSE; - return 0; -} - LRESULT CInternetToolbar::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { HMENU contextMenuBar; @@ -1553,27 +1587,78 @@ LRESULT CInternetToolbar::OnTipText(UINT idControl, NMHDR *pNMHDR, BOOL &bHandle return 0; } +LRESULT CInternetToolbar::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + LRESULT theResult; + HRESULT hResult; + HWND target = (HWND) lParam; + + if (fMenuBar) + { + CComPtr menuWinEventHandler; + hResult = fMenuBar->QueryInterface(IID_IWinEventHandler, reinterpret_cast(&menuWinEventHandler)); + if (SUCCEEDED(hResult)) + { + if (menuWinEventHandler->IsWindowOwner(target) == S_OK) + { + hResult = menuWinEventHandler->OnWinEvent(target, uMsg, wParam, lParam, &theResult); + return FAILED(hResult) ? 0 : theResult; + } + } + } + + if (fNavigationBar) + { + CComPtr menuWinEventHandler; + hResult = fNavigationBar->QueryInterface(IID_IWinEventHandler, reinterpret_cast(&menuWinEventHandler)); + if (SUCCEEDED(hResult)) + { + if (menuWinEventHandler->IsWindowOwner(target) == S_OK) + { + hResult = menuWinEventHandler->OnWinEvent(target, uMsg, wParam, lParam, &theResult); + return FAILED(hResult) ? 0 : theResult; + } + } + } + + return 0; +} LRESULT CInternetToolbar::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { - NMHDR *notifyHeader; - CComPtr menuWinEventHandler; - LRESULT theResult; - HRESULT hResult; + NMHDR *notifyHeader; + LRESULT theResult; + HRESULT hResult; - notifyHeader = (NMHDR *)lParam; - if (fMenuBar.p != NULL && notifyHeader->hwndFrom == fMenuBandWindow) + notifyHeader = (NMHDR *) lParam; + + if (fMenuBar) { + CComPtr menuWinEventHandler; hResult = fMenuBar->QueryInterface(IID_IWinEventHandler, reinterpret_cast(&menuWinEventHandler)); - hResult = menuWinEventHandler->OnWinEvent(fMenuBandWindow, uMsg, wParam, lParam, &theResult); - return theResult; + if (SUCCEEDED(hResult)) + { + if (menuWinEventHandler->IsWindowOwner(notifyHeader->hwndFrom) == S_OK) + { + hResult = menuWinEventHandler->OnWinEvent(notifyHeader->hwndFrom, uMsg, wParam, lParam, &theResult); + return FAILED(hResult) ? 0 : theResult; + } + } } - if (fNavigationBar.p != NULL && notifyHeader->hwndFrom == fNavigationWindow) + + if (fNavigationBar) { - hResult = fNavigationBar->QueryInterface( - IID_IWinEventHandler, reinterpret_cast(&menuWinEventHandler)); - hResult = menuWinEventHandler->OnWinEvent(m_hWnd, uMsg, wParam, lParam, &theResult); - return theResult; + CComPtr menuWinEventHandler; + hResult = fNavigationBar->QueryInterface(IID_IWinEventHandler, reinterpret_cast(&menuWinEventHandler)); + if (SUCCEEDED(hResult)) + { + if (menuWinEventHandler->IsWindowOwner(notifyHeader->hwndFrom) == S_OK) + { + hResult = menuWinEventHandler->OnWinEvent(notifyHeader->hwndFrom, uMsg, wParam, lParam, &theResult); + return FAILED(hResult) ? 0 : theResult; + } + } } + return 0; } diff --git a/dll/win32/browseui/internettoolbar.h b/dll/win32/browseui/internettoolbar.h index 71520e30287..0b6ae67a819 100644 --- a/dll/win32/browseui/internettoolbar.h +++ b/dll/win32/browseui/internettoolbar.h @@ -196,6 +196,7 @@ public: LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); LRESULT OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); LRESULT OnTipText(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled); + LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); BEGIN_MSG_MAP(CInternetToolbar) @@ -208,7 +209,7 @@ public: NOTIFY_HANDLER(0, TBN_DROPDOWN, OnMenuDropDown) NOTIFY_HANDLER(0, TBN_QUERYINSERT, OnQueryInsert) NOTIFY_HANDLER(0, TBN_QUERYDELETE, OnQueryDelete) - MESSAGE_HANDLER(WM_COMMAND, OnNavigateCommand) + MESSAGE_HANDLER(WM_COMMAND, OnCommand) MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu) MESSAGE_HANDLER(WM_SIZE, OnSize) MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor) diff --git a/dll/win32/browseui/precomp.h b/dll/win32/browseui/precomp.h index 45880e36102..f365ac094bf 100644 --- a/dll/win32/browseui/precomp.h +++ b/dll/win32/browseui/precomp.h @@ -38,6 +38,43 @@ #include "commonbrowser.h" #include "globalfoldersettings.h" #include "regtreeoptions.h" +#include + +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__) WINE_DEFAULT_DEBUG_CHANNEL(browseui); diff --git a/media/fonts/Marlett.ttf b/media/fonts/Marlett.ttf index 945aca8d84f58088eba4e4b7f0d833a079d62776..ff7e3e8ff1d2330e99578e25ff51a2f0b2be0c84 100644 GIT binary patch literal 4096 zcmcInZE&1b6+Y+Q-S^#1(k9!@W}CLqciDzi2{f=-7nCxggb!(K%ZJTwwUE$FNi`p9 z+R~KiIR2<(={Rj>z$I24L8=x;leV@UlnPOB*bzokM+60C+9EdS;P4}*ZL<5u=iE)o zg8sm9+}(TMbI*Csx#ym9?%7>pA}Xh^k*3DgcP+c-nZ?N=BEA;fRU3LbGKXLP!Q)uJ zhOy%Qj?J0rX&|ZcJmkLnySH!5uAO{{NOxhmtE;mktzT7JAv=!osV*?8?sfUR9vuj=mG(6Q*A#UAJ{!n(DmV<6*sl+HjtA8V(#qo?z$8{XOj2j2r` zU#4&K7Jb4CdzIgWyqm;#jP|eZsl2!H`m-RF(Lll#z_5(uznWNSkJqw&{<4p$R$eh@Ze>+qUa&e;6P{nY zVBw-mE?w+IE{iVtmeSaof%nevwg@k?izbTbt>sOIJHJQoHK>0 zc&|#@W4>(B7JCDca`py+`svi2FS6CldI{^dr`A|E@P+5GBkxvgfFHv4b0`3tkw7dE z(eOdujG<4fbuZ`t@`C5E+dZ{PkLUktwYV>-_3j_kx~XBeO#d_gHviqNA(q;-_WPQo z#5us${`^T_(}htu`(c@%10wTQ=TBPAkfEA)`kJi$qUYy`w^}(21MnIg+%pHR54aoMuORCC;3T-Z2Dq_*$63w5WoB{6U(Vl- zyA6AZn2y9F$eM5H{l{{?A@LLPVn>2J9?`L2#NQ6Y+1H?T_BF_H%Y8%scF_+aOYul9 zXZy}K@}TWA`sf4x_8EC75{L%GFb`rr-w69WDEhu{o7$1=LJy+zIH8ixV(m9MKrA^? zPfnHNIhf1wME;}(l}@`Al1Vf$?P$mL+djl>7OMr+QK zkX1kI&|(hu234Q^G-}^e{)}&zi*I4^Eo^OeA1|~V%Dx2)&!5T`9GXA2MOoN1{_WhA!t(Be+Q@OCFTOPwqkh$EC*5 zJ5WF1jq~8-E_>{JBQ7tily|^t1||I{5{jslK9jGtnh{~to9RVEREgWE;xRwRLVgZK z{Tvlh;ef;-3IEK5rFK5T5YS9a{5WTj!Y~_eia4Qa+Y^j5CBjRB3N^*Sh(?kcxFP5M zk-6bT<|~*BPZoX*pTV}8)45z4C7j81avF?@!hym~?kn7YIQ$R&2RUzoUrKHyq85sv zubAf5jMg`lKbbQ`7BYyCAZNazb6xhB z9*051c5)Z)wOr|$=xu4Uv4lo<7UvkGAb#BfQY8~tp7K@ zT2n!_6rnnb({j3z)=-kZNS(BWzCnBGVfqezpN=9}u}~}=u%khIO(a6$SlAAQ6M<+b z8s~6Ko^~**V|7umW1(m$mWbC!DVyz4^I zdIQ65z%bz9kR1&t(BSJ6v3N9u-9At&p}j?@pzGt%1{`SXL<+CN_#{(&_z>uGucm&s zPS%{_tjHYlOWz-VYN z{Km$VuXZ@;PPXxScap8-NOCQ=;pf3UBO_CL+f;g_P1tR1Nql6q6}~r|6o#<*2(Jed zZ1)MwP=_V9+$Z=bIIuXw9hM#3R#+Hm8{uSfxD95XNGACR6k7R+yAsMrVRNO-kT*08 z%WlJ0eR8->>W~)mgQzI>XjF6s|H;r^(9*euZwVhOp>4xoWN7&&sGG~O( zX)d?V&|>rM8CsX{Jtef4uI1htjCGM;Ci~9#Q!ab)j|`@wgg@8N6NX;}dM+O`bP)7B ze!#JGkU>1xalwP2S`!1rTzaOeBzepu+n zssr{q=>c$;VYJao{|?RvUnm-8vz2j4x@>{h)8c+zCrtfO-IwaQd)g zkMT*oSwShf5|(egXtB%qpP^4<-(|E7=h_UJoV^29uEcs1qSc3et^#i>FtaD@2I4+& zGt`CgIpfbJAbLQHem6K0o3(iM!>XL47d~7K9f^m7NOr=4?9^|fnLtg?MyrWd0bk6D z&vMMyU6h`JtzPJ_!mbZsq_OHlJo@pLyh`@v zca(We*HgAgePph~I*9*sA*#W5r=FjzJQLu9+nvYd(^)GIqgt5 literal 28340 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