我的应用程序使用 C# 3.5、Winforms 编写,但这很可能需要 P/Invoke,因此它与 .NET 的关系并不严格。
我通过 ContextMenu 和 MenuItem 类创建了所有者绘制的菜单项。一切都很好,但对于某些项目,我想创建一个小动画(显示有一个与该项目关联的进程正在运行)。不幸的是,上面提到的两个类没有提供 Invalidate()
方法或类似的方法。
到目前为止,我最好的想法是在第一个 OnDraw 上 P/Invoke WindowFromDC()
,保存生成的句柄,然后定期在句柄上调用 InvalidateRect()
,直到菜单已关闭。
虽然这看起来有点黑客,我还没有尝试过,想知道是否有更优雅的方法。
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.
发布评论
评论(1)
我可能建议调用
WindowFromDC >GetMenuItemRect 函数
用于检索特定菜单项的边界矩形。然后,您可以将由该函数填充的 矩形结构 传递给 < a href="http://msdn.microsoft.com/en-us/library/dd145002.aspx" rel="nofollow">InvalidateRect
函数。我同意这个解决方案有点“hackish”的感觉,但我怀疑这是因为 Windows API 提供的菜单不是设计成动画的。 .NET Framework 提供的菜单包装类不包含
Invalidate
函数,因为这是一个相对罕见的用例。通常,每次显示弹出菜单时,所有者绘制的菜单项都足以更改(通过处理WM_INITMENUPOPUP
消息)。据我所知,上述建议是做你想做的事情的最“正确”的方式。如果您确实需要对绘制菜单进行如此多的控制,那么您可能是少数几个认为俗气的
MenuStrip
/ContextMenuStrip
类实际上更好的人之一。由于它们完全在托管代码中实现,ToolStripItem
类提供了一个有效的无效
方法。Rather than using
WindowFromDC
, I might suggest calling theGetMenuItemRect
function to retrieve the bounding rectangle for a particular menu item. Then, you can pass the rectangle structure filled by that function to theInvalidateRect
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 theWM_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, theToolStripItem
class provides a workingInvalidate
method.