我想在 VBA 7.0 中创建一个无模式弹出对话框。
到目前为止,最有希望的路线似乎是CreateDialog
.
首先我尝试了 CreateDialogW
并收到 Entry point not found for CreateDialogW in DLL
。
打开DLL后,我验证了这个函数没有列出。上面链接的 MSDN 引用将 User32 显示为此函数的 DLL,并列出了函数名称 CreateDialogW
和 CreateDialogA
(分别为 Unicode/ansi),但它们未在此 DLL 中列出我的电脑(Win 7 专业版,64 位)。
所以,查看 DLL 中 的函数列表,我看到了 CreateDialogParam
and CreateDialogIndirectParam
functions (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,因为它们要求对话框模板位于资源部分。您可以使用 CreateDialogIndirectParam 从内存中的对话框模板创建对话框。你需要这个:
Private Type DLGTEMPLATE
style As Long
dwExtendedStyle As Long
cdit As Integer
x As Integer
y As Integer
cx As Integer
cy As Integer
End Type
Private Type DLGITEMTEMPLATE
style As Long
dwExtendedStyle As Long
x As Integer
y As Integer
cx As Integer
cy As Integer
id As Integer
End Type
Private Type DLG
dlgtemp As dlgtemplate
menu As Long
classname As String
title As String
End Type
Private Declare PtrSafe Function CreateDialogIndirectParam Lib "User32.dll" Alias "CreateDialogIndirectParamW" _
(ByVal hInstance As Long, _
ByRef lpTemplate As DLGTEMPLATE, _
ByVal hWndParent As Long, _
ByVal lpDialogFunc As LongPtr, _
ByVal lParamInit As Long) _
As LongPtr
Const WM_INITDIALOG As Long = &H110
Const DS_CENTER As Long = &H800&
Const DS_SETFONT As Long = &H40
Const DS_MODALFRAME As Long = &H80
Const WS_EX_APPWINDOW As Long = &H40000
然后这样调用它:
Dim d As DLG
d.dlgtemp.style = DS_MODALFRAME + WS_POPUP + WS_VISIBLE + WS_CAPTION + WS_SYSMENU
d.dlgtemp.dwExtendedStyle = WS_EX_APPWINDOW
d.dlgtemp.cdit = 0
d.dlgtemp.x = 100
d.dlgtemp.y = 100
d.dlgtemp.cx = 200
d.dlgtemp.cy = 200
d.menu = 0
d.title = "Test"
d.classname = "Test"
CreateDialogIndirectParam 0, d.dlgtemp, 0, AddressOf DlgFunc, 0
DlgFunc 看起来像这样:
Public Function DlgFunc(ByVal hwndDlg As LongPtr, ByVal uMsg As LongPtr, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
If uMsg = h110 Then ' = WM_INITDIALOG - you should make a const for the various window messages you'll need...
DlgFunc = True
Else
DlgFunc = False
End If
End Function
距离我上一次做这些事情已经十多年了。但是如果你决心走这条路,我认为这种方法是最有前途的——下一步是调整 DLG 结构以添加一些 DLGITEMTEMPLATE 成员,将 d.dlgtemp.cdit 设置为对话框上的控件数量,并开始处理 DlgFunc 中的控制消息。
关于c++ - 在 VBA 中使用 CreateDialog 尝试创建无模式对话框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26810426/