Announcement

Collapse
No announcement yet.

PBDLL 6 GDI.BAS hangs after a few minutes

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

  • Lance Edmonds
    replied
    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>

    Leave a comment:


  • Alan Dalgliesh
    Guest replied
    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.

    Leave a comment:


  • Lance Edmonds
    replied
    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>

    Leave a comment:


  • Alan Dalgliesh
    Guest replied
    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

    Leave a comment:


  • Lance Edmonds
    replied
    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>

    Leave a comment:


  • K Peel
    Guest replied

    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>

    Leave a comment:


  • Alan Dalgliesh
    Guest started a topic PBDLL 6 GDI.BAS hangs after a few minutes

    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.
Working...
X
😀
🥰
🤢
😎
😡
👍
👎