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 gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Weird Issue with containers

Status
Not open for further replies.

AlastairP

Technical User
Feb 8, 2011
286
AU
I think my FVP installation is corrupt, anyone seen this behaviour?

I have 45 containers on a form. Each container contains another nested container and a label.
When I run the form, the form freezes. If I reduce the quantity if the containers to about 15, the form will load but with visible delay
To bug test this, I tried this with zero code. The form with no code in the load or init
The containers contain no code.
But if I have 45 containers that do not have nested containers, everything is fine

Before I re-install VFP, anyone seen this behaviour before?

Oh and by the way, I tried creating new projects etc to test this. This is not a class issue with inheritance etc
 
What could slow things down is an image referenced in the picture property of the container class or any other file referenced, especially, if it doesn't exist.

So while you have no code, the initialisation of properties could cause this, also of the label, of course, though I don't see where that would reference any external file.

You could try with this code to see whether a native container/label without such a burden slows down your form initialisation:

Code:
#Define Sidelength 4
oForm = CreateObject("form")
For i = 0 To (Sidelength^2)-1
   oForm.AddObject("cntContainer"+Transform(i),"container")
   With oForm.Objects(oForm.Objects.Count)
      .BorderWidth = 0
      .BackStyle = 0
      .Left = (i%Sidelength)*(400/Sidelength)
      .Top = Int(i/Sidelength)*(400/Sidelength)
      .AddObject("cntContainerWithLabel","container")
      With .Objects(1)
         .BorderWidth = 0
         .BackStyle = 0
         .AddObject("lblLabel1","label")
         With .Objects(1)
            .BackStyle = 0
            .Caption="Test"
         Endwith
      Endwith
   Endwith
ENDFOR

WITH oForm
   .Width=400
   .Height=400
   .SetAll("Visible",.T.)
   .Show(1)
ENDWITH

Bye, Olaf.
 
Actually it only works up to 4x4 containers on Windows 10, so what you see not just a bug of your installation, seems you have found a flaw of VFPs drawing controls. Eg it does not free brushes and Windows10 GDI+ only allows a small number of them.

Bye, Olaf.
 
Yeah, but it was working. Then starting having problems.
I even took the container class that I made that has 45 nested containers and put that on a form in an existing project.
It loaded fine.
But if I create a new form, or a new project it will not load up with the containers.
I created a quick mock up of the container class that had just the containers and no ode or formating and also minus the label.
Still has problems on any NEW forms or NEW projects, but not on any existing projects
 
Only on new forms. Okay, then that gives hope we'll find a fix in the differences of old vs new forms records differences.

If it works with old and not new forms don't blame VFP itself. The bug about aero and borders also was only due to a Windows change and not due to a VFP change, reinstall is a last resort and likely will not help.

As a reference In regard to the aero bug one thing helping was simply reordering BorderStyle and DoCreate in the property memo of a form.
I'm not saying the same thing fixes container drawing, but theree might be a similar fix, if you have forms working and not working, compare them in the detail of the controls properties.

Bye, Olaf.
 
It seems to be very container related, I can create many grids without the freeze:

Code:
#Define Sidelength 50
oForm = CreateObject("form")
For i = 0 To (Sidelength^2)-1
   oForm.AddObject("grdGrid"+Transform(i),"grid")
   With oForm.Objects(oForm.Objects.Count)
      *.BorderWidth = 0
      *.BackStyle = 0
      .Left = (i%Sidelength)*(400/Sidelength)
      .Top = Int(i/Sidelength)*(400/Sidelength)
*         .AddObject("cntContainerWithLabel","container")
*         With .Objects(1)
*            .BorderWidth = 0
*            .BackStyle = 0
*            .AddObject("lblLabel1","label")
*            With .Objects(1)
*               .BackStyle = 0
*               .Caption="Test"
*            Endwith
*         Endwith
   Endwith
ENDFOR

WITH oForm
   .Width=400
   .Height=400
   .SetAll("Visible",.T.)
   .Show(1)
ENDWITH

This form is kind of sluggish, but it works.
 
