/** GDevelop - Common Dialogs Extension Copyright (c) 2008-2015 Florian Rival (Florian.Rival@gmail.com) This project is released under the MIT License. */ #include #include #include #include #include #include #include "GDCpp/Object.h" #include "GDCpp/RuntimeScene.h" #include "GDCpp/Variable.h" //Windows build uses native windows-dialogs #if defined(WINDOWS) #include #include #include #endif //Linux build uses dlib for dialogs #if defined(LINUX) || defined(MACOS) #include "nwidgets/MessageBox.h" #include "nwidgets/YesNoMsgBox.h" #include "nwidgets/OpenFile.h" #include "nwidgets/TextInput.h" #endif using namespace std; namespace GDpriv { namespace CommonDialogs { /** * Display a simple message box. */ void GD_EXTENSION_API ShowMessageBox( RuntimeScene & scene, const std::string & message, const std::string & title ) { sf::Clock timeSpent; //Display the box #if defined(WINDOWS) MessageBox(NULL, message.c_str(), title.c_str(), MB_ICONINFORMATION); #endif #if defined(LINUX) || defined(MACOS) nw::MsgBox msgBox(title, message); msgBox.wait_until_closed(); #endif scene.NotifyPauseWasMade(timeSpent.getElapsedTime().asMicroseconds());//Don't take the time spent in this function in account. } /** * Display an "open file" dialog */ void GD_EXTENSION_API ShowOpenFile( RuntimeScene & scene, gd::Variable & variable, const std::string & title, std::string filters ) { sf::Clock timeSpent; string result; //Display the dialog #if defined(WINDOWS) //Process filters to match windows dialogs filters style. filters = filters+'\0'; std::replace(filters.begin(), filters.end(), '|', '\0'); OPENFILENAME toGetFileName; //Struct for the dialog char filePath[MAX_PATH]; getcwd(filePath, MAX_PATH); ZeroMemory(&toGetFileName, sizeof(OPENFILENAME)); toGetFileName.lStructSize = sizeof(OPENFILENAME); toGetFileName.hwndOwner = NULL; toGetFileName.lpstrFile = filePath; toGetFileName.nMaxFile = MAX_PATH; toGetFileName.lpstrFilter = filters == "\0" ? NULL : filters.c_str(); toGetFileName.nFilterIndex = 1; toGetFileName.Flags = OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR;; if(GetOpenFileName(&toGetFileName) == TRUE) result = filePath; #endif #if defined(LINUX) || defined(MACOS) nw::OpenFile * dialog = new nw::OpenFile(title, true, result); dialog->wait_until_closed(); #endif scene.NotifyPauseWasMade(timeSpent.getElapsedTime().asMicroseconds());//Don't take the time spent in this function in account. //Update the variable variable.SetString(result); } /** * Show a message box with Yes/No buttons */ void GD_EXTENSION_API ShowYesNoMsgBox( RuntimeScene & scene, gd::Variable & variable, const std::string & message, const std::string & title ) { sf::Clock timeSpent; string result; //Display the box #if defined(WINDOWS) if( MessageBox(NULL, message.c_str(), title.c_str(), MB_ICONQUESTION | MB_YESNO) == IDYES) result = "yes"; else result = "no"; #endif #if defined(LINUX) || defined(MACOS) nw::YesNoMsgBox dialog(title, message, result); dialog.wait_until_closed(); #endif scene.NotifyPauseWasMade(timeSpent.getElapsedTime().asMicroseconds());//Don't take the time spent in this function in account. //Update the variable variable.SetString(result); } //Declaration and definition of a simple input box for windows #if defined(WINDOWS) #define INPUTBOX_WIDTH 400 #define INPUTBOX_HEIGHT 125 /* Author : mah Date : 13.06.2002 Description : similar to Visual Basic InputBox */ class CInputBox { static HFONT m_hFont; static HWND m_hWndInputBox; static HWND m_hWndParent; static HWND m_hWndEdit; static HWND m_hWndOK; static HWND m_hWndCancel; static HWND m_hWndPrompt; static HINSTANCE m_hInst; static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); public: // text from InputBox LPTSTR Text; BOOL DoModal(LPCTSTR szCaption, LPCTSTR szPrompt); CInputBox(HWND hWndParent); virtual ~CInputBox(); }; HFONT CInputBox::m_hFont = NULL; HWND CInputBox::m_hWndInputBox = NULL; HWND CInputBox::m_hWndParent = NULL; HWND CInputBox::m_hWndEdit = NULL; HWND CInputBox::m_hWndOK = NULL; HWND CInputBox::m_hWndCancel = NULL; HWND CInputBox::m_hWndPrompt = NULL; HINSTANCE CInputBox::m_hInst = NULL; ////////////////////////////////////////////////////////////////////// // CInputBox Class ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// /* Author : mah Date : 13.06.2002 Description : Constructs window class InputBox */ CInputBox::CInputBox(HWND hWndParent) { HINSTANCE hInst = GetModuleHandle(NULL); WNDCLASSEX wcex; if (!GetClassInfoEx(hInst, "InputBox", &wcex)) { wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInst; wcex.hIcon = NULL;//LoadIcon(hInst, (LPCTSTR)IDI_MYINPUTBOX); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW); wcex.lpszMenuName = NULL; wcex.lpszClassName = "InputBox"; wcex.hIconSm = NULL; if (RegisterClassEx(&wcex) == 0) MessageBox(NULL, "Can't create CInputBox!", "Error", MB_OK); } m_hWndParent = hWndParent; Text = NULL; } CInputBox::~CInputBox() { if (Text) delete[] Text; } /* Author : mah Date : 13.06.2002 Description : Window procedure */ LRESULT CALLBACK CInputBox::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { LOGFONT lfont; switch (message) { case WM_CREATE: // font memset(&lfont, 0, sizeof(lfont)); lstrcpy(lfont.lfFaceName, ("Arial")); lfont.lfHeight = 16; lfont.lfWeight = FW_NORMAL;//FW_BOLD; lfont.lfItalic = FALSE; lfont.lfCharSet = DEFAULT_CHARSET; lfont.lfOutPrecision = OUT_DEFAULT_PRECIS; lfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; lfont.lfQuality = DEFAULT_QUALITY; lfont.lfPitchAndFamily = DEFAULT_PITCH; m_hFont = CreateFontIndirect(&lfont); m_hInst = GetModuleHandle(NULL); // creating Edit m_hWndEdit = CreateWindowEx(WS_EX_STATICEDGE, "edit","", WS_VISIBLE | WS_CHILD | WS_TABSTOP | ES_AUTOHSCROLL, 5, INPUTBOX_HEIGHT - 50, INPUTBOX_WIDTH - 16, 20, hWnd, NULL, m_hInst, NULL); // setting font SendMessage(m_hWndEdit, WM_SETFONT, (WPARAM)m_hFont, 0); // button OK m_hWndOK = CreateWindowEx(WS_EX_STATICEDGE, "button","OK", WS_VISIBLE | WS_CHILD | WS_TABSTOP, INPUTBOX_WIDTH - 100, 10, 90, 25, hWnd, NULL, m_hInst, NULL); // setting font SendMessage(m_hWndOK, WM_SETFONT, (WPARAM)m_hFont, 0); // button Cancel m_hWndCancel = CreateWindowEx(WS_EX_STATICEDGE, "button","Cancel", WS_VISIBLE | WS_CHILD | WS_TABSTOP, INPUTBOX_WIDTH - 100, 40, 90, 25, hWnd, NULL, m_hInst, NULL); // setting font SendMessage(m_hWndCancel, WM_SETFONT, (WPARAM)m_hFont, 0); // static Propmpt m_hWndPrompt = CreateWindowEx(WS_EX_STATICEDGE, "static","", WS_VISIBLE | WS_CHILD, 5, 10, INPUTBOX_WIDTH - 110, INPUTBOX_HEIGHT - 70, hWnd, NULL, m_hInst, NULL); // setting font SendMessage(m_hWndPrompt, WM_SETFONT, (WPARAM)m_hFont, 0); SetFocus(m_hWndEdit); break; case WM_DESTROY: DeleteObject(m_hFont); EnableWindow(m_hWndParent, TRUE); SetForegroundWindow(m_hWndParent); DestroyWindow(hWnd); PostQuitMessage(0); break; case WM_COMMAND: switch (HIWORD(wParam)) { case BN_CLICKED: if ((HWND)lParam == m_hWndOK) PostMessage(m_hWndInputBox, WM_KEYDOWN, VK_RETURN, 0); if ((HWND)lParam == m_hWndCancel) PostMessage(m_hWndInputBox, WM_KEYDOWN, VK_ESCAPE, 0); break; } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } /* Author : mah Date : 13.06.2002 Description : Constructs InputBox window */ BOOL CInputBox::DoModal(LPCTSTR szCaption, LPCTSTR szPrompt) { RECT r; GetWindowRect(GetDesktopWindow(), &r); m_hWndInputBox = CreateWindowEx(WS_EX_TOOLWINDOW, "InputBox", szCaption, WS_POPUPWINDOW | WS_CAPTION | WS_TABSTOP, (r.right - INPUTBOX_WIDTH) / 2, (r.bottom - INPUTBOX_HEIGHT) / 2, INPUTBOX_WIDTH, INPUTBOX_HEIGHT, m_hWndParent, NULL, m_hInst, NULL); if(m_hWndInputBox == NULL) return FALSE; SetWindowText(m_hWndPrompt, szPrompt); SetForegroundWindow(m_hWndInputBox); BringWindowToTop(m_hWndInputBox); EnableWindow(m_hWndParent, FALSE); ShowWindow(m_hWndInputBox, SW_SHOW); UpdateWindow(m_hWndInputBox); BOOL ret = 0; MSG msg; HWND hWndFocused; while (GetMessage(&msg, NULL, 0, 0)) { if (msg.message == WM_KEYDOWN) { if (msg.wParam == VK_ESCAPE) { SendMessage(m_hWndInputBox, WM_DESTROY, 0, 0); ret = 0; } if (msg.wParam == VK_RETURN) { int nCount = GetWindowTextLength(m_hWndEdit); nCount++; if (Text) { delete[] Text; Text = NULL; } Text = new TCHAR[nCount]; GetWindowText(m_hWndEdit, Text, nCount); SendMessage(m_hWndInputBox, WM_DESTROY, 0, 0); ret = 1; } if (msg.wParam == VK_TAB) { hWndFocused = GetFocus(); if (hWndFocused == m_hWndEdit) SetFocus(m_hWndOK); if (hWndFocused == m_hWndOK) SetFocus(m_hWndCancel); if (hWndFocused == m_hWndCancel) SetFocus(m_hWndEdit); } } TranslateMessage(&msg); DispatchMessage(&msg); } return ret; } #undef INPUTBOX_WIDTH #undef INPUTBOX_HEIGHT #endif /** * Show a dialog so as to get a text from user */ bool GD_EXTENSION_API ShowTextInput( RuntimeScene & scene, gd::Variable & variable, const std::string & message, const std::string & title ) { sf::Clock timeSpent; string result; //Display the box #if defined(WINDOWS) CInputBox ibox(NULL); if (ibox.DoModal(title.c_str(), message.c_str())) result = ibox.Text; #endif #if defined(LINUX) || defined(MACOS) nw::TextInput dialog(title, message, result); dialog.wait_until_closed(); #endif scene.NotifyPauseWasMade(timeSpent.getElapsedTime().asMicroseconds());//Don't take the time spent in this function in account. //Update the variable variable.SetString(result); return true; } } } //namespace GDpriv