Wiki Home

Subclassing XGroups

Namespace: Wiki
I found that, when subclassing buttongroups, optiongroups and pageframes, there are some things you can't do, and some things you need to be careful about. I don't know if this is covered somewhere else on the wiki, but it if is, I never ran across it, even after looking for it.

I did what I thought was the obvious thing, that is, make a class library (call it _fox.vcx) and make one of everything based on the base classes. Then I used the ones in _fox for everything (actually, I inserted another level in between, but that's not relevant here).

Here are the problems I ran in to:

1. by default, a button group has 2 buttons and an option group 2 options. If you leave these 2 in, they are hardwired - their names cannot be changed from what they were in the _fox class, that is, command1 & 2 and button1 & 2. There may be other things you can't change too - I had some positional troubles that seem related.

2. so you go back to try to delete the 2 buttons (or 2 options) in the _fox class. You can't. They're part of the class and cannot be deleted. I guess I could redefine them ... I haven't tried that yet.

3. You can't delete them when they're used either ... I tried to make a pageframe that handled a bunch of common cases, figuring I could delete the pages at the end in those screens where I didn't need them. Can't do it.

4. There doesn't seem to be a way of influencing what gets created when you increment the number of buttons or options or pageframes - you'd like a place to say what class should be used to create the new item, but you can't (or at least I couldn't find one).

5. I assume grids have all the same problems but in 2 dimensions, but I haven't tried that yet.

Oh, this is all VFP6, if that matters.

Anyone got any insights or workarounds or advice or whatever?

Michael Wagner [2005.07.28]

Check out the MemberClass property of the container object to specify a subclass that is different than the object normally added to a container. As for deleting pages, change the pagecount property to add or remove pages. The deleted page is the last one in the page order. Ben Creighton.

VFP6 doesn't support MemberClass. That property was introduced in VFP8, I believe. Mike, Have you tried setting the Visible property to .F. when you want to hide the inherited objects? They wont be gone entirely, but no one using your program will see them. Tom Bellin

Ben: Doesn't work - trips the following error:

Member "name" is a class member (Error 1760)
You have attempted to remove a member from an object. The member cannot be removed because it is a member of the class the object is based on.

To remove the member, modify the class.

MemberClass might be a good reason to upgrade to VFP8. Thanks, I didn't notice that enhancement before. That solves at least some of this problem ...

Tom: No, I didn't try to make them invisible ... for things that are statically arranged, like optionbuttons, that might work. Not sure what would happen to formatting of pageframes. Worth a try, though, thanks! Michael Wagner

For VFP 7 and earlier:

In your base subclass of the VFP base classes, set the ButtonCount/PageCount properties to 0. That way you aren't stuck with any buttons or pages that you later won't want.

You can define your own page and optionbutton subclasses in a .prg file. Then you can add your own AddMembers() method to your base Pageframe and Optiongroup subclasses, along with a couple of properties--CustMemberName and CustMemberCnt. Specify the name of your page or optionbutton subclass in CustMemberName, and the number you want in CustMemberCnt. Call your AddMembers() method from the Pageframe / Optiongroup Init(). Use a FOR ... ENDFOR loop with THIS.AddObject() to add as many instances of your page or button as the CustMemberCnt property specifies.

You'll need to specify the position of each Optionbutton, but it's just a bit of math, not too difficult even for a non-math guy like me. For Pages, of course, you don't need to worry about position.

-- Ken Dibble

Guys, I found out that I was describing the situation slightly incorrectly, and in fact Bens suggestion worked when I sorted out my other complexity. I actually have 2 sets of subclassing, call them _fox.vcx and _app.vcx, for lack of better names. The _fox ones subclass the base classes for *all* my work, and live in a directory called common, and the _app ones subclass the _fox ones and live in the directory for the specific project. I was trying to change the number of pages to zero in the _app ones, which didn't work. But changing them in the _fox ones worked and solved much of my problem.

Thanks for all the good suggestions, Ken. Has anyone tried setting an assign method for buttoncount? I just tried it and it let me create one, but I don't know if it will get called at the right time and place. That could then call the routines Ken mentions if the button count is changed dynamically, and as he describes, it could all work statically from the init clause. Cool. Michael Wagner

I've not tried to do it using an assign method. I don't see why it wouldn't work if you called the AddMembers() method from the assign method. In that case, though, you'd want to cycle through any already-existing members and remove them first. It's not going to work at design-time to produce a WYSIWYG display though, if that's what you were getting at. The downside of the approach I suggested is that you don't see anything at design-time. The members are only added at run-time.

-- Ken Dibble

Thanks, Ken, getting design time to work would be nice, of course. Does MemberClass work at design time in VFP8? I solved my immediate problem, but this got me interested in the more general issues.
Michael Wagner

I haven't used the MemberClass feature in VFP 8. My development work focuses on VFP 7 because I still have to support some Win 95 machines.

-- Ken Dibble

I'm revisiting this months later. I now have VFP 9, and I can see how it should all work for pageframes and option buttons and command buttons. My problem is with grids. I can see how member class and header class works in grids to get me subclassed columns and subclassed headers. But ... how do I get subclassed entries for the main body of the grid. ... perhaps I'm very dense, but I seem to be missing a step somewhere. The problem, essentially, seems to be here: I have a .prg that contains:
DEFINE CLASS gridcolumn AS Column

and it could contain headerclass and headerclasslibrary entries, but there's no corresponding cellclass and cellclasslibrary properties (that I can find). Am I missing something? Michael Wagner

By virtue of adding a column to a grid, you automatically get a header object (baseclass or subclassed by the headerclass property) AND a cell object which is always the baseclass textbox. You cannot prevent the baseclass textbox from being automatically added.

You may, however, add one or more additional cell objects to the column using the columnobj.addobject() method (or add object in the class) to add another subclassed cell. Then set the columnobj.currentcontrol property to the name of the newly added cell. You may also use removeobject to remove unused cells (although not really necessary unless you wish to reuse the cell's name) --BenCreighton

Category: Category Class Design
( Topic last updated: 2007.08.09 11:49:59 AM )