Author Topic: Opening files  (Read 8317 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Opening files
« Reply #15 on: June 12, 2020, 10:30:35 am »
@bplus
maybe you could write a file requester using GetOpenFileName (Windows)
here are some examples in C(++) https://docs.microsoft.com/en-us/windows/win32/dlgbox/using-common-dialog-boxes
I translated the open file example on that site to FB, don't how to do it in QB64, would interesting to see

@jack

Well so far, I only care about the names of files and directories and if they are hidden with a DIR query that's been OK with me so far. With Steve's icing on the cake tip about establishing a SHARED tempFile by finding the Temp Directory, I have been very satisfied with my own Windows access, mainly for navigation in hard drive.

For someone interested in complete set of details about files and directories, your app worked out in FB might be invaluable source to translate to QB64. Maybe offer it up in Discussion Board or Off-Topic for non QB64 language to QB64 translation challenge. (FB so close to QB64 should be OK in Discussion Board since we are going for QB64 code).

You might not know, I avoid getting help from Windows apps (except SHELL of course), I even avoided Windows Message Box access as shown in QB64 Wiki for my own (and far lesser but simpler to use, IMO anyway) MessageBox.

If you did that translation challenge, I wonder if we would hear from Eric again? ;-))

Offline FilipeEstima

  • Newbie
  • Posts: 63
    • View Profile
Re: Opening files
« Reply #16 on: June 13, 2020, 11:27:04 pm »
You can either call a window from Windows via a library declaration to select a file, or you can write the whole thing and use DIRENTRY.H from Steve to list files and directories.

How do I do that? I don't know how to call the Windows function to let me pick a file with mouse and pass the file path and name to the QB64 program.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Opening files
« Reply #17 on: June 13, 2020, 11:57:29 pm »
How do I do that? I don't know how to call the Windows function to let me pick a file with mouse and pass the file path and name to the QB64 program.

I think Petr is talking about this, see instructions for DirEntry.h at bottom if don't have in folder with QB64.exe:

Code: QB64: [Select]
  1. DECLARE CUSTOMTYPE LIBRARY "IDE Files\direntry"
  2.     FUNCTION FILE_load_dir& ALIAS load_dir (s AS STRING)
  3.     FUNCTION FILE_has_next_entry& ALIAS has_next_entry ()
  4.     SUB FILE_close_dir ALIAS close_dir ()
  5.     SUB FILE_get_next_entry ALIAS get_next_entry (s AS STRING, flags AS LONG, file_size AS LONG)
  6.     SUB FILE_get_current_dir ALIAS get_current_dir (s AS STRING)
  7.     FUNCTION FILE_current_dir_length& ALIAS current_dir_length ()
  8.  
  9. SCREEN _NEWIMAGE(1024, 720, 32)
  10.  
  11. a$ = SelectFile$("*.*", 100, 100)
  12. PRINT "You selected:"; a$
  13.  
  14.  
  15. FUNCTION SelectFile$ (search$, x AS INTEGER, y AS INTEGER)
  16.     'save some old values
  17.     LoadFile_DC = _DEFAULTCOLOR: LoadFile_BG = _BACKGROUNDCOLOR
  18.     LoadFile_s = _SOURCE: LoadFile_d = _DEST
  19.     f = _FONT: _FONT 16
  20.     'some variables
  21.  
  22.     LoadFile_BoxColor = &HFFAAAAFF
  23.     LoadFile_FolderColor = &HFFFFFF00
  24.     LoadFile_FileColor = &HFFFFFFFF
  25.     IF INSTR(_OS$, "[WINDOWS]") THEN LoadFile_Slash$ = "\" ELSE LoadFile_Slash$ = "/"
  26.     LoadFile_Dir$ = SPACE$(FILE_current_dir_length)
  27.     FILE_get_current_dir LoadFile_Dir$
  28.     LoadFile_Dir$ = LoadFile_Dir$ + LoadFile_Slash$
  29.     'LoadFile_Dir$ = "." + LoadFile_Slash$
  30.     LoadFile_w = 639: LoadFile_h = 479
  31.     REDIM LoadFile_Label(0) AS STRING: LoadFile_Label(0) = "DIR"
  32.     REDIM LoadFile_DirList(-1 TO 9, -1 TO 9999) AS STRING
  33.     LoadFile_last = 1
  34.     FolderDeep = 1
  35.  
  36.     'some error checking
  37.     IF search$ = "" THEN EXIT SUB 'We can't search for nothing!
  38.  
  39.     'Copy background
  40.     PCOPY 0, 1
  41.     'set workscreen
  42.     LoadFile_ws = _NEWIMAGE(640, 480, 32)
  43.  
  44.     'Count our filetypes to display
  45.     LoadFile_TypeCount = 0
  46.     DO
  47.         LoadFile_TypeCount = LoadFile_TypeCount + 1
  48.         LoadFile_l = INSTR(LoadFile_l + 1, search$, ";") ' look for ; to denote more files
  49.         REDIM _PRESERVE LoadFile_Label(LoadFile_TypeCount) AS STRING
  50.         IF LoadFile_l > 0 THEN LoadFile_Label(LoadFile_TypeCount) = MID$(search$, LoadFile_last + 1, LoadFile_l - LoadFile_last - 1) ELSE LoadFile_Label(LoadFile_TypeCount) = MID$(search$, LoadFile_last + 1, LEN(search$) - LoadFile_last)
  51.         LoadFile_last = LoadFile_l + 1
  52.     LOOP UNTIL LoadFile_l = 0
  53.     LoadFile_l = 640 / (LoadFile_TypeCount + 1)
  54.     REDIM LoadFile_start(LoadFile_TypeCount), LoadFile_previous(LoadFile_TypeCount), LoadFile_more(LoadFile_TypeCount), LoadFile_Count(LoadFile_TypeCount)
  55.     FOR i = 0 TO LoadFile_TypeCount: LoadFile_start(i) = 1: NEXT
  56.  
  57.     _SOURCE LoadFile_ws: _DEST LoadFile_ws
  58.     DO
  59.         _LIMIT 30
  60.         FOR i = 0 TO LoadFile_TypeCount
  61.             LoadFile_Count(i) = 0
  62.             FOR j = 0 TO 9999
  63.                 LoadFile_DirList(i, j) = ""
  64.             NEXT
  65.         NEXT
  66.         'Generate our updated directory listings.
  67.  
  68.         IF FILE_load_dir&(LoadFile_Dir$ + CHR$(0)) THEN
  69.             DO
  70.                 LoadFile_length = FILE_has_next_entry 'Get length of next entry
  71.                 IF LoadFile_length > -1 THEN 'If we have a next entry
  72.                     LoadFile_nam$ = SPACE$(LoadFile_length) 'Set the size of our string
  73.                     FILE_get_next_entry LoadFile_nam$, LoadFile_flags, LoadFile_file_size 'Get the file's name, size, and 'flags'
  74.                     'Check if it's a file or a directory
  75.  
  76.                     IF _DIREXISTS(LoadFile_Dir$ + LoadFile_nam$) THEN
  77.                         IF LoadFile_nam$ <> "." THEN
  78.                             LoadFile_Count(0) = LoadFile_Count(0) + 1
  79.                             LoadFile_DirList(0, LoadFile_Count(0)) = LoadFile_nam$
  80.                         END IF
  81.                     ELSE 'We have a file
  82.                         FOR i = 1 TO LoadFile_TypeCount
  83.                             LoadFile_ext$ = RIGHT$(LoadFile_nam$, LEN(LoadFile_Label(i)))
  84.                             IF UCASE$(LoadFile_ext$) = UCASE$(LoadFile_Label(i)) THEN
  85.                                 LoadFile_Count(i) = LoadFile_Count(i) + 1
  86.                                 LoadFile_DirList(i, LoadFile_Count(i)) = LEFT$(LoadFile_nam$, LEN(LoadFile_nam$) - LEN(LoadFile_Label(i)))
  87.                                 EXIT FOR
  88.                             ELSEIF LoadFile_Label(i) = ".*" THEN
  89.                                 LoadFile_Count(i) = LoadFile_Count(i) + 1
  90.                                 LoadFile_DirList(i, LoadFile_Count(i)) = LoadFile_nam$
  91.                             END IF
  92.                         NEXT
  93.                     END IF
  94.                 END IF
  95.             LOOP UNTIL LoadFile_length = -1
  96.             FILE_close_dir
  97.         END IF
  98.  
  99.         updatelist:
  100.  
  101.  
  102.         CLS , &HFF005050 'Draw a nice display box
  103.         COLOR , 0
  104.         LINE (0, 0)-(LoadFile_w, LoadFile_h + 5 - 2 * 16), LoadFile_BoxColor, B
  105.         LINE (1, 1)-(LoadFile_w - 1, LoadFile_h + 6 - 2 * 16), LoadFile_BoxColor, B
  106.         LINE (0, 0)-(LoadFile_w, LoadFile_h), LoadFile_BoxColor, B
  107.         LINE (1, 1)-(LoadFile_w - 1, LoadFile_h - 1), LoadFile_BoxColor, B
  108.  
  109.         LINE (0, 16 + 3)-(LoadFile_w, 16 + 3), LoadFile_BoxColor
  110.         LINE (0, 16 + 4)-(LoadFile_w, 16 + 4), LoadFile_BoxColor
  111.         FOR i = 0 TO LoadFile_TypeCount
  112.             _PRINTSTRING (i * LoadFile_l + (LoadFile_l - 8 * LEN(LoadFile_Label(i))) / 2, 2), LoadFile_Label(i)
  113.             LINE (i * LoadFile_l, 0)-(i * LoadFile_l, LoadFile_h + 5 - 2 * 16), LoadFile_BoxColor
  114.         NEXT
  115.  
  116.         LINE (627, 2)-(637, 18), &HFFFF0000, BF
  117.         LINE (626, 2)-(637, 18), &HFF000000, B
  118.  
  119.         _PRINTSTRING (628, 2), "X"
  120.         IF selection > 0 THEN
  121.             IF LoadFile_Label(row) <> ".*" AND LoadFile_Label(row) <> "DIR" THEN temp$ = LoadFile_DirList(row, selection) + LoadFile_Label(row) ELSE temp$ = LoadFile_DirList(row, selection)
  122.             IF LoadFile_DirList(row, selection) = "" THEN temp$ = ""
  123.             selection = 0
  124.         END IF
  125.         _PRINTSTRING (10, 28 * 16 + 7), LoadFile_Dir$
  126.         _PRINTSTRING (630 - LEN(temp$) * 8, 28 * 16 + 7), temp$
  127.         IF temp$ = "" THEN oldselection = 0
  128.         IF oldselection > 0 THEN LINE (row * LoadFile_l, (oldselection + 1) * 16 + 5)-((row + 1) * LoadFile_l, (oldselection + 2) * 16 + 5), &HAAAAA000, BF
  129.  
  130.         FOR i = 0 TO UBOUND(LoadFile_label)
  131.             IF i = 0 THEN COLOR LoadFile_FolderColor ELSE COLOR LoadFile_FileColor
  132.             counter = 0
  133.             FOR j = LoadFile_start(i) TO LoadFile_start(i) + 24
  134.                 counter = counter + 1
  135.                 IF LoadFile_DirList(i, j) = "" THEN EXIT FOR
  136.                 _PRINTSTRING (i * LoadFile_l + 5, (counter + 1) * 16 + 7), LEFT$(LoadFile_DirList(i, j), LoadFile_l / 8 - 2)
  137.             NEXT
  138.             IF j = LoadFile_start(i) + 25 THEN LoadFile_more(i) = -1 ELSE LoadFile_more(i) = 0
  139.             IF LoadFile_start(i) > 1 THEN LoadFile_previous(i) = -1 ELSE LoadFile_previous(i) = 0
  140.             IF LoadFile_more(i) THEN
  141.                 LINE (i * LoadFile_l + 2, 27 * 16 + 5)-((i + 1) * LoadFile_l - 3, 28 * 16 + 3), &HFFFF0000, BF
  142.                 LINE (i * LoadFile_l + 2, 27 * 16 + 5)-((i + 1) * LoadFile_l - 3, 28 * 16 + 3), BoxColor, B
  143.                 COLOR &HFFFFFF00: _PRINTSTRING (i * LoadFile_l + (LoadFile_l - 8 * 11) / 2, 27 * 16 + 5), "SCROLL DOWN"
  144.                 COLOR LoadFile_FileColor
  145.             END IF
  146.             IF LoadFile_previous(i) THEN
  147.                 LINE (i * LoadFile_l + 2, 16 + 5)-((i + 1) * LoadFile_l - 3, 2 * 16 + 3), &HFFFF0000, BF
  148.                 LINE (i * LoadFile_l + 2, 16 + 5)-((i + 1) * LoadFile_l - 3, 2 * 16 + 3), BoxColor, B
  149.                 COLOR &HFFFFFF00: _PRINTSTRING (i * LoadFile_l + (LoadFile_l - 8 * 9) / 2, 16 + 5), "SCROLL UP"
  150.                 COLOR LoadFile_FileColor
  151.             END IF
  152.         NEXT
  153.  
  154.         _PUTIMAGE (0 + x, 0 + y)-(640 + x, 480 + y), LoadFile_ws, 0
  155.         _DISPLAY
  156.  
  157.         change = 0
  158.         DO
  159.             _LIMIT 30
  160.             LoadFile_LMB = 0 'This sets the left mouse button as unacceptable.
  161.             a = _KEYHIT
  162.             SELECT CASE a
  163.                 CASE 8 'backspace
  164.                     temp$ = LEFT$(temp$, LEN(temp$) - 1)
  165.                     change = -1
  166.                 CASE 13 'enter
  167.                     DO: LOOP UNTIL INKEY$ = "" 'Clear the keyboard buffer so it doesn't affect the main program.
  168.                     temp$ = LoadFile_Dir$ + temp$
  169.                     COLOR LoadFile_DC, LoadFile_BG: _SOURCE LoadFile_s: _DEST LoadFile_d: PCOPY 1, 0: _DISPLAY: SelectFile$ = temp$ 'Restore our old settings
  170.                     _FONT f
  171.                     EXIT SUB 'And leave
  172.                 CASE 27 'If ESC is pressed then...
  173.                     DO: LOOP UNTIL INKEY$ = "" 'Clear the keyboard buffer so it doesn't affect the main program.
  174.                     COLOR LoadFile_DC, LoadFile_BG: _SOURCE LoadFile_s: _DEST LoadFile_d: PCOPY 1, 0: _DISPLAY: SelectFile$ = "" 'Restore our old settings
  175.                     _FONT f
  176.                     EXIT SUB 'And leave
  177.                 CASE 32 TO 126
  178.                     temp$ = temp$ + CHR$(a)
  179.                     change = -1
  180.             END SELECT
  181.             DO
  182.                 IF _MOUSEBUTTON(1) = 0 THEN LoadFile_LMB = -1 'Only by lifting the mouse, will we count it as down
  183.                 'Note: we ignore LoadFile_LMB for the scroll bars, so we can just hold it down and scroll happily forever and ever...
  184.                 'or until we get to the limit of our file list.
  185.                 'We only check LoadFile_LMB when actually trying to select an item from our list.   No more "OOP!  I held it too long and did something I didn't want to do!"
  186.                 'Now we click once to select, click again to accept that selection.
  187.             LOOP WHILE _MOUSEINPUT
  188.             MX = _MOUSEX: MY = _MOUSEY
  189.             IF _MOUSEBUTTON(2) OR (LoadFile_LMB AND MX > 626 + x AND MX < 638 + x AND MY > 1 + y AND MY < 19 + y AND _MOUSEBUTTON(1)) THEN
  190.                 'restore those old values, and just exit.  Right mouse is an escape
  191.                 COLOR LoadFile_DC, LoadFile_BG: _SOURCE LoadFile_s: _DEST LoadFile_d: PCOPY 1, 0: _DISPLAY: SelectFile$ = ""
  192.                 _FONT f
  193.                 EXIT SUB
  194.             END IF
  195.             IF _MOUSEBUTTON(1) THEN 'Without the mouse being down, we don't need to check squat!
  196.                 'Check the 2 roLoadFile_ws for a click in the proper Y position
  197.                 IF MY >= 16 + 5 + y AND MY <= 2 * 16 + 3 + y THEN 'We're on the top row
  198.                     FOR j = 0 TO UBOUND(LoadFile_label)
  199.                         IF LoadFile_previous(j) AND MX >= j * LoadFile_l + 2 + x AND MX <= (j + 1) * LoadFile_l - 3 + x THEN
  200.                             LoadFile_start(j) = LoadFile_start(j) - 1
  201.                             change = -1: selection = 0: click = 0: temp$ = ""
  202.                             EXIT FOR
  203.                         END IF
  204.                     NEXT
  205.                 ELSEIF MY >= 27 * 16 + 5 + y AND MY <= 28 * 16 + 3 + y THEN 'We're on the bottom row
  206.                     FOR j = 0 TO UBOUND(LoadFile_label)
  207.                         IF LoadFile_more(j) AND MX >= j * LoadFile_l + 2 + x AND MX <= (j + 1) * LoadFile_l - 3 + x THEN
  208.                             LoadFile_start(j) = LoadFile_start(j) + 1
  209.                             change = -1: selection = 0: click = 0: temp$ = ""
  210.                             EXIT FOR
  211.                         END IF
  212.                     NEXT
  213.                 ELSEIF MY >= 37 + y AND MY <= 437 + y AND LoadFile_LMB THEN 'It's in a column somewhere.  Did someone click an item?!
  214.                     FOR j = 0 TO UBOUND(LoadFile_label)
  215.                         IF MX >= j * LoadFile_l + 2 + x AND MX <= (j + 1) * LoadFile_l - 3 + x THEN
  216.                             row = j
  217.                             oldselection = INT((MY - y - 37) / 16) + 1
  218.                             selection = LoadFile_start(j) + oldselection - 1
  219.                             change = -1
  220.                             click = -1
  221.                             EXIT FOR
  222.                         END IF
  223.                     NEXT
  224.                 END IF
  225.             END IF
  226.  
  227.             _DISPLAY
  228.         LOOP UNTIL change
  229.         IF click THEN 'we clicked something besides a scroll bar
  230.             IF LoadFile_Label(row) <> ".*" AND LoadFile_Label(row) <> "DIR" THEN temp1$ = LoadFile_DirList(row, selection) + LoadFile_Label(row) ELSE temp1$ = LoadFile_DirList(row, selection)
  231.             IF temp$ = temp1$ THEN
  232.                 'We picked one!
  233.                 SELECT CASE LoadFile_Label(row)
  234.                     CASE "DIR"
  235.                         IF LoadFile_DirList(row, selection) <> ".." THEN
  236.                             LoadFile_Dir$ = LoadFile_Dir$ + LoadFile_DirList(row, selection) + LoadFile_Slash$
  237.                         ELSE
  238.                             DO
  239.                                 LoadFile_Dir$ = LEFT$(LoadFile_Dir$, LEN(LoadFile_Dir$) - 1)
  240.                             LOOP UNTIL RIGHT$(LoadFile_Dir$, 1) = LoadFile_Slash$ OR LEN(LoadFile_Dir$) = 0
  241.                         END IF
  242.                         FOR i = 1 TO UBOUND(Loadfile_start)
  243.                             LoadFile_start(i) = 1
  244.                         NEXT
  245.                         selection = 0: temp$ = "": oldselection = 0
  246.                     CASE ".*": SelectFile$ = LoadFile_Dir$ + temp$: EXIT DO
  247.                     CASE ELSE: SelectFile$ = LoadFile_Dir$ + temp$: EXIT DO
  248.                 END SELECT
  249.             END IF
  250.             IF row > 0 THEN _DELAY .2: GOTO updatelist
  251.         ELSE
  252.             _DELAY .05
  253.             GOTO updatelist
  254.         END IF
  255.     LOOP
  256.     'restore those old values
  257.     COLOR LoadFile_DC, LoadFile_BG: _SOURCE LoadFile_s: _DEST LoadFile_d: PCOPY 1, 0: _DISPLAY
  258.     _FONT f
  259.  
  260. 'If you don't have a copy of direntry.h in your QB64 folder, then copy the following code into a new IDE window.
  261. 'Then remove the remarks.
  262. 'And save it as direntry.h
  263. 'direntry.h is required for this to work properly with the library files.
  264. 'I thought adding the code here would be a way to make certain that it'd be easy to recover the file
  265. 'in case something ever happened and it was accidently deleted off the drive for some reason.
  266.  
  267. '#include <dirent.h>
  268. '#include <sys/stat.h>
  269. '#include <unistd.h>
  270.  
  271. 'const int IS_DIR_FLAG = 1, IS_FILE_FLAG = 2;
  272.  
  273. 'DIR *pdir;
  274. 'struct dirent *next_entry;
  275. 'struct stat statbuf1;
  276.  
  277. 'char current_dir[FILENAME_MAX];
  278. '#ifdef QB64_WINDOWS
  279. '  #define GetCurrentDir _getcwd
  280. '#else
  281. '  #define GetCurrentDir getcwd
  282. '#endif
  283.  
  284. 'int load_dir (char * path) {
  285. '  struct dirent *pent;
  286. '  struct stat statbuf1;
  287. '//Open current directory
  288. 'pdir = opendir(path);
  289. 'if (!pdir) {
  290. 'return 0; //Didn't open
  291. '}
  292. 'return -1;
  293. '}
  294.  
  295. 'int has_next_entry () {
  296. '  next_entry = readdir(pdir);
  297. '  if (next_entry == NULL) return -1;
  298.  
  299. '  stat(next_entry->d_name, &statbuf1);
  300. '  return strlen(next_entry->d_name);
  301. '}
  302.  
  303. 'void get_next_entry (char * nam, int * flags, int * file_size) {
  304. '  strcpy(nam, next_entry->d_name);
  305. '  if (S_ISDIR(statbuf1.st_mode)) {
  306. '    *flags = IS_DIR_FLAG;
  307. '  } else {
  308. '    *flags = IS_FILE_FLAG;
  309. '  }
  310. '  *file_size = statbuf1.st_size;
  311. '  return ;
  312. '}
  313.  
  314. 'void close_dir () {
  315. '  closedir(pdir);
  316. '  pdir = NULL;
  317. '  return ;
  318. '}
  319.  
  320. 'int current_dir_length () {
  321. '  GetCurrentDir(current_dir, sizeof(current_dir));
  322. '  return strlen(current_dir);
  323. '}
  324.  
  325. 'void get_current_dir(char *dir) {
  326. '  memcpy(dir, current_dir, strlen(current_dir));
  327. '  return ;
  328. '}
  329.  
  330.  
« Last Edit: June 14, 2020, 12:00:16 am by bplus »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Opening files
« Reply #18 on: June 14, 2020, 06:52:40 am »
As for Windows dialogs, I've talked about this:

