Announcement

Collapse
No announcement yet.

Help: PB created control in VB app

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

  • Help: PB created control in VB app

    Hi folks,
    Im having problems with a simple (for now) powerbasic control
    im trying to write, to be used in a VB application. For some
    reason ive so far been unable to determine, it crashes "sometimes"
    after being run, stopped and re-run (sometimes not crashing
    until after the 5th+ re-run... sometimes only after the 1st re-run))

    Here's the PB control DLL code
    Code:
    #COMPILE DLL "simple.dll"
    #DIM ALL
    #REGISTER NONE
    
    #INCLUDE "win32api.inc"
    
    'Exported Functions
    DECLARE FUNCTION CreateControl (BYVAL hWnd AS LONG, BYVAL hInst AS LONG, BYVAL hFont AS LONG, BYVAL fCallBack AS LONG) AS LONG
    DECLARE FUNCTION TerminateControl (BYVAL hWnd AS LONG) AS LONG
    
    ' Private functions
    DECLARE FUNCTION InitWindow (BYVAL hInstance AS LONG, BYVAL hParent AS LONG) AS LONG
    
    
    FUNCTION CreateControl (BYVAL hWnd AS LONG, BYVAL hInst AS LONG, BYVAL hFont AS LONG, BYVAL fCallBack AS LONG) EXPORT AS LONG
        DIM hWindow  AS LONG
          
        ' create the window
        hWindow = InitWindow (hInst, hWnd)
    
        ' pass the handle
        FUNCTION = hWindow
    END FUNCTION
    
    
    FUNCTION TerminateControl (BYVAL hWnd AS LONG) EXPORT AS LONG
        DestroyWindow hWnd
        FUNCTION = %TRUE
    END FUNCTION
    
    
    FUNCTION InitWindow (BYVAL hInstance AS LONG, BYVAL hParent AS LONG) AS LONG
    
      LOCAL wndclass        AS WndClassEx
      LOCAL szClassName     AS ASCIIZ * 80
      LOCAL hWnd            AS LONG
    
      szClassName            = "SIMPLE"
      wndclass.cbSize        = SIZEOF(WndClass)
      wndclass.style         = %CS_HREDRAW OR %CS_VREDRAW OR %CS_DBLCLKS
      wndclass.lpfnWndProc   = CODEPTR( WndProc )
      wndclass.hInstance     = hInstance
      wndclass.hCursor       = LoadCursor( %NULL, BYVAL %IDC_ARROW )
      wndclass.hbrBackground = %COLOR_APPWORKSPACE
      wndclass.lpszMenuName  = %NULL
      wndclass.lpszClassName = VARPTR( szClassName )
      
      IF ISFALSE(RegisterClassEx(wndclass)) THEN
        RegisterClass BYVAL (VARPTR(wndclass) + 4)
      END IF
    
      ' create the control window
      hWnd = CreateWindowEx( %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, _
                                         "SIMPLE", _
                                         BYVAL %NULL, _
                                         %WS_VISIBLE OR %WS_CHILD OR %WS_CLIPCHILDREN OR _
                                         %WS_CLIPSIBLINGS,  _
                                         %CW_USEDEFAULT, %CW_USEDEFAULT, %CW_USEDEFAULT, %CW_USEDEFAULT, _
                                         hParent, _
                                         %ID, _
                                         hInstance, _
                                         BYVAL 0 )
                                         
      
      ShowWindow hWnd, %SW_MAXIMIZE  '1' %SHOW_OPENWINDOW
    
      FUNCTION = hWnd
    
    END FUNCTION
    
    FUNCTION WndProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _
                      BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
                
        FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)
        
    END FUNCTION
    Now here's the VB code. The VB program consists of just a
    form with a picture box on it.

    Code:
    Private Declare Function CREATECONTROL Lib "F:\visualb\projects\gvd\Current\simple.dll" (ByVal hWnd As Long, ByVal hInst As Long, ByVal hFont As Long, ByVal fCallBack As Long) As Long
    Private Declare Function TERMINATECONTROL Lib "F:\visualb\projects\gvd\Current\simple.dll" (ByVal hWnd As Long) As Long
    
    Dim lCtl As Long
    
    Private Sub Form_Load()
        Dim l As Long
        lCtl = CREATECONTROL(Picture1.hWnd, App.hInstance, 0, 0)
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        Dim l As Long
        l = TERMINATECONTROL(lCtl)
    End Sub
    The DLL compiles fine. The VB code compiles fine. When i run
    the VB code, it runs fine >50% of the time. The first
    run of the program always works, but when i shut down the VB
    app and re-run it, it sometimes crashes. If it doesnt crash
    on the first re-run, i only need to re-run the app
    over and over and sooner or later it will crash.

    This is the first time ive tried to write a DLL that contains
    a window to be used in a VB app. Is there something
    fundamentally wrong im doing with trying to
    draw a window created in PB onto a VB picturebox?

    Thanks for any help.
    -Mike

  • #2
    By the way, im running Windows2000 if that makes any difference.
    -Mike

    ------------------

    Comment


    • #3
      Mike;

      At first glance, I see an error in trying to "terminate" the
      control via code in your VB Form unload. If VB Forms work like any
      other Windows (created in other languages), "all" the controls
      will be destroyed when the Form is destroyed (unloaded) automatically.

      Your control could be getting multiple requests to destroy it, one
      from your terminate function and the other by Windows when the VB
      Form is unloaded. This definitely is a good candidate for causing
      a GPF. It will also likely cause a GPF periodically, rather than
      all the time.

      When a Window is destroyed (Form unloaded), Windows will send a
      message to destroy all the Children before the Window gets destroyed.
      If your control gets destroyed "before" Windows gets to it via the
      Form unload, your app will not GPF. If Windows destroys it before your
      function call Destroys it, then you likely will GPF.

      Rule #1:

      Never explicitly destroy a control in your code , unless you know the parent
      Window still exists. In VB terms, never destroy a control during
      the parents unload event.


      There is one possibility to use your code as is and explicitly destroy
      the control though. Try using a DoEvents after the terminate function
      is called. This may give windows enough time to destroy the control before
      the Form unload is processed.


      ------------------
      Chris Boss
      Computer Workshop
      Developer of "EZGUI"
      http://cwsof.com
      http://twitter.com/EZGUIProGuy

      Comment


      • #4
        1) Make your control global class.
        2) Use the instance of the DLL to create the control.

        Esp. on saving the last changes before running the VB app will crash.

        2) will help you a lot!


        ------------------
        [email protected]
        hellobasic

        Comment


        • #5
          Try using Query_Unload in VB
          I believe that this function is recommended for shutdown procedures.

          Joe

          ------------------

          Comment


          • #6
            Note:

            To make a point for any PB newbies reading this thread:

            You do "not" have to explicitly destroy Child windows.
            Whether the Child window is a control (a true Child) or whether it is simply
            an "owned" (has a parent) PopUp Window.

            When the Parent Window is Destroyed (unloaded in VB terms), Windows
            "automatically" tells all the children windows to be destroyed.

            The children "must" be destroyed, before the Parent can be destroyed.
            Since, Windows "already" does this for you, any attempts to
            explicitly Destroy child windows "during" the Parents destruction
            process (unloading), is simply "dangerous". Non-existant windows
            shouldn't receive messages. Windows could end up sending messages
            to your control, when it doesn't exist.

            The problem with the Windows "messaging" service, is that according
            to Microsoft API docs, you cannot "depend" upon messages being
            sent in a particular order (few exceptions like if mouse button
            goes down, it must come up again). Windows is "not" linear in nature.

            With the example above, if Mike explicitly destroys his custom
            control in a VB Forms (parent) unload (WM_CLOSE message) event,
            this is one possible outcome :


            (1) VB Form is "prepared" to be closed (Unload event), but still
            exists.

            (2) Custom control is destroyed, explicitly in the unload event.

            (3) Windows "attempts" to "repaint" the VB Form, since once the
            custom control is destroyed, the background behind it must be
            repainted. It sends a WM_PAINT message, but that message is posted
            and Windows will send it when "all" other messages are finished
            with first. You do not know when the Form will get the WM_PAINT
            message !


            (4)Now, the Unload event is finished and control returns back to
            Windows and Windows begins to destroy the VB Form (same with any
            Window in a 100% PB app).

            (5) The VB Form (window) destroys all the children and then gets
            destroyed itself.

            Now, the big question ?

            Has the WM_PAINT message generated by the explicit destruction of
            the custom control be processed yet ?

            Since, Windows is not linear and you don't know when Windows will
            actually get this message sent to the VB Form, it is a 50/50 chance
            it has been already sent.

            If Windows send the WM_PAINT message in time before the VB Form
            gets destroyed, you are OK. If Windows sends the WM_PAINT message
            after the VB form gets destroyed, then its GPF time !

            This is why "sometimes" Mike app GPF's and sometimes it doesn't.

            The reason I am spending so much time on this subject, is that it
            is at the core of how Windows works. Many software GPF's
            are generated simply because failing to understand how windows
            processes messages. Programming at the API level requires that one
            understands that Windows is "not" Linear in nature.

            This is one reason why the DoEvents command was created for VB and
            PB. It is used to allow Windows ample time to process a message
            "completely" before continuing with your code, which may generate
            "competing" messages (actions).




            ------------------
            Chris Boss
            Computer Workshop
            Developer of "EZGUI"
            http://cwsof.com
            http://twitter.com/EZGUIProGuy

            Comment

            Working...
            X