Jump to content
Roger Cigol

Form still on display when property Visible = false

Recommended Posts

I have an Alexandria 11.2 patch 1 VCL 64 bit windows application. I get the same problem running as an  independant exe file or running under the RAD Studio IDE. I have a tick driven check function that has made the window invisible to the user by calling Hide(), on a previous tick. Then it checks for the state of a separate thread (via a lock to ensure concurrent access is ok). When the other thread indicates that it is ready to display the form it sets a flag and I then call Show() to display the form to the user. This works most of the time. But, rarely, I get to the checking state but the user can still see the form. I have added a check in the code to change the form colour if Visible == true (as a debug aid) and it DOES NOT change colour - so I know Visible is false. Here's my code where this occurs:

      case TSGS_WaitingForDisplayDecision:
         Status = "Waiting for display decision";  // elsewhere this is displayed on the form 
         if (TestControl[TestControlID]) {
            TTestControlGUIInterface Info;
            TestControl[TestControlID]->TestControlGUIInterfaceData.Read_TS(Info);
            if (Info.GUIShouldBeVisible) {
               State = TSGS_DisplayMainTestForm;  // this next state calls Show() to display the form
            }
            else if (Visible) {
               Color = clTeal; // when the fault occurs the form can be seen but it stays at the default colour
            }
         }
         break;

a breakpoint at the line "Color = clTeal" is never hit - even though I can see the form on the screen <when the fault is present>. A breakpoint elsewhere in the code shown above is hit so I know I am passing through this state.

Has anyone else ever seen anything similar?

Share this post


Link to post

This code is taken out of context, and hard to diagnose as-is. You are going to have to show a more complete example.  But if I had to guess, you are likely seeing a completely different Form object onscreen than the one that is processing this code.

Share this post


Link to post

Hi Remy, Thanks for taking an interest here. You are right about limitation of code snippet but it's very difficult to give a "complete" example since I don't know what bits are required to make it "complete". Your guess is a very sensible lead. I think I need to add a display of the "this" address of the form - then I can check when I debug with a break point and confirm (or otherwise) that I am in the correct object. I will try to do this tomorrow.

Share this post


Link to post

I have confirmed that the break point IS on the actual object being observed.

void TTestStatusForm::DealWithState(void)
{
   String IsVis = Visible ? String("Yes") : String("No");
   Trash1Edit->Text = String(reinterpret_cast<__int64>(this)) +
      String("  Ex: ") + String(TrashExCounter) +
      String("Vis: ") + IsVis;
   if (!IsBusy) {// skip if still active from last tick
      IsBusy = true;
      try {
         DealWithStateMachine();
         // !!! delete this !
         int Trash = TrashEdit->Text.ToIntDef(0);
         Trash++;
         TrashEdit->Text = String(Trash);
      } catch (...) {
         // we don't want to lock up with IsBusy = true
         TrashEdit->Text = String(-999999);
         TrashExCounter++;
      }
      IsBusy = false;
   }
}

