CPlusPlus for Gideros Studio Help
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
#include <stdio.h>
#include <windows.h>
#include <vector>
#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
}
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
C:\dev\gideros_hgy29\libgid\src\win32\platform-win32.cpp
#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))
Convert wstring <-> string
- SO (cc-by): https://stackoverflow.com/a/18374698/870125
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
- https://gamedev.net/forums/topic/569148-c-windows-api-minimum-resize-dimensions/4638297/
- SO (cc-by): https://stackoverflow.com/q/19035481/870125
- SO (cc-by): https://stackoverflow.com/a/22261818/870125
- https://learn.microsoft.com/en-gb/windows/win32/winmsg/wm-getminmaxinfo?redirectedfrom=MSDN
- https://learn.microsoft.com/en-us/windows/win32/api/winuser/nc-winuser-wndproc
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
}else if ((strcmp(what, "openDirectoryDialog") == 0)
|| (strcmp(what, "openFileDialog") == 0)
|| (strcmp(what, "saveFileDialog") == 0))
{
/* TODO
if(args.size() == 1){
MainWindow::getInstance()->printToOutput("[[Usage Example]]");
if (strcmp(what, "openDirectoryDialog") == 0){
MainWindow::getInstance()->printToOutput("application:get(\"openDirectoryDialog\",\"Open Directory|C:/)\")");
}else if (strcmp(what, "openFileDialog") == 0){
MainWindow::getInstance()->printToOutput("application:get(\"openFileDialog\",\"Open File|C:/|Text File (*.txt);;Image File (*.jpg *.png)\")");
}else if (strcmp(what, "saveFileDialog") == 0){
MainWindow::getInstance()->printToOutput("application:get(\"saveFileDialog\",\"Save File|C:/|Text File (*.txt);;Image File (*.jpg *.png)\")");
}
}else{
QString title = QString::fromUtf8(args[0].s.c_str());
QString place = "";
QString extension = "";
if (args.size() >= 2){place = QString::fromUtf8(args[1].s.c_str());}
if (args.size() >= 3){extension = QString::fromUtf8(args[2].s.c_str());}
QString fileName = "";
if (strcmp(what, "openDirectoryDialog") == 0){
fileName = QFileDialog::getExistingDirectory(MainWindow::getInstance(),title ,place, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
}else if (strcmp(what, "openFileDialog") == 0){
fileName = QFileDialog::getOpenFileName(MainWindow::getInstance(), title,place,extension);
}else if (strcmp(what, "saveFileDialog") == 0){
fileName = QFileDialog::getSaveFileName(MainWindow::getInstance(), title,place,extension);
}
r.type=gapplication_Variant::STRING;
r.s=fileName.toStdString();
rets.push_back(r);
}*/
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED |
COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
IFileOpenDialog *pFileOpen;
// Create the FileOpenDialog object.
hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));
if (SUCCEEDED(hr))
{
// Show the Open dialog box.
hr = pFileOpen->Show(NULL);
// Get the file name from the dialog box.
if (SUCCEEDED(hr))
{
IShellItem *pItem;
hr = pFileOpen->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);
CoTaskMemFree(pszFilePath);
}
pItem->Release();
}
}
pFileOpen->Release();
}
CoUninitialize();
}
/*------------------------------------------------------------------*/
}else if (strcmp(what, "temporaryDirectory") == 0)
{