网上找的代码,添加一个可以正常,添加第二个就直接崩溃掉了。
Public Declare Function GetMenu Lib "user32" Alias "GetMenu" (ByVal hwnd As Long) As Long
Public Declare Function GetSubMenu Lib "user32" Alias "GetSubMenu" (ByVal hMenu As Long, ByVal nPos As Long) As Long
Public Declare Function InsertMenu Lib "user32" Alias "InsertMenuA" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, ByVal lpNewItem As Any) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Const MF_STRING = &H0&
Public Const MF_BYCOMMAND = &H0&
Public Const GWL_WNDPROC = (-4)
Public Const WM_COMMAND = &H111
Public OldWinProc As LongPublic Function OnMenu(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    '{响应菜单事件}
    If wMsg = WM_COMMAND Then
            If wParam = 1000 Then MsgBox "Dynamic"
    End If
    OnMenu = CallWindowProc(OldWinProc, hwnd, wMsg, wParam, lParam)
End Function窗体代码:
Private Sub Form_Load()
    Dim hMenu As Long, hSubMenu As Long
    hMenu = GetMenu(Me.hwnd)
    hSubMenu = GetSubMenu(hMenu, 0)
    InsertMenu hSubMenu, 0, MF_BYCOMMAND Or MF_STRING, 1000, "Dynamic"
    OldWinProc = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf OnMenu)
End Sub

