【问题标题】:Subclassing notepad’s Edit class (WINAPI)子类化记事本的 Edit 类 (WINAPI)
【发布时间】:2013-05-09 10:32:52
【问题描述】:

我在记事本的 Edit 类上设置了 SetWindowsHookEx,但我不知道如何从这里继续。

我希望将 Edit 类子类化为我自己的过程,然后操作文本或将其保存到文件中,然后必须将其发回记事本控件/类。

有更简单的方法可以从记事本中获取文本,但我正在尝试学习 WINAPI 和子类化,所以这是我学习它的好方法。

我的 SetWindowsHookEx 看起来像这样:

SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInstDll, npThreadId); 

如何使用钩子类型:WH_GETMESSAGE 从记事本中的 Edit 类中获取文本并将其传输到我的 GetMsgProc(I think) 函数?

它是正确的钩子类型吗?

我会给它发消息吗?如果是,我该怎么做?

我的代码如下所示:

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;
}

我对如何从这里开始有点迷茫……有什么提示吗?链接?提示?

我已阅读 MSDN 上有关 SetWindowsHookEx 函数的文档 - 但我没有在那里找到明确的答案。

【问题讨论】:

    标签: winapi callback subclass setwindowshookex


    【解决方案1】:

    WH_GETMESSAGE 在钩子线程调用 GetMessage()PeekMessage() 以从其消息队列中检索消息时调用,但并非所有消息都通过消息队列,因此您可能必须使用 WH_CALLWNDPROC/RET 钩子同样,这取决于您要拦截的消息类型。

    您的全局变量需要存储在共享内存块中,否则它们只能被安装挂钩的进程访问,因为挂钩其他进程时会加载 DLL 的新副本。

    您不能将属于另一个进程的HWND 子类化。您必须将代码注入该进程,然后该代码可以根据需要在本地进行子类化。 SetWindowsHookEx() 可用于将代码注入其他进程,但 CreateRemoteThread() 可能更适合用于此,具体取决于您的需要。

    【讨论】:

    • 谢谢,雷米。 WH_GETMESSAGE 现在更清楚了。全局变量的好点。再次感谢。
    猜你喜欢
    • 2012-05-12
    • 2012-04-26
    • 2013-03-13
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 2014-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多