Author Topic: _WINDOWHANDLE should return an _OFFSET  (Read 2708 times)

0 Members and 1 Guest are viewing this topic.

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
_WINDOWHANDLE should return an _OFFSET
« on: June 14, 2020, 08:16:54 am »
at the moment _WINDOWHANDLE returns an unsigned long which makes it unusable in 64-bit, is there a work-around?
« Last Edit: June 14, 2020, 08:18:19 am by jack »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
Re: _WINDOWHANDLE should return an _OFFSET
« Reply #1 on: June 14, 2020, 08:58:25 am »
Hi.

Try this:

Code: QB64: [Select]
  1.     FUNCTION FindWindow& (BYVAL ClassName AS _OFFSET, WindowName$)
  2.  
  3. _TITLE "My Window"
  4. hwnd& =  FindWindow(0, "My Window" + CHR$(0))
  5.  

 
« Last Edit: June 14, 2020, 10:41:58 am by Petr »

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
Re: _WINDOWHANDLE should return an _OFFSET
« Reply #2 on: June 14, 2020, 09:08:02 am »
thanks Petr, but I don't like prerequisite of the Window title, makes it unsuitable for a replacement of _WINDOWHANDLE
not only that but it won't work with 64-bit even if it's declared as
Code: [Select]
DECLARE LIBRARY
    FUNCTION FindWindow~&& (BYVAL ClassName AS _OFFSET, WindowName$) ' To get hWnd handle
END DECLARE
it looks like trying to use the WinAPI from 64-bit QB64 is severely limited
« Last Edit: June 14, 2020, 09:23:50 am by jack »

FellippeHeitor

  • Guest
Re: _WINDOWHANDLE should return an _OFFSET
« Reply #3 on: June 14, 2020, 10:01:14 am »
I was almost certain _WINDOWHANDLE had been fixed to work properly for 64bit Windows versions. I'll check it out to see what was left buggy behind.
« Last Edit: June 14, 2020, 11:01:14 am by FellippeHeitor »

FellippeHeitor

  • Guest
Re: _WINDOWHANDLE should return an _OFFSET
« Reply #4 on: June 14, 2020, 11:07:20 am »
What kind of errors did you run into while trying to use _WINDOWHANDLE on a 64bit environment?

I'm asking because I just ran the code sample from the _WINDOWHANDLE wiki page (copied below) in my 64bit version of QB64 under Windows 10, with no issues:

  [ You are not allowed to view this attachment ]  

