DLL内的CreateWindowEx()创建一个带有奇数标题的窗口

时间:2013-03-19 18:42:12

标签: c# c++ windows string dll

感谢你花了很多时间来回答这个问题。

我正在尝试创建一个DLL,它在DLL中打开一个窗口。我用C#运行创建的DLL。 DLL是在VSC中创建的,而C#代码是用VSC#。

编译的

通过调用C#中的Initalize(const char* title)Initalize(string title)来激活窗口。无论我如何尝试这样做,创建的窗口都是创建的,运行的,但它的标题不是传递的字符串。我尝试使用const wchar_t*LPCSTRLPCWSTRSystem.String[MarshalAs(UnmanagedType.LPStr)][MarshalAs(UnmanagedType.LPWStr)]。我尝试将传递的字符串复制到动态分配的数组中,并使用new / delete和malloc / free进行分配。

我认为这是一个指针错误,但最让我感到高兴的是我的C ++代码中的printf("passed string: %s", title)将正确的标题打印到控制台中,但我的窗口看起来像: Window with non-english text

我的C ++代码是:

// GameInterface.cpp : Defines the exported functions for the DLL application.
//

#include "GameInterface.h"

#include <Windows.h>

      // OpenGL was origionally implimented into here, and removed to be asked on StackOverflow.

LRESULT WINAPI DLLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

HINSTANCE   hInstance = NULL;
ATOM        wclAtom = NULL;
HWND        hWnd = NULL;
HDC         hDC = NULL;
HGLRC       hRC = NULL;
bool        running = false;

#if _DEBUG
    #include <stdio.h>
#endif

BOOL APIENTRY DllMain( HMODULE hModule,
           DWORD  ul_reason_for_call,
           LPVOID lpReserved
                     )
{
    #if _DEBUG
        printf("GameInterface.dll::DllMain()\n");
    #endif

    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
            hInstance = hModule;
            break;
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            Shutdown();
            break;
    }
    return TRUE;
}

GAMEINTERFACE_API int Initalize(const char* title)
{
    if (hWnd != NULL)
        return 0;

    #if _DEBUG
        printf("GameInterface.dll::Initalize(\"%s\")\n", title);
    #endif

    int length = strlen(title);
    char* name = new char[length+1];
    strcpy(name, title);

    WNDCLASSEXA wcl;
    wcl.cbSize        = sizeof(WNDCLASSEXA);
    wcl.style         = CS_OWNDC;
    wcl.lpfnWndProc   = DLLWindowProc;
    wcl.cbClsExtra    = 0;
    wcl.cbWndExtra    = 0;
    wcl.hInstance     = hInstance;
    wcl.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wcl.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wcl.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
    wcl.lpszMenuName  = NULL;
    wcl.lpszClassName = name;
    wcl.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    wclAtom = RegisterClassExA(&wcl);

    #if _DEBUG
        printf("  Registering Class\n");
    #endif

    if (!wclAtom)
    {
        #if _DEBUG
            printf("  Error: Could not Register Class.\nExiting with error: %i\n", GetLastError() );
        #endif

        return 1;
    }

    #if _DEBUG
        printf("  Creating Window\n");
    #endif

    hWnd = CreateWindowExA(0,
                          (LPCSTR)wclAtom,
                          (LPCSTR)name,
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          512, 512,
                          NULL, NULL,
                          hInstance, NULL);

    if (hWnd == NULL)
    {
        #if _DEBUG
            printf("  Error: Window could not be created.\nExiting with error: %i\n", GetLastError() );
        #endif

        return 2;
    }

    #if _DEBUG
        printf("  Displaying Window\n");
    #endif

                // to reduce size removed the code to initalize an OpenGL 3.1 context

    ShowWindow(hWnd, SW_SHOW);
    UpdateWindow(hWnd);

    running = true;

    delete [] name;

    #if _DEBUG
        printf("Returning from GameInterface.dll::Initalize(const char*) with errors: %i\n", GetLastError() );
    #endif

    return 0;
}

GAMEINTERFACE_API void Shutdown()
{
    if (running = false)
        return;

    #if _DEBUG
        printf("GameInterface.dll::Shutdown()\n");
    #endif

    running = false;

    wglMakeCurrent(NULL, NULL);
    if (hRC != NULL) wglDeleteContext(hRC);
    if (hDC != NULL) ReleaseDC(hWnd, hDC);

    hRC = NULL;
    hDC = NULL;

    DestroyWindow(hWnd);
    UnregisterClassA( (LPCSTR)wclAtom, hInstance);
    wclAtom = NULL;

    hWnd = NULL;

    running = false;
}

GAMEINTERFACE_API int Update()
{
    if ( (running == false) && (hWnd == NULL) )
        return 1;

    MSG msg;
    if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    if (running == false)
        return 1;

    return 0;
}

GAMEINTERFACE_API void DrawFrame()
{
    // Contained some OpenGL code that has now been removed.
}

LRESULT WINAPI DLLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            running = false;
            break;

        // handle other messages.

        default: // anything we dont handle.
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }

    return 0; // just in case
}


// GameInterface.h : Outlines the exported functions for the DLL application.
//

#pragma once

#ifdef GAMEINTERFACE_EXPORTS
    #define GAMEINTERFACE_API __declspec(dllexport)
#else
    #define GAMEINTERFACE_API __declspec(dllimport)
#endif

extern "C"
{

GAMEINTERFACE_API int  Initalize(const char* title);
GAMEINTERFACE_API void Shutdown();
GAMEINTERFACE_API int  Update();
GAMEINTERFACE_API void DrawFrame();

};

和C#代码:

// GameInterface.cs
//

using System;
using System.Runtime.InteropServices;

class GameInterface
{
    const string GameInterfaceFile = "GameInterface_d.dll";

    [DllImport(GameInterfaceFile)] public extern static int  Initalize(string title);
    [DllImport(GameInterfaceFile)] public extern static void Shutdown();
    [DllImport(GameInterfaceFile)] public extern static int  Update();
    [DllImport(GameInterfaceFile)] public extern static void DrawFrame();
};


// Program.cs
//

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class Program
{
    public static void Main()
    {
        string title = "OpenGL Window Title";
        if (GameInterface.Initalize(title) != 0)
            return;

        while ( GameInterface.Update() == 0 )
        {
            // game logic.
            GameInterface.DrawFrame();
        }

        GameInterface.Shutdown();
    }
}

我很难过,已经有一段时间了。

2 个答案:

答案 0 :(得分:4)

您是否在C ++版本中定义了UNICODE_UNICODE?你需要做到这一点,让C#像这样说话。

在C ++项目的Visual Studio属性中,在常规下,将字符集设置为使用Unicode字符集。仔细检查 C / C ++ /命令行页面上是否显示/D "UNICODE"/D "_UNICODE"

(相反的方法是将您的导出声明为ANSI,但这是一个较差的解决方案。您应该支持Unicode。)

答案 1 :(得分:1)

这可能是因为代码期望ANSI。

如果您尝试这样做会发生什么:

[DllImport(GameInterfaceFile, CharSet=CharSet.Ansi)] public extern static int  Initalize(string title)