Я хочу создать немодальный всплывающий диалог в VBA 7.0. На данный момент наиболее многообещающим маршрутом кажется CreateDialog
.
Сначала я попробовал CreateDialogW
и получил Entry point not found for CreateDialogW in DLL
.
После открытия библиотеки DLL я убедился, что этой функции нет в списке. Ссылка MSDN, указанная выше, показывает User32 как DLL для этой функции и перечисляет имена функций CreateDialogW
и CreateDialogA
(соответственно Unicode/ansi), но они не указаны в этой DLL на моем компьютере (Win 7 Professional, 64-разрядная версия).
Итак, просматривая список функций, которые находятся в 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
, чтобы узнать, почему это не удалось. Вы этого не делаете - почему бы и нет? (В любом случае, не уверен, почему вы прыгаете через все эти обручи; любой продукт Office, поддерживающий VBA, имеет гораздо более простые в использовании встроенные способы создания форм (диалогов).) - person Ken White   schedule 18.11.2014GetLastError
? В документации указано, что я должен использоватьerr.LastDllError
в VBA. В настоящее время при вызове функции ничего не происходит, поэтому я не верю, что у меня есть возврат для проверки. - person CBRF23   schedule 18.11.2014CreateDialog
как функцию и сохранили возвращаемое значение. Если возвращаемое значение равно 0 (NULL), вы вызываетеGetLastError
и проверяете его результат на наличие определенного кода ошибки. Прямо на странице документации, на которую я ссылался ранее, есть ссылка наGetLastError
. Таким образом, логика будет следующей: «Err = CreateDialog(), если Err = 0, то Err = GetLastError().
LastDllError» (как следует из названия) применяется к библиотекам DLL. Создание общей формы и использование экземпляра было бы значительно проще, чем то, что вы пытаетесь сделать сейчас (во всяком случае, из VBA). Вы создаете общий ресурс dlg — примерно то же самое. - person Ken White   schedule 18.11.2014hwnd, umsg, wParam, lParam
— это не структура данных. Вам нужно передать указатель на метод, что я даже не уверен, что это возможно сделать из VBA. Вам также нужен предопределенный ресурс DIALOG (скрипт ресурсов, скомпилированный с помощью компилятора ресурсов MS и связанный с приложением), чтобы использоватьCreateDialog
; один из параметров, который он получает, — это имя этого ресурса. Боюсь, вы даже близко не подходите. - person Ken White   schedule 18.11.2014GetLastError
. - person CBRF23   schedule 18.11.2014DialogProc
в VBA, поскольку я не могу найти никакого объяснения базовой функции. Похоже, я мог бы использовать системный ресурсDIALOGEX
, который снова выглядит как тип данных, но, вероятно, таковым не является. Думаю, я рассмотрю использование общей пользовательской формы. Меня расстраивает, что я не могу сделать это так, как хотелось бы. - person CBRF23   schedule 18.11.2014DialogProc
[задокументировано]. Это функция обратного вызова (функция, указатель которой вы передаете в WinAPI, и этот API использует ее для передачи информации обратно в ваше приложение через сообщения Windows). Это базовая основа программирования WinAPI. - person Ken White   schedule 18.11.2014