/* * ReactOS Explorer * * Copyright 2009 Andrew Hill * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Implements the toolbar band of a cabinet window */ #include "precomp.h" /* FIXME, I can't include windowsx because it conflicts with some #defines */ #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp)) class CToolsBand : public CWindowImpl, public CComObjectRootEx, public IDeskBand, public IObjectWithSite, public IInputObject, public IPersistStream { private: IDockingWindowSite *fDockSite; GUID fExecCommandCategory; CComPtr fExecCommandTarget; public: CToolsBand(); ~CToolsBand(); public: // *** IDeskBand methods *** virtual HRESULT STDMETHODCALLTYPE GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi); // *** IObjectWithSite methods *** virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown* pUnkSite); virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite); // *** IOleWindow methods *** virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd); virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); // *** IDockingWindow methods *** virtual HRESULT STDMETHODCALLTYPE CloseDW(DWORD dwReserved); virtual HRESULT STDMETHODCALLTYPE ResizeBorderDW(const RECT* prcBorder, IUnknown* punkToolbarSite, BOOL fReserved); virtual HRESULT STDMETHODCALLTYPE ShowDW(BOOL fShow); // *** IInputObject methods *** virtual HRESULT STDMETHODCALLTYPE HasFocusIO(); virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg); virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL fActivate, LPMSG lpMsg); // *** IPersist methods *** virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID); // *** IPersistStream methods *** virtual HRESULT STDMETHODCALLTYPE IsDirty(); virtual HRESULT STDMETHODCALLTYPE Load(IStream *pStm); virtual HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty); virtual HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize); // message handlers LRESULT OnGetButtonInfo(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled); BEGIN_MSG_MAP(CToolsBand) // MESSAGE_HANDLER(WM_NOTIFY, OnNotify) // MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus) NOTIFY_HANDLER(0, TBN_GETBUTTONINFOW, OnGetButtonInfo) END_MSG_MAP() BEGIN_COM_MAP(CToolsBand) COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand) COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow) COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow) COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject) COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream) END_COM_MAP() }; CToolsBand::CToolsBand() { fDockSite = NULL; } CToolsBand::~CToolsBand() { if (fDockSite) fDockSite->Release(); } HRESULT STDMETHODCALLTYPE CToolsBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi) { RECT actualRect; POINTL actualSize; POINTL idealSize; POINTL maxSize; POINTL itemSize; ::GetWindowRect(m_hWnd, &actualRect); actualSize.x = actualRect.right - actualRect.left; actualSize.y = actualRect.bottom - actualRect.top; /* Obtain the ideal size, to be used as min and max */ SendMessageW(m_hWnd, TB_AUTOSIZE, 0, 0); SendMessageW(m_hWnd, TB_GETMAXSIZE, 0, reinterpret_cast(&maxSize)); idealSize = maxSize; SendMessageW(m_hWnd, TB_GETIDEALSIZE, FALSE, reinterpret_cast(&idealSize)); /* Obtain the button size, to be used as the integral size */ DWORD size = SendMessageW(m_hWnd, TB_GETBUTTONSIZE, 0, 0); itemSize.x = GET_X_LPARAM(size); itemSize.y = GET_Y_LPARAM(size); if (pdbi->dwMask & DBIM_MINSIZE) { pdbi->ptMinSize = idealSize; } if (pdbi->dwMask & DBIM_MAXSIZE) { pdbi->ptMaxSize = maxSize; } if (pdbi->dwMask & DBIM_INTEGRAL) { pdbi->ptIntegral = itemSize; } if (pdbi->dwMask & DBIM_ACTUAL) { pdbi->ptActual = actualSize; } if (pdbi->dwMask & DBIM_TITLE) wcscpy(pdbi->wszTitle, L""); if (pdbi->dwMask & DBIM_MODEFLAGS) pdbi->dwModeFlags = DBIMF_UNDELETEABLE; if (pdbi->dwMask & DBIM_BKCOLOR) pdbi->crBkgnd = 0; return S_OK; } static const int backImageIndex = 0; static const int forwardImageIndex = 1; static const int favoritesImageIndex = 2; // 3 // 4 static const int cutImageIndex = 5; static const int copyImageIndex = 6; static const int pasteImageIndex = 7; static const int undoImageIndex = 8; static const int redoImageIndex = 9; static const int deleteImageIndex = 10; // 11 // 12 // 13 // 14 static const int propertiesImageIndex = 15; // 16 static const int searchImageIndex = 17; // 18 // 19 // 20 // 21 static const int viewsImageIndex = 22; // 23 // 24 // 25 // 26 // 27 static const int upImageIndex = 28; static const int mapDriveImageIndex = 29; static const int disconnectImageIndex = 30; // 31 static const int viewsAltImageIndex = 32; // same image as viewsImageIndex // 33 // 34 // 35 // 36 // 37 static const int viewsAlt2ImageIndex = 38; // same image as viewsAltImageIndex & viewsImageIndex // 39 // 40 // 41 // 42 static const int foldersImageIndex = 43; static const int moveToImageIndex = 44; static const int copyToImageIndex = 45; static const int folderOptionsImageIndex = 46; enum StandardToolbarButtons { BtnIdx_Back = 0, BtnIdx_Forward, BtnIdx_Up, BtnIdx_Search, BtnIdx_Folders, BtnIdx_MoveTo, BtnIdx_CopyTo, BtnIdx_Delete, BtnIdx_Undo, BtnIdx_Views, BtnIdx_Stop, BtnIdx_Refresh, BtnIdx_Home, BtnIdx_MapDrive, BtnIdx_Disconnect, BtnIdx_Favorites, BtnIdx_History, BtnIdx_FullScreen, BtnIdx_Properties, BtnIdx_Cut, BtnIdx_Copy, BtnIdx_Paste, BtnIdx_FolderOptions, }; const int numShownButtons = 13; const int numHiddenButtons = 13; TBBUTTON tbButtonsAdd[numShownButtons + numHiddenButtons] = { { backImageIndex, IDM_GOTO_BACK, TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Back }, { forwardImageIndex, IDM_GOTO_FORWARD, TBSTATE_ENABLED, BTNS_DROPDOWN, { 0 }, 0, BtnIdx_Forward }, { upImageIndex, IDM_GOTO_UPONELEVEL, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Up }, { 6, -1, TBSTATE_ENABLED, BTNS_SEP }, { searchImageIndex, gSearchCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Search }, { foldersImageIndex, gFoldersCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Folders }, { 6, -1, TBSTATE_ENABLED, BTNS_SEP }, { moveToImageIndex, gMoveToCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_MoveTo }, { copyToImageIndex, gCopyToCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_CopyTo }, { deleteImageIndex, gDeleteCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Delete }, { undoImageIndex, gUndoCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Undo }, { 6, -1, TBSTATE_ENABLED, BTNS_SEP }, { viewsImageIndex, gViewsCommandID, TBSTATE_ENABLED, BTNS_WHOLEDROPDOWN, { 0 }, 0, BtnIdx_Views }, { 0, gStopCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Stop }, { 0, IDM_VIEW_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Refresh }, { 0, gHomeCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Home }, { mapDriveImageIndex, IDM_TOOLS_MAPNETWORKDRIVE, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_MapDrive }, { disconnectImageIndex, IDM_TOOLS_DISCONNECTNETWORKDRIVE, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Disconnect }, { favoritesImageIndex, gFavoritesCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Favorites }, { 0, gHistoryCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_History }, { 0, gFullScreenCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_FullScreen }, { propertiesImageIndex, gPropertiesCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Properties }, { cutImageIndex, gCutCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Cut }, { copyImageIndex, gCopyCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Copy }, { pasteImageIndex, gPasteCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Paste }, { folderOptionsImageIndex, IDM_TOOLS_FOLDEROPTIONS, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_FolderOptions }, }; HRESULT STDMETHODCALLTYPE CToolsBand::SetSite(IUnknown* pUnkSite){ HWND parentWindow; IOleWindow *oleWindow; HWND toolbar; HRESULT hResult; if (fDockSite != NULL) fDockSite->Release(); if (pUnkSite == NULL) return S_OK; hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &fDockSite)); if (FAILED(hResult)) return hResult; parentWindow = NULL; hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow)); if (SUCCEEDED(hResult)) { oleWindow->GetWindow(&parentWindow); oleWindow->Release(); } if (!::IsWindow(parentWindow)) return E_FAIL; toolbar = CreateWindowEx( TBSTYLE_EX_DOUBLEBUFFER, TOOLBARCLASSNAMEW, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_LIST | TBSTYLE_FLAT | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP, 0, 0, 500, 20, parentWindow, NULL, _AtlBaseModule.GetModuleInstance(), 0); if (toolbar == NULL) return E_FAIL; SubclassWindow(toolbar); SendMessage(TB_ADDSTRINGW, (WPARAM) GetModuleHandle(L"browseui.dll"), IDS_STANDARD_TOOLBAR); SendMessage(WM_USER + 100, GetSystemMetrics(SM_CXEDGE) / 2, 0); SendMessage(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); SendMessage(TB_SETMAXTEXTROWS, 1, 0); SendMessage(TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS); HINSTANCE shell32Instance = GetModuleHandle(_T("shell32.dll")); HBITMAP imgNormal = reinterpret_cast( LoadImage(shell32Instance, MAKEINTRESOURCE(214), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION)); HBITMAP imgHot = reinterpret_cast( LoadImage(shell32Instance, MAKEINTRESOURCE(215), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION)); if (imgNormal && imgHot) { BITMAP bitmapInfo; GetObjectW(imgNormal, sizeof(bitmapInfo), &bitmapInfo); HIMAGELIST himlNormal = ImageList_Create(bitmapInfo.bmHeight, bitmapInfo.bmHeight, ILC_COLOR32, 4, 4); ImageList_Add(himlNormal, imgNormal, NULL); DeleteObject(imgNormal); GetObjectW(imgHot, sizeof(bitmapInfo), &bitmapInfo); HIMAGELIST himlHot = ImageList_Create(bitmapInfo.bmHeight, bitmapInfo.bmHeight, ILC_COLOR32, 4, 4); ImageList_Add(himlHot, imgHot, NULL); DeleteObject(imgHot); SendMessage(TB_SETIMAGELIST, 0, (LPARAM) himlNormal); SendMessage(TB_SETHOTIMAGELIST, 0, (LPARAM) himlHot); } SendMessage(TB_ADDBUTTONSW, numShownButtons, (LPARAM)&tbButtonsAdd); return hResult; } HRESULT STDMETHODCALLTYPE CToolsBand::GetSite(REFIID riid, void **ppvSite) { if (fDockSite == NULL) return E_FAIL; return fDockSite->QueryInterface(riid, ppvSite); } HRESULT STDMETHODCALLTYPE CToolsBand::GetWindow(HWND *lphwnd) { if (lphwnd == NULL) return E_POINTER; *lphwnd = m_hWnd; return S_OK; } HRESULT STDMETHODCALLTYPE CToolsBand::ContextSensitiveHelp(BOOL fEnterMode) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CToolsBand::CloseDW(DWORD dwReserved) { ShowDW(FALSE); if (IsWindow()) DestroyWindow(); m_hWnd = NULL; return S_OK; } HRESULT STDMETHODCALLTYPE CToolsBand::ResizeBorderDW(const RECT* prcBorder, IUnknown* punkToolbarSite, BOOL fReserved) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CToolsBand::ShowDW(BOOL fShow) { if (m_hWnd) { if (fShow) ShowWindow(SW_SHOW); else ShowWindow(SW_HIDE); } return S_OK; } HRESULT STDMETHODCALLTYPE CToolsBand::HasFocusIO() { return S_FALSE; } HRESULT STDMETHODCALLTYPE CToolsBand::TranslateAcceleratorIO(LPMSG lpMsg) { return S_FALSE; } HRESULT STDMETHODCALLTYPE CToolsBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CToolsBand::GetClassID(CLSID *pClassID) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CToolsBand::IsDirty() { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CToolsBand::Load(IStream *pStm) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CToolsBand::Save(IStream *pStm, BOOL fClearDirty) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CToolsBand::GetSizeMax(ULARGE_INTEGER *pcbSize) { return E_NOTIMPL; } LRESULT CToolsBand::OnGetButtonInfo(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled) { TBNOTIFYW *pTBntf = reinterpret_cast(pNMHDR); if (pTBntf->iItem >= 0 && pTBntf->iItem < (numShownButtons + numHiddenButtons)) { pTBntf->tbButton = tbButtonsAdd[pTBntf->iItem]; return TRUE; } else return FALSE; return 0; } HRESULT CreateToolsBar(REFIID riid, void **ppv) { CComObject *theMenuBar; HRESULT hResult; if (ppv == NULL) return E_POINTER; *ppv = NULL; ATLTRY (theMenuBar = new CComObject); if (theMenuBar == NULL) return E_OUTOFMEMORY; hResult = theMenuBar->QueryInterface(riid, reinterpret_cast(ppv)); if (FAILED(hResult)) { delete theMenuBar; return hResult; } return S_OK; }