Click here to Skip to main content
15,885,278 members
Articles / Desktop Programming / MFC

CListCtrlExt and CListViewExt controls

Rate me:
Please Sign up or sign in to vote.
4.78/5 (22 votes)
20 Feb 2012CPOL5 min read 82.8K   8.7K   84  
An enhanced list control based on the standard CListCtrl MFC class.
// MsgHook.cpp : implementation of the CMsgHook class
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MsgHook.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMsgHook

HHOOK CMsgHook::m_hHook = NULL;
int CMsgHook::m_nInstances = 0;
CMap<HWND, HWND&, CMsgHook*, CMsgHook*&> CMsgHook::m_MapHookedWindows;  // map of windows to hooks

CMsgHook::CMsgHook()
	:m_bDropDown(FALSE)
	,m_hWnd(NULL)
	,m_hParent(NULL)
	,m_hNotify(NULL)
{
	if(m_nInstances == 0)
	{
		m_hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, CallWndRetProc, NULL, GetCurrentThreadId());
		ASSERT(m_hHook);
	}
	m_nInstances++;
}

CMsgHook::~CMsgHook()
{
	m_nInstances--;
	if(m_nInstances == 0)UnhookWindowsHookEx(m_hHook);
}

LRESULT CALLBACK CMsgHook::CallWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	CWPRETSTRUCT* pMsg = (CWPRETSTRUCT*)lParam;
	if(pMsg)
	{
		CMsgHook* pHook = NULL;

		switch(pMsg->message)
		{
		case WM_KILLFOCUS:
			{
				HWND hWnd = (HWND)pMsg->hwnd;
				while(hWnd)
				{
					if(m_MapHookedWindows.Lookup(hWnd, pHook))
					{
						if(! pHook->m_bDropDown)
						{
							hWnd = (HWND)pMsg->wParam;
							while(hWnd && hWnd != pHook->m_hWnd)
							{	
								hWnd = GetParent(hWnd);
							}
							if(! hWnd)
							{
								SendMessage(pHook->m_hNotify ? pHook->m_hNotify : pHook->m_hParent, UM_HIDEEDITOR, TRUE, 0);
								break;
							}
						}
						break;
					}
					hWnd = GetParent(hWnd);
				}
			}
			break;
		case WM_NOTIFY:
			{
				LPNMHDR pnmh = (LPNMHDR)pMsg->lParam;
				if(pnmh->code == DTN_DROPDOWN || pnmh->code == DTN_CLOSEUP)
				{
					HWND hWnd = (HWND)pnmh->hwndFrom;
					while(hWnd)
					{
						if(m_MapHookedWindows.Lookup(hWnd, pHook))
						{
							pHook->m_bDropDown = (DTN_DROPDOWN == pnmh->code);						
							break;
						}
						hWnd = GetParent(hWnd);
					}
				}				
			}
			break;
		case WM_COMMAND:
			{
				WORD code = HIWORD(pMsg->wParam);
				if(code == CBN_DROPDOWN || code == CBN_CLOSEUP)
				{
					HWND hWnd = (HWND)pMsg->lParam;
					while(hWnd)
					{
						if(m_MapHookedWindows.Lookup(hWnd, pHook))
						{
							pHook->m_bDropDown = (CBN_DROPDOWN == code);
							break;
						}
						hWnd = GetParent(hWnd);
					}
				}				
			}
			break;
		case WM_KEYDOWN:
			{
				if(pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN)
				{
					HWND hWnd = (HWND)pMsg->hwnd;
					while(hWnd)
					{
						if(m_MapHookedWindows.Lookup(hWnd, pHook))
						{
							SendMessage(pHook->m_hNotify ? pHook->m_hNotify : pHook->m_hParent, UM_HIDEEDITOR, pMsg->wParam == VK_RETURN, 0);
							break;
						}
						hWnd = GetParent(hWnd);
					}
				}
			}
			break;
		case WM_DESTROY:
			{
				if(m_MapHookedWindows.Lookup(pMsg->hwnd, pHook))
				{
					pHook->Detach();
				}
			}
			break;
		case WM_LBUTTONDOWN:
		case WM_RBUTTONDOWN:
		case WM_MBUTTONDOWN:
		case WM_HSCROLL:
		case WM_VSCROLL:
		case WM_MENUSELECT:
		case WM_MOUSEWHEEL:
			{
				HWND hWnd = (HWND)pMsg->hwnd;
				while(hWnd && ! m_MapHookedWindows.Lookup(hWnd, pHook))
				{					
					hWnd = GetParent(hWnd);
				}
				if(! pHook)
				{
					POSITION pos = m_MapHookedWindows.GetStartPosition();
					HWND    hWnd;
					while(pos != NULL)
					{
						m_MapHookedWindows.GetNextAssoc(pos, hWnd, pHook);

						if(IsWindow(hWnd) && ! pHook->m_bDropDown)
						{
							BOOL dropDown = SendMessage(hWnd, CB_GETDROPPEDSTATE, 0, 0) || DateTime_GetMonthCal(hWnd);
							if(! dropDown)SendMessage(pHook->m_hNotify ? pHook->m_hNotify : pHook->m_hParent, UM_HIDEEDITOR, TRUE, 0);
						}
					}

				}
			}
			break;
		}		
	}

	return CallNextHookEx(m_hHook, nCode, wParam, lParam);
}

BOOL CMsgHook::Attach(HWND hWnd, HWND hParent, HWND hNotify)
{
	if(IsWindow(hWnd) && IsWindow(hParent))
	{
		Detach();
		m_hWnd = hWnd;
		m_hParent = hParent;
		m_hNotify = hNotify;
		m_MapHookedWindows[hWnd] = this;
		m_bDropDown = FALSE;
		return TRUE;
	}

	return FALSE;
}

BOOL CMsgHook::Detach(void)
{
	if(m_MapHookedWindows.RemoveKey(m_hWnd))
	{
		m_hWnd	= NULL;
		m_hParent = NULL;
		m_hNotify = NULL;
		m_bDropDown = FALSE;
		return TRUE;
	}

	return FALSE;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Romania Romania
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions