如何修复从32位转换为64位VBA PPT的错误

时间:2018-11-11 01:28:50

标签: vba powerpoint-vba

该VBA程序适用于32位PPT 2007,但是当我将其用于64位PPT 2013时,即使在PtrSafe前面添加了Public Declare,也会出现错误。

此功能中存在类型不匹配的情况:AddressOf BrowseCallbackProc (在公共职能Get_IMGFolderName()的中间)

我想要一些有关如何解决此问题的建议。 我一直将其编码为业余爱好,所以我不太了解。

谢谢

Option Explicit

Public Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
Public Declare PtrSafe Function SHBrowseForFolder Lib "shell32" (lpbi As BrowseInfo) As Long
Public Declare PtrSafe Function SHGetPathFromIDList Lib "shell32" (ByVal pidList As Long, ByVal lpBuffer As String) As Long
Public Declare PtrSafe Function lstrcat Lib "kernel32" Alias "lstrcatA" (ByVal lpString1 As String, ByVal lpString2 As String) As Long

Public Type BrowseInfo
    hwndOwner       As Long
    pIDLRoot        As Long
    pszDisplayName  As Long
    lpszstrMsg      As Long
    ulFlags         As Long
    lpfnCallback    As Long
    lParam          As Long
    iImage          As Long
End Type

Public Const BIF_STATUSTEXT = &H4&
Public Const BIF_RETURNONLYFSDIRS = 1
Public Const BIF_DONTGOBELOWDOMAIN = 2
Public Const MAX_PATH = 260
Public Const WM_USER = &H400
Public Const BFFM_INITIALIZED = 1
Public Const BFFM_SELCHANGED = 2
Public Const BFFM_SETSTATUSTEXT = (WM_USER + 100)
Public Const BFFM_SETSELECTION = (WM_USER + 102)

Public strCurDir As String   '현재 디렉토리

  Public Enum CHOOSE_COLOR_FLAGS
    CC_RGBINIT = &H1&
    CC_FULLOPEN = &H2&
    CC_PREVENTFULLOPEN = &H4&
    CC_SHOWHELP = &H8&
    CC_ENABLEHOOK = &H10&
    CC_ENABLETEMPLATE = &H20&
    CC_ENABLETEMPLATEHANDLE = &H40&
    CC_SOLIDCOLOR = &H80&
    CC_ANYCOLOR = &H100&
  End Enum

  Private Type CHOOSECOLOR
    lStructSize As Long
    hwndOwner As Long
    hInstance As Long
    rgbResult As Long
    lpCustColors As Long
    flags As CHOOSE_COLOR_FLAGS
    lCustData As Long
    lpfnHook As Long
    lpTemplateName As String
  End Type

  Private Declare PtrSafe Function ChooseColor_API Lib "comdlg32.dll" Alias "ChooseColorA" (lpChoosecolor As CHOOSECOLOR) As Long



Function Delete_Sheets()

'ActiveWindow.View.GotoSlide ActivePresentation.Slides.Count
While ActivePresentation.Slides.Count > 0
    ActiveWindow.Selection.SlideRange.Delete
Wend

End Function



Public Function Get_IMGFolderName() As String

Dim lpIDList As Long
Dim szstrMsg As String
Dim strBuffer As String
Dim tBrowseInfo As BrowseInfo
Dim strDir As String

strCurDir = frmBible.lblIMGFolder.Caption & vbNullChar

szstrMsg = "바탕그림용 이미지가 들어 있는 폴더를 지정해주세요"
With tBrowseInfo
    .hwndOwner = 0
    .lpszstrMsg = lstrcat(szstrMsg, "")
    .ulFlags = BIF_RETURNONLYFSDIRS + BIF_DONTGOBELOWDOMAIN + BIF_STATUSTEXT
    .lpfnCallback = GetAddressofFunction(AddressOf BrowseCallbackProc)  'get address of function.
End With

lpIDList = SHBrowseForFolder(tBrowseInfo)
If (lpIDList) Then
    strBuffer = Space(MAX_PATH)
    SHGetPathFromIDList lpIDList, strBuffer
    strBuffer = Left(strBuffer, InStr(strBuffer, vbNullChar) - 1)
    Get_IMGFolderName = strBuffer
Else
    Get_IMGFolderName = ""
End If

End Function



Public Function Remove_Special_Chars(intxt) As String

Dim wkstr As String
Dim p As Integer, c, uc

wkstr = ""
While Len(intxt) > 0
    c = Left(intxt, 1)
    uc = UCase(c)
    If c >= "가" And c <= "힝" Then
        wkstr = wkstr & c
    ElseIf uc >= "A" And uc <= "Z" Then
        wkstr = wkstr & c
    ElseIf uc >= "0" And uc <= "9" Then
        wkstr = wkstr & c
    End If
    intxt = Mid(intxt, 2)
Wend

Remove_Special_Chars = wkstr

End Function




Public Function Return_PathName(full_Path As String)

'return path name only

Dim p As Integer, ps As Integer

