ControlsEx , SerialEx and FormExDesktop help needed.

RandomCoder

Well-Known Member
Licensed User
Longtime User
I'm having a hell'ish time today, thankfully it only happens every now and then :)

First of all using ControlsEx I have a program that works perfectly in the B4PPC environment but gives errors once compiled. By inserting MsgBoxes into my code I have found the the probelm is when I add Separators into my Toolstrip...

B4X:
   #Region Create Seperators For Ts

   'Create seperators for Tool Strip controls
   For x = 0 To 4
      Control( "SprTs" & x , "ToolStripSeperator" ).New1
      Control( "SprTs" & x , "ToolStripSeperator" ).AutoSize = False
      Control( "SprTs" & x , "ToolStripSeperator" ).Height   = 50
      Control( "SprTs" & x , "ToolStripSeperator" ).Width    = 30
   Next

   #End Region


   #Region Attach Controls To Ts

   'Add controls to Tool Strip
   [COLOR="Red"]FrmTs.AddItem( SprTs0.ControlRef )[/COLOR]
   FrmTs.AddItem( BtnTsOpen.ControlRef )
   FrmTs.AddItem( BtnTsSearch.ControlRef )
   [COLOR="red"]FrmTs.AddItem( SprTs1.ControlRef )[/COLOR]
   FrmTs.AddItem( BtnTsSave.ControlRef )
   [COLOR="red"]FrmTs.AddItem( SprTs2.ControlRef )[/COLOR]
   FrmTs.AddItem( BtnTsDelete.ControlRef )
   [COLOR="red"]FrmTs.AddItem( SprTs3.ControlRef )[/COLOR]
   FrmTs.AddItem( LblTsOrder.ControlRef )
   FrmTs.AddItem( TxtTsOrder.ControlRef )
   FrmTs.AddItem( LblTsBatch.ControlRef )
   FrmTs.AddItem( TxtTsBatch.ControlRef )
   [COLOR="red"]FrmTs.AddItem( SprTs4.ControlRef )[/COLOR]
   FrmTs.AddItem( BtnTsPreview.ControlRef )
   FrmTs.AddItem( BtnTsPrint.ControlRef )

   #End Region
If I remove the For Next loop and add each seperator normally it all works :confused:
The problem only presents itself when I run the compiled file!

The next problem I have is with using a SerialEx object on a Form that is attached to a FormExDesktop.New1( "FrmPrintCapture" ) when the SerialOnComm fires it causes B4PPC to close down. Removing the FormEx items and the problem goes away. I have tried to add the SerialEx object to the extended Form but it doesn't seem to work, Is this because I need to use a controlref property for which there isn't one?

I have tried...

FrmExLib.AddControl( Serial )
FrmExLib.AddControl( "Serial" )
FrmExLib.AddControl( Serial.ControlRef )
Where Serial is a SerialEx object and FrmExLib is a FormEx object


Sorry for being a nussiance, I've attempted to fix the problem myself but am now at a loss.

Regards,
RandomCoder
 

agraham

Expert
Licensed User
Longtime User
I suspect you mean ControlExDesktop and not ControlsEx. If your code is verbatim I think the problem with ToolStripSeparator is spelling! The IDE probably ignores the type name but the optimised compiler doesn't. However you don't say what the errors are and haven't posted an sbp that I can run to investigate it so I can't comment further.

Difficult to comment on the SerialEx problem as again you haven't shown the code or said whether there is an error when the program closes or whether it does so silently. This is a potentially complicated scenario because of what has to happen behind the scene to handle cross-thread events in a FormEx Sub. It may be worth trying Serial2 instead which I fully expect not to work either. I suspect a threading issue as Serial2 and SerialEx events run on a different thread to the Basic4ppc application, although I would have expected the OnComm event to not fire rather than closing the program. Try putting this line in App_Start of the FormEx.

FormExName.EnableThreadEvent("ModuleName.SerialExName", "OnCom", B4PObject(1))

You may have noticed the difference between the EnableOnComm property with two "m"s and the OnCom event with a single "m". This is copied from Serial2 to maintain SerialEx compatibility as a string superset of Serial2.

If this doesn't work you will need to post a small (ideally) sbp that shows the problem and I will take a look.
 

RandomCoder

Well-Known Member
Licensed User
Longtime User
Thanks for the response Agraham, I don't have time to properly respond now but just so that you know, I will try your suggestions and respond accordingly later.

PS Re: the spelling of ToolStripSeperator ,you are right in that this worked in the B4PPC IDE but when comipling it faulted with the object reference not set to an object kind of fault, I then changed the "e" to "a" which is what it should have been and it compiled fine but doesn't run. The fault mentions a missing object and thats when I tracked the fault down to the bit of code I posted.

Regards,
RandomCoder
 

agraham

Expert
Licensed User
Longtime User
I've knocked up this little program with SerialEx and FormExDesktop and it works fine when optimised compiled! You are not trying run your program in the IDE are you? That is likely die instantly if you do for reasons that I don't understand because I don't know what is happening in the IDE, which is interpreted rather than compiled, though it's bound to be a threading issue of some sort as FormEx is running on a thread that the IDE knows nothing about.
 

