Solved

Detecting the desktop refresh event

Posted on 2001-09-05
43
909 Views
Last Modified: 2008-03-17
Hey all, I want to know if there is a way to detect when the desktop gets refreshed.  Either by the user pressing F5 or by clicking refresh on the menu.  If there is, I want to know how to detect the refresh in C++ in order to run some code right after it.  This is for all versions of windows.

Thanks.
0
Comment
Question by:Ra
  • 22
  • 15
  • 6
43 Comments
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6459580
listening....

i dont know any such windows API...hooks can work...but to my knowledge desktop window cannot be hooked through available microsoft hooks...and global hook is really bad idea ... so the option left is API hooking...quite difficult job...

and this is windows question... put another question in windows topic with 0 points and place a link there to this question...u might get some good advice...

Goodluck!

kuchnaheen
0
 
LVL 32

Expert Comment

by:jhance
ID: 6462005
I'm sure that this event happens as a result of a Windows message of some sort being sent to the desktop.  So you need to hook the desktop window procedure and watch for that message.  The question is what is that message and I've not seen it documented.  But since you need to hook the desktop window anyway, just write your hook and monitor it until you determine what the message you are looking for is.
0
 

Author Comment

by:Ra
ID: 6462063
ok... just one question.  How do I write a hook and how do I make it hook to the desktop?  I'll check MSDN to see if I can't figure it out.  If you have a sample, or know a web site with a sample or any kind of instructions, please post it.

Thanks.
0
 
LVL 32

Expert Comment

by:jhance
ID: 6462149
See the help for SetWindowsHookEx()
0
 

Author Comment

by:Ra
ID: 6462924
I used Spy++ to watch all the messages coming from the desktop when it was refreshed, and I found out that it doesn't send one single message.  I saw all the steps the refresh process went through, but there was no refresh message.  Is there any other way I can do this?
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6463040
to me desktop window cannot be hookd coz

FindWindow("Internet Explorer_Server",NULL)

returns invalid handle...

if some body knows the fix .... i am very anxious

RA:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ipc/hh/winbase/hooks_0837.asp

is a full hook sample code...

if u need further assistance in hooks ... let me know..i give very simple working code if this sample doesnt seeem to help u....

all the best

kuchnaheen

0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6463049
i will look for the message on getting some time...probably   in evening...and will let u know if get some success..

n keep going...there is always a way of doing any thing;)
0
 
LVL 32

Expert Comment

by:jhance
ID: 6463560
>to me desktop window cannot be hookd coz
>FindWindow("Internet Explorer_Server",NULL)
>returns invalid handle...

Well, if you used the correct window name, you'd get the window handle.  Oddly enough the window handle for the Desktop window is simply obtained with GetDesktopWindow().
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6463658
thats okay but after  that u will never be able to set a hook and setwindowshooksEx will fail with error ERROR_ACCESS_DENIED.....

try that....

i have done all that 3 months back....just getting a bit rusty with failure reasons...but i couldnt be able to set the hook on desktop window...
0
 
LVL 32

Expert Comment

by:jhance
ID: 6463821
Well, then you are not doing it correctly.  It is indeed possible to set a hook into the desktop window as there is nothing unique about this window vs. any other one.

Have you looked at the Spy++ application that comes with Visual Studio?  It uses hooks and certainly works with the desktop window. Try it out...

I've not done this myself or I would be posting some code but I'm positive that it can be done.
0
 

Author Comment

by:Ra
ID: 6463980
Hmmm.... I must have unchecked one to many things in Spy++.  When I pointed it to the desktop, it said it was a list view control so I unchecked everything excpet unknown and list view events.  The refresh messages must be in one of the others.  I'll try again after work today.
0
 
LVL 32

Expert Comment

by:jhance
ID: 6464105
I captured this with Spy++:

<00061> 0000015C S ..message:0x1050 [User-defined:WM_USER+3152] wParam:00000000 lParam:FF000000
<00062> 0000015C R ..message:0x1050 [User-defined:WM_USER+3152] lResult:00000001

I think it's this, WM_USER+3152.  I'm not sure what, if anything, the lParm or the lResult mean.
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6465049
jhance:

i dont know the reason...but i believe there is some thing special with this window....i mean why FindWindow cannot work on this....following API call works for every window in the world other than desktop window

FindWindow("Internet Explorer_Server",NULL)

