山东网站建设开发,上海做推广网站,云开发高级布道师,保定移动网站建设在使用cocos2dx c开发项目时#xff0c;通常使用cocos自带的UserDefault来存储一些项目所用到的一些配置信息#xff1a;如游戏的音量#xff0c;游戏的闯关数等...
但是windows平台下#xff0c;测试发现如果用户的帐户名使用是中文#xff0c;在启动程序时会报错#…在使用cocos2dx c开发项目时通常使用cocos自带的UserDefault来存储一些项目所用到的一些配置信息如游戏的音量游戏的闯关数等...
但是windows平台下测试发现如果用户的帐户名使用是中文在启动程序时会报错导致程序无法运行。经过排查把问题定位到CCFileUtils-win32.cpp的FileUtilsWin32::getWritablePath函数中string FileUtilsWin32::getWritablePath() const { // Get full path of executable, e.g. c:\Program Files (x86)\My Game Folder\MyGame.exe char full_path[CC_MAX_PATH 1]; ::GetModuleFileNameA(nullptr, full_path, CC_MAX_PATH 1); // Debug app uses executable directory; Non-debug app uses local app data directory //#ifndef _DEBUG // Get filename of executable only, e.g. MyGame.exe char *base_name strrchr(full_path, \\); if(base_name) { char app_data_path[CC_MAX_PATH 1]; // Get local app data directory, e.g. C:\Documents and Settings\username\Local Settings\Application Data if (SUCCEEDED(SHGetFolderPathA(nullptr, CSIDL_LOCAL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, app_data_path))) { string ret((char*)app_data_path); // Adding executable filename, e.g. C:\Documents and Settings\username\Local Settings\Application Data\MyGame.exe ret base_name; // Remove .exe extension, e.g. C:\Documents and Settings\username\Local Settings\Application Data\MyGame ret ret.substr(0, ret.rfind(.)); ret \\; // Create directory if (SUCCEEDED(SHCreateDirectoryExA(nullptr, ret.c_str(), nullptr))) { return convertPathFormatToUnixStyle(ret); } } } //#endif // not defined _DEBUG // If fetching of local app data directory fails, use the executable one string ret((char*)full_path); // remove xxx.exe ret ret.substr(0, ret.rfind(\\) 1); ret convertPathFormatToUnixStyle(ret); return ret; } 这里可以看到作者在使用 SUCCEEDED(SHGetFolderPathA(nullptr, CSIDL_LOCAL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, app_data_path)) 这个函数时目的是想通过 CSIDL_LOCAL_APPDATA 来把路径定位到帐户下的APPData目录而CSIDL_LOCAL_APPDATA这个宏的解释是
#define CSIDL_LOCAL_APPDATA 0x001c // user name\Local Settings\Applicaiton Data (non roaming)
微软在解释SHGetFolderPath时说明了用法
SHGetFolderPathW (Unicode) and SHGetFolderPathA (ANSI) 由于ANSI的兼容性不好很多情况会导致中文乱码所以这里需要修改SHGetFolderPathW来将字符集转成unicode这样比较好用。
修改过后 string FileUtilsWin32::getWritablePath() const { // Get full path of executable, e.g. c:\Program Files (x86)\My Game Folder\MyGame.exe char full_path[CC_MAX_PATH 1]; ::GetModuleFileNameA(nullptr, full_path, CC_MAX_PATH 1); // Debug app uses executable directory; Non-debug app uses local app data directory //#ifndef _DEBUG // Get filename of executable only, e.g. MyGame.exe char *base_name strrchr(full_path, \\); if(base_name) { // Get local app data directory, e.g. C:\Documents and Settings\username\Local Settings\Application Data WCHAR utf16Path[CC_MAX_PATH 1] { 0 }; if(SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, utf16Path))) { char utf8_path[1024 2] { 0 }; WideCharToMultiByte(CP_UTF8, 0, utf16Path, CC_MAX_PATH 1, utf8_path, 1024 2, NULL, NULL); string ret((char*)utf8_path); // Adding executable filename, e.g. C:\Documents and Settings\username\Local Settings\Application Data\MyGame.exe ret base_name; // Remove .exe extension, e.g. C:\Documents and Settings\username\Local Settings\Application Data\MyGame ret ret.substr(0, ret.rfind(.)); ret \\; // Create directory if (SUCCEEDED(SHCreateDirectoryExA(nullptr, ret.c_str(), nullptr))) { return convertPathFormatToUnixStyle(ret); } } } //#endif // not defined _DEBUG // If fetching of local app data directory fails, use the executable one string ret((char*)full_path); // remove xxx.exe ret ret.substr(0, ret.rfind(\\) 1); ret convertPathFormatToUnixStyle(ret); return ret; }
这样就解决了中文目录下使用userDefault造成的程序崩溃问题。