My applications in C++Builder use a VCL TTreeview with nodes of several derived TTreeNode classes. After changing the Windows Theme, the treeview somehow gets recreated, not just repainted. During the recreation the derived treenode destructors get called, but their constructors are not called. It appears the new nodes are all of the basic TTreeNode type instead of the derived types. As a result all methods and properties of the derived classes are lost in the process.
In addition, in the recreation the nodes obtain new addresses in TreeView->Items (TTreeNodes), which will become a problem if the theme change occurs during a long-time action upon a certain node ending with the creation of a child node, i.e. the child has to be added to a parent address that does not exist anymore.
Is there a way to prevent a theme change to have an effect on the TTreeView and its nodes? Or any other solution?
During the recreation the derived treenode destructors get called, but their constructors are not called. It appears the new nodes are all of the basic TTreeNode type instead of the derived types.
Correct. During HWND recreation, before its HWND is destroyed, TTreeView saves its node data to a temporary memory stream and destroys its node objects, and then after a new HWND becomes available, it creates new node objects and restores the saved node data into them. But, when saving and restoring that data, it has no concept of your derived classes, and so it can't persist them correctly.
If all of your nodes are the same derived type, then you should be OK by simply using the TTreeView.OnCreateNodeClass event or overriding the virtual TTreeView.CreateNode() method. But, if your nodes are using multiple derived types, then you are just SOL, sorry. There is simply no way for the native functionality to know which derived type to recreate for which node.
In addition, in the recreation the nodes obtain new addresses in TreeView->Items (TTreeNodes)
Yes, because they are new objects.
which will become a problem if the theme change occurs during a long-time action upon a certain node ending with the creation of a child node, i.e. the child has to be added to a parent address that does not exist anymore.
What are you doing that takes so long that it spans across a window recreation at all? Don't save TTreeNode references to begin with, and you won't have this problem. If you need to track custom data, use the TTreeNode.Data property instead, that is correctly persisted during window recreation.
Is there a way to prevent a theme change to have an effect on the TTreeView, and its nodes?
Not that I'm aware of, no.
Or any other solution?
Handle the window recreation yourself. Set the TTreeView.CreateWndRestores property to false, and then override the virtual DestroyWnd() method to save the node data however you want when the ControlState property has the csRecreating flag, and override the virtual CreateWnd() method to restore that data as needed. For instance, you could save each node's class name, and then use that to create your derived node objects again.
I certainly want to prevent the nodes from being recreated. So I derived a TTreeView class overriding CreateWnd() and DestroyWnd() (and a helper boolean variable recreating):
void __fastcall TreeView_c::CreateWnd(void)
{
if (recreating) recreating= false;
else TreeView::CreateWnd();
}
void __fastcall TreeView_c::DestroyWnd(void)
{
if (CreateWndRestores &&
Items->Count > 0 &&
ControlState.Contains(csRecreating))
recreating= true;
else TTreeView::DestroyWnd();
}
This seems to work, there are no more runtime errors after a Windows theme change. But it just seems too simple to be correct, am I not testing enough themes?
A strange thing is that a theme change does get into DestroyWnd(), setting recreating to true, but does not get into CreateWnd(). I don't understand why not?
Related
I have a data structure like this:
mod nodes {
struct Node {
predecessors: Vec<Rc<Node>>
}
}
I obviously don't need mutability of the nodes in that module. I also don't have cyclic references here.
But I have another module, which contains nodes, where I need mutability:
pub mod network {
mod nodes {...}
struct Network {
nodes: Vec<Vec<Rc<RefCell<Node>>>>
}
}
I just can't figure out a way to create the Rc<Node>s for the nodes themselves together with the Rc<RefCell<Node>>s for the Network.
Do you have any idea on how to implement the immutability in the nodes module next to the mutable nodes in the network module?
Or is there no other way than to declare the references to the predecessor nodes inside the Node struct as Rc<RefCell<Node>>, even though I don't need mutability here (I would like to avoid that)?
Rust has single ownership. If a Node is owned by a RefCell, it cannot also be owned by a different Rc at the same time.
When a Node can be modified in one place via RefCell, these changes cannot be allowed to show up elsewhere in Rc<Node>. This would violate immutability of Rc<Node>.
Also note that Node is a struct value, not a pointer to an object. There's no extra layer of indirection that would even make it possible to share it between RefCell and other Rc. Its data is copied and inlined in its container.
Consider using Rc<RefCell<Node>> in both places. If the same data is used in both places, it has to uphold all guarantees in both places, even if you're not taking advantage of that.
If you're not using both types at the same time, you can convert from one type to another by deconstructing it (into_inner, try_unwrap) and constructing the other type again. This conversion is not free, because physical memory layout of these types is different.
If you only sometimes need mutability, Rc has make_mut that works without RefCell. And RefCell has a zero-cost get_mut if you already have a mutable access to it, so you might be able to reduce their overhead in specific cases.
I got a piece of code which uses a std::set to keep a bunch of pointer.
I used this to be sure of that each pointer will present only once in my container.
Then, I heard about std::unique_ptr that ensure the pointer will exists only once in my entire code, and that's exactly what I need.
So my question is quite simple, should I change my container type to std::vector ? Or It won't changes anything leaving a std::set ?
I think the job your set is doing is probably different to unique_ptr.
Your set is likely recording some events, and ensuring that only 1 event is recorded for each object that triggers, using these terms very loosely.
An example might be tracing through a mesh and recording all the nodes that are passed through.
The objects themselves already exist and are owned elsewhere.
The purpose of unique_ptr is to ensure that there is only one owner for a dynamically allocated object, and ensure automatic destruction of the object. Your objects already have owners, they don't need new ones!
Okay, so now I want to create a COM interface that represents the data model my custom table control will take, instead of using messages passed between the table and its parent window. The table currently displays text, images, and checkboxes. Objects that implement the interface are expected to live in single-thread apartments.
I know I can use BSTRs for strings and some integer type for the checkbox booleans, and that there are already established conventions for ownership transfer for these that I can follow. But I'm not sure about bitmaps.
What I want to do is call the model object's GetCellData() method, which takes the row, column, and a pointer to a VARIANT that the model will put the cell's data in. I only need to draw the bitmap once before disposing of it. Since bitmaps can only be selected into one DC at a time, I need to be the exclusive owner of the bitmap, but only temporarily.
I tried looking for a similar COM interface by Microsoft that did this already, but didn't find anything (or didn't look using the right terms).
So my questions are:
How would I pass the HBITMAP into the VARIANT? My best guess is storing it in the byref field.
How should I negotiate ownership of the HBITMAP? I see two possibilities: either a) require a copy of the HBITMAP to be sent each time, with the table control itself calling DeleteObject(), or b) have the HBITMAP borrowed (use it and then have another model method FinishedWithBitmap() that will be called when finished). Is any one of these more suited to COM's rules than the other? Or do I have the wrong idea entirely? Would STGMEDIUM be appropriate?
I should point out the HBITMAPs are treated as 32-bit ARGB (that is, they're drawn by AlphaBlend()). I found IPicture but that doesn't seem appropriate for this format.
Thanks.
Update
Okay here's the general idea. Let's say model is the table model, which is the server. The table itself is the client. The code for drawing a bitmap cell in the client would look like this:
HBITMAP bitmap;
ITableModel_GetCellData(model, row, column, &bitmap);
// draw the bitmap (CreateCompatibleDC(), SelectObject(), AlphaBlend())
At this point the client doesn't need bitmap anymore. I'm asking if COM has a canonical way of defining the ownership of the HBITMAP to the client's drawing code, so I as the client author would know if I should either write
// the client owns the bitmap
DeleteObject(bitmap);
or
// the model still owns bitmap
// we need to explicitly give it back because only one DC can have a bitmap selected at one time
// since each client has the DCs, the server needs to know when it's safe to give the same HBITMAP to another client
ITableModel_ReturnBitmap(model, bitmap);
(IDataObject provides a solution to this problem in the form of STGMEDIUM.pUnkForRelease.)
In the end I decided to take a different approach for now: rather then returning an HBITMAP to draw, I provide a method that takes the HDC and have the model do the drawing. (The DLL will provide a helper implementation for people who do write custom models.) Other COM interfaces (like IImageList) do this already, so why not :/
I'm not sure if I'll keep the GetCellData() method as it is or break it apart into one function for each data type. Another column type I just realized I would need for the model is COLORREF (for customizing cell background colors; model columns and view columns are not equivalent). I'm also not sure what I'll do about a SetCellData() method in the same vein; it'll only be used by the Table view itself when the user decides to change something int he UI (by checking a checkbox, for instance) and I don't think I'll provide a way to change images directly from within the table, so... Adding separate model functions for each different data type would obviously be a poor idea (especially if interfaces have to remain constant once finalized), but VARIANT is looking less and less optimal.
That is certainly one way. The beauty of implementing IDataObject is that the consumer of the object can decide on what format he requires--of course you have to say what you will provide. But, with delay rendering, you can wait until they actually request the data before you provide it.
now I'm developing a GUI with pop-up windows, so actually it is a workpackage with multiple GUIs.
I have read thorough the examples given in help files (changme, and toolpalette), but I failed to animate the method to transfer data from the new one back to the old one.
Here is my problem.
I have two GUIs, A, the Main one and B that I use it to collect input data and I want to transfer the data back to B.
Question 1:
I want to define new subclasses of handles in A.
lets say,
handles.newclass
how can I define its properties, e.g. 'Strings'?
Question 2:
In A, a button has the callback
B('A', handles.A);
so we activate B.fig.
After finished the work in B,
it has collected the following data (string and double) in B(!)
title_1 itle_2 ... title_n
and
num_1 num_2 ... num_n
I want to pass the data back to A.
Following the instruction, I wrote the codes shown below.
mainHandles = guidata(A);
title = mainHandles.title_1;
set(title,'String',title_1);
However, when I go back to A, handles in A was not changed at all.
Please someon help me out here.
Thank you!
=============update================
The solution I found is adding extra variables (say handles.GUIdata) to handles structure of one GUI, and whenever the data are required, just read them from the corresponding GUI.
And It works well for me, since I have a main control panel and several sub-GUIs.
There is a short discussion of this issue here.
I have had similar issues where I wanted external batch scripts to actually control my GUI applications, but there is no reason two GUI's would not be able to do the same.
I created a Singleton object, and when the GUI application starts up it gets the reference to the Singleton controller and sets the appropriate gui handles into the object for later use. Once the Singleton has the handles it can use set and get functions to provide or exchange data to any gui control that it has the handle for. Any function/callback in the system can get the handle to the singleton and then invoke routines on that Singleton that will allow data to be exchanged or even control operations to be run. Your GUI A can, for instance, ask the controller for the value in GUI B's field X, or even modify that value directly if desired. Its very flexible.
In your case be sure to invalidate any handles if GUI A or B go away, and test if that gui component actually exists before getting or modifying any values. The Singleton object will even survive across multiple invocations of your app, as long as Matlab itself is left running, so be sure to clean up on exit if you don't want stale information laying around.
http://www.mathworks.com/matlabcentral/fileexchange/24911-design-pattern-singleton-creational
Regarding Question 2, it looks like you forgot to first specify that Figure A should be active when setting the title. Fix that and everything else looks good (at least, the small snippets you've posted).
I'm working on a MVC/MVP GUI for editing a document. The document has a tree structure, with some nodes representing text, others images. The app model also includes a command stack, with commands operating directly on the model.
Since different nodes have radically different controls, I'm planning on implementing individual MVC/MVP triads for each node. Where I'm running into trouble is how to synchronize creation and destruction of the peer V and C components.
My ideas:
- listen on each node for "childAdded" type events, and then create peers based on those events
- use a factory for creating nodes in the model, and have that factory also create the peers
What are some common patterns or best practices for dynamic view/controller generation?
I recommend looking at some of the UI Patterns at this site
As for your specific question I would do the following
The form displaying the nodes would implement a INodeView Interface
One Method of the INodeTreeForm interface would be the ability to add a individual node. It would be passing a Node class created in the NodeTreeScreen object. There will be two key property. The first is the key of the node, and the second is the type of node.
You would add the node in such a way that there is a field on the control that has the key.
Along with INodeTreeForm Interface you would have a INodeView interface. This would cover the view area or the new form you will be switching too.
When you click on the node it passes the key to NodeTreeScreen which tend looks at what type of node it is. It has a collection of INodeView objects. One of the properties of INodeView will be which type of node it is.
You retrieve the right INodeView. You close the current INodeview, set the current INodeView to the one you retrieved, pass it the node, and tell it do display itself.
You have a choice as to what INodeView will talk do. You can have a form/control registered for each of the different type. For example a INodeViewText, INodeViewImage, etc. Or just one omnibus INodeViewForm and let the object implementing INodeView take care of the actual drawing.
Depending on your GUI toolkit this could mean that one form could be implementing a lot of different interfaces.
As for adding, deleting, and creating nodes, this would be done through the interaction between the form implementing INodeTreeForm and NodeTreeScreen. Among the things this will be doing is executing the commands you already created to modify the model.
By implementing every thing behind an interface you can change the implementation without screwing up the rest of the software. The object implementing the different interfaces can change without impacting the other objects as long as they continue to implement the interfaces correctly.
This is a variant of Passive View on Martin Fowler's site.