No announcement yet.

Process in background (called from VB)

  • Filter
  • Time
  • Show
Clear All
new posts

  • #21
    I know that.
    The cb may not be invoked from inside the pb thread, that's all.


    • #22
      OK we agree, thank you for helping Mike understand my posts which might have caused a problem due to lack of clarity


      • #23
        I am probably out of my depth here and I am not sure I understand your problem but here goes. VB6 has no understanding of threads and cannot be used to control them. When you end a VB program by most means you can respond to a (from memory) Form Unload Event of the main form. In that event you should be quering the DLL as to whether all threads it has created have actually ended or Windows is going to do a dummy spit.


        • #24
          Having no problems in that area.
          Actually, everything seems to be working after using
          DIALOG DO EVENTS and not ending the function that created the thread.

          I guess this forum thread could be closed, but the different ways to
          return data from the DLL to VB are of the most interest now.
          I will be using the code in post #10.

          I'm trying to write all code in PB with a VB front end for COM.

          Note: Just noted a potential problem, not shown.
          I set a global gBusy if something is processing a request.
          This will be modified because it is possible that another function
          could reset the flag. The gBusy flag will become a counter that
          is increased and decreased to indicate something is in progress.
          Instead of setting gBusy = 1, gBusy = gBusy + 1
          and gBusy = gBusy - 1 instead of gBusy = 0.

          FUNCTION GetThreadCount EXPORT AS LONG 'VB uses to not end until threadcount = 1
          END FUNCTION 
          Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
            If GETTHREADCOUNT > 1 Then
              Splash "Background function is processing", 1000
              Cancel = True
            ElseIf gBusy Then
              Splash "Processing a request", 1000
              Cancel = True
            End If
          End Sub
          Last edited by Mike Doty; 30 May 2009, 03:56 PM.


          • #25
            >The cb may not be invoked from inside the pb thread, that's all.


            Why not, if that call will not do anything which might itself cause an re-entrant call? This is really the crux of my question about how VB works.

            ' MY_VB_PROGRAM.BAS 
            FUNCTION MainWindowProcedure (hWnd, uMSG, wParam, lparam) 
                 hThread = CreateThread (params, calling MY_VB_FUNCTION ) 
                 ' returns immediately with a thread handle 
            FUNCTION My_VB_FUNCTION (params) 
               CALL MyFunctionInmyPBDLL (params) 
               PostMessage  primaryHWnd, private_message_no, _
                  params  with results of MyFunctionInMyPbDLL
            END FUNCTION
            You don't even need a callback here. Since CreateThread returns essentially immediately, the primary GUI thread is not blocked and should run normally, shouldn't it?


            It's really not a whole lot different from the "ALL PB" demo at GUI + Worker Thread + Abort Demo 11-24-07, at least as far as I can tell.

            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]


            • #26
              Threads are working fine with VB6.

              Now about callbacks.

     'subclassing code for VB6
     'pointers with VB6
              Last edited by Mike Doty; 7 Jun 2009, 04:08 PM. Reason: Got chopped off


              • #27
                Read back strings from PB to VB using SendMesssage
                Added Peeker function to DLL below.
                s = PEEKER(lParam, wParam) 'in VB6 callback

                GLOBAL gForm1 AS LONG
                SUB Init(Form1 AS DWORD) EXPORT
                  gForm1 =Form1
                END SUB
                SUB CallVb EXPORT
                  LOCAL s AS STRING        'use STRPTR with dynamic strings
                  LOCAL lResult   AS LONG
                  LOCAL dwHandle  AS DWORD
                  LOCAL dwMsg     AS DWORD
                  LOCAL dwParam   AS DWORD
                  LOCAL lParam    AS LONG
                  dwHandle = gForm1
                  dwMsg    = &H300
                  s = "TEST COMPLETE"
                  dwParam = LEN(s)      'length
                  lParam = STRPTR(s)    'address
                  lResult = SendMessage(dwHandle,dwMsg,dwParam,lParam)
                END SUB
                FUNCTION Peeker(Address AS DWORD, Characters AS LONG) EXPORT AS STRING
                  FUNCTION  = PEEK$(address???, characters)
                END FUNCTION
                Last edited by Mike Doty; 7 Jun 2009, 04:19 PM. Reason: Changed from ASCIIZ to Dynamic strings


                • #28
                  CallBack to Visual Basic and SendMessage to Visual Basic

                  This shows how to directly SendMessage to a VB control.
                  It also shows how to use a callback.
                  All the code is in a PowerBASIC DLL.

                  VB code is in the second code window.

                  If no errors reported will post in source code forum.

                  #DIM ALL
                  #COMPILE DLL 'subDLL.bas
                  #INCLUDE ""
                  %CallBack = &H300
                  GLOBAL gControl    AS LONG
                  GLOBAL gPrevWndProc AS LONG
                  SUB TestCallBack EXPORT
                    IF gControl = 0 THEN ? "Subclass is not on":EXIT SUB
                    STATIC Counter AS LONG
                    LOCAL s       AS STRING
                    LOCAL wParam  AS DWORD
                    LOCAL lParam  AS LONG
                    INCR Counter
                    s = "Callback string" + STR$(Counter)
                    wParam = LEN(s)
                    lParam = STRPTR(s)
                    SendMessage gControl,%Callback,wParam,lParam 'let callback handle it
                  END SUB
                  SUB TestSendMessage(hControl AS LONG) EXPORT
                    STATIC Counter AS LONG
                    LOCAL s AS STRING
                    INCR Counter
                    s = "SendMessage direct to control" + STR$(counter)
                  END SUB
                  FUNCTION Peeker(Address AS DWORD, Characters AS LONG) EXPORT AS STRING
                    'Could be used by VB to read string in memory
                    FUNCTION  = PEEK$(address???, characters)
                  END FUNCTION
                  SUB EndSubClass() EXPORT
                    CALL SetWindowLong(gControl, %GWL_WNDPROC, gPrevWndProc)  'restore old address
                  END SUB
                  FUNCTION WindowProc(BYVAL hControl AS LONG, BYVAL uMsg AS LONG, _
                      BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
                    DIM sPeekString AS STRING  'string already in memory
                    IF uMsg = %CALLBACK THEN  'triggered callback
                      sPeekString = PEEKER(lParam, wParam)
                      SendMessage gControl,%LB_ADDSTRING,%NULL,STRPTR(sPeekString)
                      EXIT FUNCTION
                    END IF
                    FUNCTION = CallWindowProc(gPrevWndProc, hControl, uMsg, wParam, lParam)
                  END FUNCTION
                  SUB StartSubClass(hControl AS LONG) EXPORT
                    gControl = hControl
                    gPrevWndProc = SetWindowLong(gControl, %GWL_WNDPROC, CODEPTR (WindowProc))
                  END SUB
                  #IF 0
                   REM VB6
                   REM  1. Add a Command button
                   REM  2. Add a listbox
                  PRIVATE DECLARE SUB TESTSENDMESSAGE LIB "subdll" (hControl AS LONG)
                  PRIVATE DECLARE SUB TESTCALLBACK LIB "subdll" ()
                  PRIVATE DECLARE SUB STARTSUBCLASS LIB "subdll" (hControl AS LONG)
                  OPTION EXPLICIT
                  PRIVATE SUB Command1_Click()
                    TESTSENDMESSAGE List1.hWnd
                  END SUB
                  PRIVATE SUB Form_Load()
                    CHDIR App.Path
                    Command1.Caption = "Test"
                    STARTSUBCLASS List1.hWnd
                  END SUB
                  PRIVATE SUB Form_QueryUnload(CANCEL AS INTEGER, UnloadMode AS INTEGER)
                    ENDSUBCLASS 'required if subclassing
                  END SUB
                  Can now work in the VB6 environment with threads, callbacks and sendmessage.
                  Last edited by Mike Doty; 7 Jun 2009, 08:41 PM.