and Internet Explorer_Server is the class name of desktop window and i got it through spy++...i used the same tactic for dozen of windows with 100% success....after that the setwindowshooksex starts complaining about the thing ... i am running the same code for all windows but desktop window raises unique issues....

Ra:

here is what i got

WM_SHOWWINDOW
WM_SHOWWINDOW
WM_WINDOWPOSCHANGING
WM_WINDOWPOSCHANGING
WM_CHILDACTIVATE
WM_CHILDACTIVATE
WM_PARENTNOTIFY
WM_PARENTNOTIFY
WM_DESTROY
WM_DESTROY
WM_NCDESTROY
WM_NCDESTROY

i think u have noticed that after refreshing.. spy++ stops recieving messages...reason being the WM_DESTROY...the window is destroyed and new window is created with different handle..so to me if u process WM_DESTROY ..it will do the job for u...

and if u need hook code i can give u...but it will work for every window other than desktop window:( i couldnt find any fix for that...
0
 
LVL 32

Expert Comment

by:jhance
ID: 6465136
I still don't understand why you want to use FindWindow when the Windows API FindDesktopWindow() is designed for just this purpose.  You are ASSUMING that the desktop Windows will always be "Internet Explorer_Server" and this is not a good assumption.  

In fact on my system, the desktop window class name is "#32769 (Desktop)".


>>i think u have noticed that after refreshing.. spy++ stops recieving messages

No, in fact I did NOT notice that.  Messages continued to be logged until I stopped the logging manually.
0
 

Author Comment

by:Ra
ID: 6465166
kuchnaheen, what OS are you using?  I'm using NT 4.0 and it does not destroy the desktop window after refreshing.  I have Spy++ here too and I watched every event.  After the refresh completes the messages keep coming.  I stoped Spy++ each time after clicking refresh at home (Windows ME there) so I don't know if it destroyed the window or not.  I'll check on that tonight, but since NT does not destroy it, I can't use that event as a trigger in my app.

However, in NT I do get a WM_SETREDRAW near the end of a refresh so if that is in 9x/ME/2k also, I can use that as a trigger.  It also happens when I empty the recycle bin for some reason, but that doesn't matter too much.  I have 2k here so I can install spy++ on that and test it there also.

Yes, plese post your hook code.  I tried to get that working last night, but I did not have any luck.

Thanks
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6465185
>>I still don't understand why you want to use FindWindow

handle returned by GetDeskTopWindow() cannot be used in SetWindowsHooksEx() it raises access error....thats why i was trying Findwindow()...but findwindow is not reliable as u just mentioned and it returns invalid handle....what is ur op/sys..

and on pressing F5 spy++ stops receiving messages on my system...and i NOTICED that the window handle changes....
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6465198
at the moment i am on win 98
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6465304
forget about messages

i tracked desktop window the handle was 0000070C

then i pressed F5

and now the handle is 00000F84

WM_DESTROY is there guys....

0
 
LVL 1

Accepted Solution

by:
kuchnaheen earned 200 total points
ID: 6465319
place the  following function in a win 32 dll file and export the function in its .def  file or use the other __ export method

LRESULT CALLBACK
GetMsgProc(
    INT hc,
    WPARAM wParam,
    LPARAM lParam
    )
{
     MSG* info;
     if (hc < 0)  // do not process message
        return CallNextHookEx(NULL, hc,
            wParam, lParam);

     info=(MSG* )lParam;
     switch (hc)
    {
        case HC_ACTION:
               switch(info->message)
               {
                    case WM_KEYDOWN:
                    MessaageBox(NULL,"balbla","blabla",MB_OK);
                         break;
                    default:
                         break;
               }
               default:
                    break;
     }
    //
    // CallNextHookEx ignores the first parameter (hhook) so
    // it is acceptable (barely) to pass in a NULL.
    //
    return CallNextHookEx(NULL, hc, wParam, lParam);
}

and follow the following sequence in ur executable

DWORD dwTID=NULL;
HHOOK hhHID=NULL;
HWND hwndWindow=NULL;
HANDLE hLib=NULL;

hLib=LoadLibrary("hookdll.DLL")//name of the dll containing the hook procedure

hwndWindow=FindWindow("classname of the window to be hooked",NULL)
//or u can use any method to find the handle of the desired window

dwTID=GetWindowThreadProcessId(hwndWindow,NULL)))

and finally u can set the hook by

hhHID = SetWindowsHookEx(
          WH_GETMESSAGE,
          (HOOKPROC)GetProcAddress((HINSTANCE)hLib,"GetMsgProc"),
          (HINSTANCE) hLib,
          dwTID)))

