https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d04b4e65d6f83b40c62f4…
commit d04b4e65d6f83b40c62f477550e6213a1216a06a
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Fri Apr 5 07:59:35 2019 +0900
Commit: GitHub <noreply(a)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