Just want to say, I am using Windows 7 x64, have for a long time.
I set the theme to Windows Classic a long time ago . . . just personal preference

 
OK, then it's not Windows 10, I was making the assumption, because 1. I work on Windows 10 now, and 2. I never experienced this before.
It could still be Windows, likely a change since Vista. The container within a container issue rings a faint bell anyway, I just can't put my finger on the reason. I still don't think a reinstall fixes that, before you try a reinstall try deleting foxuser.dbf and recreate that only. Since the form behaviour even is affected by the native base container class, it's also unlikely that'll solve the issue, but it's far easier than to reinstall. What else does really change, when you reinstall?

And in regard to aero: No, aero isn't necessarily the root cause for the container, I just "quoted" the aero border problem as a similar nature problem fixable by some change in the SCX/VCX data only. You have the proof the containers in containers works on some conditions and not on others with your old/new forms. So you have the material at hand to find the essential difference. I suggest looking into the Property memo of the outer and inner container control records in working and non working forms. The difference might also be in the form level, but of course it's more likely on the level of the controls. And as the other bug show, it can also be in the order of proeprties in there, not just differing values.

Bye, Olaf.
 
Just curious: what on earth possessed you to put 45 containers on a single form?

I hate forms with 45 *cotrols*, and that's as a user much less a developer.

Are you sure you're solving the right problem here?
 
The qty of 45 is a moot point .... the problem displays itself with just 10 containers. Even 5 containers can see a slight slow down.
As of yet I have not timed it, but I would guess that each nested container is adding a significant delay.
I have some other options, Like load the container class on the the form after the form has loaded, would probably work.
The second thing is that it was working fine before. Something changed and I have not been able to find the issue causing it.
Yes and I do need 45 containers. The only other way is to not nest containers within containers and that will work. Just will take some rework.
I would rather solve the issue than do some kludge mod.
 
I use control classes based on a container with a label+control. They don't nest another container inside them, though. This way you can easaily have several containers, one for each control and forms with more than 15 controls are not unusual or overpopulated. If part of the form then is put into containers for reusability I also have containers within containers with labels in the inner containers. And it works so far, but it could catch me, too, if there were more of these reusability containers.

What changed? That's really the question. As I can produce this problem with containers added dynamic at runtime, I doubt it's any change within your VFP installation. We're talking about the native container, aren't we? So only the vfp9.exe or vfp9r.dll can be involved, and they never change. The only other thing involved are SCX/VCX files, but if you addobject at runtime, they also have no influence.

The only other thing having influence is Windows and its updates. Changing software, installing a new application or deinstalling another application, could cause come C++ runtime change. Give it a try, I stand with my prediction you'll not fix your problem reinstalling VFP+SPs+Hotfixes. What is your VERSION(4), you can cyop&paste it via _CLIPTEXT = VERSION(4), then paste here. I'm on SP2 with latest hotfix: 09.00.0000.7423. And I recently didn't change any software.

Now I've done an SCX with too many nested containers at design time to see whether it's an addobject problem. And it shows the same behaviour of being drawn blank and freezing VFP, when started. But the form designer can load it. Fast.
shipping_b8whpo.png


I've now attached it to this post: Shipping.zip (CRC32: 3ea1e342, SHA1:79fe4bca49bd850055cfcdd8633c45e153202d5e)

If someone could try this form and/or the above sample code with Sidelength>4 and confirm it's not just Alastair and me, this would help as a repro.

Bye, Olaf.
 
I think you might be on to something with the windows updates. The one thing that I did update recently was my graphics drivers. Cut a long story short, it was high time that I re-loaded windows from an Acronis image.
So I will report back when I am up and running again with a virgin installation of windows 7 x64
 
If it would be the graphic drivers, then why can the form designer draw the form but drawing the running form fails? There would need to be a fundamental difference in how a form is drawn in designer and at runtime. I'm not even talking about executable, this is running the form within the IDE, still using vfp9.exe for that rendering.

There is one fundamental drawing difference, the designer draws a grid on the form, not talking about the grid control, just the design gridlines, but thats additional, not less drawing.

Why does the form not freeze when drawn by the designer? Maybe it's not just the drawing freezing, but the load or init, something in advance of drawing the inner canvas. VFP freezes after having drawn the Winform part, the OS part of the form, the border and the main canvas in default theme color. What could be done is examine which events event tracking records up to the point of freezing. And if that yields nothing, Processmonitor could be used to see a difference between form designing and form execution.

A thought I had was, it had to do with clipping, but in this case there is no clipping, the inner container isn't larger than the outer, even the innermost label is smaller than the inner container, which I hinted on with the coloring. Outer container is green, inner is red, label has a default whitish light grey. And all the outer containers are put side to side, not overlapping.

