March 28, 2024, 10:38:43 PM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Window handler inside class

Started by LarryMc, August 16, 2007, 04:38:10 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

LarryMc

I writing a EB class that has a window in one of the methods.
The window requires a handler.

I have an inc file that has:
class MyClass
   declare _MyClass()
   declare MyClass()
   declare Edit(filename as string),int
   declare handler()
endclass


Inside my method:
sub MyClass::Edit(filename as string),int
   OPENWINDOW win,0,0,800,600,@NOAUTODRAW,0," Editor",&handler
   ...
endsub

It works with:
sub handler()
...
endsub

It doesn't work with:
sub MyClass::handler()
...
endsub

It gives me a "undefined variable - handler" error message.
Shouldn't it work like the latter?
Other subroutines work internal to the class like that.

Larry

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

Probably a parser change I need to make.  The & operator doesn't know about methods so try:

OPENWINDOW win,0,0,800,600,@NOAUTODRAW,0," Editor",&MyClass@handler
Ionic Wind Support Team

LarryMc

Worked like a champ. ;D

Thanks,

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

efgee

August 16, 2007, 06:16:07 PM #3 Last Edit: August 16, 2007, 10:50:19 PM by efgee
One question Paul:
while you are changing the parser could you please look into allowing a colon for a return type of a function?

You know for people that don't have the iBasic background it's pretty strange to have a comma before the return type.
It always looks like the parenthesis was misplaced and the last word is actually a parameter not the return type.

Here an example of what I mean:
Declare Import, _RegCloseKey Alias RegCloseKey(hkey:UINT),INT
Sub GetPath(cPath:INT,Opt bShortLong = TRUE:INT),STRING


After the change this would be possible too:
Declare Import, _RegCloseKey Alias RegCloseKey(hkey:UINT):INT
Sub GetPath(cPath:INT,Opt bShortLong = TRUE:INT):STRING


IMHO the syntax looks much cleaner and is in sync with defining the parameters of a function.

Would be nice if you would consider it.
Thanks
efgee

BTW: the comma after import looks strange too (for a Emergence newbie)  ;)

EDIT: changed a typo. Thanks Larry

LarryMc

August 16, 2007, 07:55:48 PM #4 Last Edit: August 16, 2007, 08:02:17 PM by Larry McCaughn
efgee said:
Quote...strange to have a colon before the return type...
I know you meant comma.

I would prefer Paul spend his time on more significant items.

And that suggested change would break 99 % of the programs that are currently working just fine.
All user programs that had subroutines would have to be changed.
All inc files with declarations would have to be changed.
All example programs that had declares would have to be changed.
Over 60% of the pages in the help files would have to be changed.

And if Paul changes the comma to a colon for Ebasic should he change it for Aurora also; with the same impact.

Unless it was made into a either/or setup the way the colon is now.

ie., you can use
hkey:uin
or
hkey as uint

I vote to leave it as is.

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

efgee

Larry, sorry for the confusion.

I didn't mean instead, but to allow both comma and colon at the same time.

Your example shows pretty good that it's possible to allow 'as' and ':' at the same time.

Also IMHO if such an addition would be added to Emergence it's a good idea to add this
to Aurora too. This change could attract more new users (even some from the Pascal area)  ;D

LarryMc

I give up.

It seems that Class methods that are window/dialog handlers have flaws somewhere.

In my 3 topics associated with this class I was trying to build I've run into the following:

1) Opening a window using with a class member as the window id and then opening a second window with the first windows id as the parent id causes the 2nd window to crash when you try to use it as a browser and pass it a valid url.

2) An int member variable (m_run) used in a waituntil run=0 for an opened window apparently isn't making it inside the window handler because the window won't close once opened but a print statement in the window handler says that the "onclose" is firing but the m_run variable is already 0 yet the window doesn't close.

Changing the class members to global (in the source file) makes everthing work correctly.

Attached is the source for the window won't close problem.

I'm cross-eyed from fooling with it.

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

sapero

