diff --git a/internal/c/common.h b/internal/c/common.h index a485c4a74..88aac9f46 100644 --- a/internal/c/common.h +++ b/internal/c/common.h @@ -59,6 +59,7 @@ //#include //<-causes overloading abs conflicts in Windows # include # endif +# include # include # include # include @@ -82,7 +83,6 @@ # else # include -# include # include # include # include diff --git a/internal/c/os.h b/internal/c/os.h index 1a58c3f25..d47d78bd7 100644 --- a/internal/c/os.h +++ b/internal/c/os.h @@ -7,25 +7,14 @@ * Should this be adapted to check for each type before defining? */ #ifndef QB64_OS_H_NO_TYPES -# ifdef QB64_WINDOWS -# define uint64 unsigned __int64 -# define uint32 unsigned __int32 -# define uint16 unsigned __int16 -# define uint8 unsigned __int8 -# define int64 __int64 -# define int32 __int32 -# define int16 __int16 -# define int8 __int8 -# else -# define int64 int64_t -# define int32 int32_t -# define int16 int16_t -# define int8 int8_t -# define uint64 uint64_t -# define uint32 uint32_t -# define uint16 uint16_t -# define uint8 uint8_t -# endif +# define int64 int64_t +# define int32 int32_t +# define int16 int16_t +# define int8 int8_t +# define uint64 uint64_t +# define uint32 uint32_t +# define uint16 uint16_t +# define uint8 uint8_t # define ptrszint intptr_t # define uptrszint uintptr_t diff --git a/internal/c/parts/gui/tinyfiledialogs.c b/internal/c/parts/gui/tinyfiledialogs.c index df5456ea2..3f13f7879 100644 --- a/internal/c/parts/gui/tinyfiledialogs.c +++ b/internal/c/parts/gui/tinyfiledialogs.c @@ -918,6 +918,120 @@ static int fileExists(char const * aFilePathAndName) } } +// Checks that it's the top-level Window for the process +static BOOL isMainWindow(HWND handle) +{ + return GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle); +} + +struct handle_data { + unsigned long process_id; + HWND window_handle; +}; + +static BOOL CALLBACK enumCallback(HWND handle, LPARAM lParam) +{ + struct handle_data *data = (struct handle_data*)lParam; + unsigned long process_id = 0; + + GetWindowThreadProcessId(handle, &process_id); + + if (data->process_id != process_id || !isMainWindow(handle)) + return TRUE; // Keep going to the next window + + data->window_handle = handle; + return FALSE; // End the enumeration +} + +static HWND TryGetMainWindow() +{ + struct handle_data data = { + .process_id = GetCurrentProcessId(), + .window_handle = 0, + }; + + EnumWindows(enumCallback, (LPARAM)&data); + + return data.window_handle; +} + +static LRESULT CALLBACK hiddenWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_CREATE: + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + default: + return DefWindowProc(hwnd, message, wParam, lParam); + } + return 0; +} + +static HWND CreateHiddenWindow() +{ + WNDCLASSEX wndclass = { + sizeof(WNDCLASSEX), + CS_DBLCLKS, + hiddenWindowProc, + 0, + 0, + GetModuleHandle(0), + LoadIcon(0, IDI_APPLICATION), + LoadCursor(0, IDC_ARROW), + (HBRUSH)(COLOR_WINDOW + 1), + 0, + "hiddenWindowClass", + LoadIcon(0, IDI_APPLICATION) + }; + + if (!RegisterClassEx(&wndclass)) + return 0; + + return CreateWindowEx( + 0, + "hiddenWindowClass", + "hiddenWindow", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + 0, + 0, + GetModuleHandle(NULL), + 0 + ); +} + +static HWND windowForDialogs = 0; + +// Returns a window handle sutable for displaying dialogs and notifications +// +// We attempt to find a window associated with the program, if none exists then +// we'll create a hidden one. +static HWND GetDialogWindow() +{ + if (windowForDialogs) + return windowForDialogs; + + // First see if our process has a window already + windowForDialogs = TryGetMainWindow(); + if (windowForDialogs) + return windowForDialogs; + + // Check if we have an associated console + windowForDialogs = GetConsoleWindow(); + if (windowForDialogs) + return windowForDialogs; + + // No sutable window could be found, create a hidden one for us to use + windowForDialogs = CreateHiddenWindow(); + return windowForDialogs; +} + #endif /* _WIN32 */ /* source and destination can be the same or ovelap*/ @@ -1036,7 +1150,7 @@ int tinyfd_messageBoxW( aCode += MB_TOPMOST; - lBoxReturnValue = MessageBoxW(GetForegroundWindow(), aMessage, aTitle, aCode); + lBoxReturnValue = MessageBoxW(GetDialogWindow(), aMessage, aTitle, aCode); if ( (lBoxReturnValue == IDNO) && (aDialogType && !wcscmp(L"yesnocancel", aDialogType)) ) { @@ -1052,64 +1166,12 @@ int tinyfd_messageBoxW( } } -static LRESULT CALLBACK hiddenNotifyWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - case WM_CREATE: - break; - case WM_DESTROY: - PostQuitMessage(0); - break; - default: - return DefWindowProc(hwnd, message, wParam, lParam); - } - return 0; -} - -static HWND hiddenWindow = NULL; static HICON notifyIcon = NULL; // Creates a hidden window to tie the Notifications too -static void setupHiddenWindowHandles() +static void setupNotifyIconHandle() { - if (hiddenWindow || notifyIcon) - return; - - WNDCLASSEX wndclass = { - sizeof(WNDCLASSEX), - CS_DBLCLKS, - hiddenNotifyWindowProc, - 0, - 0, - GetModuleHandle(0), - LoadIcon(0,IDI_APPLICATION), - LoadCursor(0,IDC_ARROW), - (HBRUSH)(COLOR_WINDOW + 1), - 0, - "notifyIconClass", - LoadIcon(0,IDI_APPLICATION) - }; - - if (!RegisterClassEx(&wndclass)) - return; - - hiddenWindow = CreateWindowEx( - 0, - "notifyIconClass", - "title", - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - 0, - 0, - GetModuleHandle(NULL), - 0 - ); - - if (!hiddenWindow) + if (notifyIcon) return; // Attempt to load 32x32 image @@ -1131,7 +1193,7 @@ static void createWinNotificationEntry() memset(¬ificationData, 0, sizeof(notificationData)); notificationData.cbSize = sizeof(notificationData); - notificationData.hWnd = hiddenWindow; + notificationData.hWnd = GetDialogWindow(); notificationData.uID = 0; notificationData.hIcon = notifyIcon; @@ -1146,7 +1208,7 @@ static void sendWinNotification(const wchar_t *title, const wchar_t *message, co NOTIFYICONDATAW notificationData; memset(¬ificationData, 0, sizeof(notificationData)); notificationData.cbSize = sizeof(notificationData); - notificationData.hWnd = hiddenWindow; + notificationData.hWnd = GetDialogWindow(); notificationData.uID = 0; notificationData.hIcon = notifyIcon; @@ -1175,10 +1237,10 @@ int tinyfd_notifyPopupW( { if (aTitle && !wcscmp(aTitle, L"tinyfd_query")) { strcpy(tinyfd_response, "windows_wchar"); return 1; } - setupHiddenWindowHandles(); + setupNotifyIconHandle(); // Can't send notification if the handles aren't setup - if (!hiddenWindow || !notifyIcon) + if (!notifyIcon) return 0; createWinNotificationEntry(); @@ -1228,7 +1290,7 @@ static BOOL CALLBACK dialogBoxCallback(HWND hwndDlg, UINT message, WPARAM wParam return FALSE; } -static LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, const wchar_t *title, const wchar_t *lpszMessage, const wchar_t *defaultText) +static LRESULT displayInputBox(HINSTANCE hinst, HWND hwndOwner, const wchar_t *title, const wchar_t *lpszMessage, const wchar_t *defaultText) { HGLOBAL hgbl; LPDLGTEMPLATE lpdt; @@ -1252,7 +1314,7 @@ static LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, const wchar_t * // Define a dialog box. - lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | DS_SETFONT; + lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | DS_SETFONT | DS_SYSMODAL; lpdt->cdit = 4; // Number of controls lpdt->x = 0; lpdt->y = 0; lpdt->cx = 200; lpdt->cy = 70; @@ -1271,6 +1333,27 @@ static LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, const wchar_t * for (lpwsz = (LPWSTR)lpw; ((*lpwsz++) = *font++);); // Font name lpw = (LPWORD)lpwsz; + //----------------------- + // Define a edit text control. + //----------------------- + lpw = lpwAlignDWORD(lpw); // Align DLGITEMTEMPLATE on DWORD boundary + lpdit = (LPDLGITEMTEMPLATE)lpw; + lpdit->x = 5; lpdit->y = 53; + lpdit->cx = 190; lpdit->cy = 12; + lpdit->id = ID_TEXT; // Text identifier + lpdit->style = WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL | ES_LEFT; + + if (wcslen(defaultText) == 0) + lpdit->style |= ES_PASSWORD; + + lpw = (LPWORD)(lpdit + 1); + *lpw++ = 0xFFFF; + *lpw++ = 0x0081; // Edit class + + for (lpwsz = (LPWSTR)lpw; ((*lpwsz++) = *defaultText++);); + lpw = (LPWORD)lpwsz; + *lpw++ = 0; // No creation data + //----------------------- // Define an OK button. //----------------------- @@ -1279,7 +1362,7 @@ static LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, const wchar_t * lpdit->x = 160; lpdit->y = 6; lpdit->cx = 35; lpdit->cy = 12; lpdit->id = IDOK; // OK button identifier - lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; + lpdit->style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON; lpw = (LPWORD)(lpdit + 1); *lpw++ = 0xFFFF; @@ -1298,7 +1381,7 @@ static LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, const wchar_t * lpdit->x = 160; lpdit->y = 21; lpdit->cx = 35; lpdit->cy = 12; lpdit->id = IDCANCEL; // Cancel button identifier - lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON; + lpdit->style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON; lpw = (LPWORD)(lpdit + 1); *lpw++ = 0xFFFF; @@ -1309,27 +1392,6 @@ static LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, const wchar_t * lpw += nchar; *lpw++ = 0; // No creation data - //----------------------- - // Define a edit text control. - //----------------------- - lpw = lpwAlignDWORD(lpw); // Align DLGITEMTEMPLATE on DWORD boundary - lpdit = (LPDLGITEMTEMPLATE)lpw; - lpdit->x = 5; lpdit->y = 53; - lpdit->cx = 190; lpdit->cy = 12; - lpdit->id = ID_TEXT; // Text identifier - lpdit->style = WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL | ES_LEFT; - - if (wcslen(defaultText) == 0) - lpdit->style |= ES_PASSWORD; - - lpw = (LPWORD)(lpdit + 1); - *lpw++ = 0xFFFF; - *lpw++ = 0x0081; // Edit class - - for (lpwsz = (LPWSTR)lpw; ((*lpwsz++) = *defaultText++);); - lpw = (LPWORD)lpwsz; - *lpw++ = 0; // No creation data - //----------------------- // Define a static text control. //----------------------- @@ -1373,8 +1435,7 @@ wchar_t * tinyfd_inputBoxW( aMessage = aMessage? aMessage: L""; aDefaultInput = aDefaultInput? aDefaultInput: L""; - setupHiddenWindowHandles(); - DisplayMyMessage(GetModuleHandle(NULL), hiddenWindow, aTitle, aMessage, aDefaultInput); + displayInputBox(GetModuleHandle(NULL), GetDialogWindow(), aTitle, aMessage, aDefaultInput); mbstowcs(lBuff, dialogContents, MAX_PATH_OR_CMD); return lBuff; @@ -1436,7 +1497,7 @@ wchar_t * tinyfd_saveFileDialogW( } ofn.lStructSize = sizeof(OPENFILENAMEW); - ofn.hwndOwner = GetForegroundWindow(); + ofn.hwndOwner = GetDialogWindow(); ofn.hInstance = 0; ofn.lpstrFilter = wcslen(lFilterPatterns) ? lFilterPatterns : NULL; ofn.lpstrCustomFilter = NULL; @@ -1552,7 +1613,7 @@ wchar_t * tinyfd_openFileDialogW( } ofn.lStructSize = sizeof(OPENFILENAME); - ofn.hwndOwner = GetForegroundWindow(); + ofn.hwndOwner = GetDialogWindow(); ofn.hInstance = 0; ofn.lpstrFilter = wcslen(lFilterPatterns) ? lFilterPatterns : NULL; ofn.lpstrCustomFilter = NULL; @@ -1672,7 +1733,7 @@ wchar_t * tinyfd_selectFolderDialogW( lHResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - bInfo.hwndOwner = GetForegroundWindow(); + bInfo.hwndOwner = GetDialogWindow(); bInfo.pidlRoot = NULL; bInfo.pszDisplayName = lBuff; bInfo.lpszTitle = aTitle && wcslen(aTitle) ? aTitle : NULL; @@ -1734,7 +1795,7 @@ wchar_t * tinyfd_colorChooserW( /* we can't use aTitle */ cc.lStructSize = sizeof(CHOOSECOLOR); - cc.hwndOwner = GetForegroundWindow(); + cc.hwndOwner = GetDialogWindow(); cc.hInstance = NULL; cc.rgbResult = RGB(lDefaultRGB[0], lDefaultRGB[1], lDefaultRGB[2]); cc.lpCustColors = crCustColors; diff --git a/tests/compile_tests/paint/tile_border_black_bg.bas b/tests/compile_tests/paint/tile_border_black_bg.bas index 83784e305..dbb63108f 100644 --- a/tests/compile_tests/paint/tile_border_black_bg.bas +++ b/tests/compile_tests/paint/tile_border_black_bg.bas @@ -13,7 +13,7 @@ _Dest test1& Circle (64, 25), 25, 7 Paint (64, 25), TILE$, 7 -AssertImage test1&, "tile_border_black_bg.bmp" +AssertImage test1&, "tile_border_black_bg.png" System '$include:'../utilities/imageassert.bm' diff --git a/tests/compile_tests/paint/tile_border_black_bg.bmp b/tests/compile_tests/paint/tile_border_black_bg.bmp deleted file mode 100644 index d5a59bc38..000000000 Binary files a/tests/compile_tests/paint/tile_border_black_bg.bmp and /dev/null differ diff --git a/tests/compile_tests/paint/tile_border_black_bg.png b/tests/compile_tests/paint/tile_border_black_bg.png new file mode 100644 index 000000000..ea1601e65 Binary files /dev/null and b/tests/compile_tests/paint/tile_border_black_bg.png differ diff --git a/tests/compile_tests/paint/tile_border_black_nocolor.bas b/tests/compile_tests/paint/tile_border_black_nocolor.bas index d6bf51b40..8dc41b96d 100644 --- a/tests/compile_tests/paint/tile_border_black_nocolor.bas +++ b/tests/compile_tests/paint/tile_border_black_nocolor.bas @@ -17,7 +17,7 @@ Line (0, 0)-(127, 49), 7, BF Circle (64, 25), 25, 0 Paint (64, 25), TILE$, 7 -AssertImage test1&, "tile_border_black_nocolor.bmp" +AssertImage test1&, "tile_border_black_nocolor.png" System '$include:'../utilities/imageassert.bm' diff --git a/tests/compile_tests/paint/tile_border_black_nocolor.bmp b/tests/compile_tests/paint/tile_border_black_nocolor.bmp deleted file mode 100644 index bdf2e6b60..000000000 Binary files a/tests/compile_tests/paint/tile_border_black_nocolor.bmp and /dev/null differ diff --git a/tests/compile_tests/paint/tile_border_black_nocolor.png b/tests/compile_tests/paint/tile_border_black_nocolor.png new file mode 100644 index 000000000..c46f75b09 Binary files /dev/null and b/tests/compile_tests/paint/tile_border_black_nocolor.png differ diff --git a/tests/compile_tests/paint/tile_border_white_bg.bas b/tests/compile_tests/paint/tile_border_white_bg.bas index d897c89ab..e06d94947 100644 --- a/tests/compile_tests/paint/tile_border_white_bg.bas +++ b/tests/compile_tests/paint/tile_border_white_bg.bas @@ -22,7 +22,7 @@ Pset (64, 25), 15 ' Set the starting location a third color Paint (64, 25), TILE$, 0 -AssertImage test1&, "tile_border_white_bg.bmp" +AssertImage test1&, "tile_border_white_bg.png" System '$include:'../utilities/imageassert.bm' diff --git a/tests/compile_tests/paint/tile_border_white_bg.bmp b/tests/compile_tests/paint/tile_border_white_bg.bmp deleted file mode 100644 index 35a79c041..000000000 Binary files a/tests/compile_tests/paint/tile_border_white_bg.bmp and /dev/null differ diff --git a/tests/compile_tests/paint/tile_border_white_bg.png b/tests/compile_tests/paint/tile_border_white_bg.png new file mode 100644 index 000000000..283532dfd Binary files /dev/null and b/tests/compile_tests/paint/tile_border_white_bg.png differ diff --git a/tests/compile_tests/paint/tile_border_white_nocolor.bas b/tests/compile_tests/paint/tile_border_white_nocolor.bas index ba3f52c57..4048cf4a1 100644 --- a/tests/compile_tests/paint/tile_border_white_nocolor.bas +++ b/tests/compile_tests/paint/tile_border_white_nocolor.bas @@ -17,7 +17,7 @@ Line (0, 0)-(127, 49), 7, BF Circle (64, 25), 25, 0 Paint (64, 25), TILE$, 7 -AssertImage test1&, "tile_border_white_nocolor.bmp" +AssertImage test1&, "tile_border_white_nocolor.png" System '$include:'../utilities/imageassert.bm' diff --git a/tests/compile_tests/paint/tile_border_white_nocolor.bmp b/tests/compile_tests/paint/tile_border_white_nocolor.bmp deleted file mode 100644 index bdf2e6b60..000000000 Binary files a/tests/compile_tests/paint/tile_border_white_nocolor.bmp and /dev/null differ diff --git a/tests/compile_tests/paint/tile_border_white_nocolor.png b/tests/compile_tests/paint/tile_border_white_nocolor.png new file mode 100644 index 000000000..c46f75b09 Binary files /dev/null and b/tests/compile_tests/paint/tile_border_white_nocolor.png differ diff --git a/tests/compile_tests/paint/tile_noborder_black_bg.bas b/tests/compile_tests/paint/tile_noborder_black_bg.bas index f7fb58048..b76d232a5 100644 --- a/tests/compile_tests/paint/tile_noborder_black_bg.bas +++ b/tests/compile_tests/paint/tile_noborder_black_bg.bas @@ -13,7 +13,7 @@ _Dest test1& Circle (64, 25), 25, 7 Paint (64, 25), TILE$ -AssertImage test1&, "tile_noborder_black_bg.bmp" +AssertImage test1&, "tile_noborder_black_bg.png" System '$include:'../utilities/imageassert.bm' diff --git a/tests/compile_tests/paint/tile_noborder_black_bg.bmp b/tests/compile_tests/paint/tile_noborder_black_bg.bmp deleted file mode 100644 index d5a59bc38..000000000 Binary files a/tests/compile_tests/paint/tile_noborder_black_bg.bmp and /dev/null differ diff --git a/tests/compile_tests/paint/tile_noborder_black_bg.png b/tests/compile_tests/paint/tile_noborder_black_bg.png new file mode 100644 index 000000000..ea1601e65 Binary files /dev/null and b/tests/compile_tests/paint/tile_noborder_black_bg.png differ diff --git a/tests/compile_tests/paint/tile_noborder_white_bg.bas b/tests/compile_tests/paint/tile_noborder_white_bg.bas index 9987a4bd4..1f69c15c9 100644 --- a/tests/compile_tests/paint/tile_noborder_white_bg.bas +++ b/tests/compile_tests/paint/tile_noborder_white_bg.bas @@ -16,7 +16,7 @@ Line (0, 0)-(127, 49), 7, BF Circle (64, 25), 25, 0 Paint (64, 25), TILE$ -AssertImage test1&, "tile_noborder_white_bg.bmp" +AssertImage test1&, "tile_noborder_white_bg.png" System '$include:'../utilities/imageassert.bm' diff --git a/tests/compile_tests/paint/tile_noborder_white_bg.bmp b/tests/compile_tests/paint/tile_noborder_white_bg.bmp deleted file mode 100644 index 35a79c041..000000000 Binary files a/tests/compile_tests/paint/tile_noborder_white_bg.bmp and /dev/null differ diff --git a/tests/compile_tests/paint/tile_noborder_white_bg.png b/tests/compile_tests/paint/tile_noborder_white_bg.png new file mode 100644 index 000000000..283532dfd Binary files /dev/null and b/tests/compile_tests/paint/tile_noborder_white_bg.png differ