制作网站首先要知道什么wordpress 主题更新
在使用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造成的程序崩溃问题。
  