add error handling code to it ... and this WORKS for every thing other than Desktop window

u can replace the findwindow() by GetDesktopwindow() and try that ur self...i will be really happy if u can find me a fix....

best of luck

kuchnaheen

it 12:00 here...i will proceed on this in morning...just rocking now;) but dont forget to unhook before leaving the thing ...on win 98 thread hooks r not cleaned up by the system...however on NT/2000 op/sys takes care of cleaning things...
0
 

Author Comment

by:Ra
ID: 6465814
Ok, I just ran Spy++ on Win ME and the WM_SETREDRAW message did appear at the end of the refresh.  This is the message I need to look for.  Thanks for all the help guys.  I havn't tested this on 95/98/2k/XP yet, but I will soon... if I can find a 95 machine.  I don't have one, nor do I have one at work.  Can someone here verify that 95 sends the WM_SETREDRAW event at the end of the refresh event for me?  Thanks.

I'll have to test 95/98 to see if it destroy's the desktop during the refresh like kuchnaheen says his does.  It doesn't happen in ME nor in NT, even with Active Desktop turned on.  I guess 98 just does it differently or his machine is just screwy. ;)  I can't test that until Monday when I get back to work, we have Win 98 machines there.

I'm testing that hook code now.  I think I know what I was doing wrong.
0
 

Author Comment

by:Ra
ID: 6465952
Ok, this is a stupid question, but when the dll hits the case statement for the WM_REDRAW message (WM_KEYDOWN in the example above), how does it get the info back to my app that the message was dectected?  And how does my app recieve that info?  I've never made dll files before and I'm a bit lost right now.  I used MFC app wizzard to create the dll and it compiles without error.
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6466307
this isn't a stupid question at all....in fact it can be really difficult at times but for u i think the following solution will work...

in the dll tack ur application window handle and on hitting ur desired message send a message to that window through SendMessage API....

for tracking handle FindWindow will work if u r running win32 app....in MFC the classname of the window is assigned at run time so findwindow will not work there....in this case u can have an exported function in the dll which can receive the handle form application....in MFC apps the handle is provided (i think it is member variable of view class) ...u can pass that to dll before installing the hook and then hook can report the data to application.....

this is the simplest solution to the problem:)....if u r happy with it...all the best....otherwise let me know n i will give u some really dizzling thing then....
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6466318
here is the sample code .. u can decorate it to ur needs

in dll header file

typedef struct
{
    WPARAM wParam;
    LPARAM lParam;
    BYTE ExtraData[64];
} MSGDATA, *PMSGDATA;

in cpp file

PRIVATE MSGDATA msgdata;
PRIVATE COPYDATASTRUCT cds = { 0, sizeof(MSGDATA), &msgdata };

and in the case statement say WM_KEYDOWN

msgdata.wParam =info->wParam ;
                         msgdata.lParam =info->lParam ;

                         cds.dwData = info->message ;
SendMessage(hAppWindow, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds);

BTW there is sample in MSDN that includes the some of the code for spy++...have a look at that....it is simply great...i got started with that...

best of luck!

A
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6466323
and let me know when u gethook in desktop;)
0
 

Author Comment

by:Ra
ID: 6472925
Ok, I'm having major problems with this dll.  I tried using MFC dll wizard and the Win 32 dll... but both generate this error when I try to include them in my project. "HOOKDLL.dll : fatal error LNK1136: invalid or corrupt file".

Both the MFC and the Win 32 versions compile without problem... I've even copied the hook.c and hook.h from MSDN that the spy++ program uses into an empyt Win 32 dll project, and gets this same error.  Am I completely missing something here?

I think I have figured out how to get the desktop window... but without the dll, I can't test it.

Oh, one more question.  How do I get my main program to recieve the message sent from the dll with SendMessage?

Thanks
0
 

Author Comment

by:Ra
ID: 6475601
This code will find the desktop window.  GetDesktopWindow() returned an HWND, but when I tried to send a message to that HWND, nothing happened.  However when I used the following code to generate an HWND, the SendMessage worked!

HWND Progman;
HWND Shell;
HWND Desktop;

// Get the handle to the top level window with a class name of
// "Progman" and a caption of "Program Manager".
Progman = FindWindow("Progman", "Program Manager");
// Get Program Manager's child window which has
// a class name of "SHELLDLL_DefView".
Shell = FindWindowEx(Progman, 0, "SHELLDLL_DefView", NULL);
// Now get this window's child.
Desktop = FindWindowEx(Shell, 0, "SysListView32", NULL);
// Desktop is the HWND of the desktop

