Announcement

Collapse
No announcement yet.

Using API functions in PB/CC

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dave Biggs
    replied
    you're spoiling me!
    You're right! - No more soup for you!!

    Leave a comment:


  • Michael Bell
    replied
    Originally posted by Dave Biggs View Post
    Here's a compilable example using the BrowseCallbackProc Function.
    Thanks again Dave - you're spoiling me!

    Leave a comment:


  • Michael Mattias
    replied
    But, then again, I find that my console applications are tending towards things like waiting for mouse-events and mimicking Windows-like screens for collecting parameter values, etc
    If it walks like a GUI Application and looks like a GUI Application and sounds like a GUI application.......

    Leave a comment:


  • Dave Biggs
    replied
    Here's a compilable example using the BrowseCallbackProc Function.
    That allows you to control the 'browse for folder' dialog somewhat (choose initial selection etc)..
    Code:
     
    #COMPILE EXE
    #INCLUDE "win32api.inc"
     
    FUNCTION BrowseForFolderProc(BYVAL hwnd AS DWORD, BYVAL uMsg AS LONG, BYVAL lparam AS LONG, BYVAL pData AS LONG)AS LONG
      DIM zBuffer AS ASCIIZ * %MAX_PATH
        IF uMsg = %BFFM_INITIALIZED Then                        ' Browse For Folder Messages
          SendMessage hwnd, %BFFM_SETSELECTION, %TRUE, pData    ' see BrowseCallbackProc Function in docs
        END IF 
    END FUNCTION
    '------------------/
     
    FUNCTION BrowseForFolder(hWndOwner AS LONG, sPrompt AS STRING, StartFolder AS String) AS STRING
     LOCAL BI AS BrowseInfo
     LOCAL pIDList AS LONG 
     LOCAL szPath AS ASCIIZ * %MAX_PATH
     
      BI.hWndOwner    = hWndOwner              ' 0 = DeskTop
      BI.lpszTitle    = STRPTR(sPrompt)
      BI.ulFlags      = %BIF_RETURNONLYFSDIRS OR %BIF_NEWDIALOGSTYLE OR %BIF_RETURNFSANCESTORS OR %BIF_DONTGOBELOWDOMAIN
      BI.lpfnCallback = CODEPTR(BrowseForFolderProc)  ' * callback function - so we can send messages to the browse dialog
      BI.lParam       = Strptr(StartFolder)           ' *
     
      pIDList = SHBrowseForFolder(BI)                                     
      IF pIDList THEN
        SHGetPathFromIDList (BYVAL pIDList, szPath)
        FUNCTION = szPath
        CoTaskMemFree pIDList
      END IF
    END FUNCTION
    '------------------/
     
    FUNCTION PBMAIN() AS LONG
     LOCAL sPath AS String
     
      sPath = BrowseForFolder(0, "Select folder...", CURDIR$) '"C:\Temp")' 'Replace CurDir$ with your StartFolder
     
      MessageBox 0, "sPath = " + sPath, "Folder Selected", %MB_ICONMASK 
    END FUNCTION
    '------------------/
    This is based on an example that Lance posted some time ago.. http://www.powerbasic.com/support/pb...39&postcount=7
    That code shows how to filter the selections too.
    Last edited by Dave Biggs; 12 Nov 2009, 09:01 AM. Reason: sp

    Leave a comment:


  • Michael Bell
    replied
    It just occurred to me...for a self-professed "newbie" to use of the Windows API, you are starting off with hook procedures, user-defined callbacks, dialog templates etc.....

    I think I might have started with some more basic things, like "creating a window and adding some controls."
    I take your point Michael. It's just that I'm comfortable working with console applications but have realised that there are things that can much more conveniently be done using API functions. I suppose that I'm working towards being motivated finally to take the plunge and use PB/Win (I do have a PB/Win 8 licence at home...). When I do, I will certainly start off along the lines you suggest. I think that the main mountain for me to climb is changing to an event-driven rather than linear approach. But, then again, I find that my console applications are tending towards things like waiting for mouse-events and mimicking Windows-like screens for collecting parameter values, etc.

    In the meantime, thanks for the SHBrowseForFolder code. I shall endeavour to understand and use.

    Leave a comment:


  • Michael Mattias
    replied
    It just occurred to me...for a self-professed "newbie" to use of the Windows API, you are starting off with hook procedures, user-defined callbacks, dialog templates etc.....

    I think I might have started with some more basic things, like "creating a window and adding some controls."

    Wait a minute, that's exactly what I did!

    MCM

    Leave a comment:


  • Michael Mattias
    replied
    >but is it possible to start browsing [using ShBrowseForFolder] in a subfolder?

    Yes.

    Ok?

    Oh, you wanted code .

    Code:
    %GETFOLDER_START_ROOT     = 0&
    %GETFOLDER_START_LAST     = 1&
    %GETFOLDER_START_CURRENT  = 2&
    
    .....
          LOCAL bInf AS BROWSEINFO
    
          'Set some properties of the folder dialog
          bInf.hWndOwner    = hWndModal
          bInf.ulFlags      = %BIF_RETURNONLYFSDIRS OR %BIF_DONTGOBELOWDOMAIN
    [b]      bInf.lpfnCallback = CODEPTR (BrowseForFolderCallBack)   ' to start the search in another place[/b]
       ' No callback to make sure this is working with new compiler and Win32API.INC
       '   bInf.lpfnCallback = %NULL
          bInf.lparam       = StartFolder         ' passed to callback as lparam each call
    
    FUNCTION BrowseForFolderCallBack (BYVAL hwnd AS LONG,BYVAL uMsg AS DWORD,BYVAL lparam AS LONG, BYVAL pdata AS LONG) EXPORT AS LONG
       ' my lparam=function's pdata=%GetFolder_Start_Current, %GETFOLDER_START_LAST, or %GETFOLDER_START_ROOT
    
         STATIC szStartFolder AS ASCIIZ * %MAX_PATH
         LOCAL  szDummy       AS ASCIIZ * %MAX_PATH
    
         SELECT CASE uMSG
                CASE %BFFM_INITIALIZED
    
                    SELECT CASE pdata ' does lparam come BYVAL? Yes, in Pdata.
                      ' CASE %GETFOLDER_START_ROOT      ' do nothing...
                      '    EXIT FUNCTION
                       CASE %GETFOLDER_START_CURRENT
                          szDummy = CURDIR$
                          SendMessage hWnd, %BFFM_SETSELECTIONA, %TRUE, BYVAL VARPTR(szDummy)
                       CASE %GETFOLDER_START_LAST
                          SendMessage hWnd, %BFFM_SETSELECTIONA, %TRUE, BYVAL VARPTR(szStartFolder)
                    END SELECT
               ' We are getting BFFM_SELCHANGED TWICE BEFORE WE GET BFFM_INITIALIZED
               ' On these passes, szStartFolder is null, so we do not set szStartFolder
               CASE %BFFM_SELCHANGED
                      ' we only change the szStartDir if the current option (pdata) is start_last
                      ' I suppose we could do this under any cicumstances if we wanted...
                      STDOUT "Got BGGM_SELCHANGED"
                  IF pdata = %GETFOLDER_START_LAST THEN
                      ' 6/07/02 It appears lparam, NOT PDATA is the pointer to the itemidlist!
                      ' THAT IS CORRECT!! ERROR IN MSDN DOCUMENTATION!!!
                       SHGetPathFromIDList  BYVAL lparam, szDummy
                       IF LEN(szDummy) THEN
                         szStartFolder = szDummy
                       END IF
                  END IF
    
         END SELECT    ' of which %BFFM_xxx messsage
    
         FUNCTION = 0
    END FUNCTION
    I left a little work for you to do yourself.

    MCM

    Leave a comment:


  • Michael Bell
    replied
    Dave: excellent - thanks! A little research shows me how to specify different root directories for browsing, but is it possible to start browsing in a subfolder? Specifically, it would be good to start in the folder from which the application was launched, but have access to higher-level folders too.

    Leave a comment:


  • Dave Biggs
    replied
    Another way to make using the hook 'safer' could be to declare hHook as Global and unhook imediately..
    Code:
     IF lMsg = %HCBT_ACTIVATE THEN
        UnhookWindowsHookEx hHook
    ...

    Leave a comment:


  • Dave Biggs
    replied
    Secondly, in the course of running a program I sometimes like to change my working directory. Again, easy to implement
    in the console, but not as convenient as clicking on a directory structure...
    Is there a similar function which is the right tool?
    Search the forums for the API function SHBrowseForFolder. Here is one example of it's use..
    Code:
    #COMPILE EXE
    #INCLUDE "win32api.inc"
     
    FUNCTION BrowseForFolder(hWndOwner AS LONG, sPrompt AS STRING) AS STRING
     LOCAL BI AS BrowseInfo                 ' Contains parameters for the the SHBrowseForFolder function and 
                                            ' receives information about the folder selected by the user
     LOCAL pIDList AS LONG 
     LOCAL szPath AS ASCIIZ * %MAX_PATH
     
      BI.hWndOwner = hWndOwner              ' 0 = DeskTop
      BI.lpszTitle = STRPTR(sPrompt)
      BI.ulFlags   = %BIF_RETURNONLYFSDIRS  ' try OR %BIF_DONTGOBELOWDOMAIN OR %BIF_USENEWUI OR %BIF_RETURNFSANCESTORS
      pIDList = SHBrowseForFolder(BI)       ' Returns a pointer to an item identifier list (pIDL) - specifies 
                                            ' the location of the selected folder relative to the root of the namespace. 
      ' The 'Shell namespace' organizes the file system and other objects managed by the Shell into a single 
      ' tree-structured hierarchy. Conceptually, it is a larger and more inclusive version of the file system.                                        
     
      IF pIDList THEN                       ' If the user chooses the Cancel button, pIDList is NULL.
        SHGetPathFromIDList (BYVAL pIDList, szPath)   ' Converts pIDL to a file system path.
        FUNCTION = szPath
      END IF
      CoTaskMemFree pIDList             ' Calling application is responsible for freeing the returned Item Identifier List.
    END FUNCTION
    '------------------/
     
    FUNCTION PBMAIN() AS LONG
     LOCAL sPath AS String
     
      sPath = BrowseForFolder(0, "Select folder...")
     
      MessageBox 0, "Folder = " + sPath, "Folder Selected", %MB_ICONMASK 
    END FUNCTION
    '------------------/
    Finally, is there any handy documentation for Win32API.inc, ComDlg32.inc, etc. other than Win32.hlp?
    I'm looking for simple guidance on which function does what, with examples of how to use the syntax.
    In addition to the MSDN links provided by Michael you should check out POFFS offline search engine for PB Forums - download here: http://www.reonis.com/POFFS/index.htm
    As you find yourself slidding deeper into the API you'll probably want to get a copy of the SDK Documentation on disk..
    Microsoft Platform SDK CD (available at cost of shipping only) - order here: http://mssdk.orderport.net
    (Windows XP SP2 edition is probably the best to start with)

    Leave a comment:


  • Michael Bell
    replied
    Thanks Michael for the heads-up on that particular trap for the unwary. Yes, it's pretty unlikely that I'd blunder into it in the type of simple console applications that I write, but you never know, I might get above myself with winapi in future...

    Arie: I copied SearchAPI today and am already finding it useful.

    Leave a comment:


  • Michael Mattias
    replied
    >OK, now I know what a hook function is ...how to use it and adapt it to other purposes

    I'm glad you looked that up, because there is a 'gotcha' in there.

    That 'gotcha' is, the way the hook is created it ASSUMES the only window being activated in that thread context is the window created by the MessageBox function.

    In your program(s), that may be a perfectly reasonable and safe assumption, but if you add, say, an "Open File" function and do so in that thread context you could have an interesting experience.

    In this case you are probably good to go because this is done with this sequence...
    Code:
    hHook = SetWindowsHookEx ...
    Retval = MessageBox....
    UnhookWindowsHookEx ...
    .. and the hook will be in effect only for the life of the MessageBox call. .. however, you might have created another window on this thread earlier in your program. If the user just stares at the MessageBox and then decides to activate (click on) that already-created window, your hook proc will receive an activate notification, but wParam will not refer to your message box.

    I admit this is unlikely in the case of a console program... but it is not impossible.

    You can disable that other window for this call sequence and now clicking on it won't do anything. See EnableWindow() function in your WinAPI reference)...

    ...OR...

    ... you can make that hWnd the owner window of this message box; that should disable the original window until the messagebox has been dismissed.

    I'm not here to be the "doom and gloom" guy, but sometimes when you "adapt to other purposes" the original restrictions get lost in the shuffle.

    MCM

    Leave a comment:


  • Arie Verheul
    replied
    Does PB/CC has the new open file commandset?
    Well, not included in the compiler.
    In the include files that come with the compiler there are however many macro's
    and special functions to make the use of certain Windows functions more easy.
    You might search these files for this with any suitable search tool or, if you
    don't have anything suitable, you could use the one that i posted for this purpose.
    http://www.powerbasic.com/support/pb...ad.php?t=39500

    Arie Verheul

    Leave a comment:


  • Michael Bell
    replied
    Cheers, thanks Dave! I don't know what a hook function is, but it does exactly what I want. I'll be using that one a lot.

    Later...
    OK, now I know what a hook function is (http://en.wikipedia.org/wiki/Hook_function). The details of your code are somewhat over my head, but I can certainly see how to use it and adapt it to other purposes.
    Last edited by Michael Bell; 11 Nov 2009, 04:08 AM.

    Leave a comment:


  • Dave Biggs
    replied
    I'd like to be able to have user-defined buttons,
    You could use a hook function to modify the text on a standard messagebox buttons..
    Code:
    #COMPILE EXE
    #REGISTER NONE
    #DIM ALL
    #INCLUDE "Win32Api.Inc"
     
    FUNCTION MsgBoxButtonText(BYVAL lMsg AS LONG, BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
             ' TT Pierre. [URL]http://www.powerbasic.com/support/pbforums/showpost.php?p=87690&postcount=4[/URL]
     IF lMsg = %HCBT_ACTIVATE THEN
       SetWindowText GetDlgItem(wParam, 6), "Overwrite"
       SetWindowText GetDlgItem(wParam, 7), "Append" 
       SetWindowText GetDlgItem(wParam, 2), "Abort" 
     END IF
      'in HCBT_ACTIVATE message, wParam holds the handle to the messagebox
      'API sets ID's of the buttons on a message box.
      'Values returned correspond to the IDs,
      '%IDOK      = 1     '%IDCANCEL  = 2
      '%IDABORT   = 3     '%IDRETRY   = 4
      '%IDIGNORE  = 5     '%IDYES     = 6
      '%IDNO      = 7     'etc
      ' MessageBox with flag %MB_YESNOCANCEL creates buttons with IDs = 6, 7, 2
    END FUNCTION
    '------------------/
     
    FUNCTION PBMAIN()
     Local hHook As Dword, RetVal As Long
     
      hHook = SetWindowsHookEx(%WH_CBT, CODEPTR(MsgBoxButtonText), GetModuleHandle(""), GetCurrentThreadId)
      Retval = MessageBox(0, "Yes, No or Cancel ??", "Renamed Buttons!", %MB_ICONQUESTION OR  %MB_YESNOCANCEL OR %MB_TASKMODAL)
      UnhookWindowsHookEx hHook
     
      MessageBox 0, "Selected:" + str$(RetVal) + $CR + $CR + _
                    "6 = 'Overwrite'  (aka Yes)" + $CR + _
                    "7 = 'Append'  (aka No)" + $CR + _
                    "2 = 'Abort'  (aka Cancel)", "Returned value", %MB_ICONMASK
     
    END FUNCTION
    '------------------/

    Leave a comment:


  • Michael Mattias
    replied
    > Edwin: no PB/CC doesn't provide a dialog for opening and saving files

    Native syntax, no; but the COMDLG32.INC file provided with PB/CC includes OpenFileDialog() and SaveFileDialog() functions.


    FWIW, the MSGBOX function above has as its purpose making the Pb/Win "MSGBOX" function available from PB/CC... so I can use the same #INCLUDE files regardless of which compiler I am using that day.

    Same goes for Simple STDOUT for PB/DLL and PB/Win 2-13-04 ... Makes STDOUT available if I'm working wth PB/Win that day.


    MCM

    Leave a comment:


  • Michael Bell
    replied
    Thank you James. There's a lot there for me to learn from...

    Leave a comment:


  • jcfuller
    replied
    Another alternative.

    James
    Attached Files

    Leave a comment:


  • Michael Bell
    replied
    Thanks for the replies Edwin and Michael.

    Edwin: no PB/CC doesn't provide a dialog for opening and saving files, but it's easy enough to use ComDlg32.inc to display files and folders and return a file name to open. I just want to be able to display a message box or dialog which allows the user to select the appropriate action when a file to be saved already exists. If that's not possible by calling API functions from PB/CC then I'll either just display the messages in the console or just work with what is possible.

    Michael: good links - I'll trawl through to see what's useful for my purposes. Your MSGBOX function provides me with various combinations of buttons (actually, I could already do this with MessageBox straight from Win32API.inc, but your syntax is shorter...). I'd like to be able to have user-defined buttons, but I can certainly adapt to what is already within my reach...

    Leave a comment:


  • Michael Mattias
    replied
    Code:
    #IF %DEF(%PB_CC32)
    
      #IF NOT %DEF(%WINAPI)
         DECLARE FUNCTION MessageBox LIB "USER32.DLL" ALIAS "MessageBoxA" (BYVAL hWnd AS DWORD, lpText AS ASCIIZ, lpCaption AS ASCIIZ, BYVAL dwType AS DWORD) AS LONG
         %MB_OK                        = &H00000000&
         %MB_TASKMODAL                 = &H00002000&
      #ENDIF
    
     FUNCTION MSGBOX (szText AS ASCIIZ, OPTIONAL BYVAL STYLE AS DWORD, OPTIONAL szCaption AS ASCIIZ) AS LONG
    
        LOCAL hWnd AS LONG, uType AS LONG, dwCap AS DWORD
    
        uType = IIF& (STYLE=%NULL,%MB_OK OR %MB_TASKMODAL, STYLE)
        dwCap =   VARPTR(szCaption)  ' if null, Windows uses "Error"
        FUNCTION = MessageBox (BYVAL %NULL, szText, BYVAL dwCap, BYVAL uType)
    
      END FUNCTION
    #ENDIF   ' if %DEF (%Pb_CC32)
    Useful styles and return values from Win32API.INC:
    Code:
    ' MessageBox() Flags
    %MB_OK                        = &H00000000&
    %MB_OKCANCEL                  = &H00000001&
    %MB_ABORTRETRYIGNORE          = &H00000002&
    %MB_YESNOCANCEL               = &H00000003&
    %MB_YESNO                     = &H00000004&
    %MB_RETRYCANCEL               = &H00000005&
    %MB_CANCELTRYCONTINUE         = &H00000006&
    
    %MB_ICONHAND                  = &H00000010&
    %MB_ICONQUESTION              = &H00000020&
    %MB_ICONEXCLAMATION           = &H00000030&
    %MB_ICONASTERISK              = &H00000040&
    
    %MB_USERICON                  = &H00000080&
    %MB_ICONWARNING               = %MB_ICONEXCLAMATION
    %MB_ICONERROR                 = %MB_ICONHAND
    
    %MB_ICONINFORMATION           = %MB_ICONASTERISK
    %MB_ICONSTOP                  = %MB_ICONHAND
    
    %MB_DEFBUTTON1                = &H00000000&
    %MB_DEFBUTTON2                = &H00000100&
    %MB_DEFBUTTON3                = &H00000200&
    %MB_DEFBUTTON4                = &H00000300&
    
    %IDOK       = 1
    %IDCANCEL   = 2
    %IDABORT    = 3
    %IDRETRY    = 4
    %IDIGNORE   = 5
    %IDYES      = 6
    %IDNO       = 7
    %IDCLOSE    = 8
    %IDHELP     = 9
    %IDTRYAGAIN = 10
    %IDCONTINUE = 11
    MCM

    Leave a comment:

Working...
X