解决方案 »

  1.   


    'Example Name: Changing the Display Resolution'------------------------------------------------------------------------------'BAS Module Code 
    '------------------------------------------------------------------------------
    Option ExplicitPublic Declare Function EnumDisplaySettings Lib "user32" _
        Alias "EnumDisplaySettingsA" _
       (ByVal lpszDeviceName As Long, _
        ByVal iModeNum As Long, _
        lpDevMode As Any) As Long
              
    Public Declare Function GetDeviceCaps Lib "gdi32" _
       (ByVal hdc As Long, _
        ByVal nIndex As Long) As LongPublic Declare Function ChangeDisplaySettings Lib "user32" _
        Alias "ChangeDisplaySettingsA" _
       (lpDevMode As Any, _
        ByVal dwflags As Long) As Long
              
    Public Declare Function SetMenuDefaultItem Lib "user32" _
       (ByVal hMenu As Long, _
        ByVal uItem As Long, _
        ByVal fByPos As Long) As Long
      
    Public Declare Function GetMenu Lib "user32" _
       (ByVal hWnd As Long) As Long
       
    Public Declare Function GetSubMenu Lib "user32" _
       (ByVal hMenu As Long, _
       ByVal nPos As Long) As Long
              
    Public Const LOGPIXELSX As Long = 88
    Public Const LOGPIXELSY As Long = 90
    Public Const BITSPIXEL As Long = 12
    Public Const HORZRES As Long = 8
    Public Const VERTRES As Long = 10Public Const CCDEVICENAME As Long = 32
    Public Const CCFORMNAME As Long = 32Public Const DM_GRAYSCALE As Long = &H1
    Public Const DM_INTERLACED As Long = &H2Public Const DM_BITSPERPEL As Long = &H40000
    Public Const DM_PELSWIDTH As Long = &H80000
    Public Const DM_PELSHEIGHT As Long = &H100000
    Public Const DM_DISPLAYFLAGS As Long = &H200000Public Const CDS_UPDATEREGISTRY As Long = &H1
    Public Const CDS_TEST As Long = &H2
    Public Const CDS_FULLSCREEN As Long = &H4
    Public Const CDS_GLOBAL As Long = &H8
    Public Const CDS_SET_PRIMARY As Long = &H10
    Public Const CDS_NORESET As Long = &H10000000
    Public Const CDS_SETRECT As Long = &H20000000
    Public Const CDS_RESET As Long = &H40000000
    Public Const CDS_FORCE As Long = &H80000000'Return values for ChangeDisplaySettings
    'Public Const DISP_CHANGE_SUCCESSFUL = 0
    'Public Const DISP_CHANGE_RESTART = 1
    'Public Const DISP_CHANGE_FAILED = -1
    'Public Const DISP_CHANGE_BADMODE = -2
    'Public Const DISP_CHANGE_NOTUPDATED = -3
    'Public Const DISP_CHANGE_BADFLAGS = -4
    'Public Const DISP_CHANGE_BADPARAM = -5Public Type DEVMODE
       dmDeviceName      As String * CCDEVICENAME
       dmSpecVersion     As Integer
       dmDriverVersion   As Integer
       dmSize            As Integer
       dmDriverExtra     As Integer
       dmFields          As Long
       dmOrientation     As Integer
       dmPaperSize       As Integer
       dmPaperLength     As Integer
       dmPaperWidth      As Integer
       dmScale           As Integer
       dmCopies          As Integer
       dmDefaultSource   As Integer
       dmPrintQuality    As Integer
       dmColor           As Integer
       dmDuplex          As Integer
       dmYResolution     As Integer
       dmTTOption        As Integer
       dmCollate         As Integer
       dmFormName        As String * CCFORMNAME
       dmUnusedPadding   As Integer
       dmBitsPerPel      As Integer
       dmPelsWidth       As Long
       dmPelsHeight      As Long
       dmDisplayFlags    As Long
       dmDisplayFrequency As Long
    End Type
    '--end block--'
     
      

  2.   


    '------------------------------------------------------------------------------'Form Code 
    '------------------------------------------------------------------------------ 
    'To a new form, add a top-level menu item, and name it "mnuDisplayModes". 
    'Add a single submenu item under this, and name this menu item "mnuModes". 
    'Set it's index to 0 to create the necessary menu array. Add a command button (Command1), 
    'along with the following code: Option Explicit'vars set in load
    Dim currHRes As Long
    Dim currVRes As Long
    Dim currBPP As Long'var set in mnuModes
    Dim currMenuItem As Long'array of valid resolutions & colour depths
    Dim resArray() As Long
       
    'const for the members of the array
    'i.e. resArray(resWidth, Index) = 1024
    'i.e. resArray(resHeight, Index) = 768
    'i.e. resArray(resDepth, Index)= 16  'Bits per pixel
    Const resWidth = 1
    Const resHeight = 2
    Const resDepth = 3
    Private Sub Form_Load()  'retrieves the current screen resolution for
      'later comparison against DEVMODE values in
      'CompareSettings.
       currHRes = GetDeviceCaps(hdc, HORZRES)
       currVRes = GetDeviceCaps(hdc, VERTRES)
       currBPP = GetDeviceCaps(hdc, BITSPIXEL)
       
       Dim maxItems As Long
       InitializeDisplayMenu maxItems
       FinalizeDisplayMenu maxItems
       
    End Sub
    Private Sub FinalizeDisplayMenu(maxItems As Long)  'This adds a separator and a final menu item,
      'providing the ability to open the control panel
      'display settings page from the app.
       If maxItems > 0 Then
       
          Dim hMenu As Long
          Dim r As Long
         
         'add the separator
          maxItems = maxItems + 1
          Load mnuModes(maxItems)
          mnuModes(maxItems).Caption = "-"
          
         'add the final item
          maxItems = maxItems + 1
          Load mnuModes(maxItems)
          mnuModes(maxItems).Caption = "Show Display Settings"
          
         'finally, bold the newly-added menuitem
          hMenu = GetSubMenu(GetMenu(Me.hWnd), 0)
          Call SetMenuDefaultItem(hMenu, maxItems - 1, True)
       
       End If
            
    End Sub
    Private Sub InitializeDisplayMenu(maxItems As Long)   Dim DM As DEVMODE
       Dim dMode As Long
       
      '36 should be enough to hold your settings.
      'It's trimmed back at the end of this routine.
       ReDim resArray(1 To 3, 0 To 35)
       
      'set the DEVMODE flags and structure size
       DM.dmFields = DM_PELSWIDTH Or DM_PELSHEIGHT Or DM_BITSPERPEL
       DM.dmSize = LenB(DM)
       
      'The first mode is 0
       dMode = 0
          
      'call the API to retrieve the values for the
      'specified dMode
       Do While EnumDisplaySettings(0&, dMode, DM) > 0
       
         'if the BitsPerPixel is greater than 4
         '(16 colours), then add the item to a menu
          If DM.dmBitsPerPel >= 4 Then
             Call MenuAdd(DM, resArray(), maxItems)
          End If
          
         'increment and call again. Continue until
         'EnumDisplaySettings returns 0 (no more settings)
          dMode = dMode + 1
       
       Loop
       
      'trim back the resArray to fit the number of actual entries.
       ReDim Preserve resArray(1 To 3, 0 To maxItems)
       
    End Sub
    Private Function CompareSettings(DM As DEVMODE) As Long
       
      'compares the current screen resolution with
      'the current DEVMODE values.   Returns TRUE if
      'the horizontal and vertical resolutions, and
      'the bits per pixel colour depth, are the same.
       CompareSettings = (DM.dmBitsPerPel = currBPP) And _
                          DM.dmPelsHeight = currVRes And _
                          DM.dmPelsWidth = currHRes
       
    End Function
    Private Sub MenuAdd(DM As DEVMODE, resArray() As Long, mnuCount As Long)
     
       Dim mType As String
       
      'used to determine when the colour depth has
      'changed, so we can add a separator to the menu.
       Static lastBitsPerPel As Long
       
      'select the appropriate text string based on
      'the colour depth
       Select Case DM.dmBitsPerPel
          Case 4:      mType = "16 Color"
          Case 8:      mType = "256 Color"
          Case 16:     mType = "High Color"
          Case 24, 32: mType = "True Color"
       End Select  'if this is the first item, we can't load the menu
      'array item, and it will not require a separator.
       If mnuCount > 0 Then
       
         'load a new menu item to the array
          Load mnuModes(mnuCount)
       
         'determine if the colour depth has changed. If so,
         'make the caption a separator, and load a new item
         'to hold the item.
          If lastBitsPerPel <> DM.dmBitsPerPel Then
          
             mnuModes(mnuCount).Caption = "-"
             mnuCount = mnuCount + 1
             Load mnuModes(mnuCount)
          
          End If
       End If
       
      'create the menu caption
       mnuModes(mnuCount).Caption = DM.dmPelsWidth & "x" & _
                                    DM.dmPelsHeight & "  [" & _
                                    DM.dmBitsPerPel & " bit " & _
                                    mType & "]"
       
      'see if this is the current resolution,
      'and if so, check the menu item
       mnuModes(mnuCount).Checked = CompareSettings(DM)
       If mnuModes(mnuCount).Checked Then currMenuItem = mnuCount
       
       resArray(resWidth, mnuCount) = DM.dmPelsWidth
       resArray(resHeight, mnuCount) = DM.dmPelsHeight
       resArray(resDepth, mnuCount) = DM.dmBitsPerPel
       
      'save the current DEVMODE value for depth
      'and increment the menu item count, ready for
      'the next call
       lastBitsPerPel = DM.dmBitsPerPel
       mnuCount = mnuCount + 1
       
    End Sub
    Private Sub Command1_Click()   Dim maxItems As Long
       
       InitializeDisplayMenu maxItems
       Command1.Enabled = False
       
       FinalizeDisplayMenu maxItems
       
    End Sub
    Private Sub mnuModes_Click(Index As Integer)   Dim DM As DEVMODE
       
       Select Case Index
       
          Case mnuModes.Count
          
            'show the display control panel
             Call Shell("rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,3", 1)
          
          Case Else
            
            'change the current resolution, no prompting
            'BE CAREFUL .. you could set your system to a
            'setting which renders the display difficult to read.
            
             With DM
             
                .dmPelsWidth = resArray(resWidth, Index)
                .dmPelsHeight = resArray(resHeight, Index)
                .dmBitsPerPel = resArray(resDepth, Index)
                .dmFields = DM_PELSWIDTH Or DM_PELSHEIGHT Or DM_BITSPERPEL
                .dmSize = LenB(DM)
             End With
             
             If ChangeDisplaySettings(DM, CDS_FORCE) <> 0 Then
             
                 MsgBox "Error! Perhaps your hardware is not up to the task?"
                 
             End If
             
            'indicate the current menu selection
             mnuModes(currMenuItem).Checked = False
             mnuModes(Index).Checked = True
             currMenuItem = Index
       
       End SelectEnd Sub
      

  3.   

    Public Declare Function GetWindowLong Lib "User32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As LongPublic OldWinProc As Long
    Public NewWinProc As Long
        OldWinProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)
        NewWinProc = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf OnMenu)
      

  4.   

    楼主,你的代码,我测试完全运行正常。
    Public Function OnMenu(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
       '{响应菜单事件}
       If wMsg = WM_COMMAND Then
          If wParam = 1000 Then MsgBox "Dynamic"
          If wParam = 1001 Then MsgBox "Dynamic2"
          If wParam = 1002 Then MsgBox "Dynamic3"
       End If
       OnMenu = CallWindowProc(OldWinProc, hwnd, wMsg, wParam, lParam)
    End Function'窗体代码:
    Private Sub Form_Load()
        Dim hMenu As Long, hSubMenu As Long
        hMenu = GetMenu(Me.hwnd)
        hSubMenu = GetSubMenu(hMenu, 0)
        InsertMenu hSubMenu, 0, MF_BYCOMMAND Or MF_STRING, 1000, "Dynamic"
        InsertMenu hSubMenu, 0, MF_BYCOMMAND Or MF_STRING, 1001, "Dynamic2"
        InsertMenu hSubMenu, 0, MF_BYCOMMAND Or MF_STRING, 1002, "Dynamic3"
        OldWinProc = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf OnMenu)
    End Sub