How to find out, when and why and how a component's property is changed at runtime? - delphi

I have a huge VCL Forms application in delphi and there is an option to display or hide a certain control (MyControl) on each form. Right now the traditional option is enabled, so MyControl should be hidden at runtime.
In Delphi Designer both Controls are visible. Every form is derived from a MyForm-class and in its OnCreate-Procedure the Visible-property of a MyControl (if available) is set to false (according to the traditional option enabled). This does work (as I can see with breaking points and watching expressions). For almost all forms this results in the MyControl not showing.
However for one certain form at some point the MyControl-component itself or any other part of the program sets the MyControls' visibility to true again. How do I find out where this happens?
I am using Delphi 10.1.
my approach:
I've tried to watch the visible-property through the watching-expressions-window using several breaking points. But of course the watching-expression is not available anywhere in the Code (myControl.Visible will only work if the breakingpoint is somewhere myControl is defined). I set a breaking-point anywhere I could evalute myControl.Visible but the magic seems to happen somewhere in between.
So my question: is there some kind of a global variable name, so that I can evalute and watch the visible-property wherever the debugger pauses the program?
a different approach:
I set a data- and an address-breakingpoint but they never fire. Only when I close the program they pause the program a few times.

As advised in the comments, if this is your code you can modify the property to use a Setter and then set a breakpoint on the setter. However if this is not your code and it simply exposes the variable (field) then changing the code to include a setter can be anywhere from triovial to impossible depending on what else needs to be recompiled when you make the change.
If this is your own custom component then you can redeclare an inherited property to use a setter.
If this is not your own custom component - you could make it a custom component and simply change the setter for the property.
You can set a memory breakpoint to alert you to when a memory location changes but your success with this may vary.
I encourage you to experiment with the conditions you can put on breakpoints, get the debugger to work for you.

Related

Control '' has no parent window : Why is control not named?

I've been tasked with supporting an application that is written in Delphi, which is occasionally crashing with the error message "Control '' has no parent window".
My question is not to understand WHY the error is happening, but to understand why the control has no name assigned.
Is the seeming lack of a name for the control a function of the way the control was coded (i.e., controls can have names but they are optional), or is this because the name of the control is inherited from the (non-existent) parent?
My question is not to understand WHY the error is happening, but to understand why the control has no name assigned.
Controls that are created at runtime, as opposed to design time, need not have names. So, this control has no name because the programmer created it without naming it, or it is a control created internally by another control, without being named.
It is perfectly normal for controls not to be named. It is perfectly reasonable for complex applications never to refer to control names.
There are multiple reasons, including but not necessarily limited to:
1) It wasn't given a name in the code.
2) It doesn't inherit a name for whatever function called it

TPageControl: how to prevent changing Style property

I want to prevent a descendant of TPageControl from having a Style property except tsTabs.
At first glance I tried to override SetStyle, but it is declared private in the base class. anyone have ideas?
TPageControl does not natively support what you are asking for. To accomplish what you are asking for, you would have to either:
have your component re-declare the Style property with new getter/setter methods, and then have the setter exit without doing anything. However, the inherited Style property will still technically be accessible at runtime if the user of the component really wants to access it.
derive your component from TCustomTabControl instead of TPageControl, and re-implement everything that TPageControl does, but without promoting the protected Style property. However, the inherited Style property will still technically be accessible at runtime if the user of the component really wants to access it.
have your component override the virtual CreateParams() method and force the TCS_TABS window style in the TCreateParams.Style field. The Style property will still have whatever value the user assigns (which will also affect the behavior of the TabPosition property), but at least the underlying window will always behave as if the tsTabs style were being used.
use a detouring library to hook TCustomTabControl.SetStyle() directly at runtime and make it return without doing anything.

Accessing hidden private class in Objective-C

