I have an odd issue with TChromeTabs. I know it must be something simple, but I can't figure out what needs to be done to fix it.
When I initially drop the TChromeTabs control on a form it is completely transparent. If I cut the control then paste it back to the form the contents are displayed correctly. The contents also appear if I close, then re-open the form.
As I have no idea why this is happening I can't really give you any code samples. However, you can download the source code here: http://code.google.com/p/delphi-chrome-tabs/downloads/list.
Your control doesn't paint itself because you disable painting. You call BeginUpdate in the constructor, and you don't call EndUpdate until the Loaded method is called. But Loaded is only called when loading a control from a persisted state. Usually, we think of that as being when the control is loaded from a DFM file, but the IDE uses the same technique to allow putting controls on the clipboard.
You haven't noticed this before because, apparently, you only test your control by opening a pre-made demo project. The demo project has a control in its DFM file, so the only code path you exercise is the DFM case. You don't exercise the path where the constructor is called directly — when the control is first dropped on a form, or when the control is created "dynamically" in code.
To fix this, begin by getting rid of the BeginUpdate call in your constructor. Instead, to check whether your control is still in the process of being constructed, check csCreating in ControlState.
You can also get rid of your stsLoading state. Delphi already gives you that with the csLoading bit of ComponentState. Besides, your use of stsLoading is wrong since you set it in the constructor, just like you do with BeginUpdate.
Instead of relying on Loaded being called, you might wish to move certain code into the AfterConstruction method. Put code there that needs to run after your component is created but that has nothing to do with loading properties from a DFM (or other persistence source). I'm not sure I see anything in your Loaded method that really belongs there. Nearly all of it should be able to occur in the constructor.
You should also be aware of the CreateWnd method. It's called when your control's window handle gets allocated. That's where you should start allowing paint operations to occur. When you don't have a window handle, you have nothing to paint to.
Related
I am trying to create custom control with directx10/direct2D output (panel, not a form). I do all rendering in the overriding OnPaint method, however I have read somewhere that it is wrong and RenderLoop should be used instead. But where should I insert RenderLoop.Run if I can write code only inside of the control? Thank you.
You would create a thread, and have RenderLoop.Run inside the thread. When you do this you have to make sure that events sent back and forth between the components are invoked in a safe manner.
Edit: While my comments have an iOS 5 working example, I am still getting this for other versions. I've now implememted a test to only register and dequeue cells if iOS 5, but it's really puzzling!
still receiving _accessibilityUpdateRemoveControl exceptions, strange nuisance, appears to be something with the edit controls, nothing is retained so nothing needs deallocing, but will try, and post the answer if I find it!
This was working yesterday, and now it's not... I changed nothing!
Edit: Turns out, while reloadData causes the crash, the crash does not occur without my custom tableViewCell... hmmm, something about removing the + sign, but it doesn't happen with deletion!
Actual error is this:
[CustomTableViewCell _accessibilityUpdateRemoveControl]: message sent to deallocated instance.
What's funny is, the remove button works. Essentially it removes the item from an array, adds it to another, basically putting it "to another table". No crashing, works fine.
If I remove the line that reloads the data in the table, after the insert button adds it, it also works. Eg: Don't immediately reload the data, close window, come back, everything displays fine. The exact line, so far, that crashes it is in
[theTable reloadData], but that line, for the other table (as I update both) doesn't crash at all. Actually, thanks to that, I'm gonna view the headers for UITableView's functions, and view other answers with that specific line. I just didn't see this, anywhere, after searching for that weird function call.
I'm ensuring my cell is within memory, and even quit dequeuing just to ensure it's working. I'm stumped with this, hopefully will have solution in an hr or less.
Thanks
I stepped through Apple's code, line by line, read the name of every function and noticed this:
editControlWasClicked: (id) clicked
is called just before crashing. I combined that with the error message, and the fact I call [table2 reloadData] before this is called, and pieced those pieces together.
The cell is erased (so it moves to the other table), but somehow calls its system callBack "editControlWasClicked" after the table reloads... since it's on the main thread, I'm guessing the table stuff is multi-threaded... how else would it call these in order but do that After the reload??
So to test this, I used the "afterDelay" function, and low and behold, it worked.
You may be asking why I'm using an add edit control in one and subtract in the other... there is a purpose to that.
So, possible solutions: 1) use the afterDelay method of selectors.
2) Write a custom IBAction ('cause it's a xib) or otherwise use custom images and functions to ensure that doesn't get called back.
Note, 2 involves writing an extra delegate so that messages from the cell can reach the view controller.
Basic solution: use iOS 5, use the queuing, otherwise do one of the above solutions or figure out the threading/hooks and find a way to do this without delaying. (I would prefer such if I can find it)
HI
I have an application with more than one frame that act as forms.
I have temporary files I need to delete when the user moves from a certain frame and I currently delete the file when they press OK or CANCEL.
If they just close the application I also want to delete the temporary files but cannot determine when the frame is destroyed.
Regards, Pieter
To detect when a frame is destroyed, override its destructor, Destroy.
If overriding the destructor is not appropriate (say, if the files belong to the enclosing form rather than the frame), then you can use component notification. After you create the frame, call its FreeNotification method, passing in a reference to the enclosing form. When the frame is destroyed, it will call the form's Notification method. Override that method in your form, and if the component is the frame, delete the files. (That method may be called many times in your program, so checking the AComponent parameter is important.)
I am writing a web control where I'm overriding the CreateChildControls method. In this method I create an EditModelPanel, add a button to it and then add the EditModePanel to my web control's Controls collection (this.Controls.Add(xxx)). The problem is that the button shows up in both Display mode and Edit mode. I've tried setting EditModelPanel's PageDisplayMode property and SuppressTag property and nothing works.
Why does the EditModePanel fail when adding it programatically?
I've googled this issue and someone else had the exact same problem but he got no response.
Firstly, You can detect from within your control if you are in edit mode and not create the child controls. This way you will not need the editmodepanel.
I have refactored the editmodepanel class, and it does things a bit differently. It implements IParserAccessor and the logic is in AddParsedSubObject() method of the interface. I think by manually adding the controls, you are bypassing the IParserAccessor. Hope this helps.
I have a TGraphicControl descendant which paints rather slowly. There's also a TWinControl descendant, this one paint fast. Both controls are on the same TPanel.
While scrolling, the TGraphicControl is updated more often than the TWinControl, so they look out of sync. This updating is done by Windows and/or the VCL, not by my code.
I can solve this by calling TWinControl.Update from the TGraphicControl.Paint method, but I'm a bit worried this might cause problems one way or another.
Is it safe to do this?
As long as there isn't a call back to your TWinControl that should be fine. You might get the TWinControl updating more often than strictly necessary but that's all.
It's safe, as long as they're unrelated. But it doesn't look like a very efficient approach.
The TGraphic depends on Painting by the parent Control, is that also the Parent of the TWinControl?
You might experiment a little with:
a) change the TGraphic based control to be a TWinControl (TGraphic isn't that useful or efficient anyway). That is if you own the source.
b) Embed the Graphic Control in a special (borderless etc) TPanel