https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d04b4e65d6f83b40c62f477550e6213a1216a06a

commit d04b4e65d6f83b40c62f477550e6213a1216a06a
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Fri Apr 5 07:59:35 2019 +0900
Commit:     GitHub <[email protected]>
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

Reply via email to