[FONTEXT] Support Drag&Drop font installation (#8600)

JIRA issue: CORE-12861
JIRA issue: CORE-20445
- Add IDD_INSTALL resource dialog.
- Add IDS_INSTALL_OK and IDS_INSTALL_FAILED
  resource strings.
- Add CheckDropFontFiles, GetDropFromDataObject,
  and InstallFontsFromDataObject helper functions.
- Support IDropTarget at CFontExt::GetUIObjectOf.
- Add CFontFolderViewCB.cpp and
  CFontFolderViewCB.h files and implement
  CFontFolderViewCB class.
- Implement Drag & Drop operation.
This commit is contained in:
Katayama Hirofumi MZ
2026-01-20 13:13:27 +09:00
committed by GitHub
parent f60b1c99c8
commit 9420ab7683
22 changed files with 548 additions and 93 deletions
+1 -1
View File
@@ -47,7 +47,7 @@ public:
if (m_Index < g_FontCache->Size())
{
CStringW Name = g_FontCache->Name(m_Index);
LPITEMIDLIST item = _ILCreate(Name, m_Index);
LPITEMIDLIST item = _ILCreate(Name);
if (!item)
{
hr = Fetched ? S_FALSE : E_OUTOFMEMORY;
-6
View File
@@ -144,12 +144,6 @@ CStringW CFontCache::Name(size_t Index)
CFontInfo* CFontCache::Find(const FontPidlEntry* fontEntry)
{
if (fontEntry->Index < m_Fonts.GetCount())
{
if (m_Fonts[fontEntry->Index].Name().CompareNoCase(fontEntry->Name) == 0)
return &m_Fonts[fontEntry->Index];
}
for (UINT n = 0; n < Size(); ++n)
{
if (m_Fonts[n].Name().CompareNoCase(fontEntry->Name) == 0)
+153 -36
View File
@@ -3,7 +3,7 @@
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: CFontExt implementation
* COPYRIGHT: Copyright 2019-2021 Mark Jansen <[email protected]>
* Copyright 2019-2025 Katayama Hirofumi MZ ([email protected])
* Copyright 2019-2026 Katayama Hirofumi MZ ([email protected])
*/
#include "precomp.h"
@@ -259,8 +259,7 @@ STDMETHODIMP CFontExt::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUID
DWORD column = lParam & 0x0000FFFF;
if (sortMode == SHCIDS_ALLFIELDS)
{
UNIMPLEMENTED;
result = (int)fontEntry1->Index - (int)fontEntry2->Index;
result = StrCmpIW(fontEntry1->Name, fontEntry2->Name);
}
else
{
@@ -278,11 +277,10 @@ STDMETHODIMP CFontExt::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUID
case 0xffff:
/* ROS bug? */
case FONTEXT_COL_NAME:
// These items are already ordered by name
result = (int)fontEntry1->Index - (int)fontEntry2->Index;
result = StrCmpIW(fontEntry1->Name, fontEntry2->Name);
break;
case FONTEXT_COL_FILENAME:
result = _wcsicmp(PathFindFileNameW(info1->File()), PathFindFileNameW(info2->File()));
result = StrCmpIW(PathFindFileNameW(info1->File()), PathFindFileNameW(info2->File()));
break;
case FONTEXT_COL_SIZE:
result = (int)info1->FileSize().HighPart - info2->FileSize().HighPart;
@@ -313,7 +311,6 @@ STDMETHODIMP CFontExt::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppv
if (IsEqualIID(riid, IID_IDropTarget))
{
ERR("IDropTarget not implemented\n");
*ppvOut = static_cast<IDropTarget *>(this);
AddRef();
hr = S_OK;
@@ -325,10 +322,14 @@ STDMETHODIMP CFontExt::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppv
}
else if (IsEqualIID(riid, IID_IShellView))
{
// Just create a default shell folder view, and register ourself as folder
SFV_CREATE sfv = { sizeof(SFV_CREATE) };
sfv.pshf = this;
hr = SHCreateShellFolderView(&sfv, (IShellView**)ppvOut);
CComPtr<CFontFolderViewCB> sfviewcb;
if (SUCCEEDED(hr = ShellObjectCreator(sfviewcb)))
{
SFV_CREATE create = { sizeof(create), this, NULL, sfviewcb };
hr = SHCreateShellFolderView(&create, (IShellView**)ppvOut);
if (SUCCEEDED(hr))
sfviewcb->Initialize(this, (IShellView*)*ppvOut, m_Folder);
}
}
return hr;
@@ -400,6 +401,12 @@ STDMETHODIMP CFontExt::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_
ERR("IID_IDataObject with cidl == 0 UNIMPLEMENTED\n");
}
}
else if (riid == IID_IDropTarget)
{
*ppvOut = static_cast<IDropTarget*>(this);
AddRef();
return S_OK;
}
//ERR("%s(riid=%S) UNIMPLEMENTED\n", __FUNCTION__, g2s(riid));
return E_NOTIMPL;
@@ -469,7 +476,7 @@ STDMETHODIMP CFontExt::Initialize(LPCITEMIDLIST pidl)
return hr;
}
if (_wcsicmp(PidlPath, FontsDir))
if (StrCmpIW(PidlPath, FontsDir))
{
ERR("CFontExt View initializing on unexpected folder: '%S'\n", PidlPath);
return E_FAIL;
@@ -492,18 +499,38 @@ STDMETHODIMP CFontExt::GetClassID(CLSID *lpClassId)
// *** IDropTarget methods ***
STDMETHODIMP CFontExt::DragEnter(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
{
*pdwEffect = DROPEFFECT_NONE;
m_bDragAccepted = FALSE;
CDataObjectHIDA cida(pDataObj);
if (FAILED_UNEXPECTEDLY(cida.hr()))
return cida.hr();
STGMEDIUM stg;
HDROP hDrop = GetDropFromDataObject(stg, pDataObj);
if (!hDrop)
{
*pdwEffect = DROPEFFECT_NONE;
DragLeave();
return E_FAIL;
}
*pdwEffect = DROPEFFECT_COPY;
m_bDragAccepted = CheckDropFontFiles(hDrop);
::ReleaseStgMedium(&stg);
if (!m_bDragAccepted)
{
*pdwEffect = DROPEFFECT_NONE;
return E_FAIL;
}
*pdwEffect &= DROPEFFECT_COPY;
return S_OK;
}
STDMETHODIMP CFontExt::DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
{
if (!m_bDragAccepted)
{
*pdwEffect = DROPEFFECT_NONE;
return E_FAIL;
}
*pdwEffect &= DROPEFFECT_COPY;
return S_OK;
}
@@ -512,13 +539,85 @@ STDMETHODIMP CFontExt::DragLeave()
return S_OK;
}
DWORD WINAPI CFontExt::InstallThreadProc(LPVOID lpParameter)
{
PINSTALL_FONT_DATA pData = (PINSTALL_FONT_DATA)lpParameter;
ATLASSERT(pData);
pData->hrResult = InstallFontFiles(pData);
if (pData->bCanceled)
pData->hrResult = S_FALSE;
TRACE("hrResult: 0x%08X\n", pData->hrResult);
::PostMessageW(pData->hwnd, WM_COMMAND, IDOK, 0);
pData->pDataObj->Release();
return 0;
}
INT_PTR CALLBACK
CFontExt::InstallDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, PINSTALL_FONT_DATA pData)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
pData->hwnd = hwnd;
ATLASSERT(pData->cSteps >= 0);
SendDlgItemMessageW(hwnd, IDC_INSTALL_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, pData->cSteps));
if (!SHCreateThread(CFontExt::InstallThreadProc, pData, CTF_COINIT, NULL))
{
WARN("!SHCreateThread\n");
pData->pDataObj->Release();
pData->hrResult = E_ABORT;
EndDialog(hwnd, IDABORT);
}
return TRUE;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDOK:
EndDialog(hwnd, IDOK);
break;
case IDCANCEL:
pData->bCanceled = TRUE;
EndDialog(hwnd, IDCANCEL);
break;
case IDCONTINUE:
pData->iStep += 1;
ATLASSERT(pData->iStep <= pData->cSteps);
SendDlgItemMessageW(hwnd, IDC_INSTALL_PROGRESS, PBM_SETPOS, pData->iStep, 0);
break;
}
break;
}
}
return 0;
}
INT_PTR CALLBACK
CFontExt::InstallDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PINSTALL_FONT_DATA pData = (PINSTALL_FONT_DATA)GetWindowLongPtrW(hwnd, DWLP_USER);
if (uMsg == WM_INITDIALOG)
{
pData = (PINSTALL_FONT_DATA)lParam;
SetWindowLongPtrW(hwnd, DWLP_USER, lParam);
}
ATLASSERT(pData);
ATLASSERT(pData->pFontExt);
return pData->pFontExt->InstallDlgProc(hwnd, uMsg, wParam, lParam, pData);
}
STDMETHODIMP CFontExt::Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
{
*pdwEffect = DROPEFFECT_NONE;
// NOTE: Getting cida in the other thread fails
CDataObjectHIDA cida(pDataObj);
if (!cida || cida->cidl <= 0)
{
ERR("E_UNEXPECTED\n");
return E_UNEXPECTED;
}
PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(cida);
if (!pidlParent)
@@ -532,28 +631,46 @@ STDMETHODIMP CFontExt::Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt,
{
PCUIDLIST_RELATIVE pidlRelative = HIDA_GetPIDLItem(cida, n);
if (!pidlRelative)
{
ERR("!pidlRelative\n");
return E_FAIL;
}
apidl.Add(pidlRelative);
}
CStringW strMessage;
if (InstallFontFiles(strMessage, pidlParent, cida->cidl, &apidl[0]) != S_OK)
// Show progress dialog
INSTALL_FONT_DATA data;
data.pFontExt = this;
data.pDataObj = pDataObj;
data.pidlParent = pidlParent;
data.apidl = &apidl[0];
data.cSteps = cida->cidl;
pDataObj->AddRef();
DialogBoxParamW(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCEW(IDD_INSTALL),
m_hwndView, CFontExt::InstallDialogProc, (LPARAM)&data);
if (data.bCanceled)
return E_ABORT;
CStringW text, title;
title.LoadStringW(IDS_REACTOS_FONTS_FOLDER);
if (SUCCEEDED(data.hrResult))
{
// TODO: Show message
return E_FAIL;
// Invalidate our cache
g_FontCache->Read();
// Notify the system that a font was added
SendMessageW(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
// Show successful message
text.LoadStringW(IDS_INSTALL_OK);
MessageBoxW(m_hwndView, text, title, MB_ICONINFORMATION);
}
else
{
// Show error message
text.LoadStringW(IDS_INSTALL_FAILED);
MessageBoxW(m_hwndView, text, title, MB_ICONERROR);
}
// Invalidate our cache
g_FontCache->Read();
// Notify the system that a font was added
SendMessageW(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
// Notify the shell that the folder contents are changed
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATHW, g_FontCache->FontPath().GetString(), NULL);
// TODO: Show message
return S_OK;
return data.hrResult;
}
+11 -1
View File
@@ -3,7 +3,7 @@
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: CFontExt definition
* COPYRIGHT: Copyright 2019,2020 Mark Jansen <[email protected]>
* Copyright 2019-2025 Katayama Hirofumi MZ ([email protected])
* Copyright 2019-2026 Katayama Hirofumi MZ ([email protected])
*/
#pragma once
@@ -16,11 +16,21 @@ class CFontExt :
public IDropTarget
{
CComHeapPtr<ITEMIDLIST> m_Folder;
BOOL m_bDragAccepted = FALSE;
HWND m_hwndView = nullptr;
static INT_PTR CALLBACK InstallDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK InstallDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, PINSTALL_FONT_DATA pData);
static DWORD WINAPI InstallThreadProc(LPVOID lpParameter);
public:
CFontExt();
~CFontExt();
void SetViewWindow(HWND hwndView)
{
m_hwndView = hwndView;
}
// *** IShellFolder2 methods ***
STDMETHODIMP GetDefaultSearchGUID(GUID *lpguid) override;
STDMETHODIMP EnumSearches(IEnumExtraSearch **ppenum) override;
+111
View File
@@ -0,0 +1,111 @@
/*
* PROJECT: ReactOS Font Shell Extension
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Fonts folder view callback implementation
* COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ ([email protected])
*/
#include "precomp.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell_ad);
void CFontFolderViewCB::Initialize(CFontExt* pFontExt, IShellView *psv, LPCITEMIDLIST pidlParent)
{
ATLASSERT(pFontExt);
ATLASSERT(psv);
ATLASSERT(pidlParent);
m_pFontExt = pFontExt;
m_pShellView = psv;
m_pidlParent.Attach(ILClone(pidlParent));
if (!m_pidlParent)
ERR("!m_pidlParent\n");
}
HRESULT CFontFolderViewCB::TranslatePidl(LPITEMIDLIST* ppidlNew, LPCITEMIDLIST pidl)
{
ATLASSERT(ppidlNew);
*ppidlNew = NULL;
WCHAR szFontFile[MAX_PATH];
if (!SHGetPathFromIDListW(pidl, szFontFile))
return E_FAIL;
CStringW strFontName;
HRESULT hr = DoGetFontTitle(szFontFile, strFontName);
if (FAILED_UNEXPECTEDLY(hr))
return E_FAIL;
LPITEMIDLIST pidlChild = _ILCreate(strFontName);
if (!pidlChild)
{
ERR("!pidlChild\n");
return E_OUTOFMEMORY;
}
*ppidlNew = ILCombine(m_pidlParent, pidlChild);
ILFree(pidlChild);
return *ppidlNew ? S_OK : E_OUTOFMEMORY;
}
void CFontFolderViewCB::TranslateTwoPIDLs(PIDLIST_ABSOLUTE* pidls)
{
ATLASSERT(pidls);
HRESULT hr;
if (pidls[0])
{
m_pidl0.Free();
hr = TranslatePidl(&m_pidl0, pidls[0]);
if (!FAILED_UNEXPECTEDLY(hr))
pidls[0] = m_pidl0;
}
if (pidls[1])
{
m_pidl1.Free();
hr = TranslatePidl(&m_pidl1, pidls[1]);
if (!FAILED_UNEXPECTEDLY(hr))
pidls[1] = m_pidl1;
}
}
BOOL CFontFolderViewCB::FilterEvent(LONG lEvent) const
{
switch (lEvent & ~SHCNE_INTERRUPT)
{
case SHCNE_CREATE:
case SHCNE_DELETE:
case SHCNE_RENAMEITEM:
case SHCNE_UPDATEDIR:
return FALSE; // OK
default:
return TRUE; // We don't want this event
}
}
STDMETHODIMP
CFontFolderViewCB::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case SFVM_QUERYFSNOTIFY: // Registering change notification
{
// Now, we can get the view window
ATLASSERT(m_pShellView);
ATLASSERT(m_pFontExt);
m_pShellView->GetWindow(&m_hwndView);
m_pFontExt->SetViewWindow(m_hwndView);
return S_OK;
}
case SFVM_FSNOTIFY: // Change notification
{
if (FilterEvent((LONG)lParam))
return S_FALSE; // Don't process
TranslateTwoPIDLs((PIDLIST_ABSOLUTE*)wParam);
return S_OK;
}
}
return E_NOTIMPL;
}
+37
View File
@@ -0,0 +1,37 @@
/*
* PROJECT: ReactOS Font Shell Extension
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Fonts folder view callback implementation
* COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ ([email protected])
*/
#pragma once
class CFontFolderViewCB
: public CComObjectRootEx<CComMultiThreadModelNoCS>
, public IShellFolderViewCB
{
CFontExt* m_pFontExt = nullptr; // Not ref-counted!
IShellView* m_pShellView = nullptr; // Not ref-counted!
HWND m_hwndView = nullptr;
CComHeapPtr<ITEMIDLIST> m_pidlParent;
CComHeapPtr<ITEMIDLIST> m_pidl0;
CComHeapPtr<ITEMIDLIST> m_pidl1;
HRESULT TranslatePidl(LPITEMIDLIST* ppidlNew, LPCITEMIDLIST pidl);
void TranslateTwoPIDLs(PIDLIST_ABSOLUTE* pidls);
BOOL FilterEvent(LONG lEvent) const;
public:
CFontFolderViewCB() { }
void Initialize(CFontExt* pFontExt, IShellView *psv, LPCITEMIDLIST pidlParent);
// IShellFolderViewCB
STDMETHOD(MessageSFVCB)(UINT uMsg, WPARAM wParam, LPARAM lParam) override;
DECLARE_NO_REGISTRY()
DECLARE_NOT_AGGREGATABLE(CFontFolderViewCB)
BEGIN_COM_MAP(CFontFolderViewCB)
COM_INTERFACE_ENTRY_IID(IID_IShellFolderViewCB, IShellFolderViewCB)
END_COM_MAP()
};
+2 -5
View File
@@ -8,15 +8,12 @@ list(APPEND SOURCE
CDataObject.cpp
CEnumFonts.cpp
CFontCache.cpp
CFontCache.hpp
CFontExt.cpp
CFontExt.hpp
CFontFolderViewCB.cpp
CFontMenu.cpp
fontext.cpp
fontpidl.cpp
fontpidl.hpp
precomp.h
resource.h)
precomp.h)
add_library(fontext MODULE
${SOURCE}
+96 -23
View File
@@ -102,11 +102,12 @@ STDAPI DllUnregisterServer()
HRESULT
InstallFontFiles(
_Out_ CStringW& strMsg,
_In_ PCUIDLIST_ABSOLUTE pidlParent,
_In_ UINT cidl,
_In_ PCUITEMID_CHILD_ARRAY apidl)
_Inout_ PINSTALL_FONT_DATA pData)
{
PCUIDLIST_ABSOLUTE pidlParent = pData->pidlParent;
UINT cidl = pData->cSteps;
PCUITEMID_CHILD_ARRAY apidl = pData->apidl;
CAtlArray<CStringW> FontPaths;
for (UINT n = 0; n < cidl; ++n)
{
@@ -138,9 +139,18 @@ InstallFontFiles(
for (SIZE_T iItem = 0; iItem < FontPaths.GetCount(); ++iItem)
{
HRESULT hr = DoInstallFontFile(strMsg, FontPaths[iItem], g_FontCache->FontPath(), keyFonts);
if (pData->bCanceled)
{
WARN("Canceled\n");
return E_ABORT;
}
HRESULT hr = DoInstallFontFile(FontPaths[iItem], g_FontCache->FontPath(), keyFonts);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (pData->hwnd)
::PostMessageW(pData->hwnd, WM_COMMAND, IDCONTINUE, 0);
}
return S_OK;
@@ -148,12 +158,13 @@ InstallFontFiles(
HRESULT
DoInstallFontFile(
_Out_ CStringW& strMsg,
_In_ PCWSTR pszFontPath,
_In_ PCWSTR pszFontsDir,
_In_ HKEY hkeyFonts)
{
WCHAR szDestFile[MAX_PATH];
ATLASSERT(pszFontPath);
ATLASSERT(pszFontsDir);
ATLASSERT(hkeyFonts);
// Add this font to the font list, so we can query the name
if (!AddFontResourceW(pszFontPath))
@@ -162,28 +173,52 @@ DoInstallFontFile(
return E_FAIL;
}
// Get the font name
CStringW strFontName;
HRESULT hr = DoGetFontTitle(pszFontPath, strFontName);
// We got the name, remove it again
RemoveFontResourceW(pszFontPath);
if (!SUCCEEDED(hr))
{
ERR("DoGetFontTitle failed (err=0x%x)!\n", hr);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
// Remove it now
// WINDOWS BUG: Removing once is not enough
for (INT iTry = 0; iTry < 3; ++iTry)
{
if (!RemoveFontResourceW(pszFontPath) &&
!RemoveFontResourceExW(pszFontPath, FR_PRIVATE, NULL))
{
break;
}
}
StringCchCopyW(szDestFile, sizeof(szDestFile), pszFontsDir);
// Delete font entry in registry
RegDeleteValueW(hkeyFonts, strFontName);
LPCWSTR pszFileTitle = PathFindFileName(pszFontPath);
PathAppendW(szDestFile, pszFileTitle);
if (!CopyFileW(pszFontPath, szDestFile, FALSE))
ATLASSERT(pszFileTitle);
// Build destination path
CStringW szDestFile(pszFontsDir); // pszFontsDir has backslash at back
szDestFile += pszFileTitle;
TRACE("szDestFile: '%S'\n", (PCWSTR)szDestFile);
if (!StrCmpIW(szDestFile, pszFontPath)) // Same file?
{
ERR("CopyFileW('%S', '%S') failed\n", pszFontPath, szDestFile);
ERR("Wrongly same: %S\n", pszFontPath);
return E_FAIL;
}
// Delete file
if (DeleteFileW(szDestFile))
SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW, (PCWSTR)szDestFile, NULL);
// Copy file
if (!CopyFileW(pszFontPath, szDestFile, FALSE))
{
ERR("CopyFileW('%S', '%S') failed\n", pszFontPath, (PCWSTR)szDestFile);
return E_FAIL;
}
// Write registry for font entry
DWORD cbData = (wcslen(pszFileTitle) + 1) * sizeof(WCHAR);
LONG nError = RegSetValueExW(hkeyFonts, strFontName, 0, REG_SZ,
(const BYTE *)pszFileTitle, cbData);
@@ -194,6 +229,9 @@ DoInstallFontFile(
return E_FAIL;
}
// Notify file creation
SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, (PCWSTR)szDestFile, NULL);
return AddFontResourceW(szDestFile) ? S_OK : E_FAIL;
}
@@ -214,14 +252,49 @@ DoGetFontTitle(
ret = GetFontResourceInfoW(pszFontPath, &cbInfo, pszBuffer, 1);
DWORD dwErr = GetLastError();;
strFontName.ReleaseBuffer();
if (ret)
if (!ret)
{
TRACE("pszFontName: %S\n", (LPCWSTR)strFontName);
return S_OK;
ERR("GetFontResourceInfoW failed (err: %u)\n", dwErr);
return E_FAIL;
}
ERR("GetFontResourceInfoW failed (err: %u)\n", dwErr);
return E_FAIL;
LPCWSTR pchDotExt = PathFindExtensionW(pszFontPath);
if (!StrCmpIW(pchDotExt, L".ttf") || !StrCmpIW(pchDotExt, L".ttc") ||
!StrCmpIW(pchDotExt, L".otf") || !StrCmpIW(pchDotExt, L".otc"))
{
strFontName += L" (TrueType)";
}
TRACE("pszFontName: %S\n", (LPCWSTR)strFontName);
return S_OK;
}
BOOL CheckDropFontFiles(HDROP hDrop)
{
UINT cFiles = DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0);
if (cFiles == 0)
return FALSE;
for (UINT iFile = 0; iFile < cFiles; ++iFile)
{
WCHAR szFile[MAX_PATH];
if (!DragQueryFileW(hDrop, iFile, szFile, _countof(szFile)))
return FALSE;
LPCWSTR pchDotExt = PathFindExtensionW(szFile);
if (!IsFontDotExt(pchDotExt))
return FALSE;
}
return TRUE;
}
HDROP GetDropFromDataObject(STGMEDIUM& stg, IDataObject *pDataObj)
{
FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
HRESULT hr = pDataObj->GetData(&etc, &stg);
if (FAILED_UNEXPECTEDLY(hr))
return NULL;
return reinterpret_cast<HDROP>(stg.hGlobal);
}
EXTERN_C
+1
View File
@@ -1,4 +1,5 @@
#include <windef.h>
#include <winuser.h>
#include "resource.h"
+1 -3
View File
@@ -7,7 +7,7 @@
#include "precomp.h"
LPITEMIDLIST _ILCreate(LPCWSTR lpString, ULONG Index)
LPITEMIDLIST _ILCreate(LPCWSTR lpString)
{
// Because the FontPidlEntry contains one WCHAR, we do not need to take the null terminator into account
size_t cbData = sizeof(FontPidlEntry) + wcslen(lpString) * sizeof(WCHAR);
@@ -19,8 +19,6 @@ LPITEMIDLIST _ILCreate(LPCWSTR lpString, ULONG Index)
pidl->cb = (WORD)cbData;
pidl->Magic = 'fp';
pidl->Index = Index;
wcscpy(pidl->Name, lpString);
// Should be zero already, but make sure it is
*(WORD*)((char*)pidl + cbData) = 0;
+1 -3
View File
@@ -12,11 +12,9 @@ struct FontPidlEntry
{
WORD cb;
WORD Magic;
ULONG Index; // Informative only, used for sorting
WCHAR Name[1];
};
#include <poppack.h>
LPITEMIDLIST _ILCreate(LPCWSTR lpString, ULONG Index);
LPITEMIDLIST _ILCreate(LPCWSTR lpString);
const FontPidlEntry* _FontFromIL(LPCITEMIDLIST pidl);
+12 -1
View File
@@ -7,9 +7,21 @@
LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
IDD_INSTALL DIALOG 0, 0, 205, 60
CAPTION "Installing fonts..."
STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Installing fonts...", IDC_INSTALL_TEXT, 5, 10, 195, 10
CONTROL "", IDC_INSTALL_PROGRESS, "msctls_progress32", 0, 5, 25, 195, 10
PUSHBUTTON "Cancel", IDCANCEL, 65, 40, 70, 15
END
STRINGTABLE
BEGIN
IDS_REACTOS_FONTS_FOLDER "ReactOS Schriftartenordner"
IDS_INSTALL_OK "The font files have been installed successfully."
IDS_INSTALL_FAILED "Failed to install the font files."
END
STRINGTABLE
@@ -26,7 +38,6 @@ BEGIN
IDS_COL_ATTR_LETTERS "RHSAC"
END
STRINGTABLE
BEGIN
IDS_FONT_PREVIEW "Ö&ffnen"
+12 -1
View File
@@ -2,12 +2,23 @@
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
IDD_INSTALL DIALOG 0, 0, 205, 60
CAPTION "Installing fonts..."
STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Installing fonts...", IDC_INSTALL_TEXT, 5, 10, 195, 10
CONTROL "", IDC_INSTALL_PROGRESS, "msctls_progress32", 0, 5, 25, 195, 10
PUSHBUTTON "Cancel", IDCANCEL, 65, 40, 70, 15
END
STRINGTABLE
BEGIN
IDS_REACTOS_FONTS_FOLDER "ReactOS Font Folder"
IDS_INSTALL_OK "The font files have been installed successfully."
IDS_INSTALL_FAILED "Failed to install the font files."
END
STRINGTABLE
BEGIN
IDS_COL_NAME "Name"
+12
View File
@@ -7,9 +7,21 @@
LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL
IDD_INSTALL DIALOG 0, 0, 205, 60
CAPTION "Installing fonts..."
STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Installing fonts...", IDC_INSTALL_TEXT, 5, 10, 195, 10
CONTROL "", IDC_INSTALL_PROGRESS, "msctls_progress32", 0, 5, 25, 195, 10
PUSHBUTTON "Cancel", IDCANCEL, 65, 40, 70, 15
END
STRINGTABLE
BEGIN
IDS_REACTOS_FONTS_FOLDER "Cartella dei font di ReactOS"
IDS_INSTALL_OK "The font files have been installed successfully."
IDS_INSTALL_FAILED "Failed to install the font files."
END
STRINGTABLE
+12
View File
@@ -2,9 +2,21 @@
LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
IDD_INSTALL DIALOG 0, 0, 205, 60
CAPTION "Installing fonts..."
STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Installing fonts...", IDC_INSTALL_TEXT, 5, 10, 195, 10
CONTROL "", IDC_INSTALL_PROGRESS, "msctls_progress32", 0, 5, 25, 195, 10
PUSHBUTTON "Cancel", IDCANCEL, 65, 40, 70, 15
END
STRINGTABLE
BEGIN
IDS_REACTOS_FONTS_FOLDER "Folder czcionek ReactOS"
IDS_INSTALL_OK "The font files have been installed successfully."
IDS_INSTALL_FAILED "Failed to install the font files."
END
STRINGTABLE
+12
View File
@@ -8,9 +8,21 @@
LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL
IDD_INSTALL DIALOG 0, 0, 205, 60
CAPTION "Installing fonts..."
STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Installing fonts...", IDC_INSTALL_TEXT, 5, 10, 195, 10
CONTROL "", IDC_INSTALL_PROGRESS, "msctls_progress32", 0, 5, 25, 195, 10
PUSHBUTTON "Cancel", IDCANCEL, 65, 40, 70, 15
END
STRINGTABLE
BEGIN
IDS_REACTOS_FONTS_FOLDER "Folder-ul de fonturi de ReactOS"
IDS_INSTALL_OK "The font files have been installed successfully."
IDS_INSTALL_FAILED "Failed to install the font files."
END
STRINGTABLE
+12
View File
@@ -2,9 +2,21 @@
LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
IDD_INSTALL DIALOG 0, 0, 205, 60
CAPTION "Installing fonts..."
STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Installing fonts...", IDC_INSTALL_TEXT, 5, 10, 195, 10
CONTROL "", IDC_INSTALL_PROGRESS, "msctls_progress32", 0, 5, 25, 195, 10
PUSHBUTTON "Cancel", IDCANCEL, 65, 40, 70, 15
END
STRINGTABLE
BEGIN
IDS_REACTOS_FONTS_FOLDER "ReactOS Yazı Tipi Dizini"
IDS_INSTALL_OK "The font files have been installed successfully."
IDS_INSTALL_FAILED "Failed to install the font files."
END
STRINGTABLE
+12
View File
@@ -7,9 +7,21 @@
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
IDD_INSTALL DIALOG 0, 0, 205, 60
CAPTION "Installing fonts..."
STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
FONT 9, "宋体"
BEGIN
LTEXT "Installing fonts...", IDC_INSTALL_TEXT, 5, 10, 195, 10
CONTROL "", IDC_INSTALL_PROGRESS, "msctls_progress32", 0, 5, 25, 195, 10
PUSHBUTTON "Cancel", IDCANCEL, 65, 40, 70, 15
END
STRINGTABLE
BEGIN
IDS_REACTOS_FONTS_FOLDER "ReactOS 字体文件夹"
IDS_INSTALL_OK "The font files have been installed successfully."
IDS_INSTALL_FAILED "Failed to install the font files."
END
STRINGTABLE
+12 -2
View File
@@ -7,12 +7,23 @@
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_HONGKONG
IDD_INSTALL DIALOG 0, 0, 205, 60
CAPTION "Installing fonts..."
STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
FONT 9, "新細明體"
BEGIN
LTEXT "Installing fonts...", IDC_INSTALL_TEXT, 5, 10, 195, 10
CONTROL "", IDC_INSTALL_PROGRESS, "msctls_progress32", 0, 5, 25, 195, 10
PUSHBUTTON "Cancel", IDCANCEL, 65, 40, 70, 15
END
STRINGTABLE
BEGIN
IDS_REACTOS_FONTS_FOLDER "ReactOS 字型資料夾"
IDS_INSTALL_OK "The font files have been installed successfully."
IDS_INSTALL_FAILED "Failed to install the font files."
END
STRINGTABLE
BEGIN
IDS_COL_NAME "名稱"
@@ -27,7 +38,6 @@ BEGIN
IDS_COL_ATTR_LETTERS "RHSAC"
END
STRINGTABLE
BEGIN
IDS_FONT_PREVIEW "預覽"
+12 -2
View File
@@ -7,12 +7,23 @@
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL
IDD_INSTALL DIALOG 0, 0, 205, 60
CAPTION "Installing fonts..."
STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
FONT 9, "新細明體"
BEGIN
LTEXT "Installing fonts...", IDC_INSTALL_TEXT, 5, 10, 195, 10
CONTROL "", IDC_INSTALL_PROGRESS, "msctls_progress32", 0, 5, 25, 195, 10
PUSHBUTTON "Cancel", IDCANCEL, 65, 40, 70, 15
END
STRINGTABLE
BEGIN
IDS_REACTOS_FONTS_FOLDER "ReactOS 字型資料夾"
IDS_INSTALL_OK "The font files have been installed successfully."
IDS_INSTALL_FAILED "Failed to install the font files."
END
STRINGTABLE
BEGIN
IDS_COL_NAME "名稱"
@@ -27,7 +38,6 @@ BEGIN
IDS_COL_ATTR_LETTERS "RHSAC"
END
STRINGTABLE
BEGIN
IDS_FONT_PREVIEW "預覽"
+21 -8
View File
@@ -27,10 +27,26 @@
extern const GUID CLSID_CFontExt;
extern LONG g_ModuleRefCnt;
class CFontExt;
typedef struct tagINSTALL_FONT_DATA
{
CFontExt* pFontExt = nullptr;
IDataObject* pDataObj = nullptr;
HRESULT hrResult = S_OK;
HWND hwnd = nullptr;
UINT iStep = 0;
UINT cSteps = 0;
BOOL bCanceled = FALSE;
LPCITEMIDLIST pidlParent = nullptr;
PCUIDLIST_RELATIVE* apidl = nullptr;
} INSTALL_FONT_DATA, *PINSTALL_FONT_DATA;
#include "resource.h"
#include "fontpidl.hpp"
#include "CFontCache.hpp"
#include "CFontExt.hpp"
#include "CFontFolderViewCB.h"
#define FONT_HIVE HKEY_LOCAL_MACHINE
#define FONT_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"
@@ -49,22 +65,16 @@ inline BOOL IsFontDotExt(LPCWSTR pchDotExt)
};
for (const LPCWSTR *pp = array; *pp; ++pp)
{
if (!_wcsicmp(*pp, pchDotExt))
if (!StrCmpIW(*pp, pchDotExt))
return TRUE;
}
return FALSE;
}
HRESULT
InstallFontFiles(
_Out_ CStringW& strMessage,
_In_ PCUIDLIST_ABSOLUTE pidlParent,
_In_ UINT cidl,
_In_ PCUITEMID_CHILD_ARRAY apidl);
HRESULT InstallFontFiles(_Inout_ PINSTALL_FONT_DATA pData);
HRESULT
DoInstallFontFile(
_Out_ CStringW& strMsg,
_In_ PCWSTR pszFontPath,
_In_ PCWSTR pszFontsDir,
_In_ HKEY hkeyFonts);
@@ -72,3 +82,6 @@ DoInstallFontFile(
HRESULT DoGetFontTitle(
_In_ PCWSTR pszFontPath,
_Out_ CStringW& strFontName);
BOOL CheckDropFontFiles(HDROP hDrop);
HDROP GetDropFromDataObject(STGMEDIUM& stg, IDataObject *pDataObj);
+5 -1
View File
@@ -1,8 +1,12 @@
#pragma once
#define IDD_INSTALL 100
#define IDC_INSTALL_TEXT 10000
#define IDC_INSTALL_PROGRESS 10001
#define IDS_REACTOS_FONTS_FOLDER 151
#define IDS_INSTALL_OK 152
#define IDS_INSTALL_FAILED 153
#define IDS_COL_NAME 301
#define IDS_COL_FILENAME 304
#define IDS_COL_SIZE 305