Link to home
Start Free TrialLog in
Avatar of UdiRaz
UdiRaz

asked on

Word, excel don't work with my hooking dll

Hi,
I created a hooking dll. It works well for all applications but no in word or excel. I am interested in WM_KEYDOWN, WM_KEYUP and WM_CHAR to replace characters according to my logic. For some reason, when Word is in focus WM_CHAR does not reached to my hook proc. Only WM_KEYDOWN and KEYUP.

below is a code snippest of my dll
// my app call this method
BOOL SetHook()
{
	hHook = SetWindowsHookEx(WH_CALLWNDPROC, HookProc, hMod, NULL );
 
	return(hHook ? TRUE : FALSE);
}
 
// upon enter or exit from focus
LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam)
{
	LRESULT	ret	= 0;
 
	if (code == HC_ACTION)
	{
		CWPSTRUCT	*	pData	= (CWPSTRUCT *) lParam;
 
		if (pData->message == WM_SETFOCUS)
		{
			SubclassWindow(pData->hwnd);
		}
		else if (pData->message == WM_KILLFOCUS)
		{
			UnSubclassWindow(pData->hwnd);
		}
	}
 
	return(CallNextHookEx(hHook, code, wParam, lParam));
}
 
// and 
void SubclassWindow(HWND hWnd)
{
	if (hWnd != hEdit)
	{
		UnSubclassWindow(hEdit);
 
		hEdit   = hWnd;
 
		pOldWndProc	= (WNDPROC) SetWindowLong(hEdit, GWL_WNDPROC, (LONG) MyWndProc);
	}
}
 
// finally, the method that does the work.
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
 
	switch (msg)
	{
	case WM_CHAR:
		return HandleCharMessage(hWnd, msg, wParam, lParam);
	case WM_KEYDOWN:
		return HandleKeyDownMessage(hWnd, msg, wParam, lParam);
	case WM_KEYUP:
		return HandleKeyUpMessage(hWnd, msg, wParam, lParam);
	default:
		return(CallWindowProc(pOldWndProc, hWnd, msg, wParam, lParam));
	} 	
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of JohnGaby
JohnGaby
Flag of Afghanistan image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of UdiRaz
UdiRaz

ASKER

Thanks again.
Although this example is working with word, it has it own problems.
In real life, I am replacing Hindi characters. Unfortunatly, Unlike english ,there are some hindi letters that are made of more then one character. What I do to replace the original key stroke with the characters I want is to hook the WM_KEYDOWN, simulate some WM_CHAR messages and don't pass the next WM_CHAR and WM_KEYUP. This solution works fine with the code you sent me before. The implementation of HandleKeyDownMessage() ( from my original question above ) does the job. So when I took the code you sent me here, I first modified it to work with my logic on the x and y example. It works fine ( see code snippet below ). Then, happy that it is working on word, I tried to create a hindi letter that made of three characters ( attached, is an image of character ). This letter is typed when you press the apostrophe button ( left to the enter ).Nothing was printed.

Please look at he code snippet and advice
// x and y example. Works fine
LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam)
	{
		LRESULT ret = 0;
 
		if (code == HC_ACTION)
		{
			MSG * pMsg = (MSG *) lParam;
 
			switch( pMsg->message )
			{
				case WM_KEYDOWN:
					if (pMsg->wParam == 'X')
					{
						pMsg->wParam  = 'y';
						pMsg->message = WM_CHAR;
						return(CallNextHookEx(hHook, code, wParam, lParam));
					}
					break;
				case WM_KEYUP:
					if (pMsg->wParam == 'X')
						return 0;
					else
						break;
				case WM_CHAR:
					if (pMsg->wParam == 'y' )
						return 0;
					else
						break;
			}
		}
 
		return(CallNextHookEx(hHook, code, wParam, lParam));
	}
 
 
