[For Igor] SetCursor and SetWindowsHookEx

A

Arsen V.

Hi Igor,

I asked you this before and you suggested that I use SetWindowsHookEx to
change the cursor for the IE window from within my toolbar control.

Currently I am doing the following:

In my ChangeCursor() function
....
myHook = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, NULL,
GetCurrentThreadId());
....

In my CallWndProc() function

LRESULT WINAPI CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (((CWPSTRUCT*)lParam)->message = WM_SETCURSOR)
{
// Change cursor
HCURSOR hCurs = LoadCursorFromFile("c:\\b.cur");
HCURSOR hPrevCurs = SetCursor(hCurs);
}
return CallNextHookEx(myHook, nCode, wParam, lParam);
}

When I test this, the cursor does not get changed.

When I debug and set a breakpoint in the //Change cursor section, I see that
program execution gets to this point. I also see that hCurs and hPrevCurs
get assigned not NULL values.

What am I doing wrong?

Thanks,
Arsen
 
A

Alexander Nickolov

Well, you just let the mesage fall through, so the underlying window
that actually handles it restores the cursor to what it wants. The
idea is that you don't propagate the message any further.

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: (e-mail address removed)
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================
 
A

Arsen V.

Hi Alexander,

How do I prevent it from happening?

Should I not return the CallNextHookEx when the message is WM_SETCURSOR?

Thanks,
Arsen

Alexander Nickolov said:
Well, you just let the mesage fall through, so the underlying window
that actually handles it restores the cursor to what it wants. The
idea is that you don't propagate the message any further.

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: (e-mail address removed)
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================
Arsen V. said:
Hi Igor,

I asked you this before and you suggested that I use SetWindowsHookEx to
change the cursor for the IE window from within my toolbar control.

Currently I am doing the following:

In my ChangeCursor() function
...
myHook = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, NULL,
GetCurrentThreadId());
...

In my CallWndProc() function

LRESULT WINAPI CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (((CWPSTRUCT*)lParam)->message = WM_SETCURSOR)
{
// Change cursor
HCURSOR hCurs = LoadCursorFromFile("c:\\b.cur");
HCURSOR hPrevCurs = SetCursor(hCurs);
}
return CallNextHookEx(myHook, nCode, wParam, lParam);
}

When I test this, the cursor does not get changed.

When I debug and set a breakpoint in the //Change cursor section, I see that
program execution gets to this point. I also see that hCurs and hPrevCurs
get assigned not NULL values.

What am I doing wrong?

Thanks,
Arsen
 
I

Igor Tandetnik

You cannot swallow nor modify the message with WH_CALLWNDPROC hook. Try
WH_CALLWNDPROCRET hook instead - it is called after the target window
proc has processed the message, so you can reset the cursor back to the
one you want.
--
With best wishes,
Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken

Arsen V. said:
Hi Alexander,

How do I prevent it from happening?

Should I not return the CallNextHookEx when the message is
WM_SETCURSOR?

Thanks,
Arsen

Alexander Nickolov said:
Well, you just let the mesage fall through, so the underlying window
that actually handles it restores the cursor to what it wants. The
idea is that you don't propagate the message any further.

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: (e-mail address removed)
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================
Arsen V. said:
Hi Igor,

I asked you this before and you suggested that I use
SetWindowsHookEx to change the cursor for the IE window from within
my toolbar control.

Currently I am doing the following:

In my ChangeCursor() function
...
myHook = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc,
NULL, GetCurrentThreadId());
...

In my CallWndProc() function

LRESULT WINAPI CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (((CWPSTRUCT*)lParam)->message = WM_SETCURSOR)
{
// Change cursor
HCURSOR hCurs = LoadCursorFromFile("c:\\b.cur");
HCURSOR hPrevCurs = SetCursor(hCurs);
}
return CallNextHookEx(myHook, nCode, wParam, lParam);
}

When I test this, the cursor does not get changed.

When I debug and set a breakpoint in the //Change cursor section, I
see that program execution gets to this point. I also see that
hCurs and hPrevCurs get assigned not NULL values.

What am I doing wrong?

Thanks,
Arsen
 
A

Arsen V.

Hi Igor,

Your suggestion of using CallWndRetProc instead of CallWndProc appears to
work.

It currently looks like this:

LRESULT CALLBACK CallWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// Unhook this hook after 10 seconds
time_t now;
time (&now);
double dif = difftime(now,then);
if (dif > 10)
UnhookWindowsHookEx(myHook);

if (((CWPRETSTRUCT*)lParam)->message == WM_SETCURSOR)
{
// Change cursor
HCURSOR hCurs = LoadCursorFromFile("c:\\b.cur");
HCURSOR hPrevCurs = SetCursor(hCurs);
}

return S_OK;
}

Currently I have the CallWndRetProc as a global function. How can I make it
a function of the class CToolBandObj?

The line that sets up the hook is like this (note: myHook and "then" are
global variables):

void CToolBandObj::ChangeCursor()
{
if (myHook != 0)
{
UnhookWindowsHookEx(myHook);
myHook = 0;
}

time(&then);
myHook = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC)CallWndRetProc,
NULL, GetCurrentThreadId());
}

I would like to have the myHook and then be local data members: m_hHook and
m_tThen.

How do I setup the SetWindowsHookEx() parameter #2 to reference a class
function instead of the global function?

Do you see any glaring errors with my current code?

Thanks,
Arsen
 
I

Igor Tandetnik

Arsen V. said:
myHook = SetWindowsHookEx(WH_CALLWNDPROCRET,
(HOOKPROC)CallWndRetProc, NULL, GetCurrentThreadId());
}

I would like to have the myHook and then be local data members:
m_hHook and m_tThen.

How do I setup the SetWindowsHookEx() parameter #2 to reference a
class function instead of the global function?

You can't. The hook proc must be global or static member function.
Pretty much the only thing you can do is to store your 'this' pointer in
some global variable where the hook can access it.
Do you see any glaring errors with my current code?

You fail to call CallNextHookEx from inside your hook. That'll break any
other hook that might have been installed before yours.
--
With best wishes,
Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top