Error in FreeGadget
BlitzPlus Forums/BlitzPlus Beginners Area/Error in FreeGadget
| ||
Sorry for my bad english... The code below shows errors: Win = CreateWindow("Test Window",50,200,400,140,0,17) buttonwin1=CreateButton("Win 1",50,10,300,40,Win) buttonwin2=CreateButton("Win 2",50,60,300,40,Win) Repeat event = WaitEvent() If event = $401 If EventSource()=buttonwin1 Win1 = CreateWindow("Window 1",510,200,400,140,0,17) CreateLabel("Close this window, please...",10,10,300,100,win1) EndIf If EventSource()=buttonwin2 Win2 = CreateWindow("Window 2",510,200,400,140,0,17) CreateLabel("Close this window, please...",10,10,300,100,win2) EndIf End If If event = $803 And EventSource() = win1 Then FreeGadget win1 If event = $803 And EventSource() = win2 Then FreeGadget win2 If event = $803 And EventSource() = win Then End Forever End Follow the steps after running the code: 1º - Click in the button 'Win 1' 2º - Close the Window 'Window 1' 3º - Click in the button 'Win 2' 4º - Close the Window 'Window 2' An error message will appear.. |
| ||
No error here, version 1.47 of BlitzPlus. Windows 7 64-bit. |
| ||
Thanks. My Windows is 8 pro 64-bit and in various tests this error is being displayed. I solved this problem as follows: Win = CreateWindow("Test Window",50,200,400,140,0,17) buttonwin1=CreateButton("Win 1",50,10,300,40,Win) buttonwin2=CreateButton("Win 2",50,60,300,40,Win) Repeat event = WaitEvent() If event = $401 If EventSource()=buttonwin1 Win1 = CreateWindow("Window 1",510,200,400,140,0,17) CreateLabel("Close this window, please...",10,10,300,100,win1) EndIf If EventSource()=buttonwin2 Win2 = CreateWindow("Window 2",510,200,400,140,0,17) CreateLabel("Close this window, please...",10,10,300,100,win2) EndIf End If If event = $803 And EventSource() = win1 Then DestroyWindow(QueryObject(win1,1)) If event = $803 And EventSource() = win2 Then DestroyWindow(QueryObject(win2,1)) If event = $803 And EventSource() = win Then End Forever End And add this lines in User.decls: .lib "user32.dll" DestroyWindow%(hwnd):"DestroyWindow" |
| ||
I've just noticed that there is an error after all. My laptop has Windows 8 64-bit, but doesn't have BlitzPlus installed. So I thought I would test it by compiling on my desktop PC and running the .exe on the laptop. I built the .exe and first tried it on my desktop. "Invalid Gadget Handle". There was no such error when running from the IDE. |
| ||
Hello. I hate to sound stupid but, I've never understood, or found, any information to explain what user.decls is, where it is or, what it does. Can someone point me to that link or explain? |
| ||
Sorry for my english... -> Floyd, The error is show in first or second example? -> dna, The user.decls is found in: C:\Program Files\BlitzPlus\userlibs this file add others features to Blitz. API's of dlls from Windows or others dlls. Various examples: http://www.blitzbasic.com/codearcs/codearcs.php?cat=10&order=&asc=&lang_id=1 For example, in this code: http://www.blitzbasic.com/codearcs/codearcs.php?code=3173 you need to add the lines in users.decls: .lib "shell32.dll" api_ExtractIcon% ( hWnd%, File$, Index% ) : "ExtractIconA" .lib "user32.dll" api_SendMessage% (hwnd%, wMsg%, wParam%, lParam%) : "SendMessageA" If the line '.lib "shell32.dll"' or '.lib "user32.dll"' exist, you just add the other lines below the correct headers... |
| ||
The error is with the original example. It did not happen running from IDE but did with standalone exe. To use whatever.dll with Blitz you need a corresponding whatever.decls file, which goes in the \userlibs folder. It is a plain text file created with an editor such as NotePad. The user32.dll is part of Windows. user32.decls is here: decls for user32.dll Use this to make a plain text file and save it with the name user32.decls in your BlitzPlus\userlibs folder. If you just want to try the example code in this thread, using only one function in user32.dll, then you can use a .decls file consisting of just the two lines: .lib "user32.dll" DestroyWindow%(hwnd):"DestroyWindow" |
| ||
I am so sorry for my terrible explanation here, if it really isn't clear, then let me know, I can try to elucidate further! ___________________ I don't believe this is necessarily a bug, but more because there is still a check being made to a populated handle variable although the gadget to which it points no longer exists. I think it's simply that, on execution, when processing If event = $803 And EventSource() = win1 Then FreeGadget win1 If event = $803 And EventSource() = win2 Then FreeGadget win2 It is trying to close a window that has already been closed because the handle is recycled for use so both win1 and win2 variables hold the same value. I could recreate the error message using the compiler in debug mode, but The following works without issue (notwithstanding of course, attempting to open multiple windows of the same # ): Win = CreateWindow("Test Window",50,200,400,140,0,17) buttonwin1=CreateButton("Win 1",50,10,300,40,Win) buttonwin2=CreateButton("Win 2",50,60,300,40,Win) Repeat event = WaitEvent() If event = $401 If EventSource()=buttonwin1 And (win1=0) win1 = CreateWindow("Window 1",510,200,400,140,0,17) CreateLabel("Close this window, please...",10,10,300,100,win1) DebugLog win1 EndIf If EventSource()=buttonwin2 And (win2=0) win2 = CreateWindow("Window 2",510,200,400,140,0,17) CreateLabel("Close this window, please...",10,10,300,100,win2) DebugLog win2 EndIf End If If event = $803 If (EventSource() = win) End Else If (EventSource()=win1) FreeGadget win1 win1=0 Else If EventSource()=win2 FreeGadget win2 win2=0 End If End If End If End If Forever |
| ||
A clearer explanation: Program is run. Button 1 is pressed. window 1 created - win1 populated with handle for gadget window 1. window 1 closed. win1 freed in memory. win1 still contains value for handle, although is not longer valid. Button 2 is pressed. window 2 created - win2 populated with handle for gadget window 2. window 2 closed. win2 freed in memory. win2 still contains value for handle, although is not longer valid. However a the point in code, "If (EventID=¤803) And EventSource()=win1 Then FreeGadget win1" Both Win1 and Win2, since they are opened then freed separately, are both given identical handles. (It kinda makes sense to re-use handles once they're freed and done with) However, the win1 and win2 values are still populated. Therefore, regardless of which window is actually closed in which order, provided one is created after the other is freed, the newly opened one will have the same handle as the previously closed one. Therefore, "win1", being the first check as the program runs, will count as valid, since both will be the same. And the window with that handle will be freed, whether it is window 1 or window 2. The next line, "If (EventID=¤803) And EventSource()=win2 Then FreeGadget win2" WIll also consider the EventSource as valid, since the 803¤ event had occurred with the win1 or win2 source being exactly the same. The difference, now, however, is that unfortunately, we've already Freed the actual gadget to which that handle points. Therefore, ther returned error is "Invalid Gadget Handle" It is here that the failure of the original code comes in. Essentially there was a memory leak because you had two variables pointing to the same data and neither variable was adjusted to reflect when the data was cleared from memory. ____ So my solution simply ensured that the particular win1 or win2 variable is nullified once the data it points to is cleared and to ensure that the source is accurately considered. |
| ||
Thanks. I had not paid attention to this detail. |