How to provide animation in an owner-drawn menu item?
-
25-10-2019 - |
Pergunta
My application is in C# 3.5, Winforms, but this will most likely require P/Invoke anyway, so it's not that strictly tied to .NET.
I have created owner-drawn menu items via ContextMenu
and MenuItem
classes. All works well, but for some items I'd like to create a little animation (showing that there is a process running, associated with the item). Unfortunately the above mentioned two classes do not provide an Invalidate()
method or anything similar.
My best idea so far is to P/Invoke WindowFromDC()
on the first OnDraw, save the resulting handle, and then periodically call InvalidateRect()
on the handle, until the menu is closed.
This seems kinda hackish though, I haven't tried it yet, and wonder if there is a more elegant way.
Solução
Rather than using WindowFromDC
, I might suggest calling the GetMenuItemRect
function to retrieve the bounding rectangle for a particular menu item. Then, you can pass the rectangle structure filled by that function to the InvalidateRect
function.
I agree that this solution has somewhat of a "hackish" feel to it, but I suspect that's because the menus provided by the Windows API were not designed to be animated. The menu wrapper classes provided by the .NET Framework don't include an Invalidate
function because this is a relatively rare use case. Generally, it's sufficient for owner-drawn menu items to change each time the pop-up menu is displayed (by handling the WM_INITMENUPOPUP
message). As far as I know, the above proposal is the most "correct" way that there is to do what you want.
If you really need that much control over drawing menus, you might be one of the few people for whom the cheesy MenuStrip
/ContextMenuStrip
classes are actually better. Since they're implemented entirely in managed code, the ToolStripItem
class provides a working Invalidate
method.