Work, this week, began with finishing the initial implementation of CMenuSite. This class and the window it creates act as an intermediary between a BaseBar and a MenuBand, forwarding the events and messages either to the child band, or to the parent bar, as necessary. It handles the sizing of the child band, to adapt it to changes in the available space. It also provides certain services related to the positioning and sizing of the child bar, which it handles by forwarding some requests to the child, and the rest to the parent.
This implementation was done within rshell, a DLL created by Giannis that is used to provide alternative implementations of the shell32 classes, which can be referenced instead of the real ones while constructing the Start Menu. With rshell, the code can be tested directly from within Visual Studio, using all of the debugging features of the IDE.
At this point, the CMenuSite class seemed to work mostly correctly, although it’s not yet flawless. You can see the results in the following screenshot, which shows explorer-new, running in Windows 7, but using the CMenuSite from rshell instead of Windows:
I continued by writing a wrapper for CMenuBand that logs the calls, with parameters and return values, done to a real CMenuBand from Windows. It has taken a long time, but it has allowed me to see the essential features needed to implement the basic displaying of content in a CMenuBand, in the way expected by Windows' Start Menu and Menu Site.
With this information, I ported the existing (rough, partial) implementation of CMenuBand from ReactOS' shell32 (including previous work done by me), into rshell. To allow the start menu to use this CMenuBand, I had to implement support for QueryService and Exec methods. Although the behaviour of the Exec system is still largely unknown, I had enough information from the call logs and stack traces to realize that command id 16 is used to set "large icons" mode, and id 19 is used in the Popup function, and requires returning S_FALSE.
With these changes, pressing the start menu was able to display a menu frame, albeit wrongly sized to a 0x0 content size. I traced the size calculations to the GetBandInfo method, which was receiving a null mask, which it interpreted as “no data wanted”, so everything was assigned a zero value. I made the band assume that a null mask means "give me evereything", and request the optimal size from the toolbar to provide a value different than 0. Although the contents are not fully displayed yet, the CMenuBand is now partially functional.
Here is a screenshot:
I continued the analysis of CMenuBand, to figure out the flow of callbacks. This allowed me to add rudimentary support for a custom CMenuBand which shows both a shell folder and a static menu. The callbacks are also used to obtain the icons for the static menu items. Quite a lot of work remains, both in polishing the vistual aspect, and in implementing the correct behaviour of the items while hovering, clicking, and right-clicking.
The result so far looks like this:
I continued by writting a wrapper for CMenuDeskBar, in the same style I used for CMenuBand. Likewise, I also ported the partial implementation CMenuDeskBar from shell32 to rshell. To simplify the implementation, I merged the code from CBaseBar into it. The combined log from the wrappers for CMenuDeskBar and CMenuBand allowed me to see that the SetIconSize from CMenuDeskBar is the one that is supposed to notify the CMenuBand of the icon size choice. To achieve so, it calls the Exec method with cmd=16 and opts=2. The meaning of the values is not yet known to me. But it appears that opts=2 means “big icons”, and calling this method with opts=0 keeps the icons small.
More information was needed to implement the Popup system, which is supposed to calculate the optimal size of the start menu, and notify the different objects that it are about to be displayed.
I have continued working on CMenuDeskBar, implementing missing functionality. I managed to allow the start menu to display on click, and I implemented rough size calculation and positioning of the MenuSite within the DeskBar. I also implemented the drawing of the banner image, and adjusted the calculations for it.
The results with all the custom classes enabled look like this:
I switched back to CMenuBand, to attempt to use the custom-drawn controls feature to restyle the toolbar to look like a menu. The results are not yet fully accurate, but they start to get closer.
While working on this, I noticed an issue refreshing the toolbars, if all the custom classes are activated. I have traced the main issue to CMenuSite, where using the Windows class appears to work fine, while using my code causes the issue to appear. Other minor issues remain, though, which I will have to give a closer look.
The exact cause of this issue is not yet known, but I will try to fix it over the weekend.