C#从非托管的win32 dll运行对话框

时间:2015-10-22 08:04:29

标签: c# c++ winapi dll

我制作了一个使用对话框录制和播放的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*);

Record.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实际运行对话框资源?

1 个答案:

答案 0 :(得分:0)

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;
}