【问题标题】:non-blocking "toast" like notifications for Microsoft Access (VBA)Microsoft Access (VBA) 通知之类的非阻塞“吐司”
【发布时间】:2017-01-06 13:12:59
【问题描述】:

如何在 Microsoft Access 中显示类似通知的非阻塞“toast”?那确实有某种动画,不应该阻止宿主应用程序!

【问题讨论】:

标签: ms-access notifications vba nonblocking


【解决方案1】:

我的朋友问我关于 ms 访问通知之类的非阻塞 toast。我的第一个想法是,检查谷歌你会发现很多样本。他对得到的样品不满意。

他想要(JQuery)非阻塞通知之类的东西。用户需要知道但不一定需要交互的东西。

由于在 VBA 中无法使用线程,我想,如果您可以编写自己的 .dll 会怎样?所以我最终编写了一个 .NET DLL,可以通过(Windows)VBA 代码访问它并显示一个 toast 通知。 (实际的 dll 创建和从 vba 访问 .NET dll 是另一个我将在稍后介绍的主题)(You can read more in my blog 根据您的意愿留下 cmets 或建议。)

现在,您可以从这里下载我创建的 DLL: HERE

编辑: 以上下载链接和 GitHub 链接已更新为我认为属于作者的工作链接。

如果您担心下载未知 DLL:VirusTotal Scan report

将 DLL 添加到应用程序的根文件夹,并将以下代码添加到应用程序。

'Module level public variable

Public gTOASTER As Object

' to save window metrics
Public Type RECT
    Left        As Long  ' x1
    Top         As Long  ' y1
    Right       As Long  ' x2
    Bottom      As Long  ' y2
End Type

#If VBA7 Then 
    Public Declare PtrSafe Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As LongPtr
    Public Declare PtrSafe Function KRISH_VBA_TOOLS Lib "VBA_TOOLS.dll" () As Object
    Public Declare PtrSafe Function GetWindowRect Lib "user32" (ByVal hWnd As LongPtr, ByRef lpRect As RECT) As LongPtr 
#Else
    Public Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal strFilePath As String) As Long
    Public Declare Function KRISH_VBA_TOOLS Lib "VBA_TOOLS.dll" () As Object
    Public Declare Function GetWindowRect Lib "user32" (ByVal hWnd As LongPtr, ByRef lpRect As RECT) As LongPtr
#End If

Public Function FN_TOAST_DLL(iMessage As String, Optional iCLOSE_DURATION As Long = 3000, Optional iType As String = "success", Optional iANIME_DURATION As Long = 1000, Optional iFONT_COLOR As String = "#FFFFFF", Optional iX As Long = 0, Optional iY As Long = 0, Optional iANIME_DIRECTION As Integer = 1, Optional iPARENT_HWND As Long = 0)

On Error GoTo LABEL_EXIT_ROUTINE:

    If gTOASTER Is Nothing Then
        LoadLibrary (FN_APP_GET_BASE_PATH & "VBA_TOOLS.dll")
        Set gTOASTER = KRISH_VBA_TOOLS()
        GoTo LABEL_TOAST
    Else
        GoTo LABEL_TOAST
    End If

    On Error GoTo 0
    Exit Function

LABEL_EXIT_ROUTINE:
    msgbox iMessage & vbnewline & err.description
    Exit Function

LABEL_TOAST:
    'set background color. (pass any html color code)
    Select Case iType
        Case "error"
            iType = "#F76160"
        Case "success"
            iType = "#26ad82"
        Case Else
            iType = "#26ad82"
    End Select

    'if parent object is provided show the toast on top of the parent. if custom x, y is provided use x,y coordinated. if none provided use access app's locaiton.
    Dim mRect As RECT
    If iPARENT_HWND <= 0 Then
        If iX = 0 And iY = 0 Then
            GetWindowRect Application.hWndAccessApp, mRect

            iANIME_DIRECTION = 0 'anim direction 0 to down and 1 to up
        End If
    Else ' iPARENT_HWND > 0 Then 'parent_hwnd is null
        GetWindowRect iPARENT_HWND, mRect
    End If

    'set up some offsets
    iX = mRect.Left + 360
    iY = mRect.Top + 1


    On Error Resume Next
    gTOASTER.FN_SHOW_TOAST iMessage, iCLOSE_DURATION, iType, iANIME_DURATION, iFONT_COLOR, iX, iY, iANIME_DIRECTION

End Function

Public Function FN_APP_GET_BASE_PATH()
    Dim FN As String
    FN = Application.CurrentProject.path
    If VBA.Right(Application.CurrentProject.path, 1) <> "\" Then FN = FN & "\"
    FN_APP_GET_BASE_PATH = FN
End Function

如果要自定义 fn_toast_dll 函数,则来自 DLL 的参数列表:

'    /// <summary>
'    ///
'    /// </summary>
'    /// <param name="iMessage">Message to display</param>
'    /// <param name="iDuration">Duration in Milliseconds to keep the toast before fading out..</param>
'    /// <param name="iBG_COLOR">HTML color code for your toast background...</param>
'    /// <param name="iANIME_DURATION">Millisecond value used to for fading in and out the Toast.. 1/4 is used to fade in rest to fade out..</param>
'    /// <param name="iFONT_COLOR">HTML Color code for the font..</param>
'    /// <param name="iX">x position on the screen. where the toast should appear</param>
'    /// <param name="iY">y position on the screen where the toast should appear</param>
'    /// <param name="iANIM_DIRECTION">{0,1} 0 will show/add further notifications downwards and 1 upwards.</param>
'    /// <returns></returns>