// Not working :-(
LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam)
{
	LRESULT ret = 0;
 
	if (code == HC_ACTION)
	{
		MSG * pMsg = (MSG *) lParam;
 
		switch( pMsg->message )
		{
		case WM_KEYDOWN:
			if (pMsg->wParam == 0xde)
			{
				g_ignoreChar = true;
				pMsg->wParam  = 0x936;
				pMsg->message = WM_CHAR;
				CallNextHookEx(hHook, code, wParam, lParam);
				pMsg->wParam  = 0x94d;
				CallNextHookEx(hHook, code, wParam, lParam);
				pMsg->wParam  = 0x200d;
				return(CallNextHookEx(hHook, code, wParam, lParam));
			}
			break;
		case WM_KEYUP:
			if (pMsg->wParam == 0xde)
				return 0;
			else
				break;
		case WM_CHAR:
			if ( g_ignoreChar == true)
			{
				g_ignoreChar = false;
				return 0;
			}
			else
				break;
		}
	}
 
	return(CallNextHookEx(hHook, code, wParam, lParam));
}

Open in new window

apostrophe.JPG
Avatar of UdiRaz

ASKER

b.t.w. If you will add hindi and try to see what is typed, you will not see this letter.
The reason is that windows supports Inscript Hindi and not Remington Hindi, which is a different layout of the characters. since our clients wants Remington Hindi, I am replacing the characters...
You are straying outside my area of knowledge, I am afraid.  I have not had a ton of experience with other languages.  Are you compiling for Unicode or Double Byte?  If you are not using Unicode, you might try switching to it.  Other than that, I don't think I can help much more.
Avatar of UdiRaz

ASKER

I am using a unicode. But lets rephrase the question.

lets say that when a user press x, I would like to simulate y and z. it will not work.

Thanks
I might add one other thing that I have mentioned before.  The WM_CHAR message is not generated by the keyboard at all.  It is posted when the application calls the TranslateMessage function with a WM_KEYDOWN.  Perhaps by controlling just the WM_KEYDOWN messages, you can get windows to generate the desired WM_CHAR messages?
Avatar of UdiRaz

ASKER

1. most of the job does execute upon WM_KEYDOWN.
2. please try my code snippet but simulate two english characters. Only the second will be typed.
So you are trying to change the WM_KEYDOWN message into a WM_CHAR message?  I really don't think that is a good idea, since the system will not then be getting the WM_KEYDOWN message at all.

Let me see if I understand what you want to do.  On certain WM_KEYDOWN messages, you want to generate 2 (or more) separate WM_CHAR messages, and you want to remove the normal WM_CHAR message that is generated when the WM_KEYDOWN message is processed by the TranslateMessage function?

Perhaps on the WM_KEYDOWN message you could use PostMessage to post the WM_CHAR messages that you want.  To get the real WM_CHAR message to disappear, you would need to change it into some other (hopefully benign) message. (I do not believe that returning 0 from your hook will prevent message from being sent).

I am just shooting from the hip here.  I don't know if any of this would work, and whether you are allowed to post messages in a hook.  Also, it is quite possible that because you are posting messages interspersed with key messages, that they may get out of order.

This whole thing is getting quite messy.  Maybe you should really be looking into how to get windows to handle your language correctly.  Perhaps you could post a query about that, that someone else may be able to answer.

Avatar of UdiRaz

ASKER

You undrstand right.
I think that if I don't call CallNextHookEx at the end of this method, the windows won't know that it happen ( i.e. return 0 ). It works on MyWndProc when I selectively call CallWindowProc. What is the difference between the ?

I tried another approch. The original one ( yours ). I tried to use the subclassing code that works on all application but office and to use spy++ to get a handle of the edit control that handle the message but I didn't find such a control like you found on the notepad. Can you take a look, maybe you will find the right control.

Thanks
I did use spy to spy on the edit window for word (the window class is _WwG).  Paradoxically, spy says that that window DOES receive the WM_CHAR message.  However, when I set the hook, I (like you) do not see it.  The only thing I can figure is that Word is treating the WM_CHAR message differently when it sees it returned from GetMessage in its message loop.  I cannot fathom why that would be.  I also don't understand why spy reports that the window is receiving the WM_CHAR message, when I am unable to intercept it.  Spy must be doing something different, but I am at a loss as to what it might be.

Perhaps someone else can explain?