Attachments

  • Test.sbp
    1.1 KB · Views: 160

agraham

Expert
Licensed User
Longtime User
The fault mentions a missing object
It would be easier if you posted more complete code and error message details but I suspect you missed a line out
B4X:
For x = 0 To 4
  [COLOR="Red"]AddObject("SprTs" & x, "ToolStripSeparator" )[/COLOR]
  ...
Next
 

RandomCoder

Well-Known Member
Licensed User
Longtime User
@AGraham,

I had already added the separator objects using the IDE as this allows me to see the properties when I add a period at the end of their name.
BUT.. I have noticed that all objects get set to lower case and so I wondered if this may have something to do with my probelm. Therefore I've tried adding the separator objects in code as you demonstarted but now I get this error message....
---------------------------

---------------------------
Error compiling program.

Error message: Unknown control type. Use Control("_main_sprts0",Type) instead.

Line number: 65

Line: FrmTs.AddItem( SprTs0.ControlRef )
---------------------------
OK
---------------------------

Where am I going wrong :confused:

As for the serial problem, I had everything working within the IDE using a normal Form. I then did some work controlling the Form with your library and everything appeared to be OK, but at this point I wasn't firing the OnComm event. It was only when I compiled and tried my program that I realised I had a problem, and that this problem was also present within the IDE. I determined that the fault was somehow linked with the FormEXDesktop library and that was as far as my knowledge could extend.

For what I'm doing I could use the door library to set the Form size and show/hide the form as needed. Would this be a preferable when using SerialEx?

Kind Regards,
RandomCoder

PS The Sample is from my original program and so still contains the components and objects that I was using.
 

agraham

Expert
Licensed User
Longtime User
Where am I going wrong :confused:
It seems to be an optimising compiler quirk that Erel might like to think about. He might also take a look at the reason for that misleading "Use Control("_main_sprts0",Type)" error message.

Because you reference the separators statically "FrmTs.AddItem( SprTs0.ControlRef )" the compiler allocates a global reference for them. EDIT:- Actually I think it is because they are pre-specified as objects and not by AddObject( ... ). However by Newing them dynamically "Control( "SprTs" & x , "ToolStripSeparator" ).New1" those global references are not set and cause the error. If you also add them dynamically to the ToolStrip it works OK.
B4X:
For x = 0 To 4
  Control( "SprTs" & x , "ToolStripSeparator" ).New1
  Control( "SprTs" & x , "ToolStripSeparator" ).AutoSize = False
  Control( "SprTs" & x , "ToolStripSeparator" ).Height   = 50
  Control( "SprTs" & x , "ToolStripSeparator" ).Width    = 30   
 [COLOR="Red"] FrmTs.AddItem(Control( "SprTs" & x , "ToolStripSeparator" ).ControlRef)[/COLOR]
Next


For what I'm doing I could use the door library to set the Form size and show/hide the form as needed.
This will not work on a normal Form as you will see if you try it. The Backlayer and Forelayer code assumes a fixed Form size. Anyway why do you need to set the Form size with the Door library and not in the Designer?

As I noted before you will have the same problem with Serial2 and a FormEx running in the IDE but both will be OK when optimised compiled as in the example I posted. If you want to debug the serial handling code in a FormEx try my http://www.b4x.com/forum/additional-libraries/4487-debug-suite-optimised-compiled-apps.html
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
The compiler doesn't recognize SprtTs0 because it was added with a "not trivial" AddObject (Ex: AddObject("object1",someobject) is trivial and gives the compiler the required information about object1).
So you will need to reference these controls with the Control keyword:
B4X:
    FrmTs.AddItem( Control("SprTs0",ToolStripSeparator) .ControlRef )
    FrmTs.AddItem( BtnTsOpen.ControlRef )
    FrmTs.AddItem( BtnTsSearch.ControlRef )
    FrmTs.AddItem( Control("SprTs1",ToolStripSeparator).ControlRef )
    FrmTs.AddItem( BtnTsSave.ControlRef )
    FrmTs.AddItem( Control("SprTs2",ToolStripSeparator).ControlRef )
    FrmTs.AddItem( LblTsOrder.ControlRef )
    FrmTs.AddItem( TxtTsOrder.ControlRef )
    FrmTs.AddItem( LblTsBatch.ControlRef )
    FrmTs.AddItem( TxtTsBatch.ControlRef )
    FrmTs.AddItem( Control("SprTs3",ToolStripSeparator).ControlRef )
 

agraham

Expert
Licensed User
Longtime User
The compiler doesn't recognize SprtTs0 because it was added with a "not trivial" AddObject (Ex: AddObject("object1",someobject) is trivial and gives the compiler the required information about object1)
Hi Erel. I'm actually playing with this at the moment trying to understand. I'm afraid I don't understand what a "non-trivial" AddObject against a "Trivial" one is. Please can you explain a bit more.

