2013-03-19 62 views
1

感谢您花费任何时间尝试回答此问题。DLL中的CreateWindowEx()创建一个奇数标题的窗口

我正试图创建一个DLL,从DLL中打开一个窗口。我用C#运行创建的DLL。该DLL是在VSC中创建的,而C#代码是使用VSC#编译的。

该窗口在C#中调用Initalize(const char* title)Initalize(string title)进行了安装。无论我如何尝试这样做,创建的窗口都会创建,运行,但它的标题不是传递的字符串。我已经尝试使用const wchar_t*,LPCSTR, LPCWSTR,System.String, [MarshalAs(UnmanagedType.LPStr)], [MarshalAs(UnmanagedType.LPWStr)]。我试着将传递的字符串复制到一个动态分配的数组中,分配给new/delete和malloc/free。

我认为这是一个指针错误,但得到什么是我最深的是,printf("passed string: %s", title)在我的C++代码打印正确的标题到控制台,但我的窗口看起来像: 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(); 
    } 
} 

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

+1

Unicode是我能想到的第一件事。也许标题是LPWSTR/LPCWSTR – 2013-03-19 18:44:25

回答

4

您是在C++构建中定义UNICODE_UNICODE?你需要做的是,让C#像这样谈论它。

在你的C++项目在Visual Studio的属性,下一般,设置字符集使用Unicode字符集。仔细检查/D "UNICODE"/D "_UNICODE"出现在C/C++ /命令行页面上。

(相反的方法是声明你的出口为ANSI,但是这是一个较差的方案。你应该支持Unicode的。)

+0

你靠近了。确定他们在哪里并没有这样做,但确保他们没有定义。谢谢! – 2013-03-19 19:11:39

1

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

,如果你试试这个,会发生什么:

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

我仍然有错误。但是,感谢您的帮助!它使我走上正轨。 – 2013-03-19 19:13:41