Code: QB64: [Select]
  1. 'Message Box Constant values as defined by Microsoft (MBType)
  2. CONST MB_OK& = 0                'OK button only
  3. CONST MB_OKCANCEL& = 1          'OK & Cancel
  4. CONST MB_ABORTRETRYIGNORE& = 2  'Abort, Retry & Ignore
  5. CONST MB_YESNOCANCEL& = 3       'Yes, No & Cancel
  6. CONST MB_YESNO& = 4             'Yes & No
  7. CONST MB_RETRYCANCEL& = 5       'Retry & Cancel
  8. CONST MB_CANCELTRYCONTINUE& = 6 'Cancel, Try Again & Continue
  9. CONST MB_ICONSTOP& = 16         'Error stop sign icon
  10. CONST MB_ICONQUESTION& = 32     'Question-mark icon
  11. CONST MB_ICONEXCLAMATION& = 48  'Exclamation-point icon
  12. CONST MB_ICONINFORMATION& = 64  'Letter i in a circle icon
  13. CONST MB_DEFBUTTON1& = 0        '1st button default(left)
  14. CONST MB_DEFBUTTON2& = 256      '2nd button default
  15. CONST MB_DEFBUTTON3& = 512      '3rd button default(right)
  16. CONST MB_APPLMODAL& = 0         'Message box applies to application only
  17. CONST MB_SYSTEMMODAL& = 4096    'Message box on top of all other windows
  18. CONST MB_SETFOCUS& = 65536      'Set message box as focus
  19. CONST IDOK& = 1                 'OK button pressed
  20. CONST IDCANCEL& = 2             'Cancel button pressed
  21. CONST IDABORT& = 3              'Abort button pressed
  22. CONST IDRETRY& = 4              'Retry button pressed
  23. CONST IDIGNORE& = 5             'Ignore button pressed
  24. CONST IDYES& = 6                'Yes button pressed
  25. CONST IDNO& = 7                 'No button pressed
  26. CONST IDTRYAGAIN& = 10          'Try again button pressed
  27. CONST IDCONTINUE& = 1           'Continue button pressed
  28. '----------------------------------------------------------------------------------------
  29.  
  30. FUNCTION MessageBoxA& (BYVAL hwnd AS LONG, Message AS STRING, Title AS STRING, BYVAL MBType AS _UNSIGNED LONG)
  31.  
  32.   msg& = 0: icon& = 0: DB& = 0
  33.   INPUT "Enter Message Box type(0 to 6 other Quits): ", BOX&
  34.   IF BOX& < 0 OR BOX& > 6 THEN EXIT DO
  35.  
  36.   INPUT "Enter Icon&(0=none, 1=stop, 2=?, 3=!, 4=info): ", Icon&
  37.  
  38.   IF BOX& THEN INPUT "Enter Default Button(1st, 2nd or 3rd): ", DB&
  39.   IF DB& THEN DB& = DB& - 1     'adjust value to 0, 1, or 2
  40.   msg& = MsgBox&("Box Title", "Box text message", BOX&, Icon&, DB&, 4096) 'on top of all windows
  41.  
  42.   PRINT "Button ="; msg&
  43.  
  44. FUNCTION MsgBox& (Title$, Message$, BoxType&, Icon&, DBtn&, Mode&)
  45. SELECT CASE Icon&
  46.   CASE 1: Icon& = MB_ICONSTOP&          'warning X-sign icon
  47.   CASE 2: Icon& = MB_ICONQUESTION&      'question-mark icon
  48.   CASE 3: Icon& = MB_ICONEXCLAMATION&   'exclamation-point icon
  49.   CASE 4: Icon& = MB_ICONINFORMATION&   'lowercase letter i in circle
  50.   CASE ELSE: Icon& = 0 'no icon
  51. IF BoxType& > 0 AND DBtn& > 0 THEN 'set default button as 2nd(256) or 3rd(512)
  52.   SELECT CASE BoxType&    
  53.     CASE 2, 3, 6
  54.      IF DBtn& = 2 THEN Icon& = Icon& + MB_DEFBUTTON3& ELSE Icon& = Icon& + MB_DEFBUTTON2& '3 button
  55.     CASE ELSE: Icon& = Icon& + MB_DEFBUTTON2& '2nd button default
  56. Focus& = MB_SetFocus&
  57. MsgBox& = MessageBoxA&(_WINDOWHANDLE, Message$, Title$, BoxType& + Icon& + Mode& + Focus&) 'focus on button

Offline Qwerkey

  • Forum Resident
  • Posts: 755
Re: _WINDOWHANDLE should return an _OFFSET
« Reply #5 on: June 14, 2020, 11:54:27 am »
I am afraid that I'm going to embarrass myself with my ignorance.  Wiki says that _WINDOWHANDLE returns an UNSIGNED LONG.  An UNSIGNED LONG is 4 bytes or 32 bits (4,294,967,296) so can be handled in a 64-bit system, so what's the problem?  In his Inform, Fellippe uses UNSIGNED LONG for his control IDs and there is no incompatibility with 64-bit processing (as far as I'm aware).  Colours are 32-bit and they're OK as well.  It's my lack of understanding of the simple things that makes me feel fraudulent appearing at this website.  I think that I'll change my hobby to home-crafting cloth face masks.
« Last Edit: June 14, 2020, 12:02:20 pm by Qwerkey »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: _WINDOWHANDLE should return an _OFFSET
« Reply #6 on: June 14, 2020, 12:08:42 pm »
To solve any confusion, let's go to the source: libqb.cpp:


Code: [Select]
int64 func__handle(){
    #ifdef QB64_GUI
        #ifdef QB64_WINDOWS
            while (!window_handle){Sleep(100);}
            return (ptrszint)window_handle;
        #endif
    #endif
   
    return 0;
}

The above is our function _WINDOWHANDLE, as it translates into c for us. As you can see, it is defined as an INT64 by default (not a LONG or UNSIGNED LONG), with the int64 func__handle

As for the return (ptrszint)window_handle;, that's basically our way of taking the OFFSET (ptrszint), converting it to an integer64, and then returning the value for us. 

There's no workaround to 32-bit values, as the routine is already returning 64-bits for us. 



In qb64\source\subs_functions\subs_functions.bas, we also see the following code in QB64 itself:

Code: [Select]
clearid
id.n = qb64prefix$ + "WINDOWHANDLE"
id.subfunc = 1
id.callname = "func__handle"
id.ret = INTEGER64TYPE - ISPOINTER
regid

As you can see from the id.ret (id return type), we're returning an integer64 -- not an int32 -- with the function.



Seems the wiki is simply out of date and hasn't caught up with the changes which were made back when we started offering the 64-bit versions.  Somebody might want to go in and change it.  (If nobody else does, I will later, once I hunt down my wiki credentials once again -- I just got my new PC back up and running and all my old passwords and such didn't transfer over properly.  /sigh)
« Last Edit: June 14, 2020, 12:17:38 pm by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

