【问题标题】:Using Win32 libraries through Windows Form elements通过 Windows 窗体元素使用 Win32 库
【发布时间】:2010-09-09 16:16:45
【问题描述】:

我在 Visual C++ 2008 中使用 Windows 窗体创建了一个简单的 GUI。GUI 中有一个按钮。按下按钮时,我希望鼠标光标指向坐标(0,900)。我创建了单独的头文件和 c++ 源文件,将光标位置设置为指定位置 (x,y)。为此,我使用了 Win32 的 SetCursorPos() 函数。我在单独的文件中编写了用于设置光标位置的代码,因为我只希望使用 .NET 构建 GUI。对于其他功能,我想使用本机 C++ 和 Win32 库。

在构建代码时,我在链接时收到以下错误消息:

1>SimpleForms.obj : error LNK2028: unresolved token (0A00000F) "extern "C" int __stdcall SetCursorPos(int,int)" (?SetCursorPos@@$$J18YGHHH@Z) referenced in function "private: void __clrcall SimpleForms::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@Form1@SimpleForms@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)

1>SimpleForms.obj : error LNK2019: unresolved external symbol "extern "C" int __stdcall SetCursorPos(int,int)" (?SetCursorPos@@$$J18YGHHH@Z) referenced in function "private: void __clrcall SimpleForms::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@Form1@SimpleForms@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)

【问题讨论】:

    标签: .net visual-c++ visual-studio-2008 c++-cli name-decoration


    【解决方案1】:

    (?SetCursorPos@@$$J18YGHHH@Z)

    请注意函数名称是如何获得 C++ 名称修饰的。您对函数的声明是错误的,需要使用 extern "C"。只需包含 <windows.h> 即可避免此类错误。

    但是,不要这样做。 Windows 窗体也允许您移动光标:

        System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
            System::Windows::Forms::Cursor::Position = Point(0, 900);
        }
    

    我被名称装饰严重误导了,这是一个令人不快的链接器错误消息。真正的问题是您的项目没有链接所需的 Windows 导入库。右键单击项目、属性、链接器、输入。从 Additional Dependencies 设置中删除 $(NoInherit)。如果您使用 VS2010,则将“user32.lib”放入该设置中。

    在这种特定情况下,您仍应使用 .NET Cursor 类。

    【讨论】:

    • @Hans 这就是我所做的。我已经包含了 并且我正在使用它的 SetCursorPos() 函数。我还没有自己编写 SetCursorPos()。
    • 我不知道,您必须发布复制代码才能让我们诊断。这当然不正常。
    • 之前我在一个单独的文件中编写了用于设置鼠标位置的代码,正如我在主要问题中所描述的那样。但现在我已经将它集成到 Form1.h 文件本身中。我在 Form1.h 的开头包含了 windows.h。然后在按钮的单击事件中,我调用了 SetCursorPos() 函数。
    • @nish - 你确定你选择了正确的答案吗?还有一个有 2 个有用的投票,这个没有。请去掉复选标记,以便我删除它。
    • @Hans:这绝对是正确的答案,需要在链接器输入配置中列出 user32.lib 才能解析调用。
    【解决方案2】:

    你不能这样做。

    如果您想从 .NET 使用 C++,则必须向 .NET 公开一个可以 P/Invoke 的 C 接口,或者您需要改用 C++/CLI,这将产生托管代码。 (好吧,我想你也可以公开一个 COM 元素,但那是完全不同的蠕虫)

    这听起来你只是在自找麻烦——你有什么理由不想使用完全托管的代码或完全的本机代码?让他们混合是皇家 PITA。

    【讨论】:

    • 其实我需要开发的主程序是面向性能的。所以我想使用原生 C++ 和 win32 库来编写复杂的算法。对于构建 GUI .NET 是一个简单的选择。所以我想到了合并这两个选项。看来我将不得不寻找其他可行的替代方案。
    • @nishant:也就是说,跨原生/托管屏障执行 P/Invokes 的工作量可能比用原生代码编写程序的主要部分所节省的开销要多得多。如果您需要本机速度,只需 ngen 目标机器上的库,然后再运行它们。
    • 谢谢你的建议,我的朋友!我一定会试试这个。
    • C++ 互操作甚至比 p/invoke 还要快,而且 BCL 中充满了 p/invoke 调用。例如,Hans 建议的 Cursor::Position 属性是通过安全检查实现的,然后调用 user32.dll 中的 SetCursorPos
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-09
    • 2019-10-27
    • 1970-01-01
    • 2019-05-25
    相关资源
    最近更新 更多