EDIT : Got It! (I think!). I was confusing myself by playing with "trivial" AddObject instead of "non-trivial" and not understanding why it worked. It happens if the compiler can't resolve the control name at compile time because it is specified by a variable.
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
Got It! (I think!). I was confusing myself by playing with "trivial" AddObject instead of "non-trivial" and not understanding why it worked. It happens if the compiler can't resolve the control name at compile time because it is specified by a variable.
That is correct. Any name which is not given as a single string is considered non-trivial.
BTW, that is true for all the AddControl keywords.
 

RandomCoder

Well-Known Member
Licensed User
Longtime User
Hi guys,

I've had a good day today as its finally working the way I intended. All that is left for me to do is store the program settings in a .ini file and the job will be complete. I'll post the code soon, once I've tidied it up a little. Maybe it will be of use to someone.

Anyway why do you need to set the Form size with the Door library and not in the Designer?

I have set the Form size in the designer but I use your FormExDesktop library because it allows me to hide the Form, and restrict the user from changing the overall size. I'm also using the Windowstate property to know when the app is minimised and thus remove it from the taskbar leaving only a system tray icon. I dare say there are better ways of doing all these things but I am fairly new and just doing things the best way I know how.

Thanks for all the help!

Regards,
RandomCoder
 

agraham

Expert
Licensed User
Longtime User
You are not trying run your program in the IDE are you? That is likely die instantly if you do for reasons that I don't understand because I don't know what is happening in the IDE
For my own satisfaction I've had a poke around and can now explain why OnCom events die in the IDE when using a FormEx. It's not a threading issue after all as actually the IDE does know about the thread that the FormEx is running on. The reason is that the IDE lacks a check for the presence of a main form that an optimised compiled app does have. If an optimised compiled app doesn't have a main form (one that is run with Form.Show) then it ignores a cross thread event. The IDE however solemnly tries to run a cross thread event on the main form regardless of whether there is a main form or not which is why it dies as with a FormEx there is no main form. :(

A FormEx cannot handle a cross thread event itself in the IDE, like it does when optimised compiled, as it can only run optimised compiled code Subs, not interpreted IDE/legacy Subs, which is why it gives a Msgbox warning when run under the IDE. Therefore there is no workaround to let cross thread events work in the IDE with a FormEx based application.

This will be a problem running a FormEx based application in the IDE for any library that raises events on a different thread to the FormEx thread. I know that events in the Serial2, SerialEx, GPSSerial, Threading and HTTP (WebResponse Response event) libraries will behave like this. There may be others.
 

RandomCoder

Well-Known Member
Licensed User
Longtime User
Sorry to re-raise an old thread but I've encountered another problem that may be linked to using the FormEx library.

In my program I attempted to use a Module for loading settings to/from a config file. Having never used modules before I could well be doing something wrong, but have tried many combinations of making variables public, subs public, prefing controls and variables with the module name etc... nothing seemed to work.

So attached below is a small sample that use's a timer to increment a variable called count (which is public) this should get displayed in both text boxes but doesn't. I've tried making the sub in my module public and several otther combinations but can't get it to work. Am I simply missing something or is this related with the 'threading' issue?

Regards,
RandomCoder
 

agraham

Expert
Licensed User
Longtime User
Your looking for too complicated a problem

In Main you are calling Module.Update

In Module Update doesn't exist but UpdateTxt does but is private and Count is being treated as a local variable so

Public Sub Update
Main.TxtModule.Text = Main.Count
End Sub

Et voila!

EDIT:- Oops! I omitted the Main.Count bit in the original post.
 
Last edited:

RandomCoder

Well-Known Member
Licensed User
Longtime User
Your looking for too complicated a problem

That don't surprise me, but I've been scratching my head for ages before deciding to post. Don't know how the module.update typo crept in but I still get an error message even after following your advice, but knowing that you are normally right I've disabled the check for unused variables and it does indeed run :icon_clap: . The error I was getting was....
Error compiling program.

Error description: Variable module.count is used before it is assigned any value.

Occurred on line: 7

Main.TxtModule.Text = Count

It now runs but the TxtModule does not update its count :confused:
PS This is nothing like what I was actually wanting to do, it's just a sample for me to get familiar with modules.

Thanks,
RandomCoder
 

RandomCoder

Well-Known Member
Licensed User
Longtime User
Thanks AGraham,

I think I know what I'm doing now (at least for the time being :sign0089:).

I mis-understood the help...
Scope


By default all subs and all global variables can be accessed only within their module.
By adding the Public modifier to subs, for example:
Public Sub Trim(Str)
Match1.Value = rxTrim.Match(str)
Return Match1.String
End Sub


The specific sub will be accessible from any module.
It is also possible to declare a global variable as a public variable by replacing the Dim keyword with Public, for example:
Sub Globals
Public someFlag
End Sub

I understood that as meaning that the variables would be global throughout modules without the need to prefix them with where they were declared.

Your help as always has been very appreciated.

Thanks,
RandomCoder
 
Top