[SHELL32] Initial implement SHLimitInputEdit (#2323)

Popup balloon window is not implemented yet.
CORE-11701
This commit is contained in:
Katayama Hirofumi MZ 2020-02-10 15:57:30 +09:00 committed by GitHub
parent 48160c74b7
commit c6ed215eef
2 changed files with 179 additions and 12 deletions

View file

@ -36,17 +36,6 @@ SHFindComputer(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
return FALSE;
}
/*
* Unimplemented
*/
EXTERN_C HRESULT
WINAPI
SHLimitInputEdit(HWND hWnd, IShellFolder *psf)
{
FIXME("SHLimitInputEdit() stub\n");
return S_FALSE;
}
/*
* Unimplemented
*/

View file

@ -2147,4 +2147,182 @@ SHTestTokenMembership(HANDLE TokenHandle, ULONG ulRID)
BOOL WINAPI IsUserAnAdmin(VOID)
{
return SHTestTokenMembership(NULL, DOMAIN_ALIAS_RID_ADMINS);
}
}
/*************************************************************************
* SHLimitInputEdit(SHELL32.@)
*/
/* TODO: Show baloon popup window using SetWindowRgn */
typedef struct UxSubclassInfo
{
HWND hwnd;
WNDPROC fnWndProc;
LPWSTR pwszValidChars;
LPWSTR pwszInvalidChars;
} UxSubclassInfo;
static void
UxSubclassInfo_Destroy(UxSubclassInfo *pInfo)
{
if (!pInfo)
return;
RemovePropW(pInfo->hwnd, L"UxSubclassInfo");
CoTaskMemFree(pInfo->pwszValidChars);
CoTaskMemFree(pInfo->pwszInvalidChars);
SetWindowLongPtr(pInfo->hwnd, GWLP_WNDPROC, (LONG_PTR)pInfo->fnWndProc);
HeapFree(GetProcessHeap(), 0, pInfo);
}
static LRESULT CALLBACK
LimitEditWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
WNDPROC fnWndProc;
UxSubclassInfo *pInfo = GetPropW(hwnd, L"UxSubclassInfo");
if (!pInfo)
return DefWindowProc(hwnd, uMsg, wParam, lParam);
fnWndProc = pInfo->fnWndProc;
switch (uMsg)
{
case WM_CHAR:
{
if (pInfo->pwszInvalidChars)
{
if (wcschr(pInfo->pwszInvalidChars, (WCHAR)wParam) != NULL)
{
MessageBeep(0xFFFFFFFF);
break;
}
}
else if (pInfo->pwszValidChars)
{
if (wcschr(pInfo->pwszValidChars, (WCHAR)wParam) == NULL)
{
MessageBeep(0xFFFFFFFF);
break;
}
}
return fnWndProc(hwnd, uMsg, wParam, lParam);
}
case WM_IME_CHAR:
{
WCHAR wch = (WCHAR)wParam;
if (!IsWindowUnicode(hwnd) && HIBYTE(wch) != 0)
{
CHAR data[] = {HIBYTE(wch), LOBYTE(wch)};
MultiByteToWideChar(CP_ACP, 0, data, 2, &wch, 1);
}
if (pInfo->pwszInvalidChars)
{
if (wcschr(pInfo->pwszInvalidChars, wch) != NULL)
{
MessageBeep(0xFFFFFFFF);
break;
}
}
else if (pInfo->pwszValidChars)
{
if (wcschr(pInfo->pwszValidChars, wch) == NULL)
{
MessageBeep(0xFFFFFFFF);
break;
}
}
return fnWndProc(hwnd, uMsg, wParam, lParam);
}
case WM_NCDESTROY:
{
UxSubclassInfo_Destroy(pInfo);
return fnWndProc(hwnd, uMsg, wParam, lParam);
}
default:
return fnWndProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
static UxSubclassInfo *
UxSubclassInfo_Create(HWND hwnd, LPWSTR valid, LPWSTR invalid)
{
UxSubclassInfo *pInfo;
pInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(UxSubclassInfo));
if (!pInfo)
{
ERR("HeapAlloc failed.\n");
CoTaskMemFree(valid);
CoTaskMemFree(invalid);
return NULL;
}
pInfo->fnWndProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)LimitEditWindowProc);
if (!pInfo->fnWndProc)
{
ERR("SetWindowLongPtr failed\n");
CoTaskMemFree(valid);
CoTaskMemFree(invalid);
HeapFree(GetProcessHeap(), 0, pInfo);
return NULL;
}
pInfo->hwnd = hwnd;
pInfo->pwszValidChars = valid;
pInfo->pwszInvalidChars = invalid;
if (!SetPropW(hwnd, L"UxSubclassInfo", pInfo))
{
UxSubclassInfo_Destroy(pInfo);
pInfo = NULL;
}
return pInfo;
}
HRESULT WINAPI
SHLimitInputEdit(HWND hWnd, IShellFolder *psf)
{
IItemNameLimits *pLimits;
HRESULT hr;
LPWSTR pwszValidChars, pwszInvalidChars;
UxSubclassInfo *pInfo;
pInfo = GetPropW(hWnd, L"UxSubclassInfo");
if (pInfo)
{
UxSubclassInfo_Destroy(pInfo);
pInfo = NULL;
}
hr = psf->lpVtbl->QueryInterface(psf, &IID_IItemNameLimits, (LPVOID *)&pLimits);
if (FAILED(hr))
{
ERR("hr: %x\n", hr);
return hr;
}
pwszValidChars = pwszInvalidChars = NULL;
hr = pLimits->lpVtbl->GetValidCharacters(pLimits, &pwszValidChars, &pwszInvalidChars);
if (FAILED(hr))
{
ERR("hr: %x\n", hr);
pLimits->lpVtbl->Release(pLimits);
return hr;
}
pInfo = UxSubclassInfo_Create(hWnd, pwszValidChars, pwszInvalidChars);
if (!pInfo)
hr = E_FAIL;
pLimits->lpVtbl->Release(pLimits);
return hr;
}