Difference between revisions of "CPlusPlus for Gideros Studio Help"

From GiderosMobile
Line 2: Line 2:
 
Here you will find various resources to help learn C++ for people who wish to help with Gideros Studio development.
 
Here you will find various resources to help learn C++ for people who wish to help with Gideros Studio development.
  
=== Description ===
 
Trying to add missing functions to win32 build.
 
  
C:\dev\gideros_hgy29\libgid\src\win32\platform-win32.cpp
+
=== KNOWNFOLDERID ===
<source lang="c++">
+
Refs:
#include <stdio.h>
+
* KNOWNFOLDERID: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid
#include <windows.h>
+
* shlobj_core.h header: https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/
#include <vector>
+
* SHGetKnownFolderPath function (shlobj_core.h): https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath
#include <string>
 
#include <stdlib.h>
 
 
 
#include "luaapplication.h"
 
#include <application.h>
 
#include <gapplication-win32.h>
 
//#include "platform.h" // new 20221011 XXX
 
//#include <gfile_p.h> // new 20221011 XXX
 
 
 
extern HWND hwndcopy;
 
extern char commandLine[];
 
//extern std::string commandLine; // new 20221011 XXX
 
// extern int dxChrome,dyChrome;
 
extern LuaApplication *application_;
 
 
 
static std::wstring ws(const char *str) // new 20221011 XXX
 
{
 
    if (!str) return std::wstring();
 
    int sl=strlen(str);
 
    int sz = MultiByteToWideChar(CP_UTF8, 0, str, sl, 0, 0);
 
    std::wstring res(sz, 0);
 
    MultiByteToWideChar(CP_UTF8, 0, str, sl, &res[0], sz);
 
    return res;
 
}
 
 
 
static std::string us(const wchar_t *str) // new 20221011 XXX
 
{
 
    if (!str) return std::string();
 
    int sl=wcslen(str);
 
    int sz = WideCharToMultiByte(CP_UTF8, 0, str, sl, 0, 0,NULL,NULL);
 
    std::string res(sz, 0);
 
    WideCharToMultiByte(CP_UTF8, 0, str, sl, &res[0], sz,NULL,NULL);
 
    return res;
 
}
 
 
 
void GetDesktopResolution(int& horizontal, int& vertical)
 
{
 
  RECT desktop;
 
  // Get a handle to the desktop window
 
  const HWND hDesktop = GetDesktopWindow();
 
  // Get the size of screen to the variable desktop
 
  GetClientRect(hDesktop, &desktop);
 
  // The top left corner will have coordinates (0,0)
 
  // and the bottom right corner will have coordinates
 
  // (horizontal, vertical)
 
  horizontal = desktop.right;
 
  vertical = desktop.bottom;
 
}
 
 
 
std::vector<std::string> getDeviceInfo()
 
{
 
  std::vector<std::string> result;
 
  result.push_back("Win33"); // ;-)
 
  return result;
 
}
 
 
 
void openUrl(const char* url)
 
{
 
  ShellExecute(hwndcopy,NULL,url,NULL,NULL,SW_SHOWNORMAL);
 
//  std::wstring w=ws(url); // new 20221011 XXX
 
//  ShellExecute(hwndcopy,NULL,w.c_str(),NULL,NULL,SW_SHOWNORMAL); // new 20221011 XXX
 
}
 
 
 
bool canOpenUrl(const char *url)
 
{
 
  return true;
 
}
 
 
 
std::string getLocale()
 
{
 
  TCHAR szBuff1[10], szBuff2[10];
 
 
 
  LCID lcid = GetUserDefaultLCID();
 
 
 
  GetLocaleInfo(lcid, LOCALE_SISO639LANGNAME, szBuff1, 10);
 
  GetLocaleInfo(lcid, LOCALE_SISO3166CTRYNAME, szBuff2, 10);
 
  strcat(szBuff1,"_");
 
  strcat(szBuff1,szBuff2);
 
//  std::string s=us(szBuff1)+"_"+us(szBuff2); // new 20221011 XXX
 
 
 
  return szBuff1;
 
//  return s; // new 20221011 XXX
 
}
 
 
 
std::string getLanguage()
 
{
 
  TCHAR szBuff[10];
 
  LCID lcid = GetUserDefaultLCID();
 
  GetLocaleInfo(lcid, LOCALE_SISO639LANGNAME, szBuff, 10);
 
  return szBuff;
 
//  return us(szBuff); // new 20221011 XXX
 
}
 
 
 
