Question

I have set a SetWindowsHookEx on the Edit class of notepad, but I am not sure how to continue from here.

I wish to subclass the Edit class to my own procedure, then manipulate the text or just save it to a file, then it must be send back the notepad control/class.

There are easier ways to get the text from notepad, but I am trying to learn WINAPI and Subclassing so this is a good way for me to learn it.

My SetWindowsHookEx looks like this:

SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInstDll, npThreadId); 

How do I use the hook type : WH_GETMESSAGE to get the text from the Edit class in notepad and transfer it to my GetMsgProc(I think) function?

Is it the right hook type at all?

Do I send it a message? If yes, how do I do that?

My code look like this:

dllHeader.h:

#ifdef DLLAPI
#else
#define DLLAPI extern "C" __declspec(dllimport)
#endif
DLLAPI bool hookNotepad();

dll.cpp:

#include "stdafx.h"
#include <windows.h>
#define DLLAPI extern "C" __declspec(dllexport)
#include "dllHeader.h"

// Forward references
LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);

// Global variables
HHOOK g_hHook = NULL;        // Hook for Notepad 'EDIT' class
HINSTANCE g_hInstDll = NULL; // DllMain entry (DLL_PROCESS_ATTACH)
HWND npHWND = NULL;          // Notepad handle
DWORD npThreadId = NULL;     // Notepad thread ID
HWND npeHWND = NULL;         // Notepad 'EDIT' class handle


BOOL APIENTRY DllMain(HMODULE hModule,  DWORD ul_reason_for_call,  LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        g_hInstDll = hModule;
        break;

    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

bool hookNotepad ()
{
    npHWND = FindWindow(TEXT("Notepad"), NULL); // Finds Notepad

    if (npHWND) //Notepad found
    {
        npeHWND = FindWindowEx(npHWND, NULL, L"Edit", NULL); // Finds the 'EDIT' class in notepad
        npThreadId = GetWindowThreadProcessId(npeHWND, NULL); //Find ThreadID for Notepad 'EDIT' class
        g_hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInstDll, npThreadId); //Set hook in Notepad 'EDIT' class

        if (g_hHook) //if the hook is a succes then...
        { 
            MessageBox(NULL,TEXT("Hook set in Notepad EDIT class!"), NULL, MB_OK); 
            // Now what? How to subclass the npeHWND (The 'EDIT' class of Notepad) to my own procedure? 
        }
        else
        {
            MessageBox(NULL,TEXT("SetWindowsHookEx error!"), NULL, MB_OK); //If the hook fails.
        }
    }
    return 0;
}

LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) 
{
    if (nCode >= 0)
    {
        MessageBox(NULL,TEXT("This never get called. Why?"), NULL, MB_OK);
    }
    return(CallNextHookEx(g_hHook, nCode, wParam, lParam));
}

exe.cpp

#include <stdlib.h>
#include "stdafx.h"
#include <strsafe.h>

#include "C:\Users\Kristensen\Documents\Visual Studio 2012\Projects\dll\dll\dllHeader.h"

int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int) 
{

    hookNotepad();
    return 0;
}

I am a bit a lost on how to proceed from here… Any hints? Links? Tips?

I have read the documentation on MSDN regarding the SetWindowsHookEx function – but I did not find a clear answer there.

Was it helpful?

Solution

WH_GETMESSAGE is called when the hooked thread calls GetMessage() or PeekMessage() to retrieve a message from its message queue, but not all messages go through the message queue, so you may have to use the WH_CALLWNDPROC/RET hooks as well, depending on what kind of messages you are trying to intercept.

Your global variables need to be stored in a block of shared memory or else they will only be accessible to the process that installs the hook, since a new copy of the DLL gets loaded when hooking other processes.

You cannot subclass an HWND that is owned by another process. You would have to inject code into that process and then that code can subclass locally as needed. SetWindowsHookEx() can be used to inject code into other processes, but CreateRemoteThread() may be better to use for that, depending on your needs.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top