1. Berka Frenfert
  2. PowerBuilder
  3. Thursday, 25 August 2022 13:42 PM UTC

Hi,

Is there any way i can fire an event even before any constructor of any control in that window.

I need just 1 event that fire only once and before all other events. even before open and constructor.

Problem is that many constructors keep firing in my window and i cant figure out their order and cannot restrict which one gonna fire first.

I think window should have some event but i think there is no such standard window event. May be custom events have that option but i have no idea which one to use.

Please guide ..

Thanks a lot

 

Who is viewing this page
Accepted Answer
Berka Frenfert Accepted Answer Pending Moderation
  1. Thursday, 1 September 2022 08:29 AM UTC
  2. PowerBuilder
  3. # Permalink

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.

 

 

 

 

 

Comment
  1. Roland Smith
  2. Friday, 17 February 2023 14:25 PM UTC
I tried this and it works. The window painter removes the triggerevent call when saving. It would be best to add this to an ancestor window.
  1. Helpful 2
  1. Berka Frenfert
  2. Tuesday, 28 February 2023 13:11 PM UTC
Hi Roland,

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
  1. Helpful
There are no comments made yet.
Olan Knight Accepted Answer Pending Moderation
  1. Friday, 26 August 2022 18:24 PM UTC
  2. PowerBuilder
  3. # 1

Simple.

At the very top of the Constructor event in the top-inheritance-level of your object, add the following code:

ll_return = this.ue_preConstructor ()

Then add the ue_preConstructor() event to the object.

Comment
  1. mike S
  2. Saturday, 27 August 2022 12:21 PM UTC
note that by assigning the return value it forces the triggering of the event (i assume this is an event and the event keyword was omitted).

If you omit the "ll_return = " then it gets posted and the code will not run first.



I would explicitly use the trigger keyword to make it clear what you want it to do: ll_return = event trigger ue_preConstructor()
  1. Helpful
  1. Olan Knight
  2. Monday, 29 August 2022 13:54 PM UTC
Fair enough! :)



ll_return = this.EVENT ue_preConstructor ()

  1. Helpful
  1. Berka Frenfert
  2. Thursday, 1 September 2022 08:35 AM UTC
For me in this situation, Parent.TriggerEvent("_create") is good because it wont raise error
  1. Helpful
There are no comments made yet.
John Fauss Accepted Answer Pending Moderation
  1. Thursday, 25 August 2022 15:23 PM UTC
  2. PowerBuilder
  3. # 2

Hi, Berka -

IF... your windows have a common, base ancestor window that does not contain any visual controls (called w_base, for example). then you can place a hidden visual control such as a static text control in w_base and place code in the static text control's Constructor event. As long as the window's Open event is not overridden in a descendant window, the hidden static text control's Constructor event should fire first before the Constructor event in the controls in descendant windows, since the base ancestor window class is instantiated before a descendant's class.

Maybe worth a try, if applicable to your situation?

Best regards, John

Comment
  1. Berka Frenfert
  2. Thursday, 1 September 2022 09:08 AM UTC
Yes, that is exactly i did the w_base with a hidden control worked for me. with little change , i used ON CREATE of the hidden control instead of its constructor. Thanks a lot



Regards,
  1. Helpful
  1. John Fauss
  2. Thursday, 1 September 2022 13:24 PM UTC
I'm really glad to hear the Community 'team" could help you find an acceptable solution, Berka. Good luck on your project!
  1. Helpful
There are no comments made yet.
Roland Smith Accepted Answer Pending Moderation
  1. Thursday, 25 August 2022 14:30 PM UTC
  2. PowerBuilder
  3. # 3

I am pretty sure the constructor events occur in the order they are in the Control array of the window. If you could add a non-visual control that came first in the array, you could put your special code in it's constructor event.

Here is a snippet from one of my windows. You should be able to manually change the control order in these three sections.

global type w_main from window
integer width = 3598
integer height = 1908
boolean titlebar = true
string title = "Native PDF"
boolean controlmenu = true
long backcolor = 67108864
string icon = "AppIcon!"
boolean center = true
cb_process cb_process
dw_1 dw_1
cb_cancel cb_cancel
end type
global w_main w_main

on w_main.create
this.cb_process=create cb_process
this.dw_1=create dw_1
this.cb_cancel=create cb_cancel
this.Control[]={this.cb_process,&
this.dw_1,&
this.cb_cancel}
end on

on w_main.destroy
destroy(this.cb_process)
destroy(this.dw_1)
destroy(this.cb_cancel)
end on
Comment
  1. Berka Frenfert
  2. Thursday, 1 September 2022 08:53 AM UTC
Hi Roland, Thanks to you. the idea in my mind of changing source came from your response. It worked nicely.
  1. Helpful 1
