【问题标题】:Hiding a winform & bringing it back from a DLL隐藏 winform 并从 DLL 中恢复
【发布时间】:2011-05-28 14:29:29
【问题描述】:

在我的 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 发送的方式上,但我已经搜索了一整天,找不到替代方法。

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

我不是 C++ 程序员,我通常只使用托管语言进行编程,因此请提供任何帮助(感谢耐心等待。

谢谢,

尼克。

注意

我无法解释的一件奇怪的事情是我不能从 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]

汉斯·帕桑特说:

您收到的链接器错误消息 ShowWindow() 尝试也是一个 强烈提示为什么您当前的代码是 不工作。您忘记添加错误 检查代码,GetProcAddress() 可以 失败并将返回一个 NULL 指针。 会的,函数没有导出 以“隐藏”的名义。在 32 位 构建,它将被导出为 “_hideme”,注意下划线。哪一个 被添加以表明 函数使用 __cdecl 调用 惯例。链接器错误 ShowWindow 演示 C++ 名称 装饰,你忘了#include windows.h 并自己制作, 不正确,ShowWindow 的声明。

这不是正确的做法, 你应该只设置可见 属性为假。就像你试过的那样。为什么 您不能将其设置回 true 是 完全猜不透。

出于几个原因,你所说的对我来说完全没有意义。

1)

winform 的导入:

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

如您所知,windows.h 就在其中。

2) ShowWindor 错误不在 DLL 中,我可以调用它,它在 WinForm 代码中。

3) 我从不导出 ShowWindow,只导出我自己的函数。

[/EDIT1]

[编辑2] Uwe Keim 说:

为什么需要一个额外的 DLL 只是另一个 DLL 的包装器 功能?

我会这样做,例如C# 通过使用 从您的托管 C++ 调用 PInvoke 应用。签名为 SendMessage 将是(在 C# 中):

就像评论者所说的那样,PInvoke 的东西没有任何意义。

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

程序中的一切都按预期工作,热键就像一个魅力,唯一我不能正确的是显示应用程序,从 DLL 触发。 [/EDIT2]

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

【问题讨论】:

  • 这在很多层面上都很奇怪。无需直接win32隐藏表单。在任何情况下都不需要 DLL,可以使用 Pinvoke。无论如何,您都可以从托管 C++ 直接调用 win api。最后,您不发送该消息,而是将其发送给您。再次阅读文档。在 win api 调用 ShowWindow 中隐藏窗口。
  • 我很想这样做,但是用 this->Handle.ToPointer() 调用 ShowWindow 不起作用。
  • 看来我们帮不了你了。祝你好运。

标签: c++ winforms dll name-decoration


【解决方案1】:

您在尝试 ShowWindow() 时收到的链接器错误消息也是您当前代码无法正常工作的强烈提示。您忘记添加错误检查代码,GetProcAddress() 可能会失败并返回 NULL 指针。它将,该功能不会由“hideme”名称导出。在 32 位版本中,它将导出为“_hideme”,请注意下划线。添加它以指示该函数使用 __cdecl 调用约定。 ShowWindow 上的链接器错误演示了 C++ 名称修饰,您忘记了 #include windows.h 并为 ShowWindow 编造了您自己的不正确的声明。

这不是正确的做法,您应该将 Visible 属性设置为 false。就像你试过的那样。为什么你不能将它设置回 true 是非常难以猜测的。

【讨论】:

  • 编辑了我的帖子以添加您的评论和回复以使其清楚。无法在 cmets 中进行格式化。
  • 非凡的主张需要非凡的证据。将源代码发布在文件共享服务或粘贴箱上。不需要DLL来实现热键,可以使用RegisterHotKey。即使是低级键盘挂钩也可以,也不需要 DLL。当您在此页面右上角的搜索框中键入“registerhotkey”时,您会发现很多匹配项。
  • 为什么你觉得你需要改变设计?你根本没有解决问题。请解决所提出的问题。
  • 这当然不是 SO 的义务。因为您不喜欢评论,所以对答案投反对票毫无意义。好吧,祝你好运。再见。
  • 嗯,您的评论包含不正确的信息(正如我在帖子中解释的那样),但感谢您的尝试。
【解决方案2】:

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

我会这样做,例如C# using PInvoke from your managed C++ applicationSendMessage 的签名将是(在 C# 中):

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

【讨论】:

  • 在 C++/CLI 程序中使用 pinvoke 没什么意义。
  • 编辑了我的帖子以添加您的评论和回复以明确表示。无法在 cmets 中进行格式化。
猜你喜欢
  • 2021-01-04
  • 1970-01-01
  • 2013-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多