std::string getAppId(){
 
return "";
 
}
 
 
 
void getSafeDisplayArea(int &x,int &y,int &w,int &h)
 
{
 
}
 
 
 
void setWindowSize(int width, int height)
 
{
 
  printf("setWindowSize: %d x %d. hwndcopy=%p\n",width,height,hwndcopy);
 
 
 
  Orientation app_orient=application_->orientation();
 
 
 
  if (app_orient==ePortrait || app_orient==ePortraitUpsideDown){
 
    RECT rect;
 
    rect.left=0;
 
    rect.top=0;
 
    rect.right=width;
 
    rect.bottom=height;
 
 
 
    AdjustWindowRect(&rect,WS_OVERLAPPEDWINDOW,FALSE);
 
 
 
    SetWindowPos(hwndcopy,HWND_TOP,0,0,rect.right-rect.left, rect.bottom-rect.top, SWP_NOMOVE);
 
    printf("SetWindowPos: %d %d\n",rect.right-rect.left, rect.bottom-rect.top);
 
  }
 
  else {
 
    RECT rect;
 
    rect.left=0;
 
    rect.top=0;
 
    rect.right=height;
 
    rect.bottom=width;
 
 
 
    AdjustWindowRect(&rect,WS_OVERLAPPEDWINDOW,FALSE);
 
 
 
    SetWindowPos(hwndcopy,HWND_TOP,0,0,rect.right-rect.left, rect.bottom-rect.top, SWP_NOMOVE);
 
    printf("SetWindowPos: %d %d\n",rect.right-rect.left, rect.bottom-rect.top);
 
  }
 
 
 
  //application_->setHardwareOrientation(app_orient);  // previously eFixed
 
  //application_->getApplication()->setDeviceOrientation(app_orient);
 
}
 
 
 
void W32SetFullScreen(bool fullScreen,HWND wnd,W32FullScreen *save)
 
