Hi, somewhat recently I sent some code to wine-patches to add button theming; if you have glanced at it, despite utilizing subclassing, code was duplicated from the button code in user.
In particular, the themed button does its own state management. The reason is that upon state changes, the user32 button control does some repaints internally, ie calling the paint function directly - those can't obviously be hooked by subclassing alone. In early versions I had the themed button painted over after state-changing messages, but that causes visible flickering (since the button is first painted in "classic" style and the themed style is painted above that).
The basic problem - painting that is hard to hook into - will probably also arise on other controls.
There are some ideas and approaches to deal with the problem that came up (and the results from discussion with Kevin): - Ignore. Have ugly flickering. - Change the classic controls to use InvalidateRect() instead when internal painting functions are called, so painting messages can be hooked. That would deviate from native behaviour, though (and also occasionally less efficient when the control just paints some change). - Use some magic message the control sends to itself to do some painting which is then hooked. Makes things more complex, could cause compatibility issues with apps that may not handle this message and is incompatible with native. - Code duplication - e.g. in the case of buttons, do state management in the themed class as well. - Static libraries - implement the standard controls in a static library and allow for hooks to override painting (in C++ you'd use virtual methods). Both user32 and comctl32 would link against that lib, and the latter would provide alternative painting functions. Binarily equivalent to code duplication, but not that bad in the source code. For me it looks like a good compromise, though, Kevin noted that "Historically static libs have not gone over very well".
I don't like the current code duplication for theming that much, but I'm a bit unsure what else could be done. Perhaps you have some comments or suggestions, and hopefully there will be some consent of what approach would be best for Wine.
Thanks for reading, -f.r.
Frank Richter wrote:
Hi, somewhat recently I sent some code to wine-patches to add button theming; if you have glanced at it, despite utilizing subclassing, code was duplicated from the button code in user.
In particular, the themed button does its own state management. The reason is that upon state changes, the user32 button control does some repaints internally, ie calling the paint function directly - those can't obviously be hooked by subclassing alone. In early versions I had the themed button painted over after state-changing messages, but that causes visible flickering (since the button is first painted in "classic" style and the themed style is painted above that).
You could make the code to using RedrawWindow(... RDW_UPDATENOW), assuming that the paint functions it is calling are for the whole control, not a component of the control.
On 27.07.2005 17:36, Robert Shearman wrote:
You could make the code to using RedrawWindow(... RDW_UPDATENOW), assuming that the paint functions it is calling are for the whole control, not a component of the control.
Occasionally it does... afaics mostly stuff like just drawing the focus rect or checkboxes only draw the mark when the state changes... but perhaps one could get away with repainting the whole control in this case, though I fear that this would cause flickering again.
-f.r.
Frank Richter wrote:
On 27.07.2005 17:36, Robert Shearman wrote:
You could make the code to using RedrawWindow(... RDW_UPDATENOW), assuming that the paint functions it is calling are for the whole control, not a component of the control.
Occasionally it does... afaics mostly stuff like just drawing the focus rect or checkboxes only draw the mark when the state changes... but perhaps one could get away with repainting the whole control in this case, though I fear that this would cause flickering again.
In that case, you will have to retrieve the rectangle of the changed area and pass that rectangle to RedrawWindow.
On 28.07.2005 15:54, Robert Shearman wrote:
In that case, you will have to retrieve the rectangle of the changed area and pass that rectangle to RedrawWindow.
Though, that would mean that paint messages are emitted to the window? IIRC last time I checked (with Spy++), there were no paint messages when e.g. the state of a checkbox changed. So using RedrawWindow() may mean a different behaviour than on native.
-f.r.