Windows:当我从本机代码回调到托管代码时,会出现仅消息窗口

发布于 2024-11-14 20:16:19 字数 2705 浏览 4 评论 0原文

经过相当多的努力,我设法从第三方 MFC dll 捕获 Windows 消息(我询问了此处)。简而言之,我必须创建一个仅包含消息的窗口,其中包含捕获第三方 dll 消息的消息循环。

所述仅消息窗口必须保持隐藏。最初,因为我将 HWND_MESSAGE 传递给 CreateWindowEx 并调用 ShowWindow 与 SW_HIDE。 但是,我的 C++ dll 有一些对托管代码的回调。我注意到,当我执行触发第一个操作的用户操作时,会出现一个控制台窗口。在我关闭应用程序之前它不会消失。

由于控制台窗口将我的应用程序的可执行路径作为其标题,因此我认为该窗口以某种方式与我的应用程序关联。所以我将 NULL 传递给 CreateWindowEx 的 hInstance 参数,但它不起作用。

这是我的仅消息窗口代码:

DWORD WINAPI CDRTech::MessageLoopThread( void * pParams ){
    HWND hwnd;
    MSG mensaje;
    WNDCLASSEX wincl;
    const string windowClass = "DR_TECH_MESSAGE_HANDLER";

    // Window class
    wincl.hInstance = ::GetModuleHandle(NULL);
    wincl.lpszClassName = windowClass.c_str();
    wincl.lpfnWndProc = ::DefWindowProc;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof (WNDCLASSEX);
    wincl.hIcon = ::LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = ::LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = ::LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hbrBackground = ::GetSysColorBrush(COLOR_BACKGROUND);
    if(!::RegisterClassEx(&wincl)){
        ::GetErrorLoggerInstance()->Log( LOG_TYPE_ERROR, "CDRTech", "MessageLoopThread", "Could not register Message Handling Window" );
        return 0;
    }

    //Create Window (hidden)
    hwnd = ::CreateWindowEx(
            0,                      //Default ExStyle
            windowClass.c_str(),    //Window class
            "DRTech",               //Window Title
            WS_OVERLAPPEDWINDOW,    //Default Style
            CW_USEDEFAULT,          //Let Windows decide position
            CW_USEDEFAULT,
            10,                     //Width
            10,                     //Height
            HWND_MESSAGE,           //Message-only window
            NULL,                   //No Menu
            NULL,                   //Handle to application
            NULL                    //Window creation data
    );
    ::ShowWindow( hwnd, SW_HIDE );

    CDRTech* pThis = reinterpret_cast<CDRTech*>( pParams );
    pThis->InitDRTechLibrary();
    //Start message loop
    while(TRUE == GetMessage(&mensaje, NULL, 0, 0)){
        TranslateMessage(&mensaje);
        DispatchMessage(&mensaje);
    }
    return mensaje.wParam;
}

After quite some effort, I managed to capture Windows Messages from a third party MFC dll (I asked about that here). To make it short, I had to create a Message-only window with a message loop which captured the third party dll's messages.

Said Message-only window must remain hidden. And it does, initially, since I pass HWND_MESSAGE to CreateWindowEx and call ShowWindow with SW_HIDE.
However, my C++ dll has some callbacks into managed code. And I noticed that when I perform the user actions that trigger the first of them, a console window appears. And it doesn't go away until I close my app.

Since the console window has my app's executable path as its title, I thought that the window was somehow being associated to my app. So I passed NULL to CreateWindowEx's hInstance parameter, but it didn't work.

Here's my Message-only window code:

DWORD WINAPI CDRTech::MessageLoopThread( void * pParams ){
    HWND hwnd;
    MSG mensaje;
    WNDCLASSEX wincl;
    const string windowClass = "DR_TECH_MESSAGE_HANDLER";

    // Window class
    wincl.hInstance = ::GetModuleHandle(NULL);
    wincl.lpszClassName = windowClass.c_str();
    wincl.lpfnWndProc = ::DefWindowProc;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof (WNDCLASSEX);
    wincl.hIcon = ::LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = ::LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = ::LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hbrBackground = ::GetSysColorBrush(COLOR_BACKGROUND);
    if(!::RegisterClassEx(&wincl)){
        ::GetErrorLoggerInstance()->Log( LOG_TYPE_ERROR, "CDRTech", "MessageLoopThread", "Could not register Message Handling Window" );
        return 0;
    }

    //Create Window (hidden)
    hwnd = ::CreateWindowEx(
            0,                      //Default ExStyle
            windowClass.c_str(),    //Window class
            "DRTech",               //Window Title
            WS_OVERLAPPEDWINDOW,    //Default Style
            CW_USEDEFAULT,          //Let Windows decide position
            CW_USEDEFAULT,
            10,                     //Width
            10,                     //Height
            HWND_MESSAGE,           //Message-only window
            NULL,                   //No Menu
            NULL,                   //Handle to application
            NULL                    //Window creation data
    );
    ::ShowWindow( hwnd, SW_HIDE );

    CDRTech* pThis = reinterpret_cast<CDRTech*>( pParams );
    pThis->InitDRTechLibrary();
    //Start message loop
    while(TRUE == GetMessage(&mensaje, NULL, 0, 0)){
        TranslateMessage(&mensaje);
        DispatchMessage(&mensaje);
    }
    return mensaje.wParam;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

枯寂 2024-11-21 20:16:19

您创建的窗口与您看到的控制台窗口无关。您调用的东西会创建一个控制台窗口(或者您的程序被标记为控制台应用程序,在这种情况下,控制台是在您的应用程序启动时创建的)。

AllocConsole() 处放置断点以查找谁在创建控制台。

The window you create is not related to the console window you see. Something that you call creates a console window (or you program is marked as a console application in which case the console is created when your application is launched).

Put a breakpoint at AllocConsole() to find who is creating the console.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文