Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Controls "outside" the Form 2

Status
Not open for further replies.

Scott24x7

Programmer
Jul 12, 2001
2,825
JP
So there are a number of discussions we've been having here, that seem to all be starting to tie together.
First, the elimination of PUBLIC (which I totally get is a good thing, and I'm committed to doing that).
Second the ability to print RTF in report form (Using Mike Gagnon's approach) or Office Automation (using Tamar's approach).
Which brings me to the third part -- building out the RTF capability, given the "RIBBON" bar that I've created within the MAIN form.

I was looking at the VFP Samples where they have an example of RTF, and example that I built from some other app years ago, where I stopped because I couldn't print it.
But both of these examples have the controls embedded in the form, and I want to be able to use them globally. (So any form open, will use the same controls when editing RTF editbox).

So when it's in the form, it's easy... the control and the ole box both see each other, and using the .ActiveControl property of the form, it's easy enough to get the ole field to respond to change in the RTF tools.

But, now my main form contains the "Ribbon Bar" that I've built. That bar is a pageframe inside the MAIN form as well. When I open a new window inside it, I can't reference Main.Pageframe1.basepage2.rtfControls.rtfFontSelect... To my OLE control in window CLIENTS which then has a pageframe within it, and pages, and ... down until I get to the RTF control (in one case, there is a pageframe on the page of another pagefram).

So all this deep traversing between forms which don't really see each other... to have a common set of controls like RTF font control, what is the best way to tackle this?


Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
If you were using a toolbar, this would be easy because toolbars don't get focus, so you can use _SCREEN.ActiveForm to find the form with focus and then operate on it.

But I gather you're using controls in a form, which means that your controls will get focus. (I haven't paid much attention to the RTF thread because I haven't worked with RTF.) The general solution is to track which actual form has focus. In general, this is something a framework does for you.

The good news is that this is something you can build into your forms and your application object. Put code in the Activate method of your form "base" class to call an application object method that stores a reference to the currently active form in a property of the application object. That is, the Activate method has code like:

Code:
goApp.ActivateForm(This)

and the application object's ActivateForm method has something like:

Code:
LPARAMETER oForm

This.oActiveForm = m.oForm

You'll want some error-checking in there, but that should give you the idea. Once you have this, you can find access the active form with goApp.oActiveForm. (I'll add that when I do this, I actually have corresponding code in Deactivate to clear the setting, but because you have controls in your top-level form, you can't do that. In fact, you'll need special code in that top-level form to make sure it never registers itself as the active form.)

Tamar
 
So let me get this straight: You dont really ask about RTF or OLE, the core problem is getting at a control from the man form ribbon, whereas the control is not on the main form. So you talk about communication between forms.

Forms knowing each other has many simple solutions. They all base on the principle, you don't need to know something, you only need to know someone/something else knowing what you need to know. In short loose coupling.

1. goApp.oFormhandler instantiates all forms and knows references to them. If anyone would ask the handler for a reference to a form, the handler could provide it. So the ribbon would call into goApp.oFormhandler.getreference("someform"), for example.
2. You can make use of a host/guest or publisher/subscriber pattern. Any form could register itself as publisher or subscriber to messages. So if there is a form with RTF control you want to access from main forms ribbon, you can turn around your need or want and say the RTF control form wants to subscribe to any messages about handling it's RTF control, making itself controllable this way.
3. Again and again, your communication can also happen via data, via DBFs, eg the "Bold" button is clicked in the ribbon, you save the setting bold=.t. into some table and the form with the RTF control reads it from there, you neither need the bold button to act on the RTF control nor the RTF control see the status of the bold button.

I also often give the example mail automation does not have a call to sendbutton.click(), but to mail.send(), think about it. You don't act on the frontend, the frontend is just the interface to the backend, the model, having the essential info, the frontend is just for the human in front, but as the developer you should not program in the mindset of the user seeing the interface, you define the classes with the functionalities you want to use and you define the calls to do to get something done. Then the interface just makes these calls.