FellippeHeitor

  • Guest
Re: _WINDOWHANDLE should return an _OFFSET
« Reply #7 on: June 14, 2020, 12:18:54 pm »
So it's just a matter of updating the wiki. Text there must be from before these patches were added.

Still wonder if Jack encountered issues or just  didn't try the samples cause of the bad wiki text.

@SMcNeill let me know if you need wiki credentials reset.
« Last Edit: June 14, 2020, 12:24:01 pm by FellippeHeitor »

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
Re: _WINDOWHANDLE should return an _OFFSET
« Reply #8 on: June 14, 2020, 12:36:36 pm »
@FellippeHeitor and SMcNeill
first off, thank you for your prompt and courteous help, second I am embarrassed to say that when I looked at the info in the wiki page and printing the result of _WINDOWHANDLE it led me to believe that it was returning a long, my apologies.
the example I can't get to work in 64-bit is the "FileOpen Common Dialog demo" found at https://www.qb64.org/wiki/Windows_Libraries
I tried changing hwndOwner to _offset and _integer64 but no luck

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: _WINDOWHANDLE should return an _OFFSET
« Reply #9 on: June 14, 2020, 12:48:36 pm »
@FellippeHeitor and SMcNeill
first off, thank you for your prompt and courteous help, second I am embarrassed to say that when I looked at the info in the wiki page and printing the result of _WINDOWHANDLE it led me to believe that it was returning a long, my apologies.
the example I can't get to work in 64-bit is the "FileOpen Common Dialog demo" found at https://www.qb64.org/wiki/Windows_Libraries
I tried changing hwndOwner to _offset and _integer64 but no luck


As I've explained elsewhere on the forums, the issue here is because of the difference in how 32-bit and 64-bit systems pack data into their data structures.  In 32-bit systems, the data is packed in 4-byte segments.  In 64-bit systems, it's packed into 8-byte segments (usually, by default, unless somebody has tweaked compiler settings otherwise...)

The issue comes with things such as:

TYPE FILEDIALOGTYPE
  lStructSize AS LONG '        For the DLL call
  hwndOwner AS LONG '          Dialog will hide behind window when not set correctly
  hInstance AS LONG '          Handle to a module that contains a dialog box template.
  lpstrFilter AS _OFFSET '     Pointer of the string of file filters

If you look at the above, the lStructSize and hwindOwner are LONGs... Since both of these are 4bytes each, they'd probably pack together, form an 8-byte data structure, and be fine.