How can I access an attribute that's been hidden via:
__attribute__((visibility("hidden")))
I'm trying to access UINavigationItemButtonView, but it seems sometime recent (iOS 7.1?) they've added the above into the header file. Recursively printing the window no longer reveals UINavigationItemButtonView in the view stack either.
So, given a UINavigationBar, how can I access a UINavigationItemButtonView that has been hidden via the above flag?
Printing all the subviews in UINavigationBar doesn't reveal it.
The attribute keyword is simply a message to the compiler, and has nothing to do with the runtime. Using ((visibility("xxx")) only serves to tell the compiler if the given declaration should be "visible" or usable by clients in some other package. visibility("hidden") just means that, despite the public declaration, make this thing invisible to external packages, so that they will not be able to use it. Compiling will fail if you attempt to use this class or method.
If you don't see this class being used in a recursive description, it is likely that this class is no longer used; it certainly isn't because of the attribute statement.
Since it's a private class, you shouldn't. Anything you do to bypass that restriction may result in your application failing the review process. Not to mention that, in general, accessing private and/or hidden API's, classes, instance variables, properties or whatever else it is, is a really good way to make sure your application breaks in the (not too distant) future.

Make sure nested child control is visible

I have a utility routine that I call when validating user input in a dialog fails. It sets focus to the offending control, beeps and displays an appropriate message to the user. This works well as long as the offending control is not hidden. Now I have to adapt this to a situation where the relevant controls are children of some kind of collapsible group boxes (possibly even nested), and I have to make sure that the "ancestor" boxes are expanded before calling SetFocus.
Now I have a few possibilities:
Build knowledge about the collapsible component into the error reporting routine. I'd like to avoid that as the routine should rather stay generic.
Pass an callback that can be called prior to (or instead of) SetFocus. This is error prone because one has to remember to pass the callback at all the relevant places.
My favourite solution would probably be an event (or overrideable method) (probably in TWinControl) that tells a container control "please make sure you and you child controls are visible" but I don't know of such a thing.
Any ideas how I can handle this situation?
Define an interface with a method called something like: EnsureVisible.
Implement it for all your components (you may need to derive your own versions of some of these components). This allows different controls to have quite different behaviour.
When a control needs to make sure it is visible it walks its parents and calls EnsureVisible if the interface is implemented.
If you don't like interfaces then do it with a custom Windows message, but you get the basic idea.
In my opinion the best solution would be a separate routine that builds knowledge about all container controls, allowing the dialog validation routine to stay generic and at the same time being focused enough to be easily tested and maintained. Something along the lines of:
procedure ForceControlVisible(C: TControl);
begin
// Recursive code
if Assigned(C.Parent) then ForceControlVisible(C.Parent);
// Code specific to each container control class
if C is TTabSheet then
begin
// Code that makes sure "C" is the active page in the PageControl
// goes here. We already know the PageControl itself is visible because
// of the recursive call.
end
else if C is TYourCollapsibleBox then
begin
// Code that handles your specific collapsible boxes goes here
end
end;
OOP-style methods that rely on virtual methods or implementing interfaces would be way more elegant, but require access to the source code of all the controls you want to use: even if you do have access to all required sources, it's preferable not to introduce any changes because it makes upgrading those controls difficult (you'd have to re-introduce your changes after getting the new files from the supplier).
Each component knows its Parent. You can walk up the list to make each parent visible.

What's the difference between CreateWnd and CreateWindowHandle?

Delphi components have CreateWnd and CreateWindowHandle (and DestroyWnd and DestroyWindowHandle). They're both intended to be overridden by descendants, right? And not intended to be called except by the underlying VCL implementation?
What's the difference between them; when should either of them be overridden?
So far most of the answers here are pretty much on the mark and you would do well to heed their advice. However, there is a little more to this story. To your specific question about when you would override one or the other, I'll try and nutshell things a little bit.
CreateParams();
In general, most of the time all you really need to do is to override CreateParams(). If all you want to do is to subclass (remember Windows style "subclassing?" See Petzold's seminal work on Windows programming) an existing control class and wrap it up in a VCL control, you do this from CreateParams. You can also control what style bits are set and other various parameters. We've made the process of creating a "subclass" very easy. Just call CreateSubClass() from your CreateParams() method. See the core VCL controls for an example such as TCheckBox or TButton.
CreateWnd();
You would override this one if you need to do a little bit more with the window handle once it is created. For instance, if you have a control that is some kind of list, tree, or otherwise requires post-creation configuration, you'd do that here. Call the inherited CreateWnd, and when it returns (you know you have a valid handle if you return from CreateWnd because it will raise an exception if something went awry), just apply your extra magic. A common scenario is to take the data that is cached in an instance TStrings list and actually move it into the underlying window control. The TListBox is a classic example of this.
CreateWindowHandle();
I had to go refresh my memory on this one, but it seems this is one is rarely, if ever, overridden. In the few cases inside VCL itself, it appears that it is used to work around specific Windows version and locale oddities with some controls, such as the TEdit and TMemo. The other more clear-cut case is in TCustomForm itself. In this case it is there to support the old MDI (mutli-document interface) model. In this case MDI children cannot be created using the normal CreateWindowEx() API, you have to send a message to the MDI parent frame to actually create the handle. So the only reason to overide this method is if the actual process of creating the handle is done via a means completely different than the old tried-and-true CreateWindowEx().
I did notice that your question was merely asking about the creation process, but there are corresponding methods that are overridden in some cases for both handle destruction and the "voodoo" that sometimes surrounds handle recreation. But these are other topics that should be covered separately :-).
CreateWnd first calls CreateParams, then calls CreateWindowHandle using the created Params. Generally, you'll override CreateWnd and CreateParams rather than CreateWindowHandle.
I hope this helps!
Who does what:
CreateWnd is the general contractor that creates the fully formed window for a WinControl.
First, it has to set the required attributes for the WindowClass by calling CreateParams and making sure it is correctly registered.
Then it gets the window actually created, by calling CreateWindowHandle which returns the resulting Handle from the OS.
After that, we have a valid window able to process messages, and CreateWnd does the final grooming, adjusting different visual aspects like size, font, etc.
There is also later step done by CreateHandle, after CreateWnd is finished, to help the VCL in managing its windows (identification, parentage,...).
I'm sure that the final answer can only come from the people involved in the creation of the VCL (Allen?), but IMHO the virtual method with the least responsibility / which is lowest in the chain of calls should be overridden. That's why I have always overridden CreateParams() and CreateWindowHandle(). This looks like a good fit since they are both called by CreateWnd(), and both do only one special thing.
In the end it's probably a matter of preference.

Resources