(Source code is modified from QB64 wiki, because there is used new function _WIDOWHANDLE, it is nice, BUT this source code works not under 64 bit version QB64, therefore, 32 bit older versions know not this new function name and need extra library for it:

Code: QB64: [Select]
  1. ' Dialog flag constants (use + or OR to use more than 1 flag value)
  2. CONST OFN_ALLOWMULTISELECT = &H200& '  Allows the user to select more than one file, not recommended!
  3. CONST OFN_CREATEPROMPT = &H2000& '     Prompts if a file not found should be created(GetOpenFileName only).
  4. CONST OFN_EXTENSIONDIFFERENT = &H400& 'Allows user to specify file extension other than default extension.
  5. CONST OFN_FILEMUSTEXIST = &H1000& '    Chechs File name exists(GetOpenFileName only).
  6. CONST OFN_HIDEREADONLY = &H4& '        Hides read-only checkbox(GetOpenFileName only)
  7. CONST OFN_NOCHANGEDIR = &H8& '         Restores the current directory to original value if user changed
  8. CONST OFN_NODEREFERENCELINKS = &H100000& 'Returns path and file name of selected shortcut(.LNK) file instead of file referenced.
  9. CONST OFN_NONETWORKBUTTON = &H20000& ' Hides and disables the Network button.
  10. CONST OFN_NOREADONLYRETURN = &H8000& ' Prevents selection of read-only files, or files in read-only subdirectory.
  11. CONST OFN_NOVALIDATE = &H100& '        Allows invalid file name characters.
  12. CONST OFN_OVERWRITEPROMPT = &H2& '     Prompts if file already exists(GetSaveFileName only)
  13. CONST OFN_PATHMUSTEXIST = &H800& '     Checks Path name exists (set with OFN_FILEMUSTEXIST).
  14. CONST OFN_READONLY = &H1& '            Checks read-only checkbox. Returns if checkbox is checked
  15. CONST OFN_SHAREAWARE = &H4000& '       Ignores sharing violations in networking
  16. CONST OFN_SHOWHELP = &H10& '           Shows the help button (useless!)
  17. '--------------------------------------------------------------------------------------------
  18.  
  19. DEFINT A-Z
  20. TYPE FILEDIALOGTYPE
  21.     lStructSize AS LONG '        For the DLL call
  22.     hwndOwner AS LONG '          Dialog will hide behind window when not set correctly
  23.     hInstance AS LONG '          Handle to a module that contains a dialog box template.
  24.     lpstrFilter AS _OFFSET '     Pointer of the string of file filters
  25.     lpstrCustFilter AS _OFFSET
  26.     nMaxCustFilter AS LONG
  27.     nFilterIndex AS LONG '       One based starting filter index to use when dialog is called
  28.     lpstrFile AS _OFFSET '       String full of 0's for the selected file name
  29.     nMaxFile AS LONG '           Maximum length of the string stuffed with 0's minus 1
  30.     lpstrFileTitle AS _OFFSET '  Same as lpstrFile
  31.     nMaxFileTitle AS LONG '      Same as nMaxFile
  32.     lpstrInitialDir AS _OFFSET ' Starting directory
  33.     lpstrTitle AS _OFFSET '      Dialog title
  34.     flags AS LONG '              Dialog flags
  35.     nFileOffset AS INTEGER '     Zero-based offset from path beginning to file name string pointed to by lpstrFile
  36.     nFileExtension AS INTEGER '  Zero-based offset from path beginning to file extension string pointed to by lpstrFile.
  37.     lpstrDefExt AS _OFFSET '     Default/selected file extension
  38.     lCustData AS LONG
  39.     lpfnHook AS LONG
  40.     lpTemplateName AS _OFFSET
  41.  
  42. DECLARE DYNAMIC LIBRARY "comdlg32" ' Library declarations using _OFFSET types
  43.     FUNCTION GetOpenFileNameA& (DIALOGPARAMS AS FILEDIALOGTYPE) ' The Open file dialog
  44.     FUNCTION GetSaveFileNameA& (DIALOGPARAMS AS FILEDIALOGTYPE) ' The Save file dialog
  45.  
  46.     FUNCTION FindWindow& (BYVAL ClassName AS _OFFSET, WindowName$) ' To get hWnd handle
  47.  
  48. _TITLE "FileOpen Common Dialog demo" 'set Title of program
  49. hWnd& = FindWindow(0, "Open and Save Dialog demo" + CHR$(0)) 'get window handle using _TITLE string
  50.  
  51. ' Do the Open File dialog call!
  52. Filter$ = "Batch files (*.bat)|*.BAT|JPEG images (*.jpg)|*.JPG|All files (*.*)|*.*"
  53. Flags& = OFN_FILEMUSTEXIST + OFN_NOCHANGEDIR + OFN_READONLY '    add flag constants here
  54. OFile$ = GetOpenFileName$("YEAH! Common Dialogs in QB64!!!", ".\", Filter$, 1, Flags&, hWnd&)
  55.  
  56. IF OFile$ = "" THEN ' Display Open dialog results
  57.     PRINT "Shame on you! You didn't pick any file..."
  58.     PRINT "You picked this file: "
  59.     PRINT OFile$
  60.     IF (Flags& AND OFN_READONLY) THEN PRINT "Read-only checkbox checked." 'read-only value in return
  61.  
  62. _DELAY 5 ' Do the Save File dialog call!
  63. Filter$ = "Basic files (*.bas)|*.BAS|All files (*.*)|*.*"
  64. Flags& = OFN_OVERWRITEPROMPT + OFN_NOCHANGEDIR '   add flag constants here
  65. SFile$ = GetSaveFileName$("Save will not create a file!!!", ".\", Filter$, 1, Flags&, hWnd&)
  66.  
  67. IF SFile$ = "" THEN ' Display Save dialog results
  68.     PRINT "You didn't save the file..."
  69.     PRINT "You saved this file: "
  70.     PRINT SFile$
  71.  
  72. FUNCTION GetOpenFileName$ (Title$, InitialDir$, Filter$, FilterIndex, Flags&, hWnd&)
  73. '  Title$      - The dialog title.
  74. '  InitialDir$ - If this left blank, it will use the directory where the last opened file is
  75. '  located. Specify ".\" if you want to always use the current directory.
  76. '  Filter$     - File filters separated by pipes (|) in the same format as using VB6 common dialogs.
  77. '  FilterIndex - The initial file filter to use. Will be altered by user during the call.
  78. '  Flags&      - Dialog flags. Will be altered by the user during the call.
  79. '  hWnd&       - Your program's window handle that should be aquired by the FindWindow function.
  80. '
  81. ' Returns: Blank when cancel is clicked otherwise, the file name selected by the user.
  82. ' FilterIndex and Flags& will be changed depending on the user's selections.
  83.  
  84. DIM OpenCall AS FILEDIALOGTYPE ' Needed for dialog call
  85.  
  86. fFilter$ = Filter$
  87. FOR R = 1 TO LEN(fFilter$) ' Replace the pipes with character zero
  88.     IF MID$(fFilter$, R, 1) = "|" THEN MID$(fFilter$, R, 1) = CHR$(0)
  89. fFilter$ = fFilter$ + CHR$(0)
  90.  
  91. lpstrFile$ = STRING$(2048, 0) ' For the returned file name
  92. lpstrDefExt$ = STRING$(10, 0) ' Extension will not be added when this is not specified
  93. OpenCall.lStructSize = LEN(OpenCall)
  94. OpenCall.hwndOwner = hWnd&
  95. OpenCall.lpstrFilter = _OFFSET(fFilter$)
  96. OpenCall.nFilterIndex = FilterIndex
  97. OpenCall.lpstrFile = _OFFSET(lpstrFile$)
  98. OpenCall.nMaxFile = LEN(lpstrFile$) - 1
  99. OpenCall.lpstrFileTitle = OpenCall.lpstrFile
  100. OpenCall.nMaxFileTitle = OpenCall.nMaxFile
  101. OpenCall.lpstrInitialDir = _OFFSET(InitialDir$)
  102. OpenCall.lpstrTitle = _OFFSET(Title$)
  103. OpenCall.lpstrDefExt = _OFFSET(lpstrDefExt$)
  104. OpenCall.flags = Flags&
  105.  
  106. Result = GetOpenFileNameA&(OpenCall) '            Do Open File dialog call!
  107.  
  108. IF Result THEN ' Trim the remaining zeros
  109.     GetOpenFileName$ = LEFT$(lpstrFile$, INSTR(lpstrFile$, CHR$(0)) - 1)
  110.     Flags& = OpenCall.flags
  111.     FilterIndex = OpenCall.nFilterIndex
  112.  
  113.  
  114. FUNCTION GetSaveFileName$ (Title$, InitialDir$, Filter$, FilterIndex, Flags&, hWnd&)
  115. '  Title$      - The dialog title.
  116. '  InitialDir$ - If this left blank, it will use the directory where the last opened file is
  117. '     located. Specify ".\" if you want to always use the current directory.
  118. '  Filter$     - File filters separated by pipes (|) in the same format as VB6 common dialogs.
  119. '  FilterIndex - The initial file filter to use. Will be altered by user during the call.
  120. '  Flags&      - Dialog flags. Will be altered by the user during the call.
  121. '  hWnd&       - Your program's window handle that should be aquired by the FindWindow function.
  122.  
  123. ' Returns: Blank when cancel is clicked otherwise, the file name entered by the user.
  124. ' FilterIndex and Flags& will be changed depending on the user's selections.
  125.  
  126. DIM SaveCall AS FILEDIALOGTYPE ' Needed for dialog call
  127.  
  128. fFilter$ = Filter$
  129. FOR R = 1 TO LEN(fFilter$) ' Replace the pipes with zeros
  130.     IF MID$(fFilter$, R, 1) = "|" THEN MID$(fFilter$, R, 1) = CHR$(0)
  131. fFilter$ = fFilter$ + CHR$(0)
  132.  
  133. lpstrFile$ = STRING$(2048, 0) ' For the returned file name
  134. lpstrDefExt$ = STRING$(10, 0) ' Extension will not be added when this is not specified
  135. SaveCall.lStructSize = LEN(SaveCall)
  136. SaveCall.hwndOwner = hWnd&
  137. SaveCall.lpstrFilter = _OFFSET(fFilter$)
  138. SaveCall.nFilterIndex = FilterIndex
  139. SaveCall.lpstrFile = _OFFSET(lpstrFile$)
  140. SaveCall.nMaxFile = LEN(lpstrFile$) - 1
  141. SaveCall.lpstrFileTitle = SaveCall.lpstrFile
  142. SaveCall.nMaxFileTitle = SaveCall.nMaxFile
  143. SaveCall.lpstrInitialDir = _OFFSET(InitialDir$)
  144. SaveCall.lpstrTitle = _OFFSET(Title$)
  145. SaveCall.lpstrDefExt = _OFFSET(lpstrDefExt$)
  146. SaveCall.flags = Flags&
  147.  
  148. Result& = GetSaveFileNameA&(SaveCall) ' Do dialog call!
  149.  
  150. IF Result& THEN ' Trim the remaining zeros
  151.     GetSaveFileName$ = LEFT$(lpstrFile$, INSTR(lpstrFile$, CHR$(0)) - 1)
  152.     Flags& = SaveCall.flags
  153.     FilterIndex = SaveCall.nFilterIndex
  154.  

You need OLD 32 bit version QB64 IDE for running this. Here is program output:

  [ You are not allowed to view this attachment ]  

OR,

If you need just FOLDER selecting under Windows dialog, use this also modified source code from Wiki. This works under 64 bit QB64, original source code on wiki works under 32 bit QB64
All sources working in 32 bits are here: http://www.qb64.org/wiki/Windows_Libraries

Code: QB64: [Select]
  1.     FUNCTION FindWindow& (BYVAL ClassName AS _OFFSET, WindowName$)
  2.  
  3. _TITLE "Super Window"
  4. hwnd& = _WINDOWHANDLE 'FindWindow(0, "Super Window" + CHR$(0))
  5.  
  6. TYPE BROWSEINFO 'typedef struct _browseinfo 'Microsoft MSDN
  7.     hwndOwner AS _INTEGER64 '              '  HWND
  8.     pidlRoot AS _OFFSET '             '  PCIDLIST_ABSOLUTE
  9.     pszDisplayName AS _OFFSET '      '  LPTSTR
  10.     lpszTitle AS _OFFSET '           '  LPCTSTR
  11.     ulFlags AS _UNSIGNED LONG '  UINT
  12.     lpfn AS _OFFSET '                '  BFFCALLBACK
  13.     lParam AS _OFFSET '              '  LPARAM
  14.     iImage AS LONG '                 '  int
  15. END TYPE 'BROWSEINFO, *PBROWSEINFO, *LPBROWSEINFO;
  16.  
  17.     FUNCTION SHBrowseForFolder%& (x AS BROWSEINFO) 'Microsoft MSDN
  18.     SUB SHGetPathFromIDList (BYVAL lpItem AS _OFFSET, BYVAL szDir AS _OFFSET) 'Microsoft MSDN
  19.  
  20. DIM b AS BROWSEINFO
  21. b.hwndOwner = hwnd
  22. DIM s AS STRING * 1024
  23. b.pszDisplayName = _OFFSET(s$)
  24. a$ = "Choose a folder!!!" + CHR$(0)
  25. b.lpszTitle = _OFFSET(a$)
  26. o = SHBrowseForFolder(b)
  27.     PRINT LEFT$(s$, INSTR(s$, CHR$(0)) - 1)
  28.     DIM s2 AS STRING * 1024
  29.     SHGetPathFromIDList o, _OFFSET(s2$)
  30.     PRINT LEFT$(s2$, INSTR(s2$, CHR$(0)) - 1)
  31.     PRINT "Cancel?"
  32.  

You need choosing drive or  short file name? Use this source:  (2 source codes in one program)

Code: QB64: [Select]
  1. DECLARE LIBRARY 'Directory Information using KERNEL32
  2.     FUNCTION GetShortPathNameA (lpLongPath AS STRING, lpShortPath AS STRING, BYVAL cBufferLen AS LONG)
  3.  
  4. '=== SHOW SHORT PATH NAME
  5. FileOrPath$ = "e:\video to gif converter\videotogifconverter.exe" '<< change to a relevant path or file name on computer
  6. IF _FILEEXISTS(FileOrPath$) THEN PRINT "Path ok"
  7. ShortPathName$ = SPACE$(260)
  8. Result = GetShortPathNameA(FileOrPath$ + CHR$(0), ShortPathName$, LEN(ShortPathName$))
  9. PRINT Result
  10. IF Result THEN PRINT "SHORT PATH NAME: " + ShortPathName$ ELSE PRINT "NOT Found!"
  11.  
  12.  
  13.  
  14. 'disk drivers
  15. CONST REMOVABLE = 2
  16. CONST FIXED = 3
  17. CONST REMOTE = 4
  18. CONST CDROM = 5
  19. CONST RAMDISK = 6
  20.  
  21.     FUNCTION GetDriveTypeA& (nDrive AS STRING)
  22.     FUNCTION GetLogicalDriveStringsA (BYVAL nBuff AS LONG, lpbuff AS STRING)
  23.  
  24. DIM DList AS STRING, DL AS STRING
  25. DIM i AS LONG, typ AS LONG
  26.  
  27. i = GetLogicalDriveStringsA(0, DList) 'zero returns the drive string byte size
  28. DList = SPACE$(i) 'set drive string length. Each drive is followed by CHR$(0)
  29. i = GetLogicalDriveStringsA(i, DList) 'the byte size returns a string that long
  30. PRINT DList
  31.  
  32. FOR n = 65 TO 90
  33.     IF INSTR(DList, CHR$(n)) THEN
  34.         DL = CHR$(n) + ":\" + CHR$(0)
  35.         typ = GetDriveTypeA(DL)
  36.         SELECT CASE typ
  37.             CASE REMOVABLE: PRINT DL + "Removable"
  38.             CASE FIXED: PRINT DL + "Fixed"
  39.             CASE REMOTE: PRINT DL + "Remote"
  40.             CASE CDROM: PRINT DL + "CDROM"
  41.             CASE RAMDISK: PRINT DL + "RAM"
  42.         END SELECT
  43.     END IF
  44.  

(this last source works under both QB64 versions)

Of course, I tried to run the first example under QB64 - 64 bit as well, but I couldn't find where the problem was. I used _INTEGER64 instead of LONG values, without success.

If someone could find and repair problem and run it for QB64 in 64 bit as well, it would be very useful and enjoyable.
« Last Edit: June 14, 2020, 07:10:06 am by Petr »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Opening files
« Reply #19 on: June 14, 2020, 02:20:29 pm »
So.

Here is Open/Save Windows dialog, rewrited for 64bit QB64. Jack helped me with this program upgrade:

Code: QB64: [Select]
  1. ' Dialog flag constants (use + or OR to use more than 1 flag value)
  2. CONST OFN_ALLOWMULTISELECT = &H200& '  Allows the user to select more than one file, not recommended!
  3. CONST OFN_CREATEPROMPT = &H2000& '     Prompts if a file not found should be created(GetOpenFileName only).
  4. CONST OFN_EXTENSIONDIFFERENT = &H400& 'Allows user to specify file extension other than default extension.
  5. CONST OFN_FILEMUSTEXIST = &H1000& '    Chechs File name exists(GetOpenFileName only).
  6. CONST OFN_HIDEREADONLY = &H4& '        Hides read-only checkbox(GetOpenFileName only)
  7. CONST OFN_NOCHANGEDIR = &H8& '         Restores the current directory to original value if user changed
  8. CONST OFN_NODEREFERENCELINKS = &H100000& 'Returns path and file name of selected shortcut(.LNK) file instead of file referenced.
  9. CONST OFN_NONETWORKBUTTON = &H20000& ' Hides and disables the Network button.
  10. CONST OFN_NOREADONLYRETURN = &H8000& ' Prevents selection of read-only files, or files in read-only subdirectory.
  11. CONST OFN_NOVALIDATE = &H100& '        Allows invalid file name characters.
  12. CONST OFN_OVERWRITEPROMPT = &H2& '     Prompts if file already exists(GetSaveFileName only)
  13. CONST OFN_PATHMUSTEXIST = &H800& '     Checks Path name exists (set with OFN_FILEMUSTEXIST).
  14. CONST OFN_READONLY = &H1& '            Checks read-only checkbox. Returns if checkbox is checked
  15. CONST OFN_SHAREAWARE = &H4000& '       Ignores sharing violations in networking
  16. CONST OFN_SHOWHELP = &H10& '           Shows the help button (useless!)
  17. '--------------------------------------------------------------------------------------------
  18.  
  19. DEFINT A-Z
  20.  
  21. TYPE FILEDIALOGTYPE
  22.     lStructSize AS LONG '           For the DLL call
  23.     hwndOwner AS _OFFSET '          Dialog will hide behind window when not set correctly
  24.     hInstance AS _OFFSET '          Handle to a module that contains a dialog box template.
  25.     lpstrFilter AS _OFFSET '        Pointer of the string of file filters
  26.     lpstrCustFilter AS LONG
  27.     nMaxCustFilter AS _INTEGER64
  28.     nFilterIndex AS _INTEGER64 '    One based starting filter index to use when dialog is called
  29.     lpstrFile AS _OFFSET '          String full of 0's for the selected file name
  30.     nMaxFile AS _INTEGER64 '        Maximum length of the string stuffed with 0's minus 1
  31.     lpstrFileTitle AS _OFFSET '     Same as lpstrFile
  32.     nMaxFileTitle AS _OFFSET '      Same as nMaxFile
  33.     lpstrInitialDir AS _OFFSET '    Starting directory
  34.     lpstrTitle AS _OFFSET '         Dialog title
  35.     flags AS _INTEGER64 '           Dialog flags
  36.     nFileOffset AS _INTEGER64 '     Zero-based offset from path beginning to file name string pointed to by lpstrFile
  37.     nFileExtension AS _INTEGER64 '  Zero-based offset from path beginning to file extension string pointed to by lpstrFile.
  38.     lpstrDefExt AS _OFFSET '        Default/selected file extension
  39.     lCustData AS _INTEGER64
  40.     lpfnHook AS _INTEGER64
  41.     lpTemplateName AS _INTEGER64
  42.  
  43. DECLARE DYNAMIC LIBRARY "comdlg32" ' Library declarations using _OFFSET types
  44.     FUNCTION GetOpenFileNameA&& (DIALOGPARAMS AS FILEDIALOGTYPE) ' The Open file dialog
  45.     FUNCTION GetSaveFileNameA&& (DIALOGPARAMS AS FILEDIALOGTYPE) ' The Save file dialog
  46.  
  47.     FUNCTION FindWindow~&& (BYVAL ClassName AS _OFFSET, WindowName$) ' To get hWnd handle
  48.  
  49. _TITLE "FOCdemo" 'set Title of program
  50. hWnd = _WINDOWHANDLE 'FindWindow(0, "Open and Save Dialog demo" + CHR$(0)) 'get window handle using _TITLE string
  51.  
  52. 'hWnd~&& = FindWindow(0, "FOCdemo" + CHR$(0)) 'get window handle using _TITLE string
  53.  
  54. PRINT hWnd
  55. ' Do the Open File dialog call!
  56. Filter$ = "Batch files (*.bat)|*.BAT|JPEG images (*.jpg)|*.JPG|All files (*.*)|*.*"
  57. Flags& = OFN_FILEMUSTEXIST + OFN_NOCHANGEDIR + OFN_READONLY '    add flag constants here
  58. OFile$ = GetOpenFileName$("YEAH! Common Dialogs in QB64!!!", ".\", Filter$, 1, Flags&, hWnd&&)
  59.  
  60. IF OFile$ = "" THEN ' Display Open dialog results
  61.     PRINT "Shame on you! You didn't pick any file..."
  62.     PRINT "You picked this file: "
  63.     PRINT OFile$
  64.     IF (Flags& AND OFN_READONLY) THEN PRINT "Read-only checkbox checked." 'read-only value in return
  65.  
  66. _DELAY 5 ' Do the Save File dialog call!
  67. Filter$ = "Basic files (*.bas)|*.BAS|All files (*.*)|*.*"
  68. Flags& = OFN_OVERWRITEPROMPT + OFN_NOCHANGEDIR '   add flag constants here
  69. SFile$ = GetSaveFileName$("Save will not create a file!!!", ".\", Filter$, 1, Flags&, hWnd%&)
  70.  
  71. IF SFile$ = "" THEN ' Display Save dialog results
  72.     PRINT "You didn't save the file..."
  73.     PRINT "You saved this file: "
  74.     PRINT SFile$
  75.  
  76. FUNCTION GetOpenFileName$ (Title$, InitialDir$, Filter$, FilterIndex&, Flags&, hWnd AS _INTEGER64)
  77.     '  Title$      - The dialog title.
  78.     '  InitialDir$ - If this left blank, it will use the directory where the last opened file is
  79.     '  located. Specify ".\" if you want to always use the current directory.
  80.     '  Filter$     - File filters separated by pipes (|) in the same format as using VB6 common dialogs.
  81.     '  FilterIndex - The initial file filter to use. Will be altered by user during the call.
  82.     '  Flags&      - Dialog flags. Will be altered by the user during the call.
  83.     '  hWnd&       - Your program's window handle that should be aquired by the FindWindow function.
  84.     '
  85.     ' Returns: Blank when cancel is clicked otherwise, the file name selected by the user.
  86.     ' FilterIndex and Flags& will be changed depending on the user's selections.
  87.  
  88.     DIM OpenCall AS FILEDIALOGTYPE ' Needed for dialog call
  89.  
  90.     fFilter$ = Filter$
  91.     FOR R = 1 TO LEN(fFilter$) ' Replace the pipes with character zero
  92.         IF MID$(fFilter$, R, 1) = "|" THEN MID$(fFilter$, R, 1) = CHR$(0)
  93.     NEXT R
  94.     fFilter$ = fFilter$ + CHR$(0)
  95.  
  96.     lpstrFile$ = STRING$(2048, 0) ' For the returned file name
  97.     lpstrDefExt$ = STRING$(10, 0) ' Extension will not be added when this is not specified
  98.     OpenCall.lStructSize = LEN(OpenCall)
  99.     OpenCall.hwndOwner = hWnd&&
  100.     OpenCall.lpstrFilter = _OFFSET(fFilter$)
  101.     OpenCall.nFilterIndex = FilterIndex&
  102.     OpenCall.lpstrFile = _OFFSET(lpstrFile$)
  103.     OpenCall.nMaxFile = LEN(lpstrFile$) - 1
  104.     OpenCall.lpstrFileTitle = OpenCall.lpstrFile
  105.     OpenCall.nMaxFileTitle = OpenCall.nMaxFile
  106.     OpenCall.lpstrInitialDir = _OFFSET(InitialDir$)
  107.     OpenCall.lpstrTitle = _OFFSET(Title$)
  108.     OpenCall.lpstrDefExt = _OFFSET(lpstrDefExt$)
  109.     OpenCall.flags = Flags&
  110.  
  111.     Result = GetOpenFileNameA&&(OpenCall) '            Do Open File dialog call!
  112.  
  113.     IF Result THEN ' Trim the remaining zeros
  114.         GetOpenFileName$ = LEFT$(lpstrFile$, INSTR(lpstrFile$, CHR$(0)) - 1)
  115.         Flags& = OpenCall.flags
  116.         FilterIndex = OpenCall.nFilterIndex
  117.     END IF
  118.  
  119.  
  120. FUNCTION GetSaveFileName$ (Title$, InitialDir$, Filter$, FilterIndex, Flags&, hWnd%&)
  121.     '  Title$      - The dialog title.
  122.     '  InitialDir$ - If this left blank, it will use the directory where the last opened file is
  123.     '     located. Specify ".\" if you want to always use the current directory.
  124.     '  Filter$     - File filters separated by pipes (|) in the same format as VB6 common dialogs.
  125.     '  FilterIndex - The initial file filter to use. Will be altered by user during the call.
  126.     '  Flags&      - Dialog flags. Will be altered by the user during the call.
  127.     '  hWnd&       - Your program's window handle that should be aquired by the FindWindow function.
  128.  
  129.     ' Returns: Blank when cancel is clicked otherwise, the file name entered by the user.
  130.     ' FilterIndex and Flags& will be changed depending on the user's selections.
  131.  
  132.     DIM SaveCall AS FILEDIALOGTYPE ' Needed for dialog call
  133.  
  134.     fFilter$ = Filter$
  135.     FOR R = 1 TO LEN(fFilter$) ' Replace the pipes with zeros
  136.         IF MID$(fFilter$, R, 1) = "|" THEN MID$(fFilter$, R, 1) = CHR$(0)
  137.     NEXT R
  138.     fFilter$ = fFilter$ + CHR$(0)
  139.  
  140.     lpstrFile$ = STRING$(2048, 0) ' For the returned file name
  141.     lpstrDefExt$ = STRING$(10, 0) ' Extension will not be added when this is not specified
  142.     SaveCall.lStructSize = LEN(SaveCall)
  143.     SaveCall.hwndOwner = _OFFSET(hWnd%&)
  144.     SaveCall.lpstrFilter = _OFFSET(fFilter$)
  145.     SaveCall.nFilterIndex = FilterIndex
  146.     SaveCall.lpstrFile = _OFFSET(lpstrFile$)
  147.     SaveCall.nMaxFile = LEN(lpstrFile$) - 1
  148.     SaveCall.lpstrFileTitle = SaveCall.lpstrFile
  149.     SaveCall.nMaxFileTitle = SaveCall.nMaxFile
  150.     SaveCall.lpstrInitialDir = _OFFSET(InitialDir$)
  151.     SaveCall.lpstrTitle = _OFFSET(Title$)
  152.     SaveCall.lpstrDefExt = _OFFSET(lpstrDefExt$)
  153.     SaveCall.flags = Flags&
  154.  
  155.     Result& = GetSaveFileNameA&&(SaveCall) ' Do dialog call!
  156.  
  157.     IF Result& THEN ' Trim the remaining zeros
  158.         GetSaveFileName$ = LEFT$(lpstrFile$, INSTR(lpstrFile$, CHR$(0)) - 1)
  159.         Flags& = SaveCall.flags
  160.         FilterIndex = SaveCall.nFilterIndex
  161.     END IF
  162.  
  163.  
« Last Edit: June 14, 2020, 02:21:59 pm by Petr »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Opening files
« Reply #20 on: June 14, 2020, 02:33:27 pm »
And this version should now work in both 32 and 64-bit Windows:

Code: QB64: [Select]
  1. ' Dialog flag constants (use + or OR to use more than 1 flag value)
  2. CONST OFN_ALLOWMULTISELECT = &H200& '  Allows the user to select more than one file, not recommended!
  3. CONST OFN_CREATEPROMPT = &H2000& '     Prompts if a file not found should be created(GetOpenFileName only).
  4. CONST OFN_EXTENSIONDIFFERENT = &H400& 'Allows user to specify file extension other than default extension.
  5. CONST OFN_FILEMUSTEXIST = &H1000& '    Chechs File name exists(GetOpenFileName only).
  6. CONST OFN_HIDEREADONLY = &H4& '        Hides read-only checkbox(GetOpenFileName only)
  7. CONST OFN_NOCHANGEDIR = &H8& '         Restores the current directory to original value if user changed
  8. CONST OFN_NODEREFERENCELINKS = &H100000& 'Returns path and file name of selected shortcut(.LNK) file instead of file referenced.
  9. CONST OFN_NONETWORKBUTTON = &H20000& ' Hides and disables the Network button.
  10. CONST OFN_NOREADONLYRETURN = &H8000& ' Prevents selection of read-only files, or files in read-only subdirectory.
  11. CONST OFN_NOVALIDATE = &H100& '        Allows invalid file name characters.
  12. CONST OFN_OVERWRITEPROMPT = &H2& '     Prompts if file already exists(GetSaveFileName only)
  13. CONST OFN_PATHMUSTEXIST = &H800& '     Checks Path name exists (set with OFN_FILEMUSTEXIST).
  14. CONST OFN_READONLY = &H1& '            Checks read-only checkbox. Returns if checkbox is checked
  15. CONST OFN_SHAREAWARE = &H4000& '       Ignores sharing violations in networking
  16. CONST OFN_SHOWHELP = &H10& '           Shows the help button (useless!)
  17. '--------------------------------------------------------------------------------------------
  18.  
  19. DEFINT A-Z
  20.  
  21. TYPE FILEDIALOGTYPE
  22.     $IF 32BIT THEN
  23.     TYPE FILEDIALOGTYPE
  24.     lStructSize AS LONG '        For the DLL call
  25.     hwndOwner AS LONG '          Dialog will hide behind window when not set correctly
  26.     hInstance AS LONG '          Handle to a module that contains a dialog box template.
  27.     lpstrFilter AS _OFFSET '     Pointer of the string of file filters
  28.     lpstrCustFilter AS _OFFSET
  29.     nMaxCustFilter AS LONG
  30.     nFilterIndex AS LONG '       One based starting filter index to use when dialog is called
  31.     lpstrFile AS _OFFSET '       String full of 0's for the selected file name
  32.     nMaxFile AS LONG '           Maximum length of the string stuffed with 0's minus 1
  33.     lpstrFileTitle AS _OFFSET '  Same as lpstrFile
  34.     nMaxFileTitle AS LONG '      Same as nMaxFile
  35.     lpstrInitialDir AS _OFFSET ' Starting directory
  36.     lpstrTitle AS _OFFSET '      Dialog title
  37.     flags AS LONG '              Dialog flags
  38.     nFileOffset AS INTEGER '     Zero-based offset from path beginning to file name string pointed to by lpstrFile
  39.     nFileExtension AS INTEGER '  Zero-based offset from path beginning to file extension string pointed to by lpstrFile.
  40.     lpstrDefExt AS _OFFSET '     Default/selected file extension
  41.     lCustData AS LONG
  42.     lpfnHook AS LONG
  43.     lpTemplateName AS _OFFSET
  44.     $ELSE
  45.         lStructSize AS LONG '           For the DLL call
  46.         hwndOwner AS _OFFSET '          Dialog will hide behind window when not set correctly
  47.         hInstance AS _OFFSET '          Handle to a module that contains a dialog box template.
  48.         lpstrFilter AS _OFFSET '        Pointer of the string of file filters
  49.         lpstrCustFilter AS LONG
  50.         nMaxCustFilter AS _INTEGER64
  51.         nFilterIndex AS _INTEGER64 '    One based starting filter index to use when dialog is called
  52.         lpstrFile AS _OFFSET '          String full of 0's for the selected file name
  53.         nMaxFile AS _INTEGER64 '        Maximum length of the string stuffed with 0's minus 1
  54.         lpstrFileTitle AS _OFFSET '     Same as lpstrFile
  55.         nMaxFileTitle AS _OFFSET '      Same as nMaxFile
  56.         lpstrInitialDir AS _OFFSET '    Starting directory
  57.         lpstrTitle AS _OFFSET '         Dialog title
  58.         flags AS _INTEGER64 '           Dialog flags
  59.         nFileOffset AS _INTEGER64 '     Zero-based offset from path beginning to file name string pointed to by lpstrFile
  60.         nFileExtension AS _INTEGER64 '  Zero-based offset from path beginning to file extension string pointed to by lpstrFile.
  61.         lpstrDefExt AS _OFFSET '        Default/selected file extension
  62.         lCustData AS _INTEGER64
  63.         lpfnHook AS _INTEGER64
  64.         lpTemplateName AS _INTEGER64
  65.     $END IF
  66.  
  67. DECLARE DYNAMIC LIBRARY "comdlg32" ' Library declarations using _OFFSET types
  68.     FUNCTION GetOpenFileNameA&& (DIALOGPARAMS AS FILEDIALOGTYPE) ' The Open file dialog
  69.     FUNCTION GetSaveFileNameA&& (DIALOGPARAMS AS FILEDIALOGTYPE) ' The Save file dialog
  70.  
  71.     FUNCTION FindWindow~&& (BYVAL ClassName AS _OFFSET, WindowName$) ' To get hWnd handle
  72.  
  73. _TITLE "FOCdemo" 'set Title of program
  74. hWnd = _WINDOWHANDLE 'FindWindow(0, "Open and Save Dialog demo" + CHR$(0)) 'get window handle using _TITLE string
  75.  
  76. 'hWnd~&& = FindWindow(0, "FOCdemo" + CHR$(0)) 'get window handle using _TITLE string
  77.  
  78. PRINT hWnd
  79. ' Do the Open File dialog call!
  80. Filter$ = "Batch files (*.bat)|*.BAT|JPEG images (*.jpg)|*.JPG|All files (*.*)|*.*"
  81. Flags& = OFN_FILEMUSTEXIST + OFN_NOCHANGEDIR + OFN_READONLY '    add flag constants here
  82. OFile$ = GetOpenFileName$("YEAH! Common Dialogs in QB64!!!", ".\", Filter$, 1, Flags&, hWnd&&)
  83.  
  84. IF OFile$ = "" THEN ' Display Open dialog results
  85.     PRINT "Shame on you! You didn't pick any file..."
  86.     PRINT "You picked this file: "
  87.     PRINT OFile$
  88.     IF (Flags& AND OFN_READONLY) THEN PRINT "Read-only checkbox checked." 'read-only value in return
  89.  
  90. _DELAY 5 ' Do the Save File dialog call!
  91. Filter$ = "Basic files (*.bas)|*.BAS|All files (*.*)|*.*"
  92. Flags& = OFN_OVERWRITEPROMPT + OFN_NOCHANGEDIR '   add flag constants here
  93. SFile$ = GetSaveFileName$("Save will not create a file!!!", ".\", Filter$, 1, Flags&, hWnd%&)
  94.  
  95. IF SFile$ = "" THEN ' Display Save dialog results
  96.     PRINT "You didn't save the file..."
  97.     PRINT "You saved this file: "
  98.     PRINT SFile$
  99.  
  100. FUNCTION GetOpenFileName$ (Title$, InitialDir$, Filter$, FilterIndex&, Flags&, hWnd AS _INTEGER64)
  101.     '  Title$      - The dialog title.
  102.     '  InitialDir$ - If this left blank, it will use the directory where the last opened file is
  103.     '  located. Specify ".\" if you want to always use the current directory.
  104.     '  Filter$     - File filters separated by pipes (|) in the same format as using VB6 common dialogs.
  105.     '  FilterIndex - The initial file filter to use. Will be altered by user during the call.
  106.     '  Flags&      - Dialog flags. Will be altered by the user during the call.
  107.     '  hWnd&       - Your program's window handle that should be aquired by the FindWindow function.
  108.     '
  109.     ' Returns: Blank when cancel is clicked otherwise, the file name selected by the user.
  110.     ' FilterIndex and Flags& will be changed depending on the user's selections.
  111.  
  112.     DIM OpenCall AS FILEDIALOGTYPE ' Needed for dialog call
  113.  
  114.     fFilter$ = Filter$
  115.     FOR R = 1 TO LEN(fFilter$) ' Replace the pipes with character zero
  116.         IF MID$(fFilter$, R, 1) = "|" THEN MID$(fFilter$, R, 1) = CHR$(0)
  117.     NEXT R
  118.     fFilter$ = fFilter$ + CHR$(0)
  119.  
  120.     lpstrFile$ = STRING$(2048, 0) ' For the returned file name
  121.     lpstrDefExt$ = STRING$(10, 0) ' Extension will not be added when this is not specified
  122.     OpenCall.lStructSize = LEN(OpenCall)
  123.     OpenCall.hwndOwner = hWnd&&
  124.     OpenCall.lpstrFilter = _OFFSET(fFilter$)
  125.     OpenCall.nFilterIndex = FilterIndex&
  126.     OpenCall.lpstrFile = _OFFSET(lpstrFile$)
  127.     OpenCall.nMaxFile = LEN(lpstrFile$) - 1
  128.     OpenCall.lpstrFileTitle = OpenCall.lpstrFile
  129.     OpenCall.nMaxFileTitle = OpenCall.nMaxFile
  130.     OpenCall.lpstrInitialDir = _OFFSET(InitialDir$)
  131.     OpenCall.lpstrTitle = _OFFSET(Title$)
  132.     OpenCall.lpstrDefExt = _OFFSET(lpstrDefExt$)
  133.     OpenCall.flags = Flags&
  134.  
  135.     Result = GetOpenFileNameA&&(OpenCall) '            Do Open File dialog call!
  136.  
  137.     IF Result THEN ' Trim the remaining zeros
  138.         GetOpenFileName$ = LEFT$(lpstrFile$, INSTR(lpstrFile$, CHR$(0)) - 1)
  139.         Flags& = OpenCall.flags
  140.         FilterIndex = OpenCall.nFilterIndex
  141.     END IF
  142.  
  143.  
  144. FUNCTION GetSaveFileName$ (Title$, InitialDir$, Filter$, FilterIndex, Flags&, hWnd%&)
  145.     '  Title$      - The dialog title.
  146.     '  InitialDir$ - If this left blank, it will use the directory where the last opened file is
  147.     '     located. Specify ".\" if you want to always use the current directory.
  148.     '  Filter$     - File filters separated by pipes (|) in the same format as VB6 common dialogs.
  149.     '  FilterIndex - The initial file filter to use. Will be altered by user during the call.
  150.     '  Flags&      - Dialog flags. Will be altered by the user during the call.
  151.     '  hWnd&       - Your program's window handle that should be aquired by the FindWindow function.
  152.  
  153.     ' Returns: Blank when cancel is clicked otherwise, the file name entered by the user.
  154.     ' FilterIndex and Flags& will be changed depending on the user's selections.
  155.  
  156.     DIM SaveCall AS FILEDIALOGTYPE ' Needed for dialog call
  157.  
  158.     fFilter$ = Filter$
  159.     FOR R = 1 TO LEN(fFilter$) ' Replace the pipes with zeros
  160.         IF MID$(fFilter$, R, 1) = "|" THEN MID$(fFilter$, R, 1) = CHR$(0)
  161.     NEXT R
  162.     fFilter$ = fFilter$ + CHR$(0)
  163.  
  164.     lpstrFile$ = STRING$(2048, 0) ' For the returned file name
  165.     lpstrDefExt$ = STRING$(10, 0) ' Extension will not be added when this is not specified
  166.     SaveCall.lStructSize = LEN(SaveCall)
  167.     SaveCall.hwndOwner = _OFFSET(hWnd%&)
  168.     SaveCall.lpstrFilter = _OFFSET(fFilter$)
  169.     SaveCall.nFilterIndex = FilterIndex
  170.     SaveCall.lpstrFile = _OFFSET(lpstrFile$)
  171.     SaveCall.nMaxFile = LEN(lpstrFile$) - 1
  172.     SaveCall.lpstrFileTitle = SaveCall.lpstrFile
  173.     SaveCall.nMaxFileTitle = SaveCall.nMaxFile
  174.     SaveCall.lpstrInitialDir = _OFFSET(InitialDir$)
  175.     SaveCall.lpstrTitle = _OFFSET(Title$)
  176.     SaveCall.lpstrDefExt = _OFFSET(lpstrDefExt$)
  177.     SaveCall.flags = Flags&
  178.  
  179.     Result& = GetSaveFileNameA&&(SaveCall) ' Do dialog call!
  180.  
  181.     IF Result& THEN ' Trim the remaining zeros
  182.         GetSaveFileName$ = LEFT$(lpstrFile$, INSTR(lpstrFile$, CHR$(0)) - 1)
  183.         Flags& = SaveCall.flags
  184.         FilterIndex = SaveCall.nFilterIndex
  185.     END IF
  186.  

(Unless I missed something else you changed besides the type...)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Opening files
« Reply #21 on: June 14, 2020, 02:47:24 pm »
Steve, here is upgraded your version (not work under 32 bit), this works.

See to source code,  some old 32 bit version can't  _WINDOWHANDLE function and  next repair is in row 178 in your source (OFFSET there is bad)

This is tested and working under 1.4 and 1.1

Code: QB64: [Select]
  1. ' Dialog flag constants (use + or OR to use more than 1 flag value)
  2. CONST OFN_ALLOWMULTISELECT = &H200& '  Allows the user to select more than one file, not recommended!
  3. CONST OFN_CREATEPROMPT = &H2000& '     Prompts if a file not found should be created(GetOpenFileName only).
  4. CONST OFN_EXTENSIONDIFFERENT = &H400& 'Allows user to specify file extension other than default extension.
  5. CONST OFN_FILEMUSTEXIST = &H1000& '    Chechs File name exists(GetOpenFileName only).
  6. CONST OFN_HIDEREADONLY = &H4& '        Hides read-only checkbox(GetOpenFileName only)
  7. CONST OFN_NOCHANGEDIR = &H8& '         Restores the current directory to original value if user changed
  8. CONST OFN_NODEREFERENCELINKS = &H100000& 'Returns path and file name of selected shortcut(.LNK) file instead of file referenced.
  9. CONST OFN_NONETWORKBUTTON = &H20000& ' Hides and disables the Network button.
  10. CONST OFN_NOREADONLYRETURN = &H8000& ' Prevents selection of read-only files, or files in read-only subdirectory.
  11. CONST OFN_NOVALIDATE = &H100& '        Allows invalid file name characters.
  12. CONST OFN_OVERWRITEPROMPT = &H2& '     Prompts if file already exists(GetSaveFileName only)
  13. CONST OFN_PATHMUSTEXIST = &H800& '     Checks Path name exists (set with OFN_FILEMUSTEXIST).
  14. CONST OFN_READONLY = &H1& '            Checks read-only checkbox. Returns if checkbox is checked
  15. CONST OFN_SHAREAWARE = &H4000& '       Ignores sharing violations in networking
  16. CONST OFN_SHOWHELP = &H10& '           Shows the help button (useless!)
  17. '--------------------------------------------------------------------------------------------
  18.  
  19. DEFINT A-Z
  20.  
  21. TYPE FILEDIALOGTYPE
  22.     $IF 32BIT THEN
  23.  
  24.     lStructSize AS LONG '        For the DLL call
  25.     hwndOwner AS LONG '          Dialog will hide behind window when not set correctly
  26.     hInstance AS LONG '          Handle to a module that contains a dialog box template.
  27.     lpstrFilter AS _OFFSET '     Pointer of the string of file filters
  28.     lpstrCustFilter AS _OFFSET
  29.     nMaxCustFilter AS LONG
  30.     nFilterIndex AS LONG '       One based starting filter index to use when dialog is called
  31.     lpstrFile AS _OFFSET '       String full of 0's for the selected file name
  32.     nMaxFile AS LONG '           Maximum length of the string stuffed with 0's minus 1
  33.     lpstrFileTitle AS _OFFSET '  Same as lpstrFile
  34.     nMaxFileTitle AS LONG '      Same as nMaxFile
  35.     lpstrInitialDir AS _OFFSET ' Starting directory
  36.     lpstrTitle AS _OFFSET '      Dialog title
  37.     flags AS LONG '              Dialog flags
  38.     nFileOffset AS INTEGER '     Zero-based offset from path beginning to file name string pointed to by lpstrFile
  39.     nFileExtension AS INTEGER '  Zero-based offset from path beginning to file extension string pointed to by lpstrFile.
  40.     lpstrDefExt AS _OFFSET '     Default/selected file extension
  41.     lCustData AS LONG
  42.     lpfnHook AS LONG
  43.     lpTemplateName AS _OFFSET
  44.     $ELSE
  45.         lStructSize AS LONG '           For the DLL call
  46.         hwndOwner AS _OFFSET '          Dialog will hide behind window when not set correctly
  47.         hInstance AS _OFFSET '          Handle to a module that contains a dialog box template.
  48.         lpstrFilter AS _OFFSET '        Pointer of the string of file filters
  49.         lpstrCustFilter AS LONG
  50.         nMaxCustFilter AS _INTEGER64
  51.         nFilterIndex AS _INTEGER64 '    One based starting filter index to use when dialog is called
  52.         lpstrFile AS _OFFSET '          String full of 0's for the selected file name
  53.         nMaxFile AS _INTEGER64 '        Maximum length of the string stuffed with 0's minus 1
  54.         lpstrFileTitle AS _OFFSET '     Same as lpstrFile
  55.         nMaxFileTitle AS _OFFSET '      Same as nMaxFile
  56.         lpstrInitialDir AS _OFFSET '    Starting directory
  57.         lpstrTitle AS _OFFSET '         Dialog title
  58.         flags AS _INTEGER64 '           Dialog flags
  59.         nFileOffset AS _INTEGER64 '     Zero-based offset from path beginning to file name string pointed to by lpstrFile
  60.         nFileExtension AS _INTEGER64 '  Zero-based offset from path beginning to file extension string pointed to by lpstrFile.
  61.         lpstrDefExt AS _OFFSET '        Default/selected file extension
  62.         lCustData AS _INTEGER64
  63.         lpfnHook AS _INTEGER64
  64.         lpTemplateName AS _INTEGER64
  65.     $END IF
  66.  
  67. DECLARE DYNAMIC LIBRARY "comdlg32" ' Library declarations using _OFFSET types
  68.     FUNCTION GetOpenFileNameA&& (DIALOGPARAMS AS FILEDIALOGTYPE) ' The Open file dialog
  69.     FUNCTION GetSaveFileNameA&& (DIALOGPARAMS AS FILEDIALOGTYPE) ' The Save file dialog
  70.  
  71.     FUNCTION FindWindow~&& (BYVAL ClassName AS _OFFSET, WindowName$) ' To get hWnd handle
  72.  
  73. _TITLE "FOCdemo" 'set Title of program
  74. $IF 64BIT THEN
  75.     hWnd = _WINDOWHANDLE 'FindWindow(0, "Open and Save Dialog demo" + CHR$(0)) 'get window handle using _TITLE string
  76.     hWnd&& = FindWindow(0, "FOCdemo" + CHR$(0)) 'get window handle using _TITLE string
  77. PRINT hWnd
  78. ' Do the Open File dialog call!
  79. Filter$ = "Batch files (*.bat)|*.BAT|JPEG images (*.jpg)|*.JPG|All files (*.*)|*.*"
  80. Flags& = OFN_FILEMUSTEXIST + OFN_NOCHANGEDIR + OFN_READONLY '    add flag constants here
  81. OFile$ = GetOpenFileName$("YEAH! Common Dialogs in QB64!!!", ".\", Filter$, 1, Flags&, hWnd&&)
  82.  
  83. IF OFile$ = "" THEN ' Display Open dialog results
  84.     PRINT "Shame on you! You didn't pick any file..."
  85.     PRINT "You picked this file: "
  86.     PRINT OFile$
  87.     IF (Flags& AND OFN_READONLY) THEN PRINT "Read-only checkbox checked." 'read-only value in return
  88.  
  89. _DELAY 5 ' Do the Save File dialog call!
  90. Filter$ = "Basic files (*.bas)|*.BAS|All files (*.*)|*.*"
  91. Flags& = OFN_OVERWRITEPROMPT + OFN_NOCHANGEDIR '   add flag constants here
  92. SFile$ = GetSaveFileName$("Save will not create a file!!!", ".\", Filter$, 1, Flags&, hWnd&&)
  93.  
  94. IF SFile$ = "" THEN ' Display Save dialog results
  95.     PRINT "You didn't save the file..."
  96.     PRINT "You saved this file: "
  97.     PRINT SFile$
  98.  
  99. FUNCTION GetOpenFileName$ (Title$, InitialDir$, Filter$, FilterIndex&, Flags&, hWnd AS _INTEGER64)
  100.     '  Title$      - The dialog title.
  101.     '  InitialDir$ - If this left blank, it will use the directory where the last opened file is
  102.     '  located. Specify ".\" if you want to always use the current directory.
  103.     '  Filter$     - File filters separated by pipes (|) in the same format as using VB6 common dialogs.
  104.     '  FilterIndex - The initial file filter to use. Will be altered by user during the call.
  105.     '  Flags&      - Dialog flags. Will be altered by the user during the call.
  106.     '  hWnd&       - Your program's window handle that should be aquired by the FindWindow function.
  107.     '
  108.     ' Returns: Blank when cancel is clicked otherwise, the file name selected by the user.
  109.     ' FilterIndex and Flags& will be changed depending on the user's selections.
  110.  
  111.     DIM OpenCall AS FILEDIALOGTYPE ' Needed for dialog call
  112.  
  113.     fFilter$ = Filter$
  114.     FOR R = 1 TO LEN(fFilter$) ' Replace the pipes with character zero
  115.         IF MID$(fFilter$, R, 1) = "|" THEN MID$(fFilter$, R, 1) = CHR$(0)
  116.     NEXT R
  117.     fFilter$ = fFilter$ + CHR$(0)
  118.  
  119.     lpstrFile$ = STRING$(2048, 0) ' For the returned file name
  120.     lpstrDefExt$ = STRING$(10, 0) ' Extension will not be added when this is not specified
  121.     OpenCall.lStructSize = LEN(OpenCall)
  122.     OpenCall.hwndOwner = hWnd&&
  123.     OpenCall.lpstrFilter = _OFFSET(fFilter$)
  124.     OpenCall.nFilterIndex = FilterIndex&
  125.     OpenCall.lpstrFile = _OFFSET(lpstrFile$)
  126.     OpenCall.nMaxFile = LEN(lpstrFile$) - 1
  127.     OpenCall.lpstrFileTitle = OpenCall.lpstrFile
  128.     OpenCall.nMaxFileTitle = OpenCall.nMaxFile
  129.     OpenCall.lpstrInitialDir = _OFFSET(InitialDir$)
  130.     OpenCall.lpstrTitle = _OFFSET(Title$)
  131.     OpenCall.lpstrDefExt = _OFFSET(lpstrDefExt$)
  132.     OpenCall.flags = Flags&
  133.  
  134.     Result = GetOpenFileNameA&&(OpenCall) '            Do Open File dialog call!
  135.  
  136.     IF Result THEN ' Trim the remaining zeros
  137.         GetOpenFileName$ = LEFT$(lpstrFile$, INSTR(lpstrFile$, CHR$(0)) - 1)
  138.         Flags& = OpenCall.flags
  139.         FilterIndex = OpenCall.nFilterIndex
  140.     END IF
  141.  
  142.  
  143. FUNCTION GetSaveFileName$ (Title$, InitialDir$, Filter$, FilterIndex, Flags&, hWnd&&)
  144.     '  Title$      - The dialog title.
  145.     '  InitialDir$ - If this left blank, it will use the directory where the last opened file is
  146.     '     located. Specify ".\" if you want to always use the current directory.
  147.     '  Filter$     - File filters separated by pipes (|) in the same format as VB6 common dialogs.
  148.     '  FilterIndex - The initial file filter to use. Will be altered by user during the call.
  149.     '  Flags&      - Dialog flags. Will be altered by the user during the call.
  150.     '  hWnd&       - Your program's window handle that should be aquired by the FindWindow function.
  151.  
  152.     ' Returns: Blank when cancel is clicked otherwise, the file name entered by the user.
  153.     ' FilterIndex and Flags& will be changed depending on the user's selections.
  154.  
  155.     DIM SaveCall AS FILEDIALOGTYPE ' Needed for dialog call
  156.  
  157.     fFilter$ = Filter$
  158.     FOR R = 1 TO LEN(fFilter$) ' Replace the pipes with zeros
  159.         IF MID$(fFilter$, R, 1) = "|" THEN MID$(fFilter$, R, 1) = CHR$(0)
  160.     NEXT R
  161.     fFilter$ = fFilter$ + CHR$(0)
  162.  
  163.     lpstrFile$ = STRING$(2048, 0) ' For the returned file name
  164.     lpstrDefExt$ = STRING$(10, 0) ' Extension will not be added when this is not specified
  165.     SaveCall.lStructSize = LEN(SaveCall)
  166.     SaveCall.hwndOwner = hWnd&&
  167.     SaveCall.lpstrFilter = _OFFSET(fFilter$)
  168.     SaveCall.nFilterIndex = FilterIndex
  169.     SaveCall.lpstrFile = _OFFSET(lpstrFile$)
  170.     SaveCall.nMaxFile = LEN(lpstrFile$) - 1
  171.     SaveCall.lpstrFileTitle = SaveCall.lpstrFile
  172.     SaveCall.nMaxFileTitle = SaveCall.nMaxFile
  173.     SaveCall.lpstrInitialDir = _OFFSET(InitialDir$)
  174.     SaveCall.lpstrTitle = _OFFSET(Title$)
  175.     SaveCall.lpstrDefExt = _OFFSET(lpstrDefExt$)
  176.     SaveCall.flags = Flags&
  177.  
  178.     Result& = GetSaveFileNameA&&(SaveCall) ' Do dialog call!
  179.  
  180.     IF Result& THEN ' Trim the remaining zeros
  181.         GetSaveFileName$ = LEFT$(lpstrFile$, INSTR(lpstrFile$, CHR$(0)) - 1)
  182.         Flags& = SaveCall.flags
  183.         FilterIndex = SaveCall.nFilterIndex
  184.     END IF
  185.  
« Last Edit: June 14, 2020, 02:50:09 pm by Petr »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Opening files
« Reply #22 on: June 14, 2020, 03:54:54 pm »
Quote
See to source code,  some old 32 bit version can't  _WINDOWHANDLE function and  next repair is in row 178 in your source (OFFSET there is bad)

Try inserting a small _DELAY in there before  the _WINDOWHANDLE.  It might correct the problem on older versions. _WINDOWHANDLE has been a part of the language for several years now.  (From 2017 onwards)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Opening files
« Reply #23 on: June 15, 2020, 01:41:25 pm »
I found a pretty big bug that I fixed with this version. In the previous case, the circled part in the 64-bit version was missing in the window. It's already there in this program version! (in both, 32 or 64 bit)

Code: QB64: [Select]
  1. ' Dialog flag constants (use + or OR to use more than 1 flag value)
  2. CONST OFN_ALLOWMULTISELECT = &H200& '  Allows the user to select more than one file, not recommended!
  3. CONST OFN_CREATEPROMPT = &H2000& '     Prompts if a file not found should be created(GetOpenFileName only).
  4. CONST OFN_EXTENSIONDIFFERENT = &H400& 'Allows user to specify file extension other than default extension.
  5. CONST OFN_FILEMUSTEXIST = &H1000& '    Chechs File name exists(GetOpenFileName only).
  6. CONST OFN_HIDEREADONLY = &H4& '        Hides read-only checkbox(GetOpenFileName only)
  7. CONST OFN_NOCHANGEDIR = &H8& '         Restores the current directory to original value if user changed
  8. CONST OFN_NODEREFERENCELINKS = &H100000& 'Returns path and file name of selected shortcut(.LNK) file instead of file referenced.
  9. CONST OFN_NONETWORKBUTTON = &H20000& ' Hides and disables the Network button.
  10. CONST OFN_NOREADONLYRETURN = &H8000& ' Prevents selection of read-only files, or files in read-only subdirectory.
  11. CONST OFN_NOVALIDATE = &H100& '        Allows invalid file name characters.
  12. CONST OFN_OVERWRITEPROMPT = &H2& '     Prompts if file already exists(GetSaveFileName only)
  13. CONST OFN_PATHMUSTEXIST = &H800& '     Checks Path name exists (set with OFN_FILEMUSTEXIST).
  14. CONST OFN_READONLY = &H1& '            Checks read-only checkbox. Returns if checkbox is checked
  15. CONST OFN_SHAREAWARE = &H4000& '       Ignores sharing violations in networking
  16. CONST OFN_SHOWHELP = &H10& '           Shows the help button (useless!)
  17. '--------------------------------------------------------------------------------------------
  18.  
  19. DEFINT A-Z
  20.  
  21. TYPE FILEDIALOGTYPE
  22.     $IF 32BIT THEN
  23.  
  24.     lStructSize AS LONG '        For the DLL call
  25.     hwndOwner AS LONG '          Dialog will hide behind window when not set correctly
  26.     hInstance AS LONG '          Handle to a module that contains a dialog box template.
  27.     lpstrFilter AS _OFFSET '     Pointer of the string of file filters
  28.     lpstrCustFilter AS _OFFSET
  29.     nMaxCustFilter AS LONG
  30.     nFilterIndex AS LONG '       One based starting filter index to use when dialog is called
  31.     lpstrFile AS _OFFSET '       String full of 0's for the selected file name
  32.     nMaxFile AS LONG '           Maximum length of the string stuffed with 0's minus 1
  33.     lpstrFileTitle AS _OFFSET '  Same as lpstrFile
  34.     nMaxFileTitle AS LONG '      Same as nMaxFile
  35.     lpstrInitialDir AS _OFFSET ' Starting directory
  36.     lpstrTitle AS _OFFSET '      Dialog title
  37.     flags AS LONG '              Dialog flags
  38.     nFileOffset AS INTEGER '     Zero-based offset from path beginning to file name string pointed to by lpstrFile
  39.     nFileExtension AS INTEGER '  Zero-based offset from path beginning to file extension string pointed to by lpstrFile.
  40.     lpstrDefExt AS _OFFSET '     Default/selected file extension
  41.     lCustData AS LONG
  42.     lpfnHook AS LONG
  43.     lpTemplateName AS _OFFSET
  44.     $ELSE
  45.         lStructSize AS _OFFSET '           For the DLL call
  46.         hwndOwner AS _OFFSET '          Dialog will hide behind window when not set correctly
  47.         hInstance AS _OFFSET '          Handle to a module that contains a dialog box template.
  48.         lpstrFilter AS _OFFSET '        Pointer of the string of file filters
  49.         lpstrCustFilter AS LONG
  50.         nMaxCustFilter AS LONG
  51.         nFilterIndex AS _INTEGER64 '    One based starting filter index to use when dialog is called
  52.         lpstrFile AS _OFFSET '          String full of 0's for the selected file name
  53.         nMaxFile AS _OFFSET '        Maximum length of the string stuffed with 0's minus 1
  54.         lpstrFileTitle AS _OFFSET '     Same as lpstrFile
  55.         nMaxFileTitle AS _OFFSET '      Same as nMaxFile
  56.         lpstrInitialDir AS _OFFSET '    Starting directory
  57.         lpstrTitle AS _OFFSET '         Dialog title
  58.         flags AS _INTEGER64 '           Dialog flags
  59.         nFileOffset AS _INTEGER64 '     Zero-based offset from path beginning to file name string pointed to by lpstrFile
  60.         nFileExtension AS _INTEGER64 '  Zero-based offset from path beginning to file extension string pointed to by lpstrFile.
  61.         lpstrDefExt AS _OFFSET '        Default/selected file extension
  62.         lCustData AS _INTEGER64
  63.         lpfnHook AS _INTEGER64
  64.         lpTemplateName AS _OFFSET
  65.     $END IF
  66.  
  67. DECLARE DYNAMIC LIBRARY "comdlg32" ' Library declarations using _OFFSET types
  68.     FUNCTION GetOpenFileNameA&& (DIALOGPARAMS AS FILEDIALOGTYPE) ' The Open file dialog
  69.     FUNCTION GetSaveFileNameA&& (DIALOGPARAMS AS FILEDIALOGTYPE) ' The Save file dialog
  70.  
  71.     FUNCTION FindWindow~&& (BYVAL ClassName AS _OFFSET, WindowName$) ' To get hWnd handle
  72.  
  73. _TITLE "FOCdemo" 'set Title of program
  74. $IF 64BIT THEN
  75.     hWnd = _WINDOWHANDLE 'FindWindow(0, "Open and Save Dialog demo" + CHR$(0)) 'get window handle using _TITLE string
  76.     hWnd&& = FindWindow(0, "FOCdemo" + CHR$(0)) 'get window handle using _TITLE string
  77. PRINT hWnd
  78. ' Do the Open File dialog call!
  79. Filter$ = "Batch files (*.bat)|*.BAT|JPEG images (*.jpg)|*.JPG|All files (*.*)|*.*"
  80. Flags& = OFN_FILEMUSTEXIST + OFN_NOCHANGEDIR + OFN_READONLY '    add flag constants here
  81. OFile$ = GetOpenFileName$("YEAH! Common Dialogs in QB64!!!", ".\", Filter$, 1, Flags&, hWnd&&)
  82.  
  83. IF OFile$ = "" THEN ' Display Open dialog results
  84.     PRINT "Shame on you! You didn't pick any file..."
  85.     PRINT "You picked this file: "
  86.     PRINT OFile$
  87.     IF (Flags& AND OFN_READONLY) THEN PRINT "Read-only checkbox checked." 'read-only value in return
  88.  
  89. _DELAY 5 ' Do the Save File dialog call!
  90. Filter$ = "Basic files (*.bas)|*.BAS|All files (*.*)|*.*"
  91. Flags& = OFN_OVERWRITEPROMPT + OFN_NOCHANGEDIR '   add flag constants here
  92. SFile$ = GetSaveFileName$("Save will not create a file!!!", ".\", Filter$, 1, Flags&, hWnd&&)
  93.  
  94. IF SFile$ = "" THEN ' Display Save dialog results
  95.     PRINT "You didn't save the file..."
  96.     PRINT "You saved this file: "
  97.     PRINT SFile$
  98.  
  99. FUNCTION GetOpenFileName$ (Title$, InitialDir$, Filter$, FilterIndex&, Flags&, hWnd AS _INTEGER64)
  100.     '  Title$      - The dialog title.
  101.     '  InitialDir$ - If this left blank, it will use the directory where the last opened file is
  102.     '  located. Specify ".\" if you want to always use the current directory.
  103.     '  Filter$     - File filters separated by pipes (|) in the same format as using VB6 common dialogs.
  104.     '  FilterIndex - The initial file filter to use. Will be altered by user during the call.
  105.     '  Flags&      - Dialog flags. Will be altered by the user during the call.
  106.     '  hWnd&       - Your program's window handle that should be aquired by the FindWindow function.
  107.     '
  108.     ' Returns: Blank when cancel is clicked otherwise, the file name selected by the user.
  109.     ' FilterIndex and Flags& will be changed depending on the user's selections.
  110.  
  111.     DIM OpenCall AS FILEDIALOGTYPE ' Needed for dialog call
  112.  
  113.     fFilter$ = Filter$
  114.     FOR R = 1 TO LEN(fFilter$) ' Replace the pipes with character zero
  115.         IF MID$(fFilter$, R, 1) = "|" THEN MID$(fFilter$, R, 1) = CHR$(0)
  116.     NEXT R
  117.     fFilter$ = fFilter$ + CHR$(0)
  118.  
  119.     lpstrFile$ = STRING$(2048, 0) ' For the returned file name
  120.     lpstrDefExt$ = STRING$(10, 0) ' Extension will not be added when this is not specified
  121.     OpenCall.lStructSize = LEN(OpenCall)
  122.     OpenCall.hwndOwner = hWnd&&
  123.     OpenCall.lpstrFilter = _OFFSET(fFilter$)
  124.     OpenCall.nFilterIndex = FilterIndex&
  125.     OpenCall.lpstrFile = _OFFSET(lpstrFile$)
  126.     OpenCall.nMaxFile = LEN(lpstrFile$) - 1
  127.     OpenCall.lpstrFileTitle = OpenCall.lpstrFile
  128.     OpenCall.nMaxFileTitle = OpenCall.nMaxFile
  129.     OpenCall.lpstrInitialDir = _OFFSET(InitialDir$)
  130.     OpenCall.lpstrTitle = _OFFSET(Title$)
  131.     OpenCall.lpstrDefExt = _OFFSET(lpstrDefExt$)
  132.     OpenCall.flags = Flags&
  133.  
  134.     Result = GetOpenFileNameA&&(OpenCall) '            Do Open File dialog call!
  135.  
  136.     IF Result THEN ' Trim the remaining zeros
  137.         GetOpenFileName$ = LEFT$(lpstrFile$, INSTR(lpstrFile$, CHR$(0)) - 1)
  138.         Flags& = OpenCall.flags
  139.         FilterIndex = OpenCall.nFilterIndex
  140.     END IF
  141.  
  142.  
  143. FUNCTION GetSaveFileName$ (Title$, InitialDir$, Filter$, FilterIndex, Flags&, hWnd&&)
  144.     '  Title$      - The dialog title.
  145.     '  InitialDir$ - If this left blank, it will use the directory where the last opened file is
  146.     '     located. Specify ".\" if you want to always use the current directory.
  147.     '  Filter$     - File filters separated by pipes (|) in the same format as VB6 common dialogs.
  148.     '  FilterIndex - The initial file filter to use. Will be altered by user during the call.
  149.     '  Flags&      - Dialog flags. Will be altered by the user during the call.
  150.     '  hWnd&       - Your program's window handle that should be aquired by the FindWindow function.
  151.  
  152.     ' Returns: Blank when cancel is clicked otherwise, the file name entered by the user.
  153.     ' FilterIndex and Flags& will be changed depending on the user's selections.
  154.  
  155.     DIM SaveCall AS FILEDIALOGTYPE ' Needed for dialog call
  156.  
  157.     fFilter$ = Filter$
  158.     FOR R = 1 TO LEN(fFilter$) ' Replace the pipes with zeros
  159.         IF MID$(fFilter$, R, 1) = "|" THEN MID$(fFilter$, R, 1) = CHR$(0)
  160.     NEXT R
  161.     fFilter$ = fFilter$ + CHR$(0)
  162.  
  163.     lpstrFile$ = STRING$(2048, 0) ' For the returned file name
  164.     lpstrDefExt$ = STRING$(10, 0) ' Extension will not be added when this is not specified
  165.     SaveCall.lStructSize = LEN(SaveCall)
  166.     SaveCall.hwndOwner = hWnd&&
  167.     SaveCall.lpstrFilter = _OFFSET(fFilter$)
  168.     SaveCall.nFilterIndex = FilterIndex
  169.     SaveCall.lpstrFile = _OFFSET(lpstrFile$)
  170.     SaveCall.nMaxFile = LEN(lpstrFile$) - 1
  171.     SaveCall.lpstrFileTitle = SaveCall.lpstrFile
  172.     SaveCall.nMaxFileTitle = SaveCall.nMaxFile
  173.     SaveCall.lpstrInitialDir = _OFFSET(InitialDir$)
  174.     SaveCall.lpstrTitle = _OFFSET(Title$)
  175.     SaveCall.lpstrDefExt = _OFFSET(lpstrDefExt$)
  176.     SaveCall.flags = Flags&
  177.  
  178.     Result& = GetSaveFileNameA&&(SaveCall) ' Do dialog call!
  179.  
  180.     IF Result& THEN ' Trim the remaining zeros
  181.         GetSaveFileName$ = LEFT$(lpstrFile$, INSTR(lpstrFile$, CHR$(0)) - 1)
  182.         Flags& = SaveCall.flags
  183.         FilterIndex = SaveCall.nFilterIndex
  184.     END IF
  185.  

  [ You are not allowed to view this attachment ]  

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Opening files
« Reply #24 on: June 15, 2020, 03:20:23 pm »
Yeah I noticed that the file filter doesn't work in the 64 bit version. What is the fix for that?
Shuwatch!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Opening files
« Reply #25 on: June 15, 2020, 04:04:15 pm »
Data type in field FIELDDIALOGTYPE for 64 bit version was wrong. Now it is repaired.

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Opening files
« Reply #26 on: June 16, 2020, 07:44:49 am »
Data type in field FIELDDIALOGTYPE for 64 bit version was wrong. Now it is repaired.
When I use the above code in an InForm program the file filter only works in 32 bit. I discovered that the issue must have been the DEFINT A-Z that was causing an issue for this. I removed that and it suddenly worked. Thank you all so much.
Shuwatch!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Opening files
« Reply #27 on: June 16, 2020, 11:35:04 am »
When I use the above code in an InForm program the file filter only works in 32 bit. I discovered that the issue must have been the DEFINT A-Z that was causing an issue for this. I removed that and it suddenly worked. Thank you all so much.

Ah the power of habit, so powerful when it saves us time from considering every little thing and leaves us blind when it works against our goals.

Good one to put on your debugging list: "Default Types" along with Typos and notes about INKEY$ and IF logic cautions (a whole sublist special cases for keywords) and what _LOADFILE returns when fails.

Have you started your list?  ;)

Oh,  from last night the problem _DISPLAY and  the cure _AUTODISPLAY
« Last Edit: June 16, 2020, 11:37:24 am by bplus »