显示通知调用此方法:

FN_TOAST_DLL "hello this is a green test" ' By default a success message with 3 seconds will be "toasted"
FN_TOAST_DLL "hello this is an error", 15000, "error"

用法

您可以将其用于任何非交互警报。例如登录成功、操作取消警报或用户不需要按 OK 来确认您的消息的任何内容。

目标 我将在 GitHub 上上传 Dll 项目,并请求其他 VBA C# 专家的贡献,以使其更加精美并可供所有 VBA 开发人员使用。

这是我的 GitHub 链接:GitHub 请尽可能多地贡献,并让每个人都可以使用它:) 如果你能保持主类名不变,我会很高兴。

一个样本:

【讨论】:

  • 不错!如果您可以发布 DLL 源代码,那将很有帮助。并且也许在您的答案中的代码中添加一个描述参数的函数头(例如,我不确定 iANIME_DIRECTION 做了什么)。谢谢。
  • @Andre 我已经添加了参数列表。我会将 DLL 上传到 GitHub 并在下一篇文章中提供链接,当我介绍“如何访问 .NET dll form vba”时
  • 这很好,谢谢!看起来它在 64 位办公室下不起作用。你能做64位版本的DLL吗?另外添加一个选项会很棒 - 如果鼠标指针在 toast 上方,请不要通过计时器关闭 toast。
  • @SergeyS。 64bit Dll 添加了你能测试一下吗?还添加了鼠标事件,并发布了指向我的项目的 github 链接。
  • 感谢您的快速更新,它现在显示在 64 以下,但方式有点不同:如果您在第一个 toast 消失之前打开第二个 toast,第二个 toast 会出现,但第一个 toast 立即消失,所以在屏幕上只有一个吐司可见。
【解决方案2】:

不确定这是否值得另一个答案!没有的话请见谅! 回答“如果我可以发布 DLL 源代码”,并让那些想要贡献/参与 DLL 项目的人更容易阅读/脱颖而出。

我已将 DLL 项目添加到 GitHub,我将添加更新的新功能。如果你想贡献,请做。该项目是用 C# 编写的,以证明这个概念,因此代码可能非常混乱。 (初始阶段)

Please do improve: 
  1. 新动画
  2. 也许将消息发送回主机应用程序?
  3. 更好的 x,y 位置处理?

无论你想出什么。

如果您能将主类名称保留为“KRISH_VBA_TOOLS”,我会很高兴。

这里是 GitHub 链接:
https://github.com/krishKM/VBA_TOOLS

享受吧。

【讨论】:

  • 如果您上传了源代码,我相信会有很多人会提供帮助。你只有在你的 github 页面上发布了二进制文件。
【解决方案3】:

我对这个问题的解决方案是使用内置的 Windows 10 toast 通知 API。我调用了 PowerShell,我们可以在其中利用 BurntToast。我的示例是非阻塞的,因为它在调用 PowerShell 后立即返回,因此您的应用程序可以在模块加载时继续运行。即使 PowerShell 需要一分钟来加载用户也不会注意到。在我的测试中,它的触发速度相当快。

首先制作一个如下所示的Pop-Toast.ps1 文件:

## Pop-Toast 
#Requires -Version 5
Param (
    [String]$cmdText="Test",
    [String]$cmdTitle="Example",
    [String]$cmdLogo="$PSScriptRoot\YourLogo.ico",
    [String]$thisApplication,
    [String]$appID
)



## Ensure we have the latest version of our module installed
$toastModule = "BurntToast"
if (Get-Module -ListAvailable -Name $toastModule) {
    # If you uncomment the next line it will update but each call is much slower.
    #Update-Module -Name $toastModule
} 
else {
    try {
        Install-Module -Name $toastModule -AllowClobber -Confirm:$False -Force  
    }
    catch [Exception] {
        $_.message 
        exit
    }
}

## Pop that tart!
$header = New-BTHeader -Id $appID -Title $thisApplication
New-BurntToastNotification -AppLogo $cmdLogo -Header $header -AppId $appID -Text $cmdTitle, $cmdText 

然后我们创建一个调用我们的 PowerShell 脚本的免费 VBA 过程:

Const PopToastPath As String = "Toast\Pop-Toast.ps1"

Public Sub PopToaster(ByVal toastText As String, Optional ByVal toastTitle As String, Optional ByVal toastLogoPath As String)
    Dim PSOptions As String
    PSOptions = " -WindowStyle hidden -ExecutionPolicy bypass -NonInteractive"
    
    Dim PSCommand As String
    PSCommand = "powershell.exe" & PSOptions & " -File " & PopToastPath & " -cmdText """ & toastText & """"
    If Not Trim$(toastTitle) = vbNullString Then PSCommand = PSCommand & " -cmdTitle """ & toastTitle & """"
    If Not Trim$(toastLogoPath) = vbNullString Then PSCommand = PSCommand & """ -cmdLogo """ & toastLogoPath & """"

    With CreateObject("Wscript.Shell")
        .Run PSCommand, 0, False
    End With
End Sub

注意:您可以配置应用程序名称和 appID 以使 toast 看起来来自您自己的应用程序。如果您不这样做,那么它将被视为来自 PowerShell。

【讨论】:

    猜你喜欢
    • 2013-04-09
    • 2011-09-24
    • 2014-10-18
    • 2016-08-23
    • 1970-01-01
    • 2012-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多