Link to home
Start Free TrialLog in
Avatar of stevenc317
stevenc317

asked on

SetWinHook?

How do I create a hook that will watch the title bars of windows and save the title in an AnsiString?  For example if the title was "WinZip" then title would = WinZip.

thanks
Avatar of dkremer
dkremer

You don't need a hook for that... you can call EnumWindows and provide your callback to enumerate all the windows in the system.
You can install a hook for windows creation if you'd like so every window creation will get through you and you decide whether you let the window get created or you don't... but I don't think it's what you need.
If you do need a windows hook, I wrote some class that really simplifies the use of it... check it out in www.codeguru.com in the samples section.

Avatar of stevenc317

ASKER

Could you please send me some more info on the EnumWindows function?  Please remember that I will need to monitor every window that is executed (while my app is running).

thanks
Ohh ps.

What I ment to say is.  I need the codes to monitor every window that becomes active.  So only the active window's title will be in the AnsiString.

thanks
For that you will need a windows message hook. That is if you want to be notified at any time the active window changes.  However, if at some particular time you want to know what the active window is, you could use GetActiveWindow().
The code is rather long... could you give your e-mail and I'll send sample code to you directly ?
highvoltagerd@bigfoot.com
Steven, if you decide that EnumWindows() is not good enough and you want to play with hooks, drop me a note and I'll provide you with a sample.
Well I am not sure, so please send me an example of what you think will be best.

I will then choose.
If you must keep track at all times what window is active and be notified as soon as the active window chages, then you will need the hook.  

If at certain times, you want to know what window is currently active (and don't need to be notified as soon as that changes), then use GetActiveWindow().
Then I need a hook.  Since this will be for use in a security system, and I need to be able to shut down the program as soon as that program/window is open.
such security check does not seem to be very strong.

I'll attach a sample code of a DLL that manages global hooks below.  Also, see the help on the SetWindowsHookEx() function.

This code works with MSVC 4.2 and above, BC++ needs a slightly different approach to define a global section:

////////////////////////////////////////////////////////////////////////////////
// Shared variables (must be initialized)

#pragma comment(linker, "-section:.shared,rws")
#pragma data_seg(".shared")

HHOOK   g_hHook                 = NULL;     // WH_GETMESSAGE hook handle
char    g_directory[MAX_PATH]   = { 0 };    // Home directory

#pragma data_seg()

////////////////////////////////////////////////////////////////////////////////
// Global variables

HINSTANCE   g_hinstDll          = NULL; // Current DLL instance handle

////////////////////////////////////////////////////////////////////////////////
// DLL initialization and termination routine

BOOL APIENTRY DllMain(HINSTANCE hinstDll, DWORD reason, LPVOID reserved)
{
    UNREFERENCED_PARAMETER(reserved);
   
    switch (reason)
    {
    case DLL_PROCESS_ATTACH:
        DisableThreadLibraryCalls(hinstDll);
        g_hinstDll = hinstDll;  // Save DLL instance handle
        break;
    }
   
    return TRUE; // Success
}

////////////////////////////////////////////////////////////////////////////////
// Set the hook

__declspec(dllexport) BOOL Hook(DWORD dwThreadId)
{
    // Is a hook allready in place
    if (g_hHook != NULL)
        return FALSE;
   
    g_hHook = SetWindowsHookEx(WH_CBT, CBTProc, g_hinstDll, dwThreadId);
    return (g_hHook != NULL);
   
}

////////////////////////////////////////////////////////////////////////////////
// Remove the hook

__declspec(dllexport) BOOL Unhook(void)
{
    BOOL    rc;
   
    rc = UnhookWindowsHookEx(g_hHook);
    if (rc)
        g_hHook = NULL;
   
    return rc;
}

////////////////////////////////////////////////////////////////////////////////
// The hook procedure

__declspec(dllexport) LRESULT CALLBACK CBTProc(int code, WPARAM wParam, LPARAM lParam)
{
    if (code == HCBT_CREATEWND)
    {
        // Get pointer to initialization parameters
        LPCREATESTRUCT  pCs = ((LPCBT_CREATEWND)lParam)->lpcs;

        // Is it the dialog we want?
        if (pCs->style == MY_WINDOW_STYLE &&
            !lstrcmp(pCs->lpszName, MY_WINDOW_TITLE))
        {
            /* Do whatever needed here... */
        }
    }

    // Pass through the hook chain
    return CallNextHookEx(g_hHook, code, wParam, lParam);
}

////////////////////////////////////////////////////////////////////////////////

I highly recommend Richter's "advanced windows" book.

Also you can check my answer and following discussion to https://www.experts-exchange.com/topics/comp/lang/cplusplus/Q.10048548 (worth 15 points which I won't get :-)

Hey faster, what do you suggest?

Also please only sumbit codes that will work with Borland, since I do not know how to convert VC++ into BC++.
Someone can always change the window title to bypass your check, even if it is not their program.
do you have any better ideas?
I can tell you how to convert the example to Borland
However, I don't know if you're still considering a hooks solution.  You rejected my solution awfully quickly.
Alexo's code did answer your question.  The question might not be what you should have asked, but it was what you did ask.
How do I convert it to borland?
On the platform SDK there is a sample program called TList (Task List), which will return stuff like Hwnd, ProcessID and The Window title (if there is one). With a little manipulation I'm sure you could have it spit window titles to disk.

If you need code let me know, I have some MFC code I could quickly modify.
geez, you borland people.. give with it :)
What version of Borland C is this for?  5.0 now supports __declspec(dllexport) so you don't have to change it to _export.
OK, so you can use it.  I don't have a Bc++ in front of me so I guessed.
Anyway, the fun stuff is the #pragmas...
I have Builder 3.
also what is a def file?
A .DEF file is a module definition file for your executable/DLL/library.
It specifies things like: module name, stack size, sctions, imports, exports, etc.
It is usually optional except when you want to something special (like having a shared segment).

