Announcement

Collapse
No announcement yet.

PBDLL 6 GDI.BAS hangs after a few minutes

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

    PBDLL 6 GDI.BAS hangs after a few minutes

    I modified Dave Navarro's GDI.BAS so that the window is repainted every
    one or two seconds (instead of when the mouse is left-clicked), and just
    let it run. After a few minutes (about 4 or 5) the app. froze. Sometimes
    I can close it, no apparent harm, but other times everything is locked up
    and I have to reboot. I'm using Windows 98SE, Pentium III 500 MHz, 128 MB
    Ram. Here are the mods I inserted into Dave's code:
    ' GDI.BAS test code for PB/DLL 5.0
    ' by Dave Navarro, Jr. ([email protected])
    ..
    FUNCTION WINMAIN (BYVAL hInstance AS LONG, _
    BYVAL hPrevInstance AS LONG, _
    lpCmdLine AS ASCIIZ PTR, _
    BYVAL iCmdShow AS LONG) AS LONG

    LOCAL Msg AS tagMsg
    LOCAL wndclass AS WndClassEx
    LOCAL szAppName AS ASCIIZ * 80
    LOCAL hWnd AS LONG
    LOCAL hTimer AS LONG
    ' my first added statement <------------------------------------- (1)
    ...
    ' Create a window using the registered class
    hWnd = CreateWindow("GDIWINDOW",_ ' window class name
    "PowerBASIC GDI Test", _ ' window caption
    %WS_OVERLAPPEDWINDOW, _ ' window style
    %CW_USEDEFAULT, _ ' initial x position
    %CW_USEDEFAULT, _ ' initial y position
    %CW_USEDEFAULT, _ ' initial x size
    %CW_USEDEFAULT, _ ' initial y size
    %NULL, _ ' parent window handle
    %NULL, _ ' window menu handle
    hInstance, _ ' program instance handle
    BYVAL %NULL) ' creation parameters

    hTimer = SetTimer(hWnd, 0, 1000, BYVAL %NULL) 'Timer event every 1 Secs
    ' my second added statement <---------------------------------------- (2)
    ShowWindow hWnd, iCmdShow
    UpdateWindow hWnd

    WHILE GetMessage(Msg, %NULL, 0, 0)
    TranslateMessage Msg
    DispatchMessage Msg
    WEND

    ' KillTimer hWnd, 0 ' Destroy the timer.. I tried with and without this
    ' my third added statement <--------------------------------------- (3)
    FUNCTION = msg.wParam

    END FUNCTION ' WinMain
    ...
    FUNCTION WndProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _
    BYVAL wParam AS LONG, BYVAL lParam AS LONG) EXPORT AS LONG

    LOCAL hDC AS LONG
    LOCAL LpPaint AS PaintStruct
    LOCAL tRect AS Rect

    STATIC First AS LONG

    SELECT CASE wMsg

    CASE %WM_CREATE

    ' CASE %WM_LBUTTONDOWN this is Dave's CASE statement
    CASE %WM_Timer
    ' my fourth and final added statement <---------------------------- (4)
    InvalidateRect hWnd, BYVAL %NULL, %TRUE

    I hope this is neither too short nor too long to explain what I am having
    trouble with. PBDLL 6.0 is very impressive, compared to 2.0 which I was
    able to use to replace slow code in a VB 3.0 program, but I'm having a
    little difficulty getting up to speed in the 32-bit environment.

    Thanks to Dave and others at PB for providing so many useful examples,
    such as this one. I only wish I could understand it better.

    #2

    Alan,
    Since you haven't posted all the source, I can't figure out your problem. But I see you have the hDC as a LOCAL variable, usually I would declare hDC as STATIC LONG and initialize it in the WM_CREATE message, then use ReleaseDC in the WM_DESTROY message, also be sure to delete all created objects such as CreateSolidBrush with the DeleteObject Function.

    To me it looks like a resource leak, but I could be wrong.

    Regardz,


    -------------
    Kev G Peel
    KGP Software
    Bridgwater, UK.
    mailto:[email protected][email protected]</A>

    Comment


      #3
      It is not usual to "hold" onto a DC as Kev suggests unless you are using a Private Device Context (the code snippet above suggests that a Common Device Context is in use). When dealing with a Common Device Context, you would normally only take ownership of the DC when responding to a
      %WM_PAINT event, and then immediately release the DC back to the "pool" before leaving the %WM_PAINT handler.

      However, it is likely that a resource leak is occurring, given the symptoms. If you install the Windows Resource Meter, you may be able to watch Resource Memory dropping as the app runs.

      Alan, if you can post all of the code, we may be able to help you better.

      -------------
      Lance
      PowerBASIC Support
      mailto:[email protected][email protected]</A>
      Lance
      mailto:[email protected]

      Comment


        #4
        Thanks for your help, Kev and Lance. I tried watching the Resource meter, and indeed,
        the GDI resources drop, about 1% for each 20 redraws of the window. If I speed up the
        Timer events, the resources leak away faster, but the relation to redraws seems to stay the
        same. So I have a resource leak, but deleting objects and device contexts after each
        use doesn't seem to cure the problem. I think most of the code is still the same as Dave
        Navarro's original example, although I did try making hDC, and then other handles too, STATIC
        instead of LOCAL. One more thing ... I can't seem to get a pen size of "1" to work, as it
        does in the "COOL" example that came with my PBDLL 6.0. Dave's example was written for
        PBDLL 5.0 ... would that make a difference? Here is the complete code with my modifications:
        Code:
        '
        ' GDI.BAS test code for PB/DLL 5.0
        ' by Dave Navarro, Jr. ([email protected]) modified by Alan Dalglies
        '
        
        $COMPILE EXE
        $INCLUDE "WIN32API.INC"
        
        DEFSNG A-Z
        
        FUNCTION FF(x AS SINGLE, y AS SINGLE)
          GLOBAL W AS SINGLE
          FUNCTION = 14 * EXP(-.04*W)*COS(.15*W)
        END FUNCTION
        
        SUB PLOT(BYVAL hWnd AS LONG)
        
          LOCAL LpPaint   AS PaintStruct
        '  LOCAL hMemDC    AS LONG
        '  LOCAL hBmp      AS LONG
        '  LOCAL hBrush    AS LONG
        '  LOCAL hPen      AS LONG
          LOCAL WinX      AS LONG
          LOCAL WinY      AS LONG
          LOCAL r         AS RECT
          LOCAL i         AS LONG
          LOCAL FL        AS LONG
          LOCAL yOfs      AS LONG
        
          STATIC PHI AS SINGLE
          STATIC hDC       AS LONG      ' 2000/1/18 suggested by Kev G. Peel
          STATIC hMemDC    AS LONG      '
          STATIC hBmp      AS LONG      '
          STATIC hBrush    AS LONG      '
          STATIC hPen      AS LONG      '
        
          GetClientRect hWnd, r
          WinX = r.nRight - r.nLeft
          WinY = r.nBottom - r.nTop
        
          hDC = BeginPaint(hWnd, LpPaint)
          hMemDC = CreateCompatibleDC(hDC)
          hBmp = CreateCompatibleBitmap(hDC, WinX, WinY)
        
          SelectObject hMemDC, hBmp
        
          hBrush = CreateSolidBrush(%BLACK)
          FillRect hMemDC, r, hBrush
          DeleteObject hBrush
        
          yOfs = WinY * .3
        
          hPen = CreatePen(%PS_SOLID, 2, %GREEN) ' <---- can't get "1" to work here
          SelectObject hMemDC, hPen
        
          RHO = 300 - ((WinX / 800) * 300)
          D = 2000
        
          THETA = .1
          S1 = SIN(THETA)
          C1 = COS(THETA)
        
          IF PHI THEN
            PHI = PHI+0.1
          ELSE
            PHI = 1.3
          END IF
          S2 = SIN(PHI)
          C2 = COS(PHI)
        
          DIM YMIN(0 TO WinX), YMAX(0 TO WinX)
          FOR I = 0 TO WinX : YMIN(I) = WinY \ 2 : NEXT I
        
          FOR X = 12 TO -12 STEP -.5
            FL = 0
            FOR Y = -12 TO 12 STEP .2
              W = X*X + Y*Y
              Z = FF(X, Y)
        
              XE = -X*S1 + Y*C1
              YE = -X*C1*C2 - Y*S1*C2 + Z*S2
              ZE = -X*S2*C1 - Y*S1*S2 - Z*S2 + RHO
              SX = D*XE/ZE + (WinX \ 2)
              SY = (-5*D*YE/ZE/12) + 120
        
              IF SX < 0 OR SX > WinX THEN OutOfRange
              IF FL = 0 THEN FL = 1 : F = 0 : GOTO OutOfRange
              DX = OLDX - SX : IF DX = 0 THEN DX = 1
              SL = (OLDY - SY) / DX
              YP = OLDY
        
              FOR XP = INT(OLDX) + 1 TO SX
                YP = YP + SL
                IF YP <= YMIN(XP) THEN
                  YMIN(XP) = YP
                  IF F = 0 THEN XX = XP: YY = YP : F = 1
                  MoveToEx hMemDC, XX, YY+yOfs, BYVAL %NULL
                  LineTo hMemDC, XP, YP+yOfs
                  XX = XP
                  YY = YP
                END IF
                IF YP >= YMAX(XP) THEN
                  YMAX(XP) = YP
                  IF F = 0 THEN XX = XP: YY = YP : F = 1
                  MoveToEx hMemDC, XX, YY+yOfs, BYVAL %NULL
                  LineTo hMemDC, XP, YP+yOfs
                  XX = XP
                  YY = YP
                END IF
                F = 0
              NEXT XP
        OutOfRange:
              OLDX = SX : OLDY = SY
            NEXT Y
          NEXT X
        
          BitBlt hDC, r.nLeft, r.nTop, Winx, WinY, hMemDC, 0, 0, %SRCCOPY
          DeleteObject hPen
          DeleteObject hMemDC           ' 2000/1/17 added at Kev Peel's suggestion.
          DeleteObject hBmp             '
          DeleteDC hDC                 '  not ReleaseDC.
          EndPaint hWndShow, LpPaint
        
        
        END SUB
        
        FUNCTION WINMAIN (BYVAL hInstance     AS LONG, _
                          BYVAL hPrevInstance AS LONG, _
                          lpCmdLine           AS ASCIIZ PTR, _
                          BYVAL iCmdShow      AS LONG) AS LONG
        
          LOCAL Msg         AS tagMsg
          LOCAL wndclass    AS WndClassEx
          LOCAL szAppName   AS ASCIIZ * 80
          LOCAL hWnd        AS LONG
          LOCAL hTimer      AS LONG
        
          szAppName              = "GDIWINDOW"
        
          wndclass.cbSize        = SIZEOF(WndClass)
          wndclass.style         = %CS_HREDRAW OR %CS_VREDRAW
        
          wndclass.lpfnWndProc   = CODEPTR( WndProc )
        
          wndclass.cbClsExtra    = 0
          wndclass.cbWndExtra    = 0
          wndclass.hInstance     = hInstance
          wndclass.hIcon         = %NULL
          wndclass.hCursor       = LoadCursor( %NULL, BYVAL %IDC_ARROW )
          wndclass.hbrBackground = GetStockObject( %BLACK_BRUSH )
          wndclass.lpszMenuName  = %NULL
          wndclass.lpszClassName = VARPTR( szAppName )
          wndclass.hIconSm       = LoadIcon( hInstance, BYVAL %IDI_APPLICATION )
        
          RegisterClassEx wndclass
        
          ' Create a window using the registered class
          hWnd = CreateWindow("GDIWINDOW",_              ' window class name
                              "PowerBASIC GDI Test", _   ' window caption
                              %WS_OVERLAPPEDWINDOW, _    ' window style
                              %CW_USEDEFAULT, _          ' initial x position
                              %CW_USEDEFAULT, _          ' initial y position
                              %CW_USEDEFAULT, _          ' initial x size
                              %CW_USEDEFAULT, _          ' initial y size
                              %NULL, _                   ' parent window handle
                              %NULL, _                   ' window menu handle
                              hInstance, _               ' program instance handle
                              BYVAL %NULL)               ' creation parameters
        
          hTimer = SetTimer(hWnd, 0, 500, BYVAL %NULL) 'Timer event every .5 Secs
                                                       'Alan Dalgliesh added this
          ShowWindow hWnd, iCmdShow
          UpdateWindow hWnd
        
          WHILE GetMessage(Msg, %NULL, 0, 0)
            TranslateMessage Msg
            DispatchMessage Msg
          WEND
        
          KillTimer hWnd, 0   ' Destroy the timer ... added by Alan Dalgliesh
        
          FUNCTION = msg.wParam
        
        END FUNCTION  ' WinMain
        
        '------------------------------------------------------------------------------
        
        FUNCTION WndProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _
                          BYVAL wParam AS LONG, BYVAL lParam AS LONG) EXPORT AS LONG
        
        '  LOCAL hDC       AS LONG          2000/1/17 Kev Peel's comments,
        '  LOCAL LpPaint   AS PaintStruct   I notice these aren't used
        '  LOCAL tRect     AS Rect          so I'm commenting them out.
        
          STATIC First    AS LONG
        
          SELECT CASE wMsg
        
            CASE %WM_CREATE
        
        '    CASE %WM_LBUTTONDOWN  ... changed to line below by Alan Dalgliesh
            CASE %WM_Timer
              InvalidateRect hWnd, BYVAL %NULL, %TRUE
        
            CASE %WM_ERASEBKGND
              IF First = 0 THEN
                First = 1
              ELSE
                FUNCTION = 1
                EXIT FUNCTION
              END IF
        
            CASE %WM_PAINT
              Plot hWnd
              FUNCTION = 0
              EXIT FUNCTION
        
            CASE %WM_DESTROY
              PostQuitMessage 0
              FUNCTION = 0
              EXIT FUNCTION
        
          END SELECT
        
          FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)
        
        END FUNCTION

        Comment


          #5
          Whew... there are certainly a few GDI resource leaks... as far as I remember, Dave's GDI code was never finished so it may be that you have inherited a bug or two.

          The most obvious leak is in the PLOT() routine... the variable "hWndShow" should be "hWnd", which means that EndPaint() is failing on each iteration to release the device context successfully.

          Also, the final section of PLOT() that is supposed to release GDI objects is failing miserably! I'll revise this section of code for you off-line and post the "amendments" back here later on when I'm back it my DEV PC.

          -------------
          Lance
          PowerBASIC Support
          mailto:[email protected][email protected]</A>
          Lance
          mailto:[email protected]

          Comment


            #6
            Regarding the resource leak problem in the GDI.BAS code by Dave Navarro, I still
            haven't found a solution. In your last reply, Lance, you point out that "the final
            section of PLOT() that is supposed to release GDI objects is failing miserably", and
            offered to revise the code and post the "amendments".

            I'm really looking forward to that and hope to see them soon.

            Thanks. Alan.

            Comment


              #7
              I've been a little busy, but I intent to follow up my original post as time permits...


              -------------
              Lance
              PowerBASIC Support
              mailto:[email protected][email protected]</A>
              Lance
              mailto:[email protected]

              Comment

              Working...
              X
              😀
              🥰
              🤢
              😎
              😡
              👍
              👎