https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d04b4e65d6f83b40c62f47...
commit d04b4e65d6f83b40c62f477550e6213a1216a06a Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Fri Apr 5 07:59:35 2019 +0900 Commit: GitHub noreply@github.com CommitDate: Fri Apr 5 07:59:35 2019 +0900
[SHELL32] Implement Explorer background image (Retrial of #801) (#1463)
IconArea_Image, IconArea_Text and IconArea_TextBackground values in desktop.ini in a folder will be supported. It denies network paths. CORE-5516 --- dll/win32/shell32/CDefView.cpp | 120 ++++++++++++++++++++++++++--- dll/win32/shell32/folders/CFSFolder.cpp | 130 +++++++++++++++++++++++++++++++- dll/win32/shell32/folders/CFSFolder.h | 10 ++- sdk/include/reactos/undocshell.h | 9 +++ 4 files changed, 256 insertions(+), 13 deletions(-)
diff --git a/dll/win32/shell32/CDefView.cpp b/dll/win32/shell32/CDefView.cpp index a4ba8deda1..1485e1677a 100644 --- a/dll/win32/shell32/CDefView.cpp +++ b/dll/win32/shell32/CDefView.cpp @@ -110,6 +110,7 @@ class CDefView :
CLSID m_Category; BOOL m_Destroyed; + SFVM_CUSTOMVIEWINFO_DATA m_viewinfo_data;
private: HRESULT _MergeToolbar(); @@ -257,6 +258,7 @@ class CDefView : LRESULT OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnPrintClient(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); LRESULT OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); LRESULT OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); LRESULT OnNCCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); @@ -280,7 +282,7 @@ class CDefView : { { sizeof(WNDCLASSEX), CS_PARENTDC, StartWindowProc, 0, 0, NULL, NULL, - LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1), NULL, SV_CLASS_NAME, NULL + LoadCursor(NULL, IDC_ARROW), NULL, NULL, SV_CLASS_NAME, NULL }, NULL, NULL, IDC_ARROW, TRUE, 0, _T("") }; @@ -323,6 +325,7 @@ class CDefView : MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode) MESSAGE_HANDLER(WM_DESTROY, OnDestroy) MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPrintClient) MESSAGE_HANDLER(WM_SYSCOLORCHANGE, OnSysColorChange) MESSAGE_HANDLER(CWM_GETISHELLBROWSER, OnGetShellBrowser) MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) @@ -384,12 +387,21 @@ CDefView::CDefView() : ZeroMemory(&m_sortInfo, sizeof(m_sortInfo)); ZeroMemory(&m_ptLastMousePos, sizeof(m_ptLastMousePos)); ZeroMemory(&m_Category, sizeof(m_Category)); + m_viewinfo_data.clrText = GetSysColor(COLOR_WINDOWTEXT); + m_viewinfo_data.clrTextBack = GetSysColor(COLOR_WINDOW); + m_viewinfo_data.hbmBack = NULL; }
CDefView::~CDefView() { TRACE(" destroying IShellView(%p)\n", this);
+ if (m_viewinfo_data.hbmBack) + { + ::DeleteObject(m_viewinfo_data.hbmBack); + m_viewinfo_data.hbmBack = NULL; + } + if (m_hWnd) { DestroyViewWindow(); @@ -578,8 +590,6 @@ BOOL CDefView::CreateList() m_sortInfo.nHeaderID = -1; m_sortInfo.nLastHeaderID = -1;
- UpdateListColors(); - /* UpdateShellSettings(); */ return TRUE; } @@ -620,6 +630,27 @@ void CDefView::UpdateListColors() m_ListView.SetExtendedListViewStyle(0, LVS_EX_TRANSPARENTSHADOWTEXT); } } + else + { + // text background color + COLORREF clrTextBack = GetSysColor(COLOR_WINDOW); + if (m_viewinfo_data.clrTextBack != CLR_INVALID) + { + clrTextBack = m_viewinfo_data.clrTextBack; + } + m_ListView.SetTextBkColor(clrTextBack); + + // text color + COLORREF clrText = GetSysColor(COLOR_WINDOWTEXT); + if (m_viewinfo_data.clrText != CLR_INVALID) + { + clrText = m_viewinfo_data.clrText; + } + m_ListView.SetTextColor(clrText); + + // Background is painted by the parent via WM_PRINTCLIENT. + m_ListView.SetExtendedListViewStyle(LVS_EX_TRANSPARENTBKGND, LVS_EX_TRANSPARENTBKGND); + } }
/********************************************************** @@ -950,9 +981,27 @@ HRESULT CDefView::FillList() m_sortInfo.bIsAscending = TRUE; _Sort();
+ if (m_viewinfo_data.hbmBack) + { + ::DeleteObject(m_viewinfo_data.hbmBack); + m_viewinfo_data.hbmBack = NULL; + } + + // load custom background image and custom text color + m_viewinfo_data.cbSize = sizeof(m_viewinfo_data); + _DoFolderViewCB(SFVM_GET_CUSTOMVIEWINFO, 0, (LPARAM)&m_viewinfo_data); + /*turn the listview's redrawing back on and force it to draw*/ m_ListView.SetRedraw(TRUE);
+ UpdateListColors(); + + if (!(m_FolderSettings.fFlags & FWF_DESKTOP)) + { + // redraw now + m_ListView.InvalidateRect(NULL, TRUE); + } + _DoFolderViewCB(SFVM_LISTREFRESHED, NULL, NULL);
return S_OK; @@ -1000,6 +1049,55 @@ LRESULT CDefView::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOO return 0; }
+static VOID +DrawTileBitmap(HDC hDC, LPCRECT prc, HBITMAP hbm, INT nWidth, INT nHeight, INT dx, INT dy) +{ + INT x0 = prc->left, y0 = prc->top, x1 = prc->right, y1 = prc->bottom; + x0 += dx; + y0 += dy; + + HDC hMemDC = CreateCompatibleDC(hDC); + HGDIOBJ hbmOld = SelectObject(hMemDC, hbm); + + for (INT y = y0; y < y1; y += nHeight) + { + for (INT x = x0; x < x1; x += nWidth) + { + BitBlt(hDC, x, y, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY); + } + } + + SelectObject(hMemDC, hbmOld); + DeleteDC(hMemDC); +} + +LRESULT CDefView::OnPrintClient(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + HDC hDC = (HDC)wParam; + + RECT rc; + ::GetClientRect(m_ListView, &rc); + + if (m_viewinfo_data.hbmBack) + { + BITMAP bm; + if (::GetObject(m_viewinfo_data.hbmBack, sizeof(BITMAP), &bm)) + { + INT dx = -(::GetScrollPos(m_ListView, SB_HORZ) % bm.bmWidth); + INT dy = -(::GetScrollPos(m_ListView, SB_VERT) % bm.bmHeight); + DrawTileBitmap(hDC, &rc, m_viewinfo_data.hbmBack, bm.bmWidth, bm.bmHeight, dx, dy); + } + } + else + { + FillRect(hDC, &rc, GetSysColorBrush(COLOR_WINDOW)); + } + + bHandled = TRUE; + + return TRUE; +} + LRESULT CDefView::OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { /* Update desktop labels color */ @@ -1039,14 +1137,6 @@ LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
TRACE("%p\n", this);
- if (CreateList()) - { - if (InitList()) - { - FillList(); - } - } - if (SUCCEEDED(QueryInterface(IID_PPV_ARG(IDropTarget, &pdt)))) { if (FAILED(RegisterDragDrop(m_hWnd, pdt))) @@ -1063,6 +1153,14 @@ LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl m_hNotify = SHChangeNotifyRegister(m_hWnd, SHCNRF_InterruptLevel | SHCNRF_ShellLevel, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg); }
+ if (CreateList()) + { + if (InitList()) + { + FillList(); + } + } + /* _DoFolderViewCB(SFVM_GETNOTIFY, ?? ??) */
m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_SHELLVIEW)); diff --git a/dll/win32/shell32/folders/CFSFolder.cpp b/dll/win32/shell32/folders/CFSFolder.cpp index ad205c47e1..4ce2a2babe 100644 --- a/dll/win32/shell32/folders/CFSFolder.cpp +++ b/dll/win32/shell32/folders/CFSFolder.cpp @@ -4,6 +4,7 @@ * * Copyright 1997 Marcus Meissner * Copyright 1998, 1999, 2002 Juergen Schmied + * Copyright 2019 Katayama Hirofumi MZ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -878,7 +879,7 @@ HRESULT WINAPI CFSFolder::CreateViewObject(HWND hwndOwner, } else if (IsEqualIID (riid, IID_IShellView)) { - SFV_CREATE sfvparams = {sizeof(SFV_CREATE), this}; + SFV_CREATE sfvparams = {sizeof(SFV_CREATE), this, NULL, this}; hr = SHCreateShellFolderView(&sfvparams, (IShellView**)ppvOut); } } @@ -1626,3 +1627,130 @@ HRESULT WINAPI CFSFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObjec
return Shell_DefaultContextMenuCallBack(this, pdtobj); } + +static HBITMAP DoLoadPicture(LPCWSTR pszFileName) +{ + // create stream from file + HRESULT hr; + CComPtr<IStream> pStream; + hr = SHCreateStreamOnFileEx(pszFileName, STGM_READ, FILE_ATTRIBUTE_NORMAL, + FALSE, NULL, &pStream); + if (FAILED(hr)) + return NULL; + + // load the picture + HBITMAP hbm = NULL; + CComPtr<IPicture> pPicture; + OleLoadPicture(pStream, 0, FALSE, IID_IPicture, (LPVOID *)&pPicture); + + // get the bitmap handle + if (pPicture) + { + pPicture->get_Handle((OLE_HANDLE *)&hbm); + + // copy the bitmap handle + hbm = (HBITMAP)CopyImage(hbm, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); + } + + return hbm; +} + +HRESULT WINAPI CFSFolder::GetCustomViewInfo(ULONG unknown, SFVM_CUSTOMVIEWINFO_DATA *data) +{ + if (data == NULL) + { + return E_POINTER; + } + if (data->cbSize != sizeof(*data)) + { + // NOTE: You have to set the cbData member before SFVM_GET_CUSTOMVIEWINFO call. + return E_INVALIDARG; + } + + data->hbmBack = NULL; + data->clrText = CLR_INVALID; + data->clrTextBack = CLR_INVALID; + + WCHAR szPath[MAX_PATH], szIniFile[MAX_PATH]; + + // does the folder exists? + if (!SHGetPathFromIDListW(pidlRoot, szPath) || !PathIsDirectoryW(szPath)) + { + return E_INVALIDARG; + } + + // don't use custom view in network path for security + if (PathIsNetworkPath(szPath)) + { + return E_ACCESSDENIED; + } + + // build the ini file path + StringCchCopyW(szIniFile, _countof(szIniFile), szPath); + PathAppend(szIniFile, L"desktop.ini"); + + static LPCWSTR TheGUID = L"{BE098140-A513-11D0-A3A4-00C04FD706EC}"; + static LPCWSTR Space = L" \t\n\r\f\v"; + + // get info from ini file + WCHAR szImage[MAX_PATH], szText[64]; + + // load the image + szImage[0] = UNICODE_NULL; + GetPrivateProfileStringW(TheGUID, L"IconArea_Image", L"", szImage, _countof(szImage), szIniFile); + if (szImage[0]) + { + StrTrimW(szImage, Space); + if (PathIsRelativeW(szImage)) + { + PathAppendW(szPath, szImage); + StringCchCopyW(szImage, _countof(szImage), szPath); + } + data->hbmBack = DoLoadPicture(szImage); + } + + // load the text color + szText[0] = UNICODE_NULL; + GetPrivateProfileStringW(TheGUID, L"IconArea_Text", L"", szText, _countof(szText), szIniFile); + if (szText[0]) + { + StrTrimW(szText, Space); + + LPWSTR pchEnd = NULL; + COLORREF cr = (wcstol(szText, &pchEnd, 0) & 0xFFFFFF); + + if (pchEnd && !*pchEnd) + data->clrText = cr; + } + + // load the text background color + szText[0] = UNICODE_NULL; + GetPrivateProfileStringW(TheGUID, L"IconArea_TextBackground", L"", szText, _countof(szText), szIniFile); + if (szText[0]) + { + StrTrimW(szText, Space); + + LPWSTR pchEnd = NULL; + COLORREF cr = (wcstol(szText, &pchEnd, 0) & 0xFFFFFF); + + if (pchEnd && !*pchEnd) + data->clrTextBack = cr; + } + + if (data->hbmBack != NULL || data->clrText != CLR_INVALID || data->clrTextBack != CLR_INVALID) + return S_OK; + + return E_FAIL; +} + +HRESULT WINAPI CFSFolder::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + HRESULT hr = E_NOTIMPL; + switch (uMsg) + { + case SFVM_GET_CUSTOMVIEWINFO: + hr = GetCustomViewInfo((ULONG)wParam, (SFVM_CUSTOMVIEWINFO_DATA *)lParam); + break; + } + return hr; +} diff --git a/dll/win32/shell32/folders/CFSFolder.h b/dll/win32/shell32/folders/CFSFolder.h index 73f5400fd7..947ec92222 100644 --- a/dll/win32/shell32/folders/CFSFolder.h +++ b/dll/win32/shell32/folders/CFSFolder.h @@ -28,7 +28,8 @@ class CFSFolder : public CComObjectRootEx<CComMultiThreadModelNoCS>, public IShellFolder2, public IPersistFolder3, - public IContextMenuCB + public IContextMenuCB, + public IShellFolderViewCB { private: CLSID *pclsid; @@ -84,6 +85,9 @@ class CFSFolder : // IContextMenuCB virtual HRESULT WINAPI CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ // IShellFolderViewCB + virtual HRESULT WINAPI MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam); + DECLARE_REGISTRY_RESOURCEID(IDR_SHELLFSFOLDER) DECLARE_NOT_AGGREGATABLE(CFSFolder)
@@ -96,7 +100,11 @@ class CFSFolder : COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2) COM_INTERFACE_ENTRY_IID(IID_IPersistFolder3, IPersistFolder3) COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) + COM_INTERFACE_ENTRY_IID(IID_IShellFolderViewCB, IShellFolderViewCB) END_COM_MAP() + + protected: + HRESULT WINAPI GetCustomViewInfo(ULONG unknown, SFVM_CUSTOMVIEWINFO_DATA *data); };
#endif /* _CFSFOLDER_H_ */ diff --git a/sdk/include/reactos/undocshell.h b/sdk/include/reactos/undocshell.h index c2a0b37c6b..a93fcdd070 100644 --- a/sdk/include/reactos/undocshell.h +++ b/sdk/include/reactos/undocshell.h @@ -1005,6 +1005,15 @@ typedef struct tagEXP_VISTA_ID_LIST #define EXP_KNOWN_FOLDER_SIG 0xa000000b #define EXP_VISTA_ID_LIST_SIG 0xa000000c
+/* Not compatible yet */ +typedef struct SFVM_CUSTOMVIEWINFO_DATA +{ + ULONG cbSize; + HBITMAP hbmBack; + COLORREF clrText; + COLORREF clrTextBack; +} SFVM_CUSTOMVIEWINFO_DATA, *LPSFVM_CUSTOMVIEWINFO_DATA; + #include <poppack.h>
#ifdef __cplusplus