Isn't it wierd how windows still uses Program Manager even in Windows ME.  I found this in the soucre of a VB program.  Very easy to convert.  GetDesktopWindow returned 0x00000080, which is what Spy++ shows as the handle for the desktop.  The above code returned 0x0000013c for the desktop.  I can't find that value anywhere in Spy++ but it works and the other does not... wierd.  ( Note, the values for you desktop window will probably be different, I just listed mine as an example. )

I have no idea as to weather or not this code will work in NT or 2k or XP.  I will test it tomorrow and post the results.
0
 

Author Comment

by:Ra
ID: 6475610
BTW, you must use that code outside of a CDialog based class.  The CWnd versions of FindWindow and FindWindowEx return a CWnd rather then an HWND.  So you must either have them in a function outside of the CDialog based class or in another type of class.
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6475838
drop ur mail address here ...i will send u working files...i had an off yesterday...sorry for delay....

i will experiment on ur code late in evening....at the moment really busy in office mess;)
0
 

Author Comment

by:Ra
ID: 6476620
Ok, thanks.  My email is m-fryer@home.com.  I have no idea as to what I'm doing wrong on those dll files.

The above code to get the HWND of the desktop works on ME, NT 4.0 and 2k.  I'm asuming that it works on the rest of the Windows OSs.
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6477513
i have mailed the files .... n i wrote much of the code in past half hour(specially tester).....hope fully it will go fine....i did a bit of testing on it...but let me know if any problem occur...

A
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6477545
u win the game guy....i couldnt resist....just got the hook in desktop....just replace the single findwindow statment with ur code...n u have ur thing....now me rocks...

Success!!!!!

0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6484448
if u have any other question please feel free to ask..i am very interested in this kind of stuff...other wise if u r done with the thing grade the question.....
0
 

Author Comment

by:Ra
ID: 6489341
Sorry for the delay... been busy with some other stuff.  Anyway, I tweaked your code to point to the desktop using the code I posted above and it did trap the WM_KEYDOWN event.  However, I can not get it to trap the WM_SETREDRAW event.  Any ideas?

In Spy++ the WM_SETREDRAW is always proceded by one or two dots, depending if I use F5 or click refresh from the menu.  Is that preventing me from seeing it?  I tried to add a . to the code, but that just generated a compile error.  What do these dots mean anyway???
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6489478
dont have any idea at the moment....i will try that my self today...but in evening..on reaching home...
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6498959
dont have any idea yet...infact couldnt give eough time to it but in GetMessage hook i recieved only 32770 as message..n i am sure this is not refresh message ....so my idea is to try another hook ... like message filter...or any other hook...hit and trial .....

other wise...windows might handle through some other way...
0
 

Author Comment

by:Ra
ID: 6499881
I'm still looking for a single event that means refresh, but I can't find it either.  I don't remember seeing 32770, is that an unknown event?  The [User-defined:WM_USER+3152] event that jhance submitted above is only fired during a refresh where the WM_SETREDRAW is call at other times as well.

Spy++ seems to be able to trap events from the child threads as well as the parent, but the hook only seems to be watching the parent.  Is there a way to make it watch child threads as well?

Depending on how it is called (F5 or right click -> Refresh) then the WM_USER+3152 event is 1 or 2 periods in.  According to the help file, this means that it is nested.  I'm asuming that means that the refresh event is handled in a child thread.  I'm gonna try to refresh Spy++ at the same time as I refresh the desktop to see if I can trap this thread.  Just a theory right now, but I'm not getting anywhere with the hook as it is now.

I'll also try other hooks to see what I get.  I started doing that and one of them completely froze my computer.  I couldn't even move the mouse.
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6500170
if u try printing the Messages the Getmessage hook captures ...u will find the 32770 message appearing on refresh... i really dont know what it is...but its is not refresh....

ur theory makes sense...i dont know if it is possible or not...but u can try it....we have thread id of desk top....y not enumerate its child threads n hook them as well...or enumerate the parent process n hook all its threads ....

Getmessge hook gets all messages of messge pump of concerned thread so theoratically WM_SETREDRAW should be in its way....thats y i selected this hook for u....

to my knowlegde there is no other way of doing the stuff...the sole other possibility is to find out the API that is called on refresh event n hook that..n i can tell u this is hell tough....
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6502480
okaaaaaaaaay below is the function to get aall threds of a process