{
 
  bool for_metro=false;
 
  if (fullScreen==save->isFullScreen) return;
 
 
 
  // Save current window state if not already fullscreen.
 
  if (!save->isFullScreen) {
 
      // Save current window information.  We force the window into restored mode
 
      // before going fullscreen because Windows doesn't seem to hide the
 
      // taskbar if the window is in the maximized state.
 
  save->maximized = !!::IsZoomed(wnd);
 
      if (save->maximized)
 
        ::SendMessage(wnd, WM_SYSCOMMAND, SC_RESTORE, 0);
 
      save->style = GetWindowLong(wnd, GWL_STYLE);
 
      save->ex_style = GetWindowLong(wnd, GWL_EXSTYLE);
 
      GetWindowRect(wnd, &save->window_rect);
 
    }
 
 
 
    if (fullScreen) {
 
      // Set new window style and size.
 
      SetWindowLong(wnd, GWL_STYLE,
 
      save->style & ~(WS_CAPTION | WS_THICKFRAME));
 
      SetWindowLong(wnd, GWL_EXSTYLE,
 
      save->ex_style & ~(WS_EX_DLGMODALFRAME |
 
                    WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
 
 
 
      // On expand, if we're given a window_rect, grow to it, otherwise do
 
      // not resize.
 
      if (!for_metro) {
 
        MONITORINFO monitor_info;
 
        monitor_info.cbSize = sizeof(monitor_info);
 
        GetMonitorInfo(MonitorFromWindow(wnd, MONITOR_DEFAULTTONEAREST),
 
                      &monitor_info);
 
        SetWindowPos(wnd, NULL, monitor_info.rcMonitor.left, monitor_info.rcMonitor.top,
 
        monitor_info.rcMonitor.right-monitor_info.rcMonitor.left,
 
monitor_info.rcMonitor.bottom-monitor_info.rcMonitor.top,
 
                    SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
 
      }
 
    } else {
 
      // Reset original window style and size.  The multiple window size/moves
 
      // here are ugly, but if SetWindowPos() doesn't redraw, the taskbar won't be
 
      // repainted.  Better-looking methods welcome.
 
      SetWindowLong(wnd, GWL_STYLE, save->style);
 
      SetWindowLong(wnd, GWL_EXSTYLE, save->ex_style);
 
 
 
      if (!for_metro) {
 
        // On restore, resize to the previous saved rect size.
 
        SetWindowPos(wnd, NULL, save->window_rect.left,save->window_rect.top,
 
        save->window_rect.right-save->window_rect.left,
 
save->window_rect.bottom-save->window_rect.top,
 
                    SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
 
      }
 
      if (save->maximized)
 
        SendMessage(wnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
 
    }
 
 
 
  save->isFullScreen=fullScreen;
 
}
 
 
 
static W32FullScreen saved_window_info_;
 
 
 
void setFullScreen(bool fullScreen)
 
{
 
W32SetFullScreen(fullScreen,hwndcopy,&saved_window_info_);
 
}
 
 
 
void vibrate(int ms)
 
{
 
}
 
 
 
void setKeepAwake(bool awake)
 
{
 
}
 
 
 
bool setKeyboardVisibility(bool visible){
 
return false;
 
}
 
 
 
bool setTextInput(int type,const char *buffer,int selstart,int selend,const char *label,const char *actionLabel, const char *hintText)
 
{
 
return false;
 
}
 
 
 
int setClipboard(std::string data,std::string mimeType, int luaFunc) {
 
return -1;
 
}
 
 
 
int getClipboard(std::string &data,std::string &mimeType, int luaFunc) {
 
return -1;
 
}
 
 
 
int getKeyboardModifiers() {
 
int m=0; // new 20221011 XXX
 
if (GetKeyState(VK_CONTROL)) m|=GINPUT_CTRL_MODIFIER; // new 20221011 XXX
 
if (GetKeyState(VK_SHIFT)) m|=GINPUT_SHIFT_MODIFIER; // new 20221011 XXX
 
if (GetKeyState(VK_MENU)) m|=GINPUT_ALT_MODIFIER; // new 20221011 XXX
 
// return 0;
 
return m; // new 20221011 XXX
 
}
 
 
 
static int s_fps = 60;
 
 
 
extern "C" {
 
  int g_getFps()
 
  {
 
    return s_fps;
 
  }
 
  void g_setFps(int fps)
 
  {
 
    s_fps = fps;
 
  }
 
}
 
 
 
void g_exit()
 
{
 
  exit(0);
 
}
 
 
 
bool g_checkStringProperty(bool isSet, const char* what){
 
    if (isSet){
 
        if ( (strcmp(what, "cursor") == 0)
 
            || (strcmp(what, "windowTitle") == 0)
 
            || (strcmp(what, "windowModel") == 0)
 
            || (strcmp(what, "clipboard") == 0)
 
            || (strcmp(what, "mkDir") == 0)
 
            || (strcmp(what, "documentDirectory") == 0)
 
            || (strcmp(what, "temporaryDirectory") == 0)
 
          )
 
        {
 
            return true;
 
        }else{
 
            return false;
 
        }
 
    }else{
 
        if ( (strcmp(what, "openFileDialog") == 0)
 
            || (strcmp(what, "openDirectoryDialog") == 0)
 
            || (strcmp(what, "saveFileDialog") == 0)
 
            || (strcmp(what, "directory") == 0)
 
          )
 
        {
 
            return true;
 
        }else{
 
            return false;
 
        }
 
    }
 
}
 
 
 
void g_setProperty(const char* what, const char* arg){
 
//    QString argGet = QString::fromUtf8(arg);
 
    std::string argGet = arg;
 
    int arg1 = 0;
 
    int arg2 = 0;
 
    int arg3 = 0;
 
//    QString argString = "";
 
    std::string argString = "";
 
 
 
    if ( g_checkStringProperty(true,what)){
 
        argString = argGet;
 
//        argString.replace("\\","\\\\");
 
//        std::replace(argString.begin(), argString.end(), "\\", "\\\\");
 
//        printf(argString);
 
    }else{
 
//        QStringList arrayArg = argGet.split("|",Qt::KeepEmptyParts);
 
//        std::vector<std::string> split =
 
//        QStringList arrayArg = argGet.split("|",Qt::KeepEmptyParts);
 
//        arg1 = arrayArg.at(0).toInt();
 
//        arg2 = arrayArg.at(1).toInt();
 
//        arg3 = arrayArg.at(2).toInt();
 
    }
 
 
 
  if (strcmp(what, "windowPosition") == 0) // I should move the windows here, like we do in platform-qt.cpp!
 
  {
 
//    if (args.size()>=2) {
 
      printf("*** windowPosition Y *** \n");
 
//    SetWindowPos(wnd,HWND_TOP,rect.left,rect.top, rect.right-rect.left, rect.bottom-rect.top, SWP_NOSIZE);
 
      SetWindowPos(hwndcopy,0,128,128,0,0,SWP_NOSIZE);
 
//      SetWindowPos(hwndcopy,HWND_TOP,128,128,0,0,SWP_NOSIZE);
 
  }else if (strcmp(what, "windowSize") == 0)
 
  {
 
    // XXX
 
  }
 
}
 
 
 
const char* g_getProperty(const char* what, const char* arg)
 
{
 
  if (strcmp(what,"commandLine")==0)
 
    return commandLine;
 
 
 
  return 0; // new 20221011 XXX
 
}
 
</source>
 
 
 
=== Description ===
 
Trying to add missing functions to win32 build. Refs:
 
*KNOWNFOLDERID: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid
 
*shlobj_core.h header: https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/
 
*SHGetKnownFolderPath function (shlobj_core.h): https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath
 
 
* SO (cc-by): https://stackoverflow.com/a/50660989/870125
 
* SO (cc-by): https://stackoverflow.com/a/50660989/870125
  
 
C:\dev\gideros_hgy29\libgid\src\win32\platform-win32.cpp
 
C:\dev\gideros_hgy29\libgid\src\win32\platform-win32.cpp
<source lang="c++">
 
#include <ShlObj.h> // new 20221013 XXX
 
...
 
        }else if (strcmp(what, "directory") == 0)
 
        {
 
/* TODO
 
            QStringList acceptedValue;
 
            acceptedValue << "executable" << "document"  << "desktop" << "temporary" << "data" ;
 
            acceptedValue << "music" << "movies"  << "pictures" << "cache" << "download" ;
 
            acceptedValue << "home";
 
 
            if (args.size()>0)&&(acceptedValue.contains(args[0].s)){
 
                QString argString=args[0].s;
 
                QString pathGet = "";
 
                if (argString == "executable"){
 
                    pathGet = QDir::currentPath();
 
                }else if (argString == "document"){
 
                    pathGet = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
 
                }else if (argString == "desktop"){
 
                    pathGet = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
 
                }else if (argString == "temporary"){
 
                    pathGet = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
 
                }else if (argString == "data"){
 
    #ifdef RASPBERRY_PI
 
                    pathGet = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
 
    #else
 
                    pathGet = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
 
    #endif
 
                }else if (argString == "music"){
 
                    pathGet = QStandardPaths::writableLocation(QStandardPaths::MusicLocation);
 
                }else if (argString == "movies"){
 
                    pathGet = QStandardPaths::writableLocation(QStandardPaths::MoviesLocation);
 
                }else if (argString == "pictures"){
 
                    pathGet = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
 
                }else if (argString == "cache"){
 
                    pathGet = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
 
                }else if (argString == "download"){
 
                    pathGet = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
 
                }else if (argString == "home"){
 
                    pathGet = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
 
 
                }else{
 
 
                }
 
                r.type=gapplication_Variant::STRING;
 
                r.s=pathGet.toStdString();
 
                rets.push_back(r);
 
            }else{
 
                QString info = "Accepted value for ";
 
                info.append(what);
 
                info.append(" :");
 
                MainWindow::getInstance()->printToOutput(info.toStdString().c_str());
 
                for( int i=0; i<acceptedValue.size(); ++i ){
 
                    MainWindow::getInstance()->printToOutput( QString("- ").append(acceptedValue.at(i)).toStdString().c_str() );
 
                }
 
            }
 
*/
 
            printf("*** FOLDERID_Documents ***");
 
//        wchar_t xpath[1024];
 
//        GetWindowText(hwndcopy,xpath,1024);
 
            PWSTR  ppszPath; // variable to receive the path memory block pointer
 
            HRESULT hr = SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &ppszPath);
 
            std::wstring myPath;
 
            if (SUCCEEDED(hr)) {
 
                myPath = ppszPath; // make a local copy of the path
 
            }
 
            CoTaskMemFree(ppszPath); // free up the path memory block
 
  
            r.type=gapplication_Variant::STRING;
 
            r.s=us(myPath);
 
            rets.push_back(r);
 
            /*------------------------------------------------------------------*/
 
        }else if ((strcmp(what, "openDirectoryDialog") == 0)
 
                || (strcmp(what, "openFileDialog") == 0)
 
                || (strcmp(what, "saveFileDialog") == 0))
 
</source>
 
  
 
=== Convert wstring <-> string ===
 
=== Convert wstring <-> string ===
Line 449: Line 39:
 
}
 
}
 
</source>
 
</source>
 +
  
 
=== win32 minimum, maximum screen size ===
 
=== win32 minimum, maximum screen size ===
Line 461: Line 52:
 
<source lang="c++">
 
<source lang="c++">
 
</source>
 
</source>
 +
  
 
=== win32 LFS problem with separator ===
 
=== win32 LFS problem with separator ===

Revision as of 01:40, 26 October 2022

Here you will find various resources to help learn C++ for people who wish to help with Gideros Studio development.


KNOWNFOLDERID

Refs:

C:\dev\gideros_hgy29\libgid\src\win32\platform-win32.cpp


Convert wstring <-> string

C:\dev\gideros_hgy29\libgid\src\win32\platform-win32.cpp

#include <locale> // new 20221014 XXX
#include <codecvt> // new 20221014 XXX

...

std::wstring s2ws(const std::string& str)
{
    using convert_typeX = std::codecvt_utf8<wchar_t>;
    std::wstring_convert<convert_typeX, wchar_t> converterX;

    return converterX.from_bytes(str);
}

std::string ws2s(const std::wstring& wstr)
{
    using convert_typeX = std::codecvt_utf8<wchar_t>;
    std::wstring_convert<convert_typeX, wchar_t> converterX;

    return converterX.to_bytes(wstr);
}


win32 minimum, maximum screen size

https://www.youtube.com/watch?v=-kg4TG7GoYI

C:\dev\gideros_hgy29\libgid\src\win32\platform-win32.cpp


win32 LFS problem with separator

Recent changes to path handling (most likely [0]) caused AssetCatalogTest.create_catalog_after_loading_file to fail on WIN32.

The test relied on the resulting path to be joined with "/" as a path separator. The resulting path used both forward and back-slashes. While these do work for some API's on WIN32, mixing both in a file path isn't expected behavior in most cases, so update the tests to use native slash direction for file-paths.

 * \note If you want a trailing slash, add `SEP_STR` as the last path argument,
 * duplicate slashes will be cleaned up.
 */
size_t BLI_path_join(char *__restrict dst, size_t dst_len, const char *path, ...)
#  define SEP '\\'
#  define ALTSEP '/'
#  define SEP_STR "\\"
#  define ALTSEP_STR "/"
#else
#  define SEP '/'
#define SEP_CHR     '#'
#define SEP_STR     "#"

#define EPS 0.001

#define UN_SC_KM    1000.0f
#define UN_SC_HM    100.0f
      str_tmp, TEMP_STR_SIZE, "*%.9g" SEP_STR, unit->scalar / scale_pref);

  if (len_num > len_max) {
    len_num = len_max;
  }

  if (found_ofs + len_num + len_move > len_max) {


openFileDialog

platform-win32.cpp

refs:

        }else if (strcmp(what, "openDirectoryDialog") == 0)
        {
       	    /* TODO */
            /*------------------------------------------------------------------*/

        }else if (strcmp(what, "openFileDialog") == 0)
        {
            /* TODO */
            if (args.size()>0)
            {
                HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
                if (SUCCEEDED(hr))
                {
                    IFileOpenDialog *pFile;

                    // Create the FileOpenDialog object.
                    hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, 
                            IID_IFileOpenDialog, reinterpret_cast<void**>(&pFile));

                    if (SUCCEEDED(hr))
                    {
                        // Show the Open dialog box.
                        hr = pFile->Show(NULL);

                        // Get the file name from the dialog box.
                        if (SUCCEEDED(hr))
                        {
                            IShellItem *pItem;
                            hr = pFile->GetResult(&pItem);
                            if (SUCCEEDED(hr))
                            {
                                PWSTR pszFilePath;
                                hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);

                                // Display the file name to the user.
                                if (SUCCEEDED(hr))
                                {
//                                  MessageBoxW(NULL, pszFilePath, L"File Path", MB_OK);
                                    r.type=gapplication_Variant::STRING;
                                    r.s=us(pszFilePath);
                                    rets.push_back(r);

                                    CoTaskMemFree(pszFilePath);
                                }
                                pItem->Release();
                            }
                        }
                        pFile->Release();
                    }
                    CoUninitialize();
                }
            }
            /*------------------------------------------------------------------*/

        }else if (strcmp(what, "saveFileDialog") == 0)