August 18, 2007, 11:23:40 AM #7 Last Edit: August 18, 2007, 12:48:06 PM by sapero
OpenWindow with a method pointer will never work - would with static method - EB method always takes one (hidden) parameter, but you can code a wrapper for OpenWindow that will redirect the 'sub handler' to any method

Attached modified MyClass.eba - replaced OpenWindow with COpenWindow that takes additional parameter - 'this'. The 'this' and method pointer is appended to the window title, then passed to the oriiginal OpenWindow function with redirected handler, that reads the 'this' and method pointer from caption and calls the method.

// added RemoveProp

LarryMc

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

LarryMc

Sapero,
will your Copenwindow fix automatically take care of the parent id when I open a second window, like this?
OPENWINDOW m_win,0,0,800,600,@NOAUTODRAW,0,"CWyswygLM - Editor",&CWyswygLM@whandler
OPENWINDOW m_cont,0,0,800,580,@NOAUTODRAW|@NOCAPTION,m_win,"",&CWyswygLM@bhandler

and are the COpenwindow and _static2class() subroutines common( meaning I can open as many windows as I want with those exact routines) and not dedicated (like when a control is subclassed and I have to have a different one for each window I want to open)

My guess is that they are common.

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

sapero

Yes, they are shareable, the pointers are stored in window property. So you can open thousands windows using the COpenWindow.

And no, the original OPENWINDOW is unmodified, you must replace
OPENWINDOW(a,b,c,..., sub_handler)
with
COpenWindow(class_pointer, a,b,c,..., method_handler)

I've forgot to remove the window propeties. Quote from the SDK:
QuoteBefore a window is destroyed (that is, before it returns from processing the WM_NCDESTROY message), an application must remove all entries it has added to the property list. The application must use the RemoveProp function to remove the entries.

so in function _static2class right before "return result", paste this:
declare import, RemovePropA(hwnd as uint,name as string),int
if (@message = @iddestroy)
RemovePropA(hwnd, "procedure_")
RemovePropA(hwnd, "this_")
endif


After @iddestroy the window receives WM_NCDESTROY, also this is the good place to cleanup. I have updated the attachment.

LarryMc

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Barney

Sapero, you are incredible. Thank you for sharing this with us.

Barney

efgee

One question...
Added to the constructor and destructor a print command like this:
sub MyClass::MyClass()
print "constructor"
endsub

sub MyClass::_MyClass()
print "destructor"
endsub

and realized that the destructor is always called.

Did another test:
If the class init is not done when the main window is created, but the button is pressed:
SUB d1_handler
SELECT @MESSAGE
CASE @IDINITDIALOG
CENTERWINDOW d1
'MyClass zz
CASE @IDCLOSEWINDOW
'zz._MyClass()
CLOSEDIALOG d1,@IDOK
CASE @IDCONTROL
SELECT @CONTROLID
CASE BUTTON_1
IF @NOTIFYCODE = 0
                                               'test
MyClass zz
zz.Edit()
ENDIF
ENDSELECT
ENDSELECT
RETURN
ENDSUB

you can actually see that the constructor is only called once (when the object is created by clicking on the button) but the destructor is called all the time even if the object is not initialized.

This is really weird.
Or am I missing something?

Ionic Wind Support Team

The position of the variable has no effect, it has local scope no matter where you put it in the subroutine.  You should always define your variables at the beginning of a subroutine, unless you are dynamically creating them which would be proper in this case.

Ionic Wind Support Team

efgee

 ???

Paul, don't know how your answer is explaining why the destructor is not called once at object destruction but all the time and more than once...


Ionic Wind Support Team

zz is just a local variable, having it within a "select/case" block isn't doing what you think.  All locally defined classes are created when the subroutine starts and destructed when the subroutine ends, not within your select block.  So it is being created/destructed for EVERY message sent to your handler...Use a debug build and DEBUGPRINT instead of PRINT to see what I mean.  There is no block scoping of variables in Emergence like there is in C#

If you only wanted the object to be created/destucted when the button was pressed then you would need to create it dynamically, not statically as you are doing now.

pointer zz
zz = NEW(MyCLASS,1)
*<MyClass>zz.Edit()
DELETE zz

Paul.


Ionic Wind Support Team

efgee