try that.....

BOOL RefreshThreadList (DWORD dwOwnerPID,DWORD dwTID)
{
    HANDLE        hThreadSnap = NULL;
    BOOL          bRet        = FALSE;
    THREADENTRY32 te32        = {0};
     char BUFF[20];
     // Take a snapshot of all threads currently in the system.

    hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (hThreadSnap == (HANDLE)-1)
        return (FALSE);
 
    // Fill in the size of the structure before using it.

    te32.dwSize = sizeof(THREADENTRY32);
 
    // Walk the thread snapshot to find all threads of the process.
    // If the thread belongs to the process, add its information
    // to the display list.
 
    if (Thread32First(hThreadSnap, &te32))
    {
        do
        {
            if (te32.th32OwnerProcessID == dwOwnerPID)
            {
                    if(!(hhHID[count] =
                    SetWindowsHookEx(
                    WH_GETMESSAGE,
                    (HOOKPROC)GetProcAddress(
                         (HINSTANCE)hFilter,"GetMsgProc"),
                    (HINSTANCE) hFilter,
                    dwTID)))
                    {
                         sprintf(BUFF,"Hook Installation Error NO : %d",GetLastError ());
                         MessageBox (GetForegroundWindow (),
                              BUFF,"SetWindowshoooksEx()",MB_OK);
                         return NULL;
                    }
                    else
                         MessageBox(NULL,"hook installed", "hehe",MB_OK);

                    count++;
               }
               
        }
        while (Thread32Next(hThreadSnap, &te32));
        bRet = TRUE;
    }
    else
        bRet = FALSE;          // could not walk the list of threads
 
    // Do not forget to clean up the snapshot object.

    CloseHandle (hThreadSnap);
     char buff[5];
     memset(buff,0,sizeof(buff));
     sprintf(buff,"%d",count);
     MessageBox (NULL,buff,"Thread count",MB_OK);
 
    return (bRet);
}

n yes dont for get to change every unhookwindowshookEx(hhID) to a loop unhooking all threads...i got 12 threads on my system...get an array of 20 handles tio remain safe...

n try to print all messages that the hook(any one u r trying) captures in filter dll ....the code i used for purpose is

case HC_ACTION:
sprintf(buff,"%d",iMsg);
               if(!(hdc=GetDC(FindWindow("Notepad",NULL))))
                    break;
               TextOut(hdc,200,200,buff,sizeof(buff));
               ReleaseDC(FindWindow("Notepad",NULL),hdc);
...........
...........
that prints the messges in notepad window....remeber this is very very bad piece of code...the worst part is that notepad window should be there in the system when u execute this piece...other wise u will get stuck with the debug file of filter...n the only solution will be the system restart.......

do let me know about present condition...will be great if some progress news....
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6502482
n i forgot to tell how to get the process id to feed the function...
DWORD dwTID=NULL;
DWORD dwPID=NULL;
dwTID=GetWindowThreadProcessId(hTarget,&dwPID)
0
 

Author Comment

by:Ra
ID: 6843207
kuchnaheen, sorry it's been so long.  I got pissed at this project because I couldn't get it to work and basically threw it out the window.  Since then I've read up on creating dll files and have restarted the project from scratch.  I am taking a completely different aproach as to how I'm creating the project and it is much easier this time.  I should have it working and this question graded within a week.  Thanks for your patience.
0
 

Author Comment

by:Ra
ID: 6849713
Thanks, kuchnaheen.  I finally got it to work.  I got a bit of help from this project here -> http://www.codeproject.com/dll/hooks.asp

The hook works great now.  Just for simplicity, I hooked it to the WM_PAINT event.  Thanks for the help and sorry again for the delay.  This grade is like 5 months overdue. ;)  I gave you some bonus points since you spent so much time on this before and I kept you waiting for so long.
0
 

Author Comment

by:Ra
ID: 6849724
well... darn.  I set the points to 500 when I accepted the answer and when it came up I got this message at the top of the screen: "The maximum points allowed for any question is 300, please consider a lower amount."  Now that the question is answered, I can't change the amount.  There needs to be a warning about that next to the increase points box.  Sorry dude.
0
 
LVL 1

Expert Comment

by:kuchnaheen
ID: 6852438
Thank YOU
A Compliment like this one is more than 1000 points:)
Look u r talking to 21 years old under grad;)
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now