Bye, Olaf.
 
If I think about GDI+ drawing I remember there is somethiing like a limited amount of so called resources, brushes, for example. So if the designer draws a single container, frees resources before drawing the next and the runtime draw mode begins with the outer containers and nests the drawing differently you could have a deadlock in reserving brush resources. But I can't believe there would be a different nesting of the order of drawing.

What I found related to this is a registry entry called "GDIProcessHandleQuota", which is set to 10000 (ten thousand), should be enough for 16 nested containers.

Bye, Olaf.
 
Ah so I timed the loading of the container class which was very quick, like .004 seconds. I set the class visible=.f.
I then do not have the freezing, lagging issues such as when the form is moved around the screen.
So that would indicate that it is a painting issue.
 
AlastairP,

You might be able to use the Form.LockScreen setting to limit the refresh repeats, so they do not stack. I use it frequently when I have multiple refreshes stacking up due to too many images layered in containers.

At the first move detection
ThisForm.LockScreen = .T.

When you release the mouse ThisForm.MouseUp
ThisForm.LockScreen = .F.
ThisForm.Refresh()

In the right situation, it accelerates the refresh immensely.

And at the start, you may not need to set anything invisible. Just use the LockScreen in one of the early events.

Cheers,



Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
I can reproduce the freezing even on a HP Elitebook (desktop replacement laptop) with Intel Core i7 and a separate graphic NVIDIA Quadro K3000M.
Yes, if I set all containers invisible the form works, so it may not be the class loading, but unsure what VFP really loads for invisible controls.
SetAll causes a freeze again, I wouldn't have expected otherwise.

I selected all containers and set them invisible, then added following code:

Code:
Thisform.AddProperty("nCounter",1)

Code:
With thisform.Objects(Thisform.nCounter)
   .Visible = .T.
   .SetAll("Visible",.T.)
EndWith

Thisform.nCounter = Thisform.nCounter + 1

So every click on the form makes one container visible. It freezes after 16 containers are visible. The forms gets sluggish with less containers visible.
My graphic card control panel doesn't allow me to turn on or off hardware (2D) accelration, it has lots of 3D feature related stuff surely not influencing GDI+ drawing as used by VFP.

I added the column "GDI Object" to the details tab of task manager and it shows 215 GDI objects used constantly, no rise, not even temporarily and also not, when VFP freezes. It doesn't even show any resource going through the roof, though 12-13% CPU usage should mean taking a whole of 8 cores to its maximum and the CPU fan maxes out, the vfp9 process becomes "Inactive" and only seldom goes back to the normal.
For comparison: The overall CPU usage (all processes total sum) goes down to 1-3% after ending the vfp9 process.

Since the cpu spikes it's hardly a gpu issue, though rendering graphics via GDI/GDI+ as VFP does, does only make use of graphics acceleration as far as a grphics driver hooks into to GDI+, it can be a very CPU heavy thing, if there is no graphics driver support.

16 is the magic number here, and that's a bit too low, even thinking about using other parent controls like pages and grids to lower the number of containers used, the mere concept of label+basiccontrol put into a container is needing this aside of not having the container in container scenario, you get to it, if you bundle a few controls into an outer container class, as VFP does if you select controls and choose Save As class.

Bye, Olaf.
 
Heres one interesting reference and thought:

wiki said:
When VFP runs a form, it wants to find a place to rest focus. If it can't find one but the form contains a number of containers, it appears to go into an endless loop in its attempt to find one.

So a solution seems to be to add any control able to get focus!

And there you go, just adding a textbox to my test form it doesn't freeze or hang anymore.

So VFP is on the loss in finding a focussable control and that's the only problem with just having exactly that setup of all non focussable controls. It's not the nesting nor the graphics.

Bye, Olaf.
 
Very nice and useful (as usual) investigation.

Just to add a confirmation that the same behavior is verifiable in my machines, too (will try later on the effects of these final observations by Olaf).
 
So VFP is on the loss in finding a focussable control and that's the only problem with just having exactly that setup of all non focussable controls. It's not the nesting nor the graphics.

And it's VERY old behavior. Pre-VFP, FPW had a similar problem when no control could get focus. You could actually watch the highlight as it moved from control to control looking for a place to land. We called it the pinball machine effect.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top