In Owlet, as part of my work on "GDI object encapsulation and implementation overhaul" [feature-requests:#178], I have reimplemented the TGdiObject derived classes to use std::shared_ptr for the implementation of the shared handle encapsulated by these classes; HBRUSH, HFONT, HPEN, etc. (see [discussion:00f93e1a3a#d641]). All of these classes previously had shared-pointer semantics through (messy and brittle) reference-counting implemented in the base class TGdiObject. The use of std::shared_ptr has now completely eliminated the latter, while providing a much simpler and more robust solution.
For an example, see the new implementation of TPen.
Note that the use of std::shared_ptr here is completely hidden from the user through the use of private inheritance. The client code still uses the classes as before, and there is no need to explicitly use std::shared_ptr in client code.
I have extended my work on this solution to other handle-encapsulating classes, such as TCursor, TDC, TDib, TIcon and other classes derived from TGdiBase, with the aim to completely eliminate the latter as well. However, this is a notable design change, since these classes did not have shared-pointer semantics before. Objects either had strict sole ownership of the handle, or no ownership at all (configurable at run-time by passing enum TAutoDelete to the TGdiBase constructor). However, these classes were not copy-able, so enabling shared-pointer semantics (and hence allow copying) should not break existing code in the normal case. The ability to copy (and move) will for the most part be entirely new, and will eliminate awkward and brittle workarounds using pointers and dynamic allocation.
That said, there are a couple of exceptions, such as TBitmap and TDib, that originally implemented copy-constructors with deep-copy semantics. TBitmap now has a dedicated method to perform deep copy, while the copy constructor and assignment operator implement handle sharing. I plan to do the same for TDib and others. These may be breaking changes — but for the good, in my view.
There are further handle-encapsulating classes in OWL, notably the support classes for the Common Controls library, and these are also good candidates for a similar rewrite. For example, TImageList has now been rewritten to have shared-pointer semantics, similar to the GDI classes, and it works nicely.
I plan to commit my latest changes soon, and I welcome review and feedback on this work. If there is sufficient interest and support, maybe some or all of it may be adopted on the trunk in the future. If not, Owlet is freely available for experimentation and use.
Discussion: Running out of (menu) handles
Feature Requests: #178
Feature Requests: #262
Anonymous
TImageList was overhauled and given shared-pointer semantics in [r6061].
Related
Commit: [r6061]
Diff:
Related
Feature Requests: #178