我试图通过使用SHGetSpecialFolderPath
在C ++应用程序(通过DLL)中获取用户的Desktop文件夹:
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
TCHAR path[MAX_PATH];
export LPSTR desktop_directory()
{
if (SHGetSpecialFolderPath(HWND_DESKTOP, path, CSIDL_DESKTOP, FALSE)) {
return path;
}
}
首先,我想返回一个其他案例。我返回“错误”,但编译器警告我,我试图将CHAR
转换为LPSTR
。如果有,那么如果由于某种原因它无法获取目录,它看起来可能会崩溃。
同样来自MSDN文档,它说“[SHGetSpecialFolderPath不受支持。而是使用ShGetFolderPath。]”,然后我导航到该页面,它显示“ShGetFolderPath:Deprecated。获取由CSIDL值标识的文件夹的路径。”我应该用什么呢?
所以:
编辑
这是所要求的更新代码,
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
export LPCWSTR desktop_directory()
{
static wchar_t path[MAX_PATH+1];
if (SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, 0, path)) {
MessageBox(NULL, path, L"TEST", MB_OK); //test
return path;
} else {
return L"ERROR";
}
}
使用以下命令编译MinGW:g++ "src\dll\main.cpp" -D UNICODE -D _UNICODE -O3 -DNDEBUG -s -shared -o "output\main.dll"
我需要使用WideCharToMultiByte(CP_UTF8, ...)
将DLL中的字符串作为UTF-8传递,但我不知道该怎么做。
SHGetFolderPath()
返回一个HRESULT
,其中0是S_OK
,但是你的代码期望它返回像BOOL
那样的SHGetSpecialFolderPath()
,其中0是FALSE
。因此,您需要在代码中修复该错误,因为它目前正在将成功视为失败。
话虽如此,你将从你的功能返回一个LPSTR
。这是一个char*
。但是你使用TCHAR
作为你的缓冲区。 TCHAR
根据char
是否定义,映射到wchar_t
或UNICODE
。所以你需要决定是否要无条件地返回char*
,或者你想要返回TCHAR*
,或两者兼而有之。它有很大的不同,例如:
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
export LPSTR desktop_directory()
{
static char path[MAX_PATH+1];
if (SHGetSpecialFolderPathA(HWND_DESKTOP, path, CSIDL_DESKTOP, FALSE))
return path;
else
return "ERROR";
}
与:
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
export LPTSTR desktop_directory()
{
static TCHAR path[MAX_PATH+1];
if (SHGetSpecialFolderPath(HWND_DESKTOP, path, CSIDL_DESKTOP, FALSE))
return path;
else
return TEXT("ERROR");
}
与:
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
export LPSTR desktop_directory_ansi()
{
static char path[MAX_PATH+1];
if (SHGetSpecialFolderPathA(HWND_DESKTOP, path, CSIDL_DESKTOP, FALSE))
return path;
else
return "ERROR";
}
export LPWSTR desktop_directory_unicode()
{
static wchar_t path[MAX_PATH+1];
if (SHGetSpecialFolderPathW(HWND_DESKTOP, path, CSIDL_DESKTOP, FALSE))
return path;
else
return L"ERROR";
}
更新:大多数Win32 API函数不支持UTF-8,因此如果您希望函数返回UTF-8字符串,则必须调用函数的Unicode风格,然后使用WideCharToMultiByte()
将输出转换为UTF- 8。但是你有一个问题 - 谁分配并释放UTF-8缓冲区?有几种不同的方法来处理:
__declspec(thread)
说明符:
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
__declspec(thread) char desktop_dir_buffer[((MAX_PATH*4)+1];
export LPCSTR desktop_directory()
{
wchar_t path[MAX_PATH+1] = {0};
if (SHGetFolderPathW(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, path) != S_OK)
{
MessageBoxW(NULL, L"ERROR in SHGetFolderPathW", L"TEST", MB_OK);
return NULL;
}
MessageBoxW(NULL, path, L"TEST", MB_OK);
int buflen = WideCharToMultiByte(CP_UTF8, 0, path, lstrlenW(path), desktop_dir_buffer, MAX_PATH*4, NULL, NULL);
if (buflen <= 0)
{
MessageBoxW(NULL, L"ERROR in WideCharToMultiByte", L"TEST", MB_OK);
return NULL;
}
desktop_dir_buffer[buflen] = 0;
return desktop_dir_buffer;
}
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
export LPCSTR desktop_directory()
{
wchar_t path[MAX_PATH+1] = {0};
if (SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, path) != S_OK)
{
MessageBoxW(NULL, L"ERROR in SHGetFolderPathW", L"TEST", MB_OK);
return NULL;
}
MessageBoxW(NULL, path, L"TEST", MB_OK);
int pathlen = lstrlenW(path);
int buflen = WideCharToMultiByte(CP_UTF8, 0, path, pathlen, NULL, 0, NULL, NULL);
if (buflen <= 0)
{
MessageBoxW(NULL, L"ERROR in WideCharToMultiByte", L"TEST", MB_OK);
return NULL;
}
char *buffer = new char[buflen+1];
buflen = WideCharToMultiByte(CP_UTF8, 0, path, pathlen, buffer, buflen, NULL, NULL);
if (buflen <= 0)
{
delete[] buffer;
MessageBoxW(NULL, L"ERROR in WideCharToMultiByte", L"TEST", MB_OK);
return NULL;
}
buffer[buflen] = 0;
return buffer;
}
export void free_buffer(LPVOID buffer)
{
delete[] (char*) buffer;
}
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
export LPCSTR desktop_directory()
{
wchar_t path[MAX_PATH+1] = {0};
if (SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, path) != S_OK)
{
MessageBoxW(NULL, L"ERROR in SHGetFolderPathW", L"TEST", MB_OK);
return NULL;
}
MessageBoxW(NULL, path, L"TEST", MB_OK);
int pathlen = lstrlenW(path);
int buflen = WideCharToMultiByte(CP_UTF8, 0, path, pathlen, NULL, 0, NULL, NULL);
if (buflen <= 0)
{
MessageBoxW(NULL, L"ERROR in WideCharToMultiByte", L"TEST", MB_OK);
return NULL;
}
char *buffer = (char*) LocalAlloc(LMEM_FIXED, buflen+1);
if (!buffer)
{
MessageBoxW(NULL, L"ERROR in LocalAlloc", L"TEST", MB_OK);
return NULL;
}
buflen = WideCharToMultiByte(CP_UTF8, 0, path, pathlen, buffer, buflen, NULL, NULL);
if (buflen <= 0)
{
LocalFree(buffer);
MessageBoxW(NULL, L"ERROR in WideCharToMultiByte", L"TEST", MB_OK);
return NULL;
}
buffer[buflen] = 0;
return buffer; // caller can use LocalFree() to free it
}
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
// the caller can set buffer=NULL and buflen=0 to calculate the needed buffer size
export int desktop_directory(LPSTR buffer, int buflen)
{
wchar_t path[MAX_PATH+1] = {0};
if (SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, path) != S_OK)
{
MessageBoxW(NULL, L"ERROR in SHGetFolderPathW", L"TEST", MB_OK);
return -1;
}
MessageBoxW(NULL, path, L"TEST", MB_OK);
int pathlen = lstrlenW(path);
int len = WideCharToMultiByte(CP_UTF8, 0, path, pathlen, buffer, buflen, NULL, NULL);
if (len <= 0)
{
MessageBoxW(NULL, L"ERROR in WideCharToMultiByte", L"TEST", MB_OK);
return -1;
}
if (!buffer)
++len;
else if (len < buflen)
buffer[len] = 0;
return len;
}
有一个比WidecharToMultibyte
更好的方法
wstring wcharthingy = wstring(widechar);
string convertedthingy = string(wcharthingy.Begin(),wcharthingy.end())
这是更多的伪代码,因为我不记得确切,但Visual Studio或XCode可能会纠正你的任何问题。