我想在VBA 7.0中创建一个非模态弹出对话框。
到目前为止,最有希望的途径似乎是使用CreateDialog
。
首先我尝试了CreateDialogW
,但收到了DLL中找不到CreateDialogW的入口点
的错误信息。
打开DLL后,我验证了此函数未列出。上述链接的MSDN参考文献显示User32是此函数的DLL,并列出了函数名称CreateDialogW
和CreateDialogA
(分别是Unicode / ansi),但它们没有列在我的计算机(Win 7专业版,64位)的此DLL中。
因此,查看DLL中列出的函数列表,我看到了CreateDialogParam和CreateDialogIndirectParam
函数(每个函数都有Ansi和Unicode版本)。
我一直在尝试遵循MSDN并将C示例转换为VB,但我在某个地方遗漏了什么,并且我陷入了困境,因为我不知道我做错了什么。该代码可以编译和运行,但在API调用时什么也不会发生-它执行但没有任何反应。
如果有人能给我指点方向,我将非常感激。 我的当前解决方法很糟糕,我真的想把这个项目完成。
Option Explicit
'Reference conversion of C to VB type declarations here
'http://msdn.microsoft.com/en-us/library/aa261773(v=vs.60).aspx
'Declare function to Win API CreateDialog function
'http://msdn.microsoft.com/en-us/library/ms645434(v=vs.85).aspx
Private Declare PtrSafe Function CreateDialog Lib "User32.dll" Alias "CreateDialogParamW" _
(ByVal lpTemplateName As LongPtr, _
ByRef lpDialogFunc As DIALOGPROC, _
ByVal dwInitParam As Long, _
Optional ByVal hInstance As Long, _
Optional ByVal hWndParent As Long) _
As Long
'Windows Style Constants
'http://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx
Public Const WS_BORDER As Long = &H800000
Public Const WS_CAPTION As Long = &HC00000
Public Const WS_CHILD As Long = &H40000000
Public Const WS_CHILDWINDOW As Long = &H40000000
Public Const WS_CLIPCHILDREN As Long = &H2000000
Public Const WS_CLIPSIBLINGS As Long = &H4000000
Public Const WS_DISABLED As Long = &H8000000
Public Const WS_DLGFRAME As Long = &H400000
Public Const WS_GROUP As Long = &H20000
Public Const WS_HSCROLL As Long = &H100000
Public Const WS_ICONIC As Long = &H20000000
Public Const WS_MAXIMIZE As Long = &H1000000
Public Const WS_MAXIMIZEBOX As Long = &H10000
Public Const WS_MINIMIZE As Long = &H20000000
Public Const WS_MINIMIZEBOX As Long = &H20000
Public Const WS_OVERLAPPED As Long = &H0
Public Const WS_POPUP As Long = &H80000000
Public Const WS_SIZEBOX As Long = &H40000
Public Const WS_SYSMENU As Long = &H80000
Public Const WS_TABSTOP As Long = &H10000
Public Const WS_THICKFRAME As Long = &H40000
Public Const WS_TILED As Long = &H0
Public Const WS_VISIBLE As Long = &H10000000
Public Const WS_VSCROLL As Long = &H200000
Public Const WS_OVERLAPPEDWINDOW As Long = (WS_OVERLAPPED + WS_CAPTION + WS_SYSMENU + WS_THICKFRAME + WS_MINIMIZEBOX + WS_MAXIMIZEBOX)
Public Const WS_TILEDWINDOW As Long = (WS_OVERLAPPED + WS_CAPTION + WS_SYSMENU + WS_THICKFRAME + WS_MINIMIZEBOX + WS_MAXIMIZEBOX)
Public Const WS_POPUPWINDOW As Long = (WS_POPUP + WS_BORDER + WS_SYSMENU)
'Declare custom type for lpDialogFunc argument
'http://msdn.microsoft.com/en-us/library/windows/desktop/ms645469(v=vs.85).aspx
Public Type DIALOGPROC
hwndDlg As Long
uMsg As LongPtr
wparam As Long
lparam As Long
End Type
'MAKEINTRESOURCE Macro emulation
'http://msdn.microsoft.com/en-us/library/windows/desktop/ms648029(v=vs.85).aspx
'Bitwise function example found here: http://support.microsoft.com/kb/112651
'VB conversion found here: https://groups.google.com/forum/#!topic/microsoft.public.vb.winapi/UaK3S-bJaiQ _
modified with strong typing and to use string pointers for VB7
Private Function MAKEINTRESOURCE(ByVal lID As Long) As LongPtr
MAKEINTRESOURCE = StrPtr("#" & CStr(MAKELONG(lID, 0)))
End Function
Private Function MAKELONG(ByRef wLow As Long, ByRef wHi As Long)
'Declare variables
Dim LoLO As Long
Dim HiLO As Long
Dim LoHI As Long
Dim HiHI As Long
'Get the HIGH and LOW order words from the long integer value
GetHiLoWord wLow, LoLO, HiLO
GetHiLoWord wHi, LoHI, HiHI
If (wHi And &H8000&) Then
MAKELONG = (((wHi And &H7FFF&) * 65536) Or (wLow And &HFFFF&)) Or &H80000000
Else
MAKELONG = LoLO Or (&H10000 * LoHI)
'MAKELONG = ((wHi * 65535) + wLow)
End If
End Function
Private Function GetHiLoWord(lparam As Long, LOWORD As Long, HIWORD As Long)
'This is the LOWORD of the lParam:
LOWORD = lparam And &HFFFF&
'LOWORD now equals 65,535 or &HFFFF
'This is the HIWORD of the lParam:
HIWORD = lparam \ &H10000 And &HFFFF&
'HIWORD now equals 30,583 or &H7777
GetHiLoWord = 1
End Function
Public Function TstDialog()
Dim dpDialog As DIALOGPROC
dpDialog.hwndDlg = 0
dpDialog.uMsg = StrPtr("TEST")
dpDialog.lparam = 0
dpDialog.wparam = 0
CreateDialog hInstance:=0, lpTemplateName:=MAKEINTRESOURCE(WS_POPUPWINDOW + WS_VISIBLE), lpDialogFunc:=dpDialog, dwInitParam:=&H110
End Function
CreateDialog
在其文档中指出它是一个实际使用CreateDialogParam
的宏。它还指出它返回一个值,如果该返回值为NULL,则应使用GetLastError
查找失败原因。你没有这样做 - 为什么不呢?(不确定为什么你要跳过所有这些步骤;任何支持VBA的Office产品都有更容易使用的内置创建表单(对话框)的方法。) - Ken WhiteGetLastError
函数?文档指出我应该在VBA中使用err.LastDllError
。目前调用该函数时没有任何反应,因此我认为我没有返回值可以检查。 - CBRF23hwnd, umsg, wParam, lParam
- 它不是一个数据结构。你需要传递一个方法的指针,我甚至不确定从VBA是否可能这样做。此外,您还需要预定义的DIALOG资源(使用MS资源编译器编译的资源脚本,并链接到应用程序中),以便使用CreateDialog; 它接收的参数之一是该资源的名称。恐怕你离正确还有很远的距离。 - Ken White