windows-nt/Source/XPSP1/NT/shell/inc/cwndproc.cpp
2020-09-26 16:20:57 +08:00

193 lines
5.3 KiB
C++

#include "cwndproc.h"
#define ID_NOTIFY_SUBCLASS (DWORD)'CHN' // CHN change notify
//
// CImpWndProc
//
LRESULT CALLBACK CImpWndProc::s_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (WM_NCCREATE == uMsg)
{
CImpWndProc* pThis = (CImpWndProc*)(((LPCREATESTRUCT)lParam)->lpCreateParams);
if (EVAL(pThis))
{
pThis->_hwnd = hwnd;
SetWindowPtr(hwnd, 0, pThis);
// Even if pThis->vWndProc fails the create, USER will always
// send us a WM_NCDESTROY so we always get a chance to clean up
return pThis->v_WndProc(hwnd, uMsg, wParam, lParam);
}
return FALSE;
}
else
{
CImpWndProc* pThis = (CImpWndProc*)GetWindowPtr0(hwnd); // GetWindowLong(hwnd, 0);
LRESULT lres;
if (pThis)
{
// Always retain a ref across the v_WndProc in case
// the window destroys itself during the callback.
pThis->AddRef();
lres = pThis->v_WndProc(hwnd, uMsg, wParam, lParam);
if (uMsg == WM_NCDESTROY)
{
SetWindowPtr(hwnd, 0, NULL);
pThis->_hwnd = NULL;
}
pThis->Release();
}
else
{
//
// The only way this should happen is if we haven't actually
// gotten a WM_NCCREATE yet. User sends a WM_GETMINMAXINFO
// to some windows before WM_NCCREATE (for legacy compat).
// Assert that we're hitting that case.
//
ASSERT(uMsg == WM_GETMINMAXINFO);
lres = SHDefWindowProc(hwnd, uMsg, wParam, lParam);
}
return lres;
}
}
#ifndef NO_NOTIFYSUBCLASSWNDPROC
//
// CNotifySubclassWndProc
//
UINT g_idFSNotify; // the message SHChangeNotify sends
BOOL CNotifySubclassWndProc::_SubclassWindow(HWND hwnd)
{
if (0 == g_idFSNotify)
{
g_idFSNotify = RegisterWindowMessage(TEXT("SubclassedFSNotify"));
}
DEBUG_CODE( _hwndSubclassed = hwnd; );
return SetWindowSubclass(hwnd, _SubclassWndProc, ID_NOTIFY_SUBCLASS, (DWORD_PTR)this);
}
void CNotifySubclassWndProc::_UnsubclassWindow(HWND hwnd)
{
RemoveWindowSubclass(hwnd, _SubclassWndProc, ID_NOTIFY_SUBCLASS);
}
LRESULT CNotifySubclassWndProc::_DefWindowProc(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
return DefSubclassProc(hwnd, uMessage, wParam, lParam);
}
LRESULT CALLBACK CNotifySubclassWndProc::_SubclassWndProc(
HWND hwnd, UINT uMessage,
WPARAM wParam, LPARAM lParam,
UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
CNotifySubclassWndProc* pObj = (CNotifySubclassWndProc*)dwRefData;
if (pObj)
{
if (uMessage == g_idFSNotify)
{
LPSHChangeNotificationLock pshcnl;
LPITEMIDLIST *ppidl;
LONG lEvent;
if (g_fNewNotify && (wParam || lParam))
{
// New style of notifications need to lock and unlock in order to free the memory...
pshcnl = SHChangeNotification_Lock((HANDLE)wParam, (DWORD) lParam, &ppidl, &lEvent);
if (pshcnl)
{
pObj->OnChange(lEvent, ppidl[0], ppidl[1]);
}
}
else
{
lEvent = (DWORD) lParam; // process id's are 32bits even in WIN64
ppidl = (LPITEMIDLIST*)wParam;
pshcnl = NULL;
if (ppidl)
{
pObj->OnChange(lEvent, ppidl[0], ppidl[1]);
}
}
if (pshcnl)
{
SHChangeNotification_Unlock(pshcnl);
}
return 0;
}
else
{
return pObj->_DefWindowProc(hwnd, uMessage, wParam, lParam);
}
}
else
{
return DefSubclassProc(hwnd, uMessage, wParam, lParam);
}
}
void CNotifySubclassWndProc::_FlushNotifyMessages(HWND hwnd)
{
MSG msg;
ASSERT(hwnd == _hwndSubclassed);
// This SHChangeNotify calls flushes notifications
// via PostMessage, so I need to remove them
// myself and process them immediately...
//
SHChangeNotify(0, SHCNF_FLUSH, NULL, NULL);
while (PeekMessage(&msg, hwnd, g_idFSNotify, g_idFSNotify, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
void CNotifySubclassWndProc::_RegisterWindow(HWND hwnd, LPCITEMIDLIST pidl, long lEvents,
UINT uFlags/* = SHCNRF_ShellLevel | SHCNRF_InterruptLevel*/)
{
ASSERT(0 != g_idFSNotify);
// We only register if there's something to listen to
//
if (0==_uRegister)
{
// Since we don't know what this pidl actually points to,
// we have to register to listen to everything that might affect it...
//
_uRegister = RegisterNotify(hwnd, g_idFSNotify, pidl, lEvents, uFlags, TRUE);
ASSERT(hwnd == _hwndSubclassed);
}
}
void CNotifySubclassWndProc::_UnregisterWindow(HWND hwnd)
{
if (_uRegister)
{
ASSERT(hwnd == _hwndSubclassed);
// Avoid getting reentered...
UINT uRegister = _uRegister;
_uRegister = 0;
SHChangeNotifyDeregister(uRegister);
}
}
#endif // NO_NOTIFYSUBCLASSWNDPROC