Just create a text file called <your project>.DEF, paste the stuff into it and add it to your project.

ASKER CERTIFIED SOLUTION
Avatar of alexo
alexo
Flag of Antarctica 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
Merde!  As if I remember it...

OK, a .DEF file is a module definition file that instructs the linker what to do when building your EXE/DLL file.  You don't need one unless you want to override default behaviour (such as declaring shared sections).

Just make a text file called <your project>.DEF, put the data in it and add it to your project.  Should work (modulo bugs).
alexo please repost your answer, I am unable to see if (weird).
The infamous EE bug.  I reproduced the answer as a comment.
I do not think that the code you have given me are what I need.  I need to my app to allways know what the Active Window is, and have the title of the active window put into and AnsiString called title.

thanks
The code I gave you is an example to be tailored for your needs.
HCBT_CREATEWND is used for hooking window creation.  Use HCBT_ACTIVATE to hook window activation (of course you'll also need to use CBTACTIVATESTRUCT instead of CBT_CREATEWND)

Example:

__declspec(dllexport) LRESULT CALLBACK CBTProc(int code, WPARAM wParam, LPARAM lParam)
{
    if (code == HCBT_CREATEWND)
    {
        HWND hwnd = ((LPCBTACTIVATESTRUCT)lParam)->hWndActive;
        /* Do whatever needed here... */
    }
    return CallNextHookEx(g_hHook, code, wParam, lParam);
}

Read the help on SetWindowsHookEx() carefully.  This is non-trivial stuff and it will save you grief while debugging your application.
That is really true.  Usually if you have a bug in you application, the program might die but the rest of the OS (the other programs running) will usually be fine.  If you make a mistake in a windows hook, you can take down the whole system.  So write carefully and be prepared for a few serious crashes until the kinks are worked out.  Make sure all your files are saved before you test!
On the other hand, if your needs are modest, you can just have a loop in your application that will do:

    char buffer[256];
    HWND hwnd = GetForegroundWindow();
    GetWindowText(hwnd, buffer, sizeof buffer);

No hooks, no schmooks.  You can put it in the mesasge loop or, even better, in a separate thread, possibly with Sleep(0) calls.

And the autograder hits again!