hIsntance is a long, ipstrFiler is an _OFFSET, and in this case, that's a total of 12-bytes....  64-bit systems pack data into 8-byte "chunks", so there's got to be some filler in there somewhere...  (Whether that 4 bytes needs to be *before* hInstance, or *after*, I'm not certain, off the top of my head.  Testing and experimentation would need to ensue.)

For a working example of the issue, take a look at the Windows Printer API and the changes necessary for it to work in 32 vs 64 bit OSes here: https://www.qb64.org/forum/index.php?topic=1858.msg110954#msg110954

(Or, if you just want to look at the types themselves to compare where I changed them, they're these:

Code: [Select]
$IF 32BIT THEN
    TYPE PRINTDLGEX
    lStructSize AS _UNSIGNED LONG
    hwndOwner AS _UNSIGNED _OFFSET ' HWND
    hDevMode AS _UNSIGNED _OFFSET ' HGLOBAL
    hDevNames AS _UNSIGNED _OFFSET ' HGLOBAL
    hDC AS _UNSIGNED _OFFSET ' HDC
    Flags AS _UNSIGNED LONG
    Flags2 AS _UNSIGNED LONG
    ExclusionFlags AS _UNSIGNED LONG
    nPageRanges AS _UNSIGNED LONG
    nMaxPageRanges AS _UNSIGNED LONG
    lpPageRanges AS _UNSIGNED _OFFSET ' LPPRINTPAGERANGE
    nMinPage AS _UNSIGNED LONG
    nMaxPage AS _UNSIGNED LONG
    nCopies AS _UNSIGNED LONG
    hInstance AS _UNSIGNED _OFFSET ' HINSTANCE
    lpPrintTemplateName AS _UNSIGNED _OFFSET ' LPCSTR
    lpCallback AS _UNSIGNED _OFFSET ' LPUNKNOWN
    nPropertyPages AS _UNSIGNED LONG
    lphPropertyPages AS _UNSIGNED _OFFSET ' HPROPSHEETPAGE *
    nStartPage AS _UNSIGNED LONG
    dwResultAction AS _UNSIGNED LONG
    END TYPE
$ELSE
    TYPE PRINTDLGEX
        lStructSize AS _UNSIGNED _INTEGER64
        hwndOwner AS _UNSIGNED _OFFSET ' HWND
        hDevMode AS _UNSIGNED _OFFSET ' HGLOBAL
        hDevNames AS _UNSIGNED _OFFSET ' HGLOBAL
        hDC AS _UNSIGNED _OFFSET ' HDC
        Flags AS _UNSIGNED LONG
        Flags2 AS _UNSIGNED LONG
        ExclusionFlags AS _UNSIGNED LONG
        nPageRanges AS _UNSIGNED LONG
        nMaxPageRanges AS _UNSIGNED _INTEGER64
        lpPageRanges AS _UNSIGNED _OFFSET ' LPPRINTPAGERANGE
        nMinPage AS _UNSIGNED LONG
        nMaxPage AS _UNSIGNED LONG
        nCopies AS _UNSIGNED _INTEGER64 'LONG
        hInstance AS _UNSIGNED _OFFSET ' HINSTANCE
        lpPrintTemplateName AS _UNSIGNED _OFFSET ' LPCSTR
        lpCallback AS _UNSIGNED _OFFSET ' LPUNKNOWN
        nPropertyPages AS _UNSIGNED _INTEGER64 'LONG
        lphPropertyPages AS _UNSIGNED _OFFSET ' HPROPSHEETPAGE *
        nStartPage AS _UNSIGNED LONG
        dwResultAction AS _UNSIGNED LONG
    END TYPE
$END IF

It's not the handle that's giving you the issue; it's the data structure isn't aligning properly for you, giving you invalid results.

Someone needs to sit down and experiment to pad the properly spaces into the 32-bit structure so that it'll compile and work properly for 64-bit window systems. ;)



To highlight the changes even better, just look at the first few lines of the data type structure:

32-bit:

    TYPE PRINTDLGEX
        lStructSize AS LONG
        hwndOwner AS _UNSIGNED _OFFSET ' HWND

64-bit:

    TYPE PRINTDLGEX
        lStructSize AS _UNSIGNED _INTEGER64
        hwndOwner AS _UNSIGNED _OFFSET ' HWND

lStructSize can be 4-bytes in the 32-bit version, as the data structures align every 4-bytes, but for the 64-bit versions, it's 4 bytes and then 4 bytes of padding (which I just read as an int64 which will always have 4 bytes of 0 padding the beginning of it), which makes it align to the 8-byte structure the system wants.
« Last Edit: June 14, 2020, 12:53:52 pm by SMcNeill »
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.
Re: _WINDOWHANDLE should return an _OFFSET
« Reply #10 on: June 14, 2020, 12:58:34 pm »
Jack wrote:

Quote
the example I can't get to work in 64-bit is the "FileOpen Common Dialog demo" found at https://www.qb64.org/wiki/Windows_Libraries

That you read the Open files thread? :) Well, it's weird. I tried everything possible, but illogically, I couldn't run it in 64-bit QB64.

https://www.qb64.org/forum/index.php?topic=2689.msg119203#msg119203

  Interestingly, for the second source code (folder selection), it was enough to change the HwndOwner from the LONG type to the _INTEGER64 type in the BROWSEINFO struct (and it also works with the _OFFSET type) and this program was then run in a 64-bit version.

I assume that some data type in the struct FILEDIALOGTYPE of the first program in the thread I am referring to will probably not be of type LONG, but larger, either OFFSET or INTEGER64. But I have no idea (not the slightest) which of the components in the filedialogtype struct it could be.

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
Re: _WINDOWHANDLE should return an _OFFSET
« Reply #11 on: June 14, 2020, 01:41:54 pm »
hi Petr
I will checkout your link asap, but first here's the demo with corrections to the FILEDIALOGTYPE structure
Code: [Select]
' Dialog flag constants (use + or OR to use more than 1 flag value)
CONST OFN_ALLOWMULTISELECT = &H200& '  Allows the user to select more than one file, not recommended!
CONST OFN_CREATEPROMPT = &H2000& '     Prompts if a file not found should be created(GetOpenFileName only).
CONST OFN_EXTENSIONDIFFERENT = &H400& 'Allows user to specify file extension other than default extension.
CONST OFN_FILEMUSTEXIST = &H1000& '    Chechs File name exists(GetOpenFileName only).
CONST OFN_HIDEREADONLY = &H4& '        Hides read-only checkbox(GetOpenFileName only)
CONST OFN_NOCHANGEDIR = &H8& '         Restores the current directory to original value if user changed
CONST OFN_NODEREFERENCELINKS = &H100000& 'Returns path and file name of selected shortcut(.LNK) file instead of file referenced.
CONST OFN_NONETWORKBUTTON = &H20000& ' Hides and disables the Network button.
CONST OFN_NOREADONLYRETURN = &H8000& ' Prevents selection of read-only files, or files in read-only subdirectory.
CONST OFN_NOVALIDATE = &H100& '        Allows invalid file name characters.
CONST OFN_OVERWRITEPROMPT = &H2& '     Prompts if file already exists(GetSaveFileName only)
CONST OFN_PATHMUSTEXIST = &H800& '     Checks Path name exists (set with OFN_FILEMUSTEXIST).
CONST OFN_READONLY = &H1& '            Checks read-only checkbox. Returns if checkbox is checked
CONST OFN_SHAREAWARE = &H4000& '       Ignores sharing violations in networking
CONST OFN_SHOWHELP = &H10& '           Shows the help button (useless!)
'--------------------------------------------------------------------------------------------

DEFINT A-Z

TYPE FILEDIALOGTYPE
    lStructSize AS LONG '        For the DLL call
    hwndOwner AS _OFFSET '          Dialog will hide behind window when not set correctly
    hInstance AS _OFFSET '          Handle to a module that contains a dialog box template.
    lpstrFilter AS _OFFSET '     Pointer of the string of file filters
    lpstrCustFilter AS _OFFSET
    nMaxCustFilter AS LONG
    nFilterIndex AS LONG '       One based starting filter index to use when dialog is called
    lpstrFile AS _OFFSET '       String full of 0's for the selected file name
    nMaxFile AS LONG '           Maximum length of the string stuffed with 0's minus 1
    lpstrFileTitle AS _OFFSET '  Same as lpstrFile
    nMaxFileTitle AS LONG '      Same as nMaxFile
    lpstrInitialDir AS _OFFSET ' Starting directory
    lpstrTitle AS _OFFSET '      Dialog title
    flags AS LONG '              Dialog flags
    nFileOffset AS INTEGER '     Zero-based offset from path beginning to file name string pointed to by lpstrFile
    nFileExtension AS INTEGER '  Zero-based offset from path beginning to file extension string pointed to by lpstrFile.
    lpstrDefExt AS _OFFSET '     Default/selected file extension
    lCustData AS _INTEGER64
    lpfnHook AS _UNSIGNED _OFFSET
    lpTemplateName AS _OFFSET
END TYPE

DECLARE DYNAMIC LIBRARY "comdlg32" ' Library declarations using _OFFSET types
    FUNCTION GetOpenFileNameA& (DIALOGPARAMS AS FILEDIALOGTYPE) ' The Open file dialog
    FUNCTION GetSaveFileNameA& (DIALOGPARAMS AS FILEDIALOGTYPE) ' The Save file dialog
END DECLARE

DECLARE LIBRARY
    FUNCTION FindWindow~&& (BYVAL ClassName AS _OFFSET, WindowName$) ' To get hWnd handle
END DECLARE

_TITLE "FOCdemo" 'set Title of program
'DIM hWnd AS _UNSIGNED _INTEGER64
hWnd%& = _WINDOWHANDLE 'FindWindow(0, "Open and Save Dialog demo" + CHR$(0)) 'get window handle using _TITLE string
'hWnd~&& = FindWindow(0, "FOCdemo" + CHR$(0)) 'get window handle using _TITLE string

PRINT hWnd%&
' Do the Open File dialog call!
Filter$ = "Batch files (*.bat)|*.BAT|JPEG images (*.jpg)|*.JPG|All files (*.*)|*.*"
Flags& = OFN_FILEMUSTEXIST + OFN_NOCHANGEDIR + OFN_READONLY '    add flag constants here
OFile$ = GetOpenFileName$("YEAH! Common Dialogs in QB64!!!", ".\", Filter$, 1, Flags&, hWnd%&)

IF OFile$ = "" THEN ' Display Open dialog results
    PRINT "Shame on you! You didn't pick any file..."
ELSE
    PRINT "You picked this file: "
    PRINT OFile$
    IF (Flags& AND OFN_READONLY) THEN PRINT "Read-only checkbox checked." 'read-only value in return
END IF

_DELAY 5 ' Do the Save File dialog call!
Filter$ = "Basic files (*.bas)|*.BAS|All files (*.*)|*.*"
Flags& = OFN_OVERWRITEPROMPT + OFN_NOCHANGEDIR '   add flag constants here
SFile$ = GetSaveFileName$("Save will not create a file!!!", ".\", Filter$, 1, Flags&, hWnd%&)

IF SFile$ = "" THEN ' Display Save dialog results
    PRINT "You didn't save the file..."
ELSE
    PRINT "You saved this file: "
    PRINT SFile$
END IF
END

FUNCTION GetOpenFileName$ (Title$, InitialDir$, Filter$, FilterIndex, Flags&, hWnd%&)
    '  Title$      - The dialog title.
    '  InitialDir$ - If this left blank, it will use the directory where the last opened file is
    '  located. Specify ".\" if you want to always use the current directory.
    '  Filter$     - File filters separated by pipes (|) in the same format as using VB6 common dialogs.
    '  FilterIndex - The initial file filter to use. Will be altered by user during the call.
    '  Flags&      - Dialog flags. Will be altered by the user during the call.
    '  hWnd&       - Your program's window handle that should be aquired by the FindWindow function.
    '
    ' Returns: Blank when cancel is clicked otherwise, the file name selected by the user.
    ' FilterIndex and Flags& will be changed depending on the user's selections.

    DIM OpenCall AS FILEDIALOGTYPE ' Needed for dialog call

    fFilter$ = Filter$
    FOR R = 1 TO LEN(fFilter$) ' Replace the pipes with character zero
        IF MID$(fFilter$, R, 1) = "|" THEN MID$(fFilter$, R, 1) = CHR$(0)
    NEXT R
    fFilter$ = fFilter$ + CHR$(0)

    lpstrFile$ = STRING$(2048, 0) ' For the returned file name
    lpstrDefExt$ = STRING$(10, 0) ' Extension will not be added when this is not specified
    OpenCall.lStructSize = LEN(OpenCall)
    OpenCall.hwndOwner = hWnd%&
    OpenCall.lpstrFilter = _OFFSET(fFilter$)
    OpenCall.nFilterIndex = FilterIndex
    OpenCall.lpstrFile = _OFFSET(lpstrFile$)
    OpenCall.nMaxFile = LEN(lpstrFile$) - 1
    OpenCall.lpstrFileTitle = OpenCall.lpstrFile
    OpenCall.nMaxFileTitle = OpenCall.nMaxFile
    OpenCall.lpstrInitialDir = _OFFSET(InitialDir$)
    OpenCall.lpstrTitle = _OFFSET(Title$)
    OpenCall.lpstrDefExt = _OFFSET(lpstrDefExt$)
    OpenCall.flags = Flags&

    Result = GetOpenFileNameA&(OpenCall) '            Do Open File dialog call!

    IF Result THEN ' Trim the remaining zeros
        GetOpenFileName$ = LEFT$(lpstrFile$, INSTR(lpstrFile$, CHR$(0)) - 1)
        Flags& = OpenCall.flags
        FilterIndex = OpenCall.nFilterIndex
    END IF

END FUNCTION

FUNCTION GetSaveFileName$ (Title$, InitialDir$, Filter$, FilterIndex, Flags&, hWnd%&)
    '  Title$      - The dialog title.
    '  InitialDir$ - If this left blank, it will use the directory where the last opened file is
    '     located. Specify ".\" if you want to always use the current directory.
    '  Filter$     - File filters separated by pipes (|) in the same format as VB6 common dialogs.
    '  FilterIndex - The initial file filter to use. Will be altered by user during the call.
    '  Flags&      - Dialog flags. Will be altered by the user during the call.
    '  hWnd&       - Your program's window handle that should be aquired by the FindWindow function.

    ' Returns: Blank when cancel is clicked otherwise, the file name entered by the user.
    ' FilterIndex and Flags& will be changed depending on the user's selections.

    DIM SaveCall AS FILEDIALOGTYPE ' Needed for dialog call

    fFilter$ = Filter$
    FOR R = 1 TO LEN(fFilter$) ' Replace the pipes with zeros
        IF MID$(fFilter$, R, 1) = "|" THEN MID$(fFilter$, R, 1) = CHR$(0)
    NEXT R
    fFilter$ = fFilter$ + CHR$(0)

    lpstrFile$ = STRING$(2048, 0) ' For the returned file name
    lpstrDefExt$ = STRING$(10, 0) ' Extension will not be added when this is not specified
    SaveCall.lStructSize = LEN(SaveCall)
    SaveCall.hwndOwner = _OFFSET(hWnd%&)
    SaveCall.lpstrFilter = _OFFSET(fFilter$)
    SaveCall.nFilterIndex = FilterIndex
    SaveCall.lpstrFile = _OFFSET(lpstrFile$)
    SaveCall.nMaxFile = LEN(lpstrFile$) - 1
    SaveCall.lpstrFileTitle = SaveCall.lpstrFile
    SaveCall.nMaxFileTitle = SaveCall.nMaxFile
    SaveCall.lpstrInitialDir = _OFFSET(InitialDir$)
    SaveCall.lpstrTitle = _OFFSET(Title$)
    SaveCall.lpstrDefExt = _OFFSET(lpstrDefExt$)
    SaveCall.flags = Flags&

    Result& = GetSaveFileNameA&(SaveCall) ' Do dialog call!

    IF Result& THEN ' Trim the remaining zeros
        GetSaveFileName$ = LEFT$(lpstrFile$, INSTR(lpstrFile$, CHR$(0)) - 1)
        Flags& = SaveCall.flags
        FilterIndex = SaveCall.nFilterIndex
    END IF
END FUNCTION
I am fairly confident that it's acceptably accurate, I printed out the types and sizes in FB
however, it doesn't work
« Last Edit: June 14, 2020, 01:46:54 pm by jack »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
Re: _WINDOWHANDLE should return an _OFFSET
« Reply #12 on: June 14, 2020, 02:12:34 pm »
I hit the keyboard for so long and changed data types for so long that the stubborn program gave it up and started working!

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.  


Please save it somewhere as 64 - bit example for wiki... Yeah!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
Re: _WINDOWHANDLE should return an _OFFSET
« Reply #13 on: June 14, 2020, 02:13:39 pm »
Thank you for your interest, Jack!

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
Re: _WINDOWHANDLE should return an _OFFSET
« Reply #14 on: June 14, 2020, 02:18:48 pm »
you did it Petr :)