There are no comments made yet.
Chris Pollach @Appeon Accepted Answer Pending Moderation
  1. Thursday, 25 August 2022 14:02 PM UTC
  2. PowerBuilder
  3. # 4

Hi Berka;

  I have never had to use this type of processing timing but as a guess, I would try the Window class's OTHER event and see if that fires before any Window Control's constructor event.  HTH

Regards ... Chris

Comment
  1. Berka Frenfert
  2. Thursday, 1 September 2022 07:51 AM UTC
:)

Hi Chris,

I could not find the custom event. I will try again later if the other way i found yesterday will not work in my real project. So far its good to go.
  1. Helpful
  1. Berka Frenfert
  2. Thursday, 1 September 2022 09:40 AM UTC
Can you help me to list of all windows system events in order they are fired. I used the Process Monitor but could not see exactly what i am looking for. Thanks a lot.



Regards,
  1. Helpful
  1. Chris Pollach @Appeon
  2. Thursday, 1 September 2022 11:35 AM UTC
Yes, you would need the Microsoft Spy++ utility for that.
  1. Helpful
There are no comments made yet.
Andreas Mykonios Accepted Answer Pending Moderation
  1. Thursday, 25 August 2022 14:00 PM UTC
  2. PowerBuilder
  3. # 5

Also if your issue is based on inheritance (as you speak about many constructors), then you may consider disabling "Extend Ancestor Script" option, using instead super to call ancestor's events when needed. But this may be a difficult task, and you may run in a lot of issues, if you are not sure how your object's inheritance is designed to work.

Andreas.

Comment
  1. Berka Frenfert
  2. Tuesday, 30 August 2022 10:42 AM UTC
Instance variable TheParentWin is declared in uo_dw and GetParent() in a loop sets it when TypoeOf() = Window! . Constructor event of uo_dw does it. So, all the uo_dw controls in a window do the same. Thats the problem because new translation process taking time and i want to avoid that loop.

Recently got too busy in many things and still looking for a good time to check all the solutions given. Thanks a lot.



Regards,
  1. Helpful
  1. Miguel Leeuwe
  2. Tuesday, 30 August 2022 11:41 AM UTC
That "loop" will take very very little time to run. Also, if "TheParentWin" is in all of your uo_dw objects, they should all run the code. If one uo_dw gets the parent window, the other uo_dw objects won't know about it, unless they run the same code to assign TheParentWin.

regards
  1. Helpful
  1. Berka Frenfert
  2. Thursday, 1 September 2022 09:31 AM UTC
Exactly, loop takes no time, and other constructors repeat same thing. It was no issue until translation of English was not needed. I really got upset that day when i was exploring another way around. One little thing was missing and that was the create event of window. I thought open and create are two separate things and that is why a window's open have to wait constructors to complete their job. That is why i said its too annoying when leaves keep growing but root is no where. But actually, if you look into source of a window, you will see that window's On CREATE goes before all constructor of other controls. Obviously if control[] array does not exist how could constructors get fired. So, root is created first and leaves follows. So i needed a ON CREATE but when i changed ON CREATE of window in its source, PowerBuilder was reverting it back in design mode. Strange thing happened when i used ON CREATE of other controls, like a line control and to my surprise design mode was not reverting it. There i got the new idea and solved this problem. Please the the answer i posted today. Thanks a lot.
  1. Helpful
There are no comments made yet.
Andreas Mykonios Accepted Answer Pending Moderation
  1. Thursday, 25 August 2022 13:52 PM UTC
  2. PowerBuilder
  3. # 6

Hi.

If you really need an event or function to fire before window constructor, then you possibly don't need it as an event in that window. The constructor is the first event that fires upon any object creation. You may consider to create a global function that will do whatever you want to accomplish, and that will be called just before opening the window. That's my opinion.

Andreas.

Comment
  1. Andreas Mykonios
  2. Thursday, 25 August 2022 14:18 PM UTC
Try to describe as root event and leaves.

Andreas.
  1. Helpful
  1. Andreas Mykonios
  2. Thursday, 25 August 2022 14:19 PM UTC
In your case of course.
  1. Helpful
  1. Berka Frenfert
  2. Thursday, 1 September 2022 10:06 AM UTC
Thanks a lot for suggestions. I agree with you. We cannot explain everything by just typing in this support forum. The way inheritance i used might not be the best way to do it. and certainly its true, i would do it different way if i do it again after 2 decades. But, to make things much more simpler and understandable, we follow rues of nature. A child is born before he/she starts crying. :) Strange example right ?

A window need to have a create event and fired much before its open event, even much before existence of its own children.

Examples of other software systems can prove it right. But lets not worry about it too much. We know PowerBuilder took decades to reach 64bit (if its true). I know i have to keep fixing things that are not even any sort of problems in other programming environments. And thats where my company found me very useful.

  1. Helpful
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.