View Full Version : Problem Leaving Callback Function
gungadout
03-03-2010, 06:12
Hi Folks,
I'm having problems exiting a window by means of button clicking. The window exits OK when the X button in the corner is clicked.
In the code snippet below, messagebox displays prove that the callback logic for the Exit and Logoff buttons is being entered, and that the presence of the messageboxes does not interfere with the overall logic. (See the Case %WM_CLOSE.)
Clicking on the X triggers the "Back from cbDialogMenu" popup and closes the window, as wanted and expected.
Clicking on the Exit or Logoff button does not trigger the "Back from cbDialogMenu" message.
(As you will see, I've also tried using Dialog End instead of Exit Function, but that kills everything immediately, including the procedure (major function) from which the Callback function was initiated.)
I'd love to know what I am doing wrong.
Thanks,
Peter H. (gungadout)
.
.
.
Dialog Show Modal hDlgMenu, Call cbDialogMenu
MsgBox (0, "Back from cbDialogMenu")
End Function
CallBack Function cbDialogMenu()
Select Case Callback_Message
Case %WM_COMMAND
Select Case Callback_Control
Case %btnExit
' MsgBox(0, "btnExit clicked")
MenuTreeLevel -= 1
' Dialog End hDlgMenu
Exit Function
Case %btnTop
MenuTreeLevel = 1
' Dialog End hDlgMenu
Exit Function
Case %btnLogoff
' MsgBox(0, "btnLogoff clicked")
LogOffFlag = 1
MenuTreeLevel = 0
' Dialog End hDlgMenu
Exit Function
End Select
Case %WM_CLOSE
' MsgBox(0, "Close (x) clicked")
MenuTreeLevel = 0
LogOffFlag = 1
' Dialog End hDlgMenu
Exit Function
End Select
End Function
D.J.Peters
03-03-2010, 06:49
normaly in other programing languages it will work like this
(sorry if it isn't the right hint for you)
Joshy
...
case WM_CLOSE
DestroyWindow(hWin or hDialog)
case WM_DESTROY
PostQuitMessage(0)
...
gungadout
03-03-2010, 08:16
Hi Joshy,
Thanks for the tips.
They did not work directly, but led me on a chase that was fruitful.
I needed to say Dialog End CBHNDL rather than Dialog End hDlgMenu.
I'm not sure why, but I'll do some homework to find out.
Regards,
Peter H. (gungadout)
Lionheart008
03-03-2010, 08:25
good morning, peter, joshy.
peter perhaps this little example helps, don't know.
' Empty GUI script created on 03-03-2010 07:11:50 by (ThinAIR)
Uses "UI"
'---Define a button ID
%ButtonClose = 1001
%ButtonX = 1002
%ButtonY = 1003
Dim hDlg As DWord
Dialog New 0, "hello peter :)",-1,-1, 330, 203, _
%WS_POPUP Or _
%WS_VISIBLE Or _
%WS_CLIPCHILDREN Or _
%WS_CAPTION Or _
%WS_SYSMENU Or _
%WS_MINIMIZEBOX, _
0 To hDlg
Control Add Button, hDlg, %ButtonClose, "Click to kill", 90, 50, 70, 30
Control Add Button, hDlg, %ButtonX, "X_Click ", 190, 50, 70, 30
Control Add Button, hDlg, %ButtonY, "Other_Clicks ", 20, 50, 70, 30
Dialog Show Modal hDlg Call cbDialog
'------------------------------------------------
' Callback function used to handle dialog events
'------------------------------------------------
CallBack Function cbDialog() As Long
Select Case CBMSG
Case %WM_COMMAND
If CBWPARAM = %ButtonClose Then Dialog End CBHNDL
If CBWPARAM = %ButtonX Then
MsgBox 0, "I close the app too"
Dialog End CBHNDL
End If
If CBWPARAM = %ButtonY Then
MsgBox 0, "I do quite other things and calculate: " + Str$(calculateMe() ), %MB_OK, "test for calc"
End If
Case %WM_DESTROY
MsgBox 0, "Window is to be destroyed."
End Select
End Function
Function calculateMe() As Long
Local a,b,c As Long
a=10
b=60
c= a*b
Function = c
End Function
better to show whole callback/ui example for finding errors, sometime there is missing only one or two little things. must go at work now.
best regards, frank
gungadout
03-03-2010, 09:53
Hi Folks,
I have returned to my normal confused state.
I checked the values of CBHNDL and hDlgMenu. They are the same.
So I changed the logic for one button back to Dialog End hDlgMenu. It worked.
So I changed all the buttons back. They all work now.
Sigh.
Regards,
Peter H. (gungadout)
Michael Clease
03-03-2010, 09:57
Peter in your callback routine it will return the handle from its calling window into CBHNDL if you also store this handle when creating the window they are going to be the same, its how windows references the window.
ErosOlmi
03-03-2010, 10:30
Peter,
Michael already explained the situation.
Worth few words more.
CALLBACKs functions are functions automatically executed when an event occurs in a window (remember that for Microsoft Windows everything is a window: a dialog, a button, a menu, ...). To make it simple, just know that when CALLBACKs are executed it is important to know the handle of the window that generated the event plus other data. Windows automatically pass those info to callbacks. thinBasic internally get those info and populate pseudo variable CB* like CBHNDL, CBWPARAM, ... and so on
If you store the handle of the window into a global variables of course it will be the same as CBHNDL but what if you decide to have more than one window and just one single callback function? This is perfectly possible. But now how can you know the handle of the window that fired the event?
So, my suggestion is to avoid as much as possible (better to avoid always) to use personal variables when you refer to windows handle inside a callback and always use CB* pseudo variables. You code will be much easier to be read and what is important will be much easier to maintain it in future. The best would be to avoid to use any global variable inside a callback and have callbacks function very general (no dependant from any other varoable). This will create great code very easy to be maintained.
Ciao
Eros
gungadout
03-03-2010, 23:11
Hi Folks,
Thank you (in order of posts) Frank (Lionheart008), Michael and Eros.
(Frank, I did not see your post until just now. It must have posted while my last post was waiting for me to hit the Post button, which I forgot to do for quite some time.)
Eros, the concept of having multiple windows all sharing the one callback function is new for me. I will think more on it.
At the moment, probably because of my inexperience in the thinBasic environment, I have created one specific callback and related sub functions for each window. Using the specific window handle in the code helps me to find any callback code segment I'm looking for with a quick eyeball scan, and for me makes the code more self-documenting. Ultimately, I may place the set of functions for each window into its own include file. (I realise that the use of specific window handles would be superfluous in such includes.)
Once again, thank you all for helping me with my learning experience.
Regards,
Peter H. (gungadout)
Michael Hartlef
04-03-2010, 18:07
Hi Folks,
Thank you (in order of posts) Frank (Lionheart008), Michael and Eros.
(Frank, I did not see your post until just now. It must have posted while my last post was waiting for me to hit the Post button, which I forgot to do for quite some time.)
Eros, the concept of having multiple windows all sharing the one callback function is new for me. I will think more on it.
At the moment, probably because of my inexperience in the thinBasic environment, I have created one specific callback and related sub functions for each window. Using the specific window handle in the code helps me to find any callback code segment I'm looking for with a quick eyeball scan, and for me makes the code more self-documenting. Ultimately, I may place the set of functions for each window into its own include file. (I realise that the use of specific window handles would be superfluous in such includes.)
Once again, thank you all for helping me with my learning experience.
Regards,
Peter H. (gungadout)
Hi Peter, was hDlgMenu defined as local? Then the callback routine doesn't know anything about it. Even if you had declared it inside a TBMAIN function.
gungadout
06-03-2010, 15:23
Hi Michael,
The hDlgMenu was and is defined with a DIM at the very top of the program, before the TBMAIN function. So were my other hDlg.... variables.
I predefine every variable I use, that way. (I don't think there are any exceptions, except maybe in code I've copied from examples.)
In the many legacy system languages I have used in the past (including assembly-level languages), generally speaking all variables were global, no matter where initially used, and they did not need predefinition or need to be typed. A statement like A = B in those languages was the equivalent of DIM A As Variant, followed by A = B.
I state this simply to indicate that the global existence of variables is a natural concept for me, and is not a source of confusion in any way. I am aware that people who have a different background to mine, might find the idea of having all variables global, to be confusing, although I would have difficulty understanding why.
The question for me is, instead of Dim-ing TemporaryVariableA in multiple places (in multiple functions), why not define it once only? Other people may validly ask, what if you accidentally use the same For Next loop counter more than once in nested functions? It is all a matter of perspective.
Thanks again for your continued interest.
Regards,
Peter H.
Michael Hartlef
06-03-2010, 15:42
Define it once as a global should do the job. I am not 100% sure if DIM is the same as GLOBAL. Means if you use DIM inside a function, is it global or local then.
Anyway, if a global hDlgMenu still doesn't do the job, than I would consider this as a bug. As long it is still filled with the same value like CBHNDL it should be able to be used.
Edit: Which datatype hDlgMenu was defined as?
ErosOlmi
07-03-2010, 10:05
In thinBasic beta versions there was a bug: CallBack_* pseudo variables bug when passed to functions as parameters.
http://community.thinbasic.com/index.php?topic=3218.msg24105#msg24105
The above bug was causing original post of Peter
As far as I understand using thinBasic 1.8 all problems are solved now, right?
_________________________________________________On defining variables: for thinBasic, unless you use the GLOBAL statement, all variables are LOCAL to the scope you define in.
So inside a function DIM and LOCAL are exactly the same.
_________________________________________________On programming style (GLOBAL and/or LOCAL) it is a personal matter.
Personally, whenever possible, I tend to create situations where a function never depends from global variables.
This mainly because that function will be very reusable.
Pseudo CallBacks Variables have been implemented exactly not to rely on global variables because Callbacks are executed asynchronously by the Operating system when an event occurs. Also inside a CallBack you can have many different events related to many different controls you can have on your window so it is important to keep coding very clear and pseudo variables does the job just fine.
_________________________________________________But again, every programmer has its style and experience. When you program alone you have one style, when you program in a group you have another style, when you program is quite little you can adopt a style, many times when your project start to have significant size and you need to maintain your projects over many years and from different persons, you ... change your style.
Ciao
Eros
gungadout
07-03-2010, 22:57
Hi (in order of recent posts) Michael and Eros,
Thank you both once again for your continued interest and help. My appreciation remains unabated.
Eros, yes, my problem is solved.
Michael, I used Dim hDlgMenu As Long.
In case there is any misunderstanding, the confusion expressed in my post of « Reply #4 on: March 03, 2010, 08:53:28 am », was triggered by my problem actually being solved :D. Everything worked using the global variables which had formerly appeared not to work.
I am presently blunting the edge of my sword battling other challenges, some at the database end.
Thanks again to all who have offered help on this and other matters.
Regards to all,
Peter H. (gungadout)