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>
Announcement
Collapse
No announcement yet.
PBDLL 6 GDI.BAS hangs after a few minutes
Collapse
X
-
Guest repliedRegarding 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:
-
-
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:
-
-
Guest repliedThanks 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:
-
-
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:
-
-
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:
-
-
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.
Tags: None
-
Leave a comment: