【问题标题】:C# run dialog from unmanaged win32 dllC# 从非托管 win32 dll 运行对话框
【发布时间】:2015-10-22 08:04:28
【问题描述】:

我制作了一个使用对话框进行录制和播放的 win32 DLL。我试图在我的 C# 代码中通过一个函数传递一个指针来使用它,这样我就可以保留数据并实际上让对话框打开另一个函数调用 CreateDialog 并将其提供给我的 DLGPROC。我想让 dll 尽可能独立运行,只保留对数据的引用并告诉它何时打开和关闭。

Header.h:

#pragma once
#pragma comment(lib, "winmm.lib")

#include <Windows.h>

#ifdef __cplusplus
#define EXPORT extern "C" __declspec (dllexport)
#else
#define EXPORT __declspec (dllexport)
#endif

EXPORT BOOLEAN StartDiag();
EXPORT BOOLEAN SetData(DOUBLE*);

记录.c:

#include <windows.h>
#include "resource.h"
#include "Header.h"

#define INP_BUFFER_SIZE 16384

BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);

TCHAR szAppName[] = TEXT("Record1");
double* pData;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
{
    return 0;
}

BOOLEAN StartDiag()
{
    if (CreateDialog(NULL, MAKEINTRESOURCE(DLG_RECORD), NULL, DlgProc) == 
        NULL)
    {
        return FALSE;
    }
    return TRUE;
}

BOOLEAN SetData(double* p)
{
    p = pData;
    return TRUE;
}

BOOL CALLBACK DlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   ...
}

C#:

    [DllImport("RecordLib.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
    public static extern Boolean SetData(ref double[] d);
    [DllImport("RecordLib.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
    public static extern Boolean StartDiag();

我非常有信心 StartDiag 被正确调用,因为它总是返回 false,这意味着输入了函数的主体并且正确地评估了 if 语句。明显的问题是这意味着 DLL 没有像我想要的那样创建对话框。 Dialog 显然在一个 rc 文件中,应该包含在 dll 中,那么它是如何工作的呢?如何让我的 DLL 真正运行对话框资源?

【问题讨论】:

    标签: c# c++ winapi dll


    【解决方案1】:
    if (CreateDialog(NULL, ...)
    

    你不能在这里传递 NULL 并希望成功。这仅适用于简单的单模块程序,这种程序只有一个包含所有内容的 EXE 文件。在您的方案中,Windows 将在托管程序集中搜索资源。那是一条失败的鲸鱼。它必须是包含对话框资源的模块的句柄。肯定是 DLL。

    您需要 DllMain() 而不是 WinMain()。存放您获得的手柄,以便以后使用。样板:

    HMODULE ThisDllHandle;
    
    BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID)
    {
        if (reason == DLL_PROCESS_ATTACH) {
            ThisDllHandle = hModule;
            DisableThreadLibraryCalls(hModule);
        }
        return TRUE;
    }
    

    【讨论】:

    • 注意DisableThreadLibraryCalls: "不要从链接到静态 C 运行时库 (CRT) 的 DLL 调用此函数。静态 CRT 需要 DLL_THREAD_ATTACH 和 DLL_THREAD_DETATCH 通知才能功能正常。”
    猜你喜欢
    • 1970-01-01
    • 2015-05-28
    • 1970-01-01
    • 2013-01-07
    • 1970-01-01
    • 2018-03-25
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    相关资源
    最近更新 更多