Trash1Edit is the blue box across the top of the screen shot. - DealWithState is called very 20ms (and the TrashEdit counter under the comment // !!! delete this is seen to be counting upwards). You can see that the status is showing that Visible = set to false and yet the form is still visible (hence I could do the screen shot). Note that the screen shot does not show the TrashEdit counter (this is off to the right) but this does count up.

VisNotVis.JPG

Share this post


Link to post

Without more code hard to tell but keep in mind messages are sent as part of changing the visibility so the event loop can't be blocked if you want the form to go away. 

Edited by Brian Evans

Share this post


Link to post

Hi Brian, A good point (and accurate). But I think I am happy that this is not the problem because the same underlying message approach is used to update the form contents and on the "visible but Visible = false" form there is a tick counter being displayed (in TrashEdit->Text) and this IS seen to be updating. Also a debug aid button on the form works - in it's OnClick event I reset the trash counter to zero and this happens when I click it. I think this all means there is no block on the main VCL message loop.

 

Share this post


Link to post

Without a reproducible example, there is simply no way for anyone to diagnose your problem with the limited information provided so far.  You might have to enable Debug DCUs and step into the VCL source code with the debugger to figure out what is actually going on internally when you are setting Visible = false.  Clearly there is a step being skipped inside of it when updating the underlying Win32 window.

Edited by Remy Lebeau

Share this post


Link to post

Hi Remy - it's a 64 bit app - but other than that your advice is (as always) a good idea of what to try next. Thank you. I already have another "debug aid" button who's on  click handler calls Hide() - and this doesn't cause the form to go away in this fault condition (it does "hide" it (ie make it non-visible) when i click on it when it is all working and expected to be visible)). This will provide a convenient entry point for the stepping as you describe. Might be a challenge to follow the thing through but I'll give it a go.

Edited by Roger Cigol

Share this post


Link to post

I am not certain that I've single stepped into the VCL code before. But it doesn't seem to be working. Can anyone advise what I am missing, please?

 

I have set project | options | Delphi compiler | compiling | use debug .dcus  to true (all the options in this "debug" section are set to true or to their highest level)

I have done a project "clean"

I have compiled (ie full build) the Clang64 code with "debug" settings.

 

When I run the code (under the IDE) it does stop at breakpoints ok.

I wait for my code to get to the "faulty" state (ie with the form on the screen and Visible property set to false).

I hit my recently added extra button and it breaks at my break point in the OnClick event handler ok. I can confirm that the "this" value matches the displayed value on my form.

The event handler has the single line of code: Hide();

I now try to single step INTO this function and it just jumps over to the end of the event handler, rather than going into the VCL pascal which is what I was expecting (and wanting) it to do.

 

Share this post


Link to post

I don't use C++ Builder myself, but here is an answer from StackOverflow for a question from a few years ago:  you must change two settings. Turn off the Dynamic RTL in the linker settings and disable linking with runtime packages in the package settings.

 

delphi - Can I step into the VCL (Pascal) code while debugging a C++ app? - Stack Overflow

debugging - C++ Builder XE2 - is it possible to debug vcl data library? - Stack Overflow

Edited by Brian Evans

Share this post


Link to post

I think this question is becoming "how do I step (debug) into the VCL in C++ VCL Windows 64bit project. I am on Windows 10 - RAD Studio 11.2 with patch 1

I have created a simple dummy VCL C++ project. Set static linking. Set "use debug dcus". If I target Win32 I can single step into VCL (eg breakpoint on Hide() in line 22 of unit2.cpp. Clicking on the IDE step into button leads me into the VCL code where it sets the property Visible to false.  All good. If I compile for Win64 when I get to the break point it breaks but this time the IDE step into button just steps over the Hide() function.

Library path is strange. For windows 64 it uses the same default path: $(BDSLIB)\$(PLATFORM)\debug but this is greyed out for Win64 (indicating that it is not a valid path). 

My installation is on my "D:" drive. I think these macros equate to D:\Program Files (x86)\Embarcadero\Studio\22.0\lib\win64\debug. This directory exists and looks as if it has all the files I expect.

If I explicitly add this path ( D:\Program Files (x86)\Embarcadero\Studio\22.0\lib\win64\debug) to the library paths it appears not-greyed-out (ie it is valid). But no change to behaviour when I try to step into Hide().

If it needs this library path to build the exe I don't understand how it manages to build without it being there. Maybe the "greyed out" library path is valid ?

Project source (no exe) as a zip file attached.

 

C Code Hide Show 64.zip

Share this post


Link to post

If I compile my simple sample project (C Code Hide Show 64) with static linking for either Win32 or Win64 with the Project | options | C++ shared options | Library path complete empty it still builds, links and runs ok. Somehow the linker must know about the library file path..... How can I tell which path it is using ? (maybe my original problem is due to the wrong libraries being linked in?). Answer by looking at the TwineCompile console output. The Linker part of this is as follows

 

Linking...
Target _PerformLink:
    Target _PerformBCCILink:
        d:\program files (x86)\embarcadero\studio\22.0\bin\ilink64.exe -G8 -L.\Win64\Debug;"d:\program files (x86)\embarcadero\studio\22.0\lib\win64\release";"d:\program files (x86)\embarcadero\studio\22.0\lib\win64\release\psdk";C:\Users\Public\Documents\Embarcadero\Studio\22.0\Dcp\Win64;C:\Users\Public\Documents\Embarcadero\Studio\22.0\DCP\Win64\Debug;C:\Users\Public\Documents\Embarcadero\Studio\22.0\Dcp\Win64 -j.\Win64\Debug;"d:\program files (x86)\embarcadero\studio\22.0\lib\win64\release";"d:\program files (x86)\embarcadero\studio\22.0\lib\win64\release\psdk";C:\Users\Public\Documents\Embarcadero\Studio\22.0\Dcp\Win64;C:\Users\Public\Documents\Embarcadero\Studio\22.0\DCP\Win64\Debug;C:\Users\Public\Documents\Embarcadero\Studio\22.0\Dcp\Win64 -l.\Win64\Debug -v -Gn -aa -Tpe c0w64w memmgr.a sysinit.o .\Win64\Debug\Project1.o .\Win64\Debug\Unit1.o .\Win64\Debug\Unit2.o , .\Win64\Debug\Project1.exe , .\Win64\Debug\Project1.map , rtl.a vcl.a import64.a cp64mt.a , , .\Win64\Debug\Project1.res

 

So I can see that, even though the library path is empty, the library files paths are being passed to the linker. But why is the first path in the -L switch a "release" path ? Is this why the single stepping into Hide() is not working?

 

Edited by Roger Cigol
adding more information

Share this post


Link to post

STOP PRESS - I now know (from info direct from Embarcadero) that it is not possible to single step into VCL on a Win64 C++ project with RAD Studio 11.2. Delphi and Clang64 use different debuggers in this case.

Share this post


Link to post
1 hour ago, DelphiUdIT said:

I think you cannot debug Delphi and C++ at the same time

That is not what Roger is saying.  C++Builder can certainly step into the Delphi-written VCL source code under 32bit (I've done it countless times) - just apparently not when compiling for 64bit (which I never do) due to the different debuggers being used by C++ and Delphi under 64bit.

Share this post


Link to post

Going back to my original problem I am suspicious of the library issue. One reason for this is when I explicitly add the library path D:\Program Files (x86)\Embarcadero\Studio\22.0\lib\win64\debug to my project the problem still happens but seems to be much rarer. Over the next few days (weeks?) I am going to try removing this path and running again to confirm that this statement is true (sometimes it takes an hour or more for the problem to appear). I will also try running it in "release" mode. If there is a release library being chosen for some reason that doesn't match a debug library (is this possible?) then a release mode build might be expected to run perfectly. This will take some time......

23 minutes ago, Remy Lebeau said:

C++Builder can certainly step into the Delphi-written VCL source code under 32bit

Remy is absolutely correct here 

Edited by Roger Cigol
typo in Remy's name

Share this post


Link to post

Just a hunch, following Remy's suggestion: is the form auto created? If auto, and if you also create a dynamic instance, you could be looking at another form than you think.

 

 

Share this post


Link to post

In the past using Showing property never worked well for me...  I just the removed the if Showing and just Hide and Show as needed.  

 

Also I added Step, Run, Stop buttons for timer state.  A Step "freezes" the "program" if timer was enabled. If !timer.Enabled the Step does one OnTimer event. In runtime. 

Or say in Edit mode vs "Freeze". The State machine tells the Windows tiling what to do.  The tiling should have not to deal with the State machine. This tiling either forms or controls get control when active or have focus.  UI is dealt by State machine. The tiler (UI) plays the cards dealt. 

 

Also simply changing the parent of control can "show" or "hide" in a hurry.    

 

Edited by Pat Foley
Explain need to remove if showing tests.

Share this post


Link to post
18 hours ago, Harry Bego said:

Just a hunch, following Remy's suggestion: is the form auto created? If auto, and if you also create a dynamic instance, you could be looking at another form than you think.

 

 

Hi Harry, thanks for this: All help appreciated. In my case the form is NOT autocreated (I've removed it from the list in project | options). By displaying the value of "this" in my debug TEdit box and hitting a breakpoint I can confirm that I am on the correct instance of the form. Also the TEdit box clearly indicates that the form visible property is false - yet I am reading the TEdit box contents as it IS visible on the screen. This should never happen.

Share this post


Link to post
On 11/4/2023 at 3:29 PM, Harry Bego said:

Just a hunch, following Remy's suggestion: is the form auto created? If auto, and if you also create a dynamic instance, you could be looking at another form than you think.

 

 

Hi Harry, thanks for this: All help appreciated. In my case the form is NOT autocreated (I've removed it from the list in project | options). By displaying the value of "this" in my debug TEdit box and hitting a breakpoint I can confirm that I am on the correct instance of the form. Also the TEdit box clearly indicates that the form visible property is false - yet I am reading the TEdit box contents as it IS visible on the screen. This should never happen.

Share this post


Link to post

I am interested in the library information passed to the linker.

With my simple hide show project (source code zip already included above) if I compile for Win64 for debugging and have no entry in the Project | Options | C++ Shared Options | Library path for any of the available levels of the tree (ie nothing in All configuration all platforms, nothing in All configurations - Windows 64, nothing in Debug configuration, nothing Debug configuration - Windows 64 and nothing in Release configuration and nothing in release configuration Win 64) if I then look at the text in the Console Output tab following the TwineCompile full build I can see the paths passed to the ILinker as parameters of the -L switch. These are as follows:

 

-L.\Win64\Debug;

"d:\program files (x86)\embarcadero\studio\22.0\lib\win64\release";

"d:\program files (x86)\embarcadero\studio\22.0\lib\win64\release\psdk";

C:\Users\Public\Documents\Embarcadero\Studio\22.0\Dcp\Win64;

C:\Users\Public\Documents\Embarcadero\Studio\22.0\DCP\Win64\Debug;C:\Users\Public\Documents\Embarcadero\Studio\22.0\Dcp\Win64

 

I don't think the second and third in this list should be "release" - I think they should be "debug". 

 

But how to fix this? where do these come from? 

 

If I open up the project file with a text editor and search for "release" there is no entry that is related to library file specification. so I don't think it is a problem with the project file.

 

Edited by Roger Cigol
parameters of -L switch is more accurate description

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×