|
|
#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
|