隐藏一个通知并将其从DLL中带回

Hiding a winform & bringing it back from a DLL

本文关键字:DLL 通知 一个 隐藏      更新时间:2023-10-16

在我的DDL中,我定义了以下函数:

extern "C" __declspec(dllexport) void hideme(HWND h) {
    //ShowWindow(h, SW_HIDE);
    SendMessage(h, WM_SHOWWINDOW, FALSE, 0);
}

正如你所看到的,我已经尝试了多种方法来让它发挥作用。。。

我在我的winform中声明如下:

typedef void (*HideMe)(HWND); 

在我的System::Windows::Forms::Form Load事件中,我有以下代码:

...
HINSTANCE hinst = LoadLibrary(_T("My.dll"));
if (hinst == NULL)
    System::Diagnostics::Debug::WriteLine("null hinst"); 
else
    hideme = (HideMe) GetProcAddress(hinst, "hideme");
...

在我的System::Windows::Forms::Form Shown事件中,我有以下代码:

...
hideme((HWND)this->Handle.ToPointer());
...

我想问题一定出在我发送HWND的方式上,但我已经搜索了一整天,找不到其他选择。

我也尝试过设置这个->Visible=false;但我不知道如何触发它从DLL中恢复可见(滥用sendmessage?)。

我不是C++程序员,我通常只用托管语言编程,所以任何帮助(和耐心)都很感激。

谢谢,

尼克。

N.B.

我无法解释的一件奇怪的事情是,我无法从WinForm本身调用ShowWindow。它会抛出这个宝石:

Error   2   error LNK2028: unresolved token (0A00001E) "extern "C" int __stdcall ShowWindow(struct HWND__ *,int)" (?ShowWindow@@$$J18YGHPAUHWND__@@H@Z) referenced in function "private: void __clrcall CheckMSNCpp::frmMain::frmMain_Shown(class System::Object ^,class System::EventArgs ^)" (?frmMain_Shown@frmMain@CheckMSNCpp@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)
Error   3   error LNK2019: unresolved external symbol "extern "C" int __stdcall ShowWindow(struct HWND__ *,int)" (?ShowWindow@@$$J18YGHPAUHWND__@@H@Z) referenced in function "private: void __clrcall CheckMSNCpp::frmMain::frmMain_Shown(class System::Object ^,class System::EventArgs ^)" (?frmMain_Shown@frmMain@CheckMSNCpp@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)
Error   4   error LNK1120: 2 unresolved externals

[编辑1]

Hans Passant说:

您收到的链接器错误消息ShowWindow()尝试也是强烈提示您当前代码的原因不起作用。您忘记添加错误检查代码,GetProcAddress()可以失败并将返回一个NULL指针。会的,函数不会导出以"隐藏者"的名字命名。在32位生成,它将导出为"_hidme",注意下划线。哪一个添加以表示函数使用__cdecl调用习俗上的链接器错误ShowWindow演示C++名称装饰,你忘了#includewindows。h并自己制作,ShowWindow的声明不正确。

这不是正确的做法,您应该只设置Visible属性设置为false。就像你试过的那样。为什么?你不能把它还原为真的很难找到。

你说的话对我来说毫无意义,原因有几个。

1)

winform:的导入

#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <stdio.h>

正如你所知,windows.h在里面。

2) ShowWindor错误不在DLL中,我可以称之为fine,它在WinForm代码中。

3) 我从未导出过ShowWindow,只是导出了我自己的函数。

[/EDIT1]

[编辑2]Uwe Keim说:

为什么你需要一个额外的DLL只是另一个DLL的包装器作用

我会像在C#中那样使用PInvoke来自您的托管C++应用的签名SendMessage将是(在C#中):

正如评论者所说,PInvoke的东西毫无意义。

至于DLL,它需要是一个DLL,因为我需要一个全局挂钩来响应我的热键&WH_CBT。在这种情况下,我希望程序启动隐藏&只需在按下组合键时显示设置屏幕。

程序中的一切都如预期的那样工作,热键的工作方式就像一个魅力,唯一我做不到的是显示应用程序,从DLL触发。[/EDIT2]

[编辑3]示例代码位于:http://www.nickkusters.com/CPP_PROBLEM_Demo-NOBIN.zip[/EDIT3]

您在ShowWindow()尝试中收到的链接器错误消息也是当前代码无法工作的有力提示。您忘记添加错误检查代码,GetProcAddress()可能会失败并返回NULL指针。会的,函数不会以"隐藏"名称导出。在32位构建中,它将被导出为"_hidme",请注意下划线。添加它是为了指示该函数使用__cdecl调用约定。ShowWindow上的链接器错误演示了C++名称修饰,您忘记了#includewindows.h,并为ShowWindow编写了自己的错误声明。

这不是正确的方法,您应该将Visible属性设置为false。就像你试过的那样。你为什么不能把它还原成真的,这是完全不可辩驳的。

为什么需要一个额外的DLL,它只是另一个DLL函数的包装?

我想在C#中使用托管C++应用程序中的PInvoke来实现这一点。SendMessage的签名将是(在C#中):

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(
    IntPtr hWnd, 
    UInt32 Msg, 
    IntPtr wParam, 
    IntPtr lParam);