ps = 1
p = 1
Do While p > 0
    p = InStr(ps, full_Path, "\", vbBinaryCompare)
    If p > 0 Then
        ps = p + 1
    End If
Loop

Return_PathName = Left(full_Path, ps - 1)

End Function

Public Function Return_FileName(full_Path As String)

' return file name only

Dim p As Integer, ps As Integer

ps = 1
p = 1
Do While p > 0
    p = InStr(ps, full_Path, "\", vbBinaryCompare)
    If p > 0 Then
        ps = p + 1
    End If
Loop

Return_FileName = Mid(full_Path, ps)

End Function

Public Function Return_FolderName(full_Path)

' return folder name only

Dim p As Integer

p = InStrRev(full_Path, "\", Len(full_Path) - 1)

Return_FolderName = Mid(full_Path, p + 1)

End Function





Public Function BrowseCallbackProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal lp As Long, ByVal pData As Long) As Long
Dim lpIDList As Long
Dim lngRet As Long
Dim strBuffer As String

On Error Resume Next

Select Case uMsg

    Case BFFM_INITIALIZED
        Call SendMessage(hWnd, BFFM_SETSELECTION, 1, strCurDir)

    Case BFFM_SELCHANGED
        strBuffer = Space(MAX_PATH)

        lngRet = SHGetPathFromIDList(lp, strBuffer)
    If lngRet = 1 Then
        Call SendMessage(hWnd, BFFM_SETSTATUSTEXT, 0, strBuffer)
    End If

End Select
On Error GoTo 0

BrowseCallbackProc = 0

End Function



Public Function GetAddressofFunction(lngAdd As Long) As Long

GetAddressofFunction = lngAdd

End Function


Public Function FileDateInfo(filespec)
    Dim fs, f
    Set fs = CreateObject("Scripting.FileSystemObject")
    Set f = fs.GetFile(filespec)
    FileDateInfo = f.DateLastModified

End Function


Public Function WinRegistry_CommonGet()

Dim TmpName As String
Dim i As Integer
Dim x

Version_Release = GetSetting("BibleChoir", "LatestVal", "Version_Release", "vv.rr")


frmBible.lblIMGFolder.Caption = GetSetting("BibleChoir", "LatestVal", "IMGFolder", "없음")
'frmPicture.sldBright = GetSetting(appname:="BibleChoir", section:="LatestVal", key:="Bright", Default:=70)
frmBible.chkEachPage = GetSetting("BibleChoir", "LatestVal", "EachPage", False)

 File2Open = frmBible.lblIMGFolder.Caption


 If File2Open <> "없음" Then
  On Error Resume Next
 frmBible.ImgPreview.Picture = LoadPicture(File2Open)
 End If
 On Error GoTo 0
End Function

Public Function WinRegistry_CommonSave()

Dim i As Integer

SaveSetting "BibleChoir", "LatestVal", "Version_Release", Version_Release

SaveSetting "BibleChoir", "LatestVal", "IMGFolder", frmBible.lblIMGFolder.Caption
'SaveSetting "BibleChoir", "LatestVal", "Bright", frmPicture.sldBright
SaveSetting "BibleChoir", "LatestVal", "EachPage", frmBible.chkEachPage


End Function

1 个答案:

答案 0 :(得分:3)

您需要做的不仅仅是添加PtrSafe声明。您的某些Long数据类型也需要转换为LongPtr

#If VBA7 Then

    Public Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" _
            (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, _
            ByVal lParam As String) As LongPtr
    Public Declare PtrSafe Function SHBrowseForFolder Lib "shell32" _
            (lpbi As BrowseInfo) As LongPtr
    Public Declare PtrSafe Function SHGetPathFromIDList Lib "shell32" _
            (ByVal pidList As LongPtr, ByVal lpBuffer As String) As LongPtr
    Public Declare PtrSafe Function lstrcat Lib "kernel32" Alias "lstrcatA" _
            (ByVal lpString1 As String, ByVal lpString2 As String) As Long

#Else

    Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
            (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
            ByVal lParam As String) As Long
    Public Declare Function SHBrowseForFolder Lib "shell32" _
            (lpbi As BrowseInfo) As Long
    Public Declare Function SHGetPathFromIDList Lib "shell32" _
            (ByVal pidList As Long, ByVal lpBuffer As String) As Long
    Public Declare Function lstrcat Lib "kernel32" Alias "lstrcatA" _
            (ByVal lpString1 As String, ByVal lpString2 As String) As Long

#End If
  

来自Microsoft Docs

     
    

注意 推荐使用 PtrSafe 关键字声明语句。仅在 Declare 语句中的所有数据类型(参数和返回值)之后,包含 PtrSafe 的声明语句才能在32位和64位平台上的VBA7开发环境中正常工作),需要存储64位数量的数据将更新为对LongLong使用64位积分,对LongPtr使用指针和句柄。为了确保与VBA版本6和更早版本的向后兼容性,请使用以下结构:

#If VBA7 Then 
    Declare PtrSafe Sub... 
#Else 
    Declare Sub... 
#EndIf
         

在64位版本的Office中运行 Declare 语句必须包含 PtrSafe 关键字。 PtrSafe 关键字断言,在64位开发环境中运行 Declare 语句是安全的。将 PtrSafe 关键字添加到 Declare 语句仅表示Declare语句明确地以64位为目标,该语句中需要存储64位的所有数据类型(包括返回值)和参数)仍然必须修改,以使用LongLong(用于64位积分)或LongPtr(用于指针和句柄)来容纳64位数量。