Index: /trunk/MFCtooling/userlog/userlog.cpp
===================================================================
--- /trunk/MFCtooling/userlog/userlog.cpp	(revision 46)
+++ /trunk/MFCtooling/userlog/userlog.cpp	(revision 47)
@@ -30,4 +30,15 @@
 static MSG lastmsg;
 
+static bool keysPressed[256];
+
+inline bool keyAlreadyPressed(const MSG & msg) {
+	return (msg.message==WM_KEYDOWN || msg.message==WM_SYSKEYDOWN) && keysPressed[msg.wParam];
+}
+
+inline bool keyNotPressed(const MSG & msg) {
+	return (msg.message==WM_KEYUP || msg.message==WM_SYSKEYUP) && !keysPressed[msg.wParam];
+}
+
+
 HANDLE mutex;
 
@@ -39,4 +50,7 @@
 	if( mutex == NULL ) {
 		MessageBox(0, L"MutexFailure", L"MutexFailure", 0);
+	}
+	for(int i=0; i<256; i++) {
+		keysPressed[i] = false;
 	}
 
@@ -126,8 +140,5 @@
 	msg.pt.y = -1;
 	msg.time = -1;
-	if( !MessageEquals(lastmsg, msg) ) {
-		lastmsg = msg;
-		HookProc(CALLWNDHOOKID, nCode, &msg);
-	}
+	HookProc(CALLWNDHOOKID, nCode, &msg);
 
 	return CallNextHookEx(myhookdata[CALLWNDHOOKID].hookhandle, nCode, wParam, lParam);
@@ -136,8 +147,6 @@
 LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) {
 	PMSG msg = (PMSG) lParam;
-	if( !MessageEquals(*msg, lastmsg)) {
-		lastmsg = *msg;
-		HookProc(GETMSGHOOKID,nCode, msg);
-	}
+	HookProc(GETMSGHOOKID,nCode, msg);
+
 	return CallNextHookEx(myhookdata[GETMSGHOOKID].hookhandle, nCode, wParam, lParam);
 }
@@ -151,4 +160,78 @@
 
 	DWORD waitResult;
+	// simple heuristic to eliminate duplicate messages
+	if( !( MessageEquals(*msg, lastmsg) || keyAlreadyPressed(*msg) || keyNotPressed(*msg) ) ) {
+		lastmsg = *msg;
+		if( msg->message==WM_KEYDOWN || msg->message==WM_SYSKEYDOWN ) {
+			keysPressed[msg->wParam] = true;
+		}
+		if( msg->message==WM_KEYUP || msg->message==WM_SYSKEYUP ) {
+			keysPressed[msg->wParam] = false;
+		}
+
+		// message filter:
+		// all messages that are defined in this switch statement will be part of the log
+		switch(msg->message) {
+			// messages for monitoring GUI state
+			case WM_CREATE:
+			case WM_DESTROY:
+			case WM_SETTEXT:
+
+			// mouse messages
+			case WM_LBUTTONDOWN:
+			case WM_LBUTTONUP:
+			case WM_LBUTTONDBLCLK:
+			case WM_RBUTTONDOWN:
+			case WM_RBUTTONUP:
+			case WM_RBUTTONDBLCLK:
+			case WM_MBUTTONDOWN:
+			case WM_MBUTTONUP:
+			case WM_MBUTTONDBLCLK:
+			case WM_XBUTTONDOWN:
+			case WM_XBUTTONUP:
+			case WM_XBUTTONDBLCLK:
+			case WM_NCLBUTTONDOWN:
+			case WM_NCLBUTTONUP:
+			case WM_NCLBUTTONDBLCLK:
+			case WM_NCRBUTTONDOWN:
+			case WM_NCRBUTTONUP:
+			case WM_NCRBUTTONDBLCLK:
+			case WM_NCMBUTTONDOWN:
+			case WM_NCMBUTTONUP:
+			case WM_NCMBUTTONDBLCLK:
+			case WM_NCXBUTTONDOWN:
+			case WM_NCXBUTTONUP:
+			case WM_NCXBUTTONDBLCLK:
+
+			// keyboard messages
+			case WM_KEYDOWN:
+			case WM_KEYUP:
+			case WM_SYSKEYDOWN:
+			case WM_SYSKEYUP:
+
+			// internal messages usefull for replay/matching of events
+			case WM_KILLFOCUS:
+			case WM_SETFOCUS:
+			case WM_COMMAND:
+			case WM_HSCROLL:
+			case WM_VSCROLL:
+			case WM_MENUSELECT:
+			case WM_USER:
+				waitResult = WaitForSingleObject(mutex, 1000);
+				if( waitResult==WAIT_OBJECT_0 ) {
+					WriteLogentryWString(msg, nFrom);
+					ReleaseMutex(mutex);
+				}
+#ifdef __TIMING__
+				msgCounter++;
+				msgCounterChange = true;
+#endif // __TIMING__
+				break;
+			default:
+				break;
+		}
+	}
+
+	/* Source code for an inverse filter
 
 	// inverse filter: defined messages will be filtered, all else just passes through
@@ -252,17 +335,9 @@
 			// exclude messages 0xC000-0xFFFF
 			if( !(msg->message>=0xC000 && msg->message<=0xFFFF) ) {
-				waitResult = WaitForSingleObject(mutex, 1000);
-				if( waitResult==WAIT_OBJECT_0 ) {
-					WriteLogentryWString(msg, nFrom);
-					ReleaseMutex(mutex);
-				}
-
-#ifdef __TIMING__
-				msgCounter++;
-				msgCounterChange = true;
-#endif // __TIMING__
+				// CODE HERE!
 			}
 			break;
-	}
+	} */
+
 #ifdef __TIMING__
 	GetSystemTime( &systemTime );
