What is tmenu? It is the base class of tmainmenu and tpopupmenu encapsulated in VCL. Not so much disappointment with tmenu, it is actually disappointment with tmainmenu and tpopupmenu in VCL.
Why? This is basically due to Microsoft itself. While introducing windows, Microsoft is definitely pushing office products. In addition, the update speed of office is almost the same as that of windows. More importantly, the interface style of office products, especially menus, is completely different from that of standard windows.
When Microsoft's office is very popular, we are eager to design the same interface. For a demand that only changes the appearance, you can naturally consider overwriting the draw method of tmenuitem.
However, when you really want to do this, you will find two things, one to make you happy, one to disappoint you. Let's talk about happy things first:
Two methods for working with draw: advanceddrawitem and measureitem are declared virtual functions. That is to say, we can fully implement it by overwriting these methods. Obviously, tmenuitem designers have already considered such extensions.
In addition, by observing the advanceddrawitem implementation, you can also find that you need to modifyCodePoint.
If (Parentmenu <> Nil) and (parentmenu. ownerdraw or (imagelist <> Nil) and
(Assigned (fonadvanceddrawitem) or assigned (fondrawitem) then
Begin
Drawitem (acanvas, arect, selected );
If Assigned (fonadvanceddrawitem) then
Fonadvanceddrawitem (self, acanvas, arect, State );
End Else
If (Parentmenu <> Nil) and (not parentmenu. isrighttoleft) then
Normaldraw
Else
Bididraw;
See normaldraw and bididraw. Therefore, we only need to select officedraw in parallel. Of course, it would be easier to give up the original method.
Unfortunately, we must listen to another disappointing thing. That is, all the places where tmenuitem is created in the menus unit call the tmenuitem. Create method directly. If you want to derive a tofficemenuitem class, you cannot find the place where you can create your class.
In this case, the general design is to have a virtual method in the tmenu class and return an instance of the tmenuitem type. The specific type can be determined by the derived class of tmenu. For example, if you customize a tofficemenu, you can use tofficemenuitem to create a tmenuitem instance. The following code is simple:
Function createmenuitem: tmenuitem; override;
The following code is used for implementation:
Result: = tofficemenuitem. Create;
Whenever I had to face this reality, I began to consider whether there was a way to get around. One way is to implement the ondrawitem event of tmenuitem. Another way is to replace the tmenuitem class with the hook method.
The above two methods can only be considered as solutions to problems in specific applications. As I am keen on componentization design, I obviously prefer to implement tofficemenu and tofficemenuitem on my own. In addition, this function is completed not only by modifying events, but by Object-Oriented polymorphism.
We are disappointed that tmenu is not considered in terms of scalability. Because of this, the default two methods are used in VCL. The booming third-party interface controls, such as the tbx series and raze series, also prove their lack of design.
In fact, we can also think about it. design should consider the principle of opening and closing. In particular, "The future is open to derivation. The current functions can be completed through any design. But whether or not we can consider the future expansion is that the design is good or bad.