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.

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top