You only think about direct solutions, as they seem simpler. But they have one big disadvantage, they mean an entanglement. If you only program in a direct way, you can only act on controls on the same form, yes. That makes it bad code, as it binds things together and you can't separate them.

Going back to the mail example: Is every computer directly connected to any other computer to send a mail by putting it on the target computer? No, there is a protocol and mail servers receive and forward the mails, there are intermediate stations and indirection.

It only seems more complex, but every single entity only has to do quite simple and easy to understand things. The complexity results from the collaboration of the single components.

Bye, Olaf.

 
Hi Tamar and Olaf,
Yes, you're quite right, at the base level this is about communicating between forms. It's just the RTF example is the first time I've ever needed to do this, but as I build out the ribbon bar, I suspect this will crop up in other areas where I want to interact with forms and that ribbon form class. Thanks for the clarity and description you've put together Olaf, it makes it much clearer in my head. And I figured the goApp object is going to play in this. I've almost got the RTF edit box working and interacting with the controls I've built (in another simple form where it's just them, so I could play with getting the edit functions to work as desired first).
Once I'm done with that, I'm going to dive into the goApp implementation. I think I've got a better understanding now of it. I'll start with this, and my glTipState (getting rid of it as a PUBLIC) as my entry point, and then expand it from there.
So hopefully quite for the next couple of days as I work this out, and then maybe more questions as I get stumped. :)
Many thanks.

Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Scott, I'm not sure if this is what you are asking, but I'll tell you how I handle this.

In my base form class, I have property named oCaller, which holds an object reference to the calling form. This means that any form can access the properties and methods of the form that calls it, and of the controls on the calling form.

So if your main form holds the ribbon, and a subsidiary form needs to access a control on the ribbon, it can do so by refering to [tt]THISFORM.oCaller.oRibbon.SomeProperty[/tt].

Note that this approach does not need any changes to your existing code. To store the object reference in oCaller, you just add this line to the Load event of the base form class:

[tt]THISFORM.oCaller = _SCREEN.ActiveForm[/tt]

This works because, during the Load event of a given form, that form is not yet active. The previous form (that is, the one calling the current form) is still the active form.

