需要 Windows API InsertMenuItem 帮助
我想将新菜单插入其他进程。但我收到一个错误:
尝试读取或写入受保护的内存。这通常表明其他内存已损坏。
按钮代码:
Mmenuhandle = GetMenu(mainhandle)
Mmenucount = GetMenuItemCount(Mmenuhandle)
Smenuhandle = GetSubMenu(Mmenuhandle, 0)
Smenucount = GetMenuItemCount(Smenuhandle)
With mii
.cbSize = Len(mii)
.fMask = MIIM_STATE Or MIIM_ID Or MIIM_STRING Or MIIM_FTYPE
.fType = MFT_STRING
.fState = MFS_ENABLED
.wID = MENUID
.dwTypeData = "My Menu"
.cch = Len(.dwTypeData)
End With
InsertMenuItem(Smenuhandle, Smenucount + 1, True, mii) ' ERROR here
DrawMenuBar(mainhandle)
声明 InsertMenuItem
:
Private Declare Function InsertMenuItem Lib "user32" Alias "InsertMenuItemA" _
(ByVal hMenu As Integer, ByVal uItem As Integer, ByVal fByPosition As Boolean, ByVal lpmii As MENUITEMINFO) As Integer
声明 MENUITEMINFO
:
Public Structure MENUITEMINFO
Public cbSize As Integer
Public fMask As Integer
Public fType As Integer
Public fState As Integer
Public wID As Integer
Public hSubMenu As Integer
Public hbmpChecked As Integer
Public hbmpUnchecked As Integer
Public dwItemData As Integer
Public dwTypeData As String
Public cch As Integer
Public a As Integer
End Structure
如何修复此错误?
I want to insert a new menu into other process. But I get an error:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
code for button:
Mmenuhandle = GetMenu(mainhandle)
Mmenucount = GetMenuItemCount(Mmenuhandle)
Smenuhandle = GetSubMenu(Mmenuhandle, 0)
Smenucount = GetMenuItemCount(Smenuhandle)
With mii
.cbSize = Len(mii)
.fMask = MIIM_STATE Or MIIM_ID Or MIIM_STRING Or MIIM_FTYPE
.fType = MFT_STRING
.fState = MFS_ENABLED
.wID = MENUID
.dwTypeData = "My Menu"
.cch = Len(.dwTypeData)
End With
InsertMenuItem(Smenuhandle, Smenucount + 1, True, mii) ' ERROR here
DrawMenuBar(mainhandle)
declare for InsertMenuItem
:
Private Declare Function InsertMenuItem Lib "user32" Alias "InsertMenuItemA" _
(ByVal hMenu As Integer, ByVal uItem As Integer, ByVal fByPosition As Boolean, ByVal lpmii As MENUITEMINFO) As Integer
declare for MENUITEMINFO
:
Public Structure MENUITEMINFO
Public cbSize As Integer
Public fMask As Integer
Public fType As Integer
Public fState As Integer
Public wID As Integer
Public hSubMenu As Integer
Public hbmpChecked As Integer
Public hbmpUnchecked As Integer
Public dwItemData As Integer
Public dwTypeData As String
Public cch As Integer
Public a As Integer
End Structure
How do I fix this error?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
P/Invoke 代码不正确...它看起来是从 VB 6 源代码复制的,并且等效名称的数据类型在 VB 6 中与在 VB.NET 中具有非常不同的语义含义。
此外,句柄/指针是使用固定整数类型声明的,这在 64 位环境中无法正常工作。这些类型的值应始终使用专门为此目的设计的
IntPtr
类型来声明。并且,在 VB.NET 中,需要通过
ByRef
传递指向结构的指针。您无法传递它们ByVal
。您需要使用
System.Runtime 中找到的工具.InteropServices
命名空间 和 .NET 编组器可以帮助您。这也是为什么您永远不应该在不了解其含义和用途的情况下复制和粘贴在网上找到的代码的另一个原因。
声明应该如下所示:
然后您可以使用这样的函数(重新编写代码以匹配):
一切都按预期工作,至少在同一进程中。请注意,P/Invoke 是一个相当困难的主题,您不仅需要对 VB.NET 还需要对 Win32 API 有相当透彻的了解才能使其正常工作。复制和粘贴您在网上找到的代码本质上是有风险的。大多数时候,这是行不通的。其余时间,这可能存在安全风险。不幸的是,您需要的不仅仅是 Stack Overflow 上的答案来向您解释这一切是如何工作的。
编辑:实际上,上面的代码跨进程也可以正常工作。不需要特别努力。我尝试在记事本的运行实例中修改菜单,一切正常。并不是说我建议在没有非常理由的情况下这样做......
The P/Invoke code is incorrect... It looks to be copied from a VB 6 source, and the data types of equivalent names have very different semantic meanings in VB 6 than they do in VB.NET.
In addition, handles/pointers are declared using fixed integer types, which will not work properly in 64-bit environments. These types of values should always be declared using the
IntPtr
type specifically designed for this purpose.And, pointers to structures need to be passed
ByRef
in VB.NET. You can't pass themByVal
.You need to use the tools found in the
System.Runtime.InteropServices
namespace and the .NET marshaller to help you out.This is yet another reason why you should never just copy and paste code that you find online without understanding what it means and what it does.
The declarations should look like this:
Then you can use the function like this (re-write your code to match):
Everything works as expected, at least within the same process. Note that P/Invoke is a fairly difficult topic, and you'll need to have a fairly thorough understanding of not only VB.NET but also the Win32 API to get it to work correctly. Copying and pasting code that you find online is an inherently risky proposition. Most of the time, it won't work. The rest of the time, it's a possible security risk. Unfortunately, you'll need more than an answer on Stack Overflow to explain to you how it all works.
Edit: Actually, the above code works just fine across processes, too. No special effort required. I tried monkeying with the menus in a running instance of Notepad, and everything worked fine. Not that I recommend doing this without a very good reason...