Updated on 2023-03-14:
I used this technique in my real application and observed very unexpected behavior. During initial testing everything seemed to be working fine. But now i am sure this technique is dangerous.
I was getting error : event must be declared before it can be used
This same error was used to happened even before this technique was used and it could easily be resolved by regenerating child object first before regenerating the parent object. But after using this TriggerEvent() on Create, there was no way for me to get rid of the error. I am not sure what went wrong. I had to revert my code completely and abandoned this _create() event idea. This took my 2 days work. Do what you think is right.
Regards,
Berka
Answer updated: 2023-02-01
Objective is to fire a window event before any of the constructor events that exist in control array of that window. And of course even before windows own Open event. And it is not possible to do in design mode So need to edit source of the window.
Look for place in source where your custom events are defined. If you have no custom event defined you can define one temporary event in design mode and again open the source and look for the event. It will be under 'global type w_yourwindowname from window' and above 'global w_yourwindowname'.
Once you found the right location you will add your new event _create(). Lets say there were 5 custom events you defined in design mode and now you want to define another event but this one goes in text mode(the window source).
My window has following
global type w_yourwindowname from window
integer x = 23
integer y = 188
integer width = 3936
integer height = 2048
boolean titlebar = true
string title = "W-ah-just-test"
long backcolor = 79741120
boolean center = true
integer animationtime = 50
event ue_save ( )
event ue_retrieve ( )
event ue_delete ( )
event ue_add ( )
event ue_close ( )
event _create ( )
logo logo
st_screen_title st_screen_title
dw_1 dw_1
global w_yourwindowname
Step 1:
What you need to do is that you add name of the new event (i used _create) at the end of list of other custom event. You can add before start of the list of other events or after other events it does not make any difference. I added at the end like this event _create ( ) as you can see above.
Step 2:
Now you need to write the create statement for your _create() event. You can write that at the end of the source. I checked it does not make any difference you can write the create statement after 'end on' of destroy block. How you write the create statement is as following but don't forget to trigger it for parent if window source you are editing was inherited from another window otherwise just trigger the event. If i am editing w_child and it is inherited from w_sheet then you have to do Parent.TriggerEvent. If w_sheet has no parent and you are adding _create event in it then you do just the TriggerEvent. (made correction in this Step 2 today)
/// i was editing w_child so i did the following. really have no idea why.
on create
Parent.TriggerEvent("_create")
end on
This method has nothing to do with inheritance but i added it same way in my real app that has few levels of inheritance. And it worked for me. The important point is that _create() does not depend on existence of any other controls of the window array which previously was assumed as requirement. Please Digg further on your own and don't do it like Russia did with kola project. There may be new world on the other end. :)
enjoy!
Update: Its quite simple. After you have defined the _create() event under global types, all you need to do is trigger _create from "on create" block of code. for example you are editing source of w_sheet and w_sheet is not inherited from any other object. Just go to the on create block for w_sheet and write trigger statement.
Parent.TriggerEvent("_create")
now _create() event will fire before any other constructor because you trigger it in on create
OLD Text :
1st thing that confused me too was inheritance. So i decided to get rid of it. because objects inheritance is created the way we want and was not the main objective of this question at 1st place.
I would describe this question in this way now
w_win has no parent (not inherited)
dw_1 has no parent (not inherited)
dw_2 has no parent (not inherited)
Events: constructors() and open have 1 message in each of them just to show who fires first.
If I run project the messages in constructors will fire 1st and then in the end open will show its message.
That is not what i wanted. I need a way of open message show up first and then in any order remaining 2 messages from constructors show up.
How:
Well the open event wont let me do it. so need to create a custom event in w_win but not fired from any other event. Also create dw_1 and dw_2 and write messages in constructors. one message goes in the custom event also to see constructors fires their messages 1st or the custom event of w_win
After saving w_win i open source of the w_win and change it the following way. Have to do it because found no other way to handle this problem but it works for me. Please check
forward
global type w_main from window
end type
type dw_2 from datawindow within w_main
end type
type dw_1 from datawindow within w_main
end type
type life_line from line within w_main
end type
end forward
global type w_main from window
integer width = 100
integer height = 100
event _create ( )
dw_2 dw_2
dw_1 dw_1
life_line life_line
end type
global w_main w_main
event _create();
Messagebox("hey", "Im in before everyone else")
end event
on w_main.create
this.dw_1=create dw_1
this.dw_2=create dw_2
this.life_line=create life_line
this.Control[]={this.dw_1,&
this.dw_2,&
this.life_line}
end on
on w_main.destroy
destroy(this.dw_1)
destroy(this.dw_2)
destroy(this.life_line)
end on
event timer;
Close(This)
end event
type dw_2 from datawindow within w_main
end type
event constructor;
MessageBox("coz", "soon enough weil die")
Timer(1)
end event
type dw_1 from datawindow within w_main
end type
event constructor;
MessageBox("Well, dont leave", "without saying goodbye")
end event
type life_line from line within w_main
end type
on create
Parent.TriggerEvent("_create")
end on
That was not i was thinking to do at first. i was thinking to use combination of send() and custom event pbm_ but i will try the idea later. The above idea came from reading all the solutions given by you guys.
As you can see i used a line object and its ON CREATE will not be erased by PowerBuilder compiler if w_win is changed in design mode. And that is it, just fired the _create custom event.
And the inheritance model will take the line in very top most window as the very 1st control in the control[] array.
That is how it works for me. Please suggest better way you might do it.
Thank you. I defined it in top most window. design mode does not remove it neither regeneration removes it. all inherited windows fire _create before constructors.
Regards,
Berka