Does that help at all?

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi Mike,
I think I understand your point. Let me try it, and see if I'm able to get the behavior that I'm expecting out of it.


Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Hi Mike,
I completely forgot you had mentioned this when discussed before (as I wound up spending about a week extra getting some ribbon behavior to work the way I needed, which took a lot longer than I expected, but it was worth giving it the time, because it's flawless now).

So, if I understand this I add the property oCaller to the baseclass form (lowest level), so even the TopLevel form and the form called from it will have this property?

And does it matter what they default setting of oCaller is? 0, .F., ""?
I'm giving it a try now, if this works, it will save me huge amounts of plinking around.


Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Hi Mike,
WOW! Not that I doubted you, but I am still delighted when something that feels like a magical "leap of faith" works!
So, here's my next question, because it gets to ba bit of work here...
In my example, I have the RTF controls embedded in a page in a frame on the basepage.
So my call from the RTF control back to the ribbon controls is a bit ugly and looks like this:

ThisForm.oCaller.pgfRibbonBar.Pagebase2.RTFFormatting.CBOFontName1.Value = This.SelFontName

So what this does, is passes the font name of the test in the control back to the RTF controls so that it is aligned to that of the test in the box. (Or default font value if the box is empty). When I clikced in the box, it updated my combo box control on the ribbon, so that was terribly exciting.

The concern I have is, all this "Path" back to the control is needed: ThisForm.oCaller.pgfRibbonBar.Pagebase2.RTFFormating.CBOFontName1 (and I have about a dozen RTF controls built onto the Ribbon so far, and I'm expecting to add in a few more, so this is more like standard "Office" type text control... this makes it very familiar to my user for how to make great text features).

Is there some way that is best to control this kind of thing? It feels like the "pagefram and page" make for long addresses. If it's the only way, I will make it work, but thought there might be something more elegant I'm missing. What I love about this Mike, and I'm so grateful... I thought I was going to have to make some very complex transitions and transformations to goAPP and then I didn't know how I was going to get goAPP to let the calling form know about changes at the child form level. This is like super magic to me. Very Very cool.
Thanks! I wish I could star this 10 times.


One thing I just encountered too though is, this is fine going "one way". From the child form back to the Top Level, but what about when I need to send some update back to the child?
For instance, in my RTF example, slicking in the RTF Control box on the child form, it automatically updates the font and size (and other attributes that I have the RTF control set to update, like bold and italic). But if I go to the Ribbon now, with text selected in the RTF field on the child table, and I change the state of Bold or the font from Ariel to Segeo UI, how do I tell it which control on the child form that is to be used? In the Samples example, it utilized the .ActiveControl. property of ThisForm. I haven't tried that yet, but my thought was that it won't work.

Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Hi Mike,
So this seems to have worked from the Called Form BACK to the Top Level form, but not from that form back to the child form.

So what I have is:
Top Level Form calls = Data Edit
Data Edit form has some edit boxes on it, 2 RTF, 2 Test and 1 text box.

DataEdit.oCaller can see all the properties of TopLevel
But TopLevel, doesn't see DataEdit at all. (Other than as something like "WONTOP").


There is an interaction I'm trying to make work here with the RTF Controls, so "backward" it works, but then not forward.

If there is text in the RTF box, that is maybe Bold and has a color Green as properties, when you select that text, the RTF controls at the TopLevel form refelct that (the color selector turns Green and the Font Name switches to the font of that text, and the BOLD attribute shows active).

Now if with the text selected When I go to the RTF controls the "Selection" seems to go away (but if you click back on the form, it does show that its still selected). But if I then try to turn bold off, I get a message about values not existing (related to calling that object back). The RTF demo has something like ThisForm.ActiveControl.SelBold = This.Value (or something like that...)

So from what I can tell, I'm "communicating" back to the parent form, but it's not "communicating" back to the child, because the references don't exist. It seems oCaller is "one-way"?


Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Mikes suggestion always only works one way, yes, because only one form is the caller form and the other is called. The caller form can know what form it called even more easily, though, as it calls it, it will have a reference to it in the moment of generating it, so you can put that to the process of creating a child form. I'd add another oCalledForm property. Even though The ribbon form will never have a caller form, it's the root form always existing, you could reuse it's oCaller property to store the child form reference, but it feels wrong, doesn't it? If you find another name for the oCaller property that could work.

But I'd go back to what I suggested earlier, and not work with such form properties. Make a form handler knowing form references and give it methods to ask for a from reference and you don't have to feed and set any properties as your memory of form references.

Besides that, as the ribbon form is always existing and its reference never will change, you can add its reference to a property like goApp.oRobbon, Simply in the Init() of the ribbon you can then set goApp.oRibbon = THIS and everywhere you need access to the ribbon form, you can reference goApp.oRibbon. Remember the discussion about goApp and the "big ball of gum"?

Mikes suggested mechanism is for differing sets of parent/child forms. For ribbon/any active form the situation is easier, you don't have a varying parent form, so make use of that.

The ribbon knowing all it's child forms is harder than just storing one reference, Since clicking in the ribbon makes it the _Screen.ActiveForm, unlike a toolbar, which does not change this, you can't reference it via this system property. It comes back to a form handler knowing all forms and being able to tell you references and for the ribbon to effect all relevant forms when you make some general setting like font size or language, it also comes back to the topic of host/guest or publisher/subscriber.

If you publish a newspaper you also don't call every subscriber to read out the new articles of it, you publish the paper and every subscriber gets it. In the example of a language setting in the ribbon, for example, you let a drop-down list combo box be bound to a list of languages each with their language ID and then have the controlsource goApp.iLangugeID. Everyone interested does not read the ...pgfRibbonBar.PagebaseX.REgionAndLanguage.CBOLanguage.Value, but the goApp.iLanguageID, and everybody interested simply uses the ability to be informed about property changes via BINDEVENT(): A form does [tt]BINDEVENT(goApp,"iLanguageID",THISFORM,"SetLanguage")[/tt] Now everytime goApp.iLangaugeID changes anybody subscribed to this property is informed and can read the new ID value in a method of its own choice. So the ribbon does not need to know who's reacting or who it needs to act on, it simply cares for the simple concern to "publish" what is the current language choice.

This whole concept then also gets rid of acting on any deep paths. Neither the ribbon should need to know paths of child forms to act on, nor any form should know how the ribbon is structured. The core thing you want to transport is information, not controls.

Bye, Olaf.
 
Olaf,
I think I'm following you on this. I'm going to try your suggestion with goAPP.oRibbon and see if it allows me to do what I need, I think in conjunction with oCaller (for one way, and oRibbon for the other). Will let you know if I run into trouble, or how the solution works.
Thanks.


Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Scott,

Let me answer your earlier questions:
So, if I understand this I add the property oCaller to the baseclass form (lowest level), so even the TopLevel form and the form called from it will have this property?

Yes, that is exactly right.

And does it matter what they default setting of oCaller is? 0, .F., ""?

I would set it to NULL, since that is the normal "empty" value for an object reference. But you can't set a propert to NULL in the class designer; you have to do it in code.

The default value applies if the form is the highest-level form, which in your case is the ribbon. So you could do something like this:

Code:
* In the Load event of your base form class
THISFORM.oCaller = _SCREEN.ActiveForm

* In the Load event of your ribbon form
THISFORM.oCaller = NULL

In all your other forms, don't do anything special in the Load event. Just let it inherit from the base form class.

One problem is that, if you try to reference _SCREEN.ActiveForm when there is no active form on the screen (for example, if you were calling a form from a menu), it would raise an error ("ACTIVEFORM is not an object"). You can avoid that by doing something like this:

Code:
* In the Load event of your base form class
THISFORM.oCaller = IIF(_SCREEN.FormCount > 0, _SCREEN.ActiveForm, NULL)

I haven't had time to read your subsequent question. It's possible that Olaf has answered it. I'll come back to it later.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi Olaf,
I'm still missing something.
Here's what I have (simple example).

The Ribbon has the RTF controls in a container on Page 2 (that shouldn't matter). But as you know it's in the Top Level form.
My test form (RTFTest) is it's on form IN the Top Level Form, and has some RTF box on it.
The RTFTest form creates oCaller in the LOAD event of itself (THISFORM.oCaller = _SCREEN.ActiveForm) when it gets launched by the button on the ribbon bar.
The INIT of the Ribbon, I put in your suggestion: goAPP.oRibbon = THIS (so I assume makes an object called oRibbon that has all the properties of THIS (being the properties of pgrRibbonBar, and its objects).

So my dilemma then is, I select text in the OLE control on the RTFTest form.
When I go back to my RTF Control in the ribbon and I change the font size from 8 to 12 (as example) from my dropdown listbox for Font Size, it's Interactive Change event needs to tell the RTFTest OLEObject to apply the font size to the selected text.
I guess now I'm confused about the state of goAPP.oRibbon... When I click FONT SIZE change, how does oRibbon become aware of that change, and more importantly how does the OLEcontrol with my RTF text that is selected, know to apply the font size from the previous "10" to the now state changed "12"?

There is a big gap here I don't understand.
-S

Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
1. so I assume makes an object called oRibbon
No, oRibbon has to preexist or you need a call of ADDPROPERTY. Setting a nonexisting property will give you an error you should have had that. Notice, this is advice of the more general type, not having any little tiny baby step you need.

2. You wanted the oRib bon reference, didn't you? I thought of it as the form reference, not as the pageframe or control reference, that would not be calld oRibbon, would it`?
Whatever you wanted to do with it, do it.

The hint on BINDEVENT is about a totally different solution strategy, this is about two separate solutions and you should notice that. Why would you need an oRibbon reference, if the child form/control can notice a goApp.iLangugeID or in your case a goApp.Fontsize property change itself?

The idea about status and information and binding to their change is more valuable in this kind of involvement with the ribbon. Neither the ribbon should need to know what it influences nor should a control on any form - child form or main form - know the ribbon structure to pick out an information. Both ribbon and form should act on the so-called model. Data, properties, state, information. That's what you share.

The necessity to know references comes, if you want to interact with more than just the necessary information.

So perhaps let's concentrate on the effect of binding to a property with a short example:
Code:
goApp = CREATEOBJECT("vfpApplication")

* event source: A textbox on screen:
_screen.AddObject("txtFontsize","Textbox")
WITH _screen.txtFontsize
    .controlsource = "goApp.nFontsize"
    .visible = .t.
ENDWITH

oEventsink = CREATEOBJECT("eventsink")

SET ESCAPE ON
ON ESCAPE CLEAR EVENTS
READ EVENTS


DEFINE CLASS vfpApplication as custom
   Appname= "My fine app"
   iLanguageID = 1 && english
   nFontsize = 10
   
   PROCEDURE Init()
      * Initialisaze anything, eg load config
   ENDPROC
   
   PROCEDURE QuitApp()
      QUIT
   ENDPROC
   
   *....
ENDDEFINE

DEFINE CLASS eventsink as custom
   PROCEDURE INIT()
      BINDEVENT(goApp,"nFontsize",This,"FontSizeChange",1+4)
   ENDPROC
   
   PROCEDURE FontSizeChange()
      MESSAGEBOX("Font size changed to "+TRANSFORM(goApp.nFontsize))
      * instead of displaying this new knowledge, this can apply it to itself, eg if eventsink is your RTF control
      * it can act on the current selection, of there is any, and change that selection font size.
      * Whatever you want.
   ENDPROC
ENDDEFINE

Notice some the important characteristics of this: Both the "Ribbon" (here just represented with a textbox on the screen) and the form (here represented with the eventsink) don't know each other. The font size textbox (ribbon) just changes goApp.nFontsize and that in turn is noticed by the eventsink (which could be the form with RTF control or the RTF control itself, wherever you add the method triggered by the nFontSize property changing its value)

This is decoupling things. Now you neither need code in the ribbon to address rtfform.pageframe.pageX.rtfcontrol.Selection.Fontsize nor does the RTF control needs to know oRibbon.pagframe3.fontrelatedpage.txtFontsize.Value, where it finds the picked font size.

You may think it's getting more complicated if not two objects know each other, but interact via a third object, but it is important for the topic of encapsulation. This third information interchange object (goAPP and it's properties, you might vary this in many ways) is just a dumb data storing object. Each active object, the ribbon form and the RTF Control form, only knows itself and gets information from outside. You avoid the entanglement of knowing each other directly and the maintenance that would mean. If you'd ever change the location of the font size picking control in the ribbon, every single place in your whole application related to that would need to change.

Sharing object references instead of only sharing state and information should be limited to the cases you care about this type of entanglement and see both involved classes as belonging to each other like mother and child do. But in this case you have any child, any form of your application and the ribbon, the general toolbox of your application. The entanglement of knowing each other directly via references is a good case, if the both belong to a certain feature, eg an order list form and an order details form might perhaps know each other to implement some interaction with each other. Making any form know any other is like programming with GOTO, this is not advancing, what you could do, this is spaghetti programming. So Mikes idea would rather work for a situation a form you start from menu/ribbon calls a child form, so that child form is much more related to the parent form than to the ribbon form. Of course, every form has a relation to the ribbon form, as it has general options and settings, but in itself, it should only influence a settings object and any form, which wants to react to setting changes should do so via binding to the settings object, too.

And also think about it this way: It's much easier to define such setting properties and stay with them the next 1,2,5,10,20 years then defining forms and pages, etc. and stay with their structure to not need to adapt any code referencing each other. The moment a form accepts a reference and acts on it, you can see its definition including in at least the part of the referenced class you act with. This means a dependency, which you take as everlasting burden. Even though it is part of two separate class definitions.

Before you begin adding all kinds of properties to goApp directly look back how I talked about sub-objects, handlers, which are the first level objects of goApp. Eg the font size could really have its place in goApp.oSettings.oFontsettings.nFontSize and you could also differentiate a general application font size driven by config data and a current ribbon font size influencing only the current bound controls or their selection. That also means if you don't want a ribbon font size change to affect all controls having their own FontSizeChange method (which really becomes an Event by the bindevent binding), but only the active control. There is UNBINDEVENT() to unbind as soon, as a control is not the active one anymore and then BINDEVENT again when the control becomes active.

Bye, Olaf.
 
Olaf,
Early in my startup.prg before the MAIN form is called and set with READ EVENTS, I issue:

goAPP = NewObject("cusAppClass", "AppClass.PRG")


I use a trick from Tore in that class with this function:
Code:
FUNCTION This_Access(tcMember)
	IF ! PEMSTATUS(This, tcMember, 5)
		This.AddProperty(tcMember, NULL)
	ENDIF
RETURN This
*
ENDFUNC

So later at the init of the Ribbon, I issue:
goAPP.oRibbon = THIS

That is why there is no error.

I'm looking through the rest of your solution now to figure out how I put it together with my application. It is not so intuitive to me, so hopefully I can get it to work in a try or two from now.


Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
I edited my post and added some more explanation, so please read back.

Also, it was not meant to be integrated as is into yyour application but as a standalone sample. So you pick out, what you really need, of course you have your own READ EVENTS logic, etc.

Bye, Olaf.
 
Hi Olaf,
Yeah, I figure the meat of your solution is:
Code:
DEFINE CLASS eventsink as custom
   PROCEDURE INIT()
      BINDEVENT(goApp,"nFontsize",This,"FontSizeChange",1+4)
   ENDPROC
   
   PROCEDURE FontSizeChange()
      MESSAGEBOX("Font size changed to "+TRANSFORM(goApp.nFontsize))
      * instead of displaying this new knowledge, this can apply it to itself, eg if eventsink is your RTF control
      * it can act on the current selection, of there is any, and change that selection font size.
      * Whatever you want.
   ENDPROC
ENDDEFINE

And

Code:
* event source: A textbox on screen:
_screen.AddObject("txtFontsize","Textbox")
WITH _screen.txtFontsize
    .controlsource = "goApp.nFontsize"
    .visible = .t.
ENDWITH

I have heard of BINDEVENTS, but I've never used it, so I'll need time to figure out how it works with the way you've put it together. The "objects" defined outside like goAPP and manipulation of them like oActiveForm are taking some getting used to.

Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Ah, re-reading it now. I'm still having a lot of trouble, I think maybe because it isn't intuitive in how I think of how things "work". I see some new explanation, so I'll try again, but my first two attempts were failure.


Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
So question, in your code:

Is this:
Code:
* event source: A textbox on screen:
_screen.AddObject("txtFontsize","Textbox")
WITH _screen.txtFontsize
    .controlsource = "goApp.nFontsize"
    .visible = .t.
ENDWITH

oEventsink = CREATEOBJECT("eventsink")

SET ESCAPE ON
ON ESCAPE CLEAR EVENTS
READ EVENTS

In the INIT of the Textbox on the form?

Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
>The "objects" defined outside like goAPP and manipulation of them like oActiveForm are taking some getting used to.

Well, you can put the nFontsize anywhere, just both sides, the ribbon, and a form have to be able to address it as controlsource and/or as object/property to bind to.

If you make the font size a property of the ribbon, you have not made the problem to know the ribbon much easier. It could only be in a more stable and obvious place, at the root level of the ribbon form as form property.

You already decided to go for goApp, therefore it is your usual place for anything needing a scope you can't solve within one of two involved objects.

Wanting to have properties on the one or other side is like thinking of foreign keys only ever being part of the one or other table related. But in table relations you also quite often have the need for a third table to act as n:m relations, eg between for example persons and addresses.

I also already hinted on configuration, so there is a place for the default font size in a configuration record and then there is a config data loader involved, what else is best to handle access of more than one object than a totally separate object, just like a table is? Since triggering behavior of the front end with a change of data has limited justification in triggers or field rules, which only should be concerned with data validity and quality, you load this into a separate object, which you can bind to.

goApp or sub-objects of goApp cannot only bind font size to RTF controls, you have a n:m relation object with many fields relating many forms/controls to many ribbon features, font size is just one example.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top