【UserForm】窗体の显隐动画
一、前言不知道你有没有去网上搜索过关于VBA动画窗体的内容其实相关的教学文章挺少的大多数文章都是贴一些动图抄一下官方文档的API函数定义再给几句调用代码就完事儿了。其实用户要想在VBA中完整地实现窗体显隐动画并不是一件很容易的事情。你的代码该如何写、在哪个事件中写哎真的会遇到各种问题哈......这期文章晚间让大家看看动画窗体的实现过程到底是什么样的。二、本期明星函数本期的明星函数是AnimateWindow你可以用它来更改窗口在显示或隐藏时的动画。这是它在VBA中的完整声明代码还有一些配套的常量晚间一并列在这里了#If VBA7 And Win64 Then Public Declare PtrSafe Function AnimateWindow Lib user32 ( _ ByVal hwnd As LongPtr, _ ByVal dwTime As Long, _ ByVal dwFlags As Long _ ) As Long #Else Public Declare Function AnimateWindow Lib user32 ( _ ByVal hwnd As Long, _ ByVal dwTime As Long, _ ByVal dwFlags As Long _ ) As Long #End If Public Const AW_ACTIVATE H20000 Public Const AW_HIDE H10000 Public Const AW_BLEND H80000 Public Const AW_SLIDE H40000 Public Const AW_CENTER H10 Public Const AW_HOR_POSITIVE H1 Public Const AW_HOR_NEGATIVE H2 Public Const AW_VER_POSITIVE H4 Public Const AW_VER_NEGATIVE H8三、窗体显隐动画的正确调用代码建议收藏在以下代码中晚间取消了窗体的标题栏和双层边框样式1. 窗体显示动画你要在UserForm_Initialize事件中调用窗体显示动画的代码并提前手动设置窗体的显示位置代码如下Private Sub UserForm_Initialize() 获取窗体句柄 Uf.Form FindWindowA(IIf(Application.Version 9, ThunderXFrame, ThunderDFrame), Me.Caption) 取消标题栏和双层边框 SetWindowLongA Uf.Form, GWL_STYLE, GetWindowLongA(Uf.Form, GWL_STYLE) And Not WS_CAPTION SetWindowLongA Uf.Form, GWL_EXSTYLE, GetWindowLongA(Uf.Form, GWL_EXSTYLE) And Not WS_EX_DLGMODALFRAME DrawMenuBar Uf.Form 手动确定窗体的显示位置 Me.StartUpPosition 0 在表格中心显示 Me.Left Application.Left Application.Width / 2 - (Me.Width / 2) - 1.4 Me.Top Application.Top Application.Height / 2 - (Me.Height / 2) 在屏幕中心显示 Uf.Shdc GetDC(0) Dim DpiX: DpiX GetDeviceCaps(Uf.Shdc, LOGPIXELSX) Dim DpiY: DpiY GetDeviceCaps(Uf.Shdc, LOGPIXELSY) Dim HorzresX: HorzresX GetDeviceCaps(Uf.Shdc, HORZRES) Dim HorzresY: HorzresY GetDeviceCaps(Uf.Shdc, VERTRES) ReleaseDC 0, Uf.Shdc Me.Left ((HorzresX / 2) / DpiX) * 1440 / 20 - (Me.Width / 2) - 0.5 Me.Top ((HorzresY / 2) / DpiY) * 1440 / 20 - (Me.Height / 2) 窗体显示动画 AnimateWindow Uf.Form, 500, AW_ACTIVATE Or AW_BLEND End Sub2. 窗体隐藏动画你要在UserForm_QueryClose事件中调用窗体隐藏动画的代码Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) 窗体隐藏动画 AnimateWindow Uf.Form, 500, AW_HIDE Or AW_BLEND 渐隐 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_CENTER 向内折叠隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_HOR_POSITIVE 向右滚动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_SLIDE Or AW_HOR_POSITIVE 向右滑动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_HOR_NEGATIVE 向左滚动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_SLIDE Or AW_HOR_NEGATIVE 向左滑动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_VER_POSITIVE 向下滚动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_SLIDE Or AW_VER_POSITIVE 向下滑动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_VER_NEGATIVE 向上滚动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_SLIDE Or AW_VER_NEGATIVE 向上滑动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_HOR_POSITIVE Or AW_VER_POSITIVE 向右下角滚动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_SLIDE Or AW_HOR_POSITIVE Or AW_VER_POSITIVE 向右下角滑动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_HOR_POSITIVE Or AW_VER_NEGATIVE 向右上角滚动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_SLIDE Or AW_HOR_POSITIVE Or AW_VER_NEGATIVE 向右上角滑动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_HOR_NEGATIVE Or AW_VER_POSITIVE 向左下角滚动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_SLIDE Or AW_HOR_NEGATIVE Or AW_VER_POSITIVE 向左下角滑动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_HOR_NEGATIVE Or AW_VER_NEGATIVE 向左上角滚动隐藏 AnimateWindow Uf.Form, 1000, AW_HIDE Or AW_SLIDE Or AW_HOR_NEGATIVE Or AW_VER_NEGATIVE 向左上角滑动隐藏 End Sub注意以上注释部分整理了所有的窗体隐藏动画的调用代码。你可以将其中的AW_HIDE更改为AW_ACTIVATE以变为窗体的显示动画。四、自学者大概率会遇到的问题1. 为什么在UserForm_Initialize事件中调用显示动画时窗体会先在屏幕左上角做动画显示然后再移动到表格中心这个问题对应的代码一定长这个样子这个问题的答案是这样的AnimateWindow代码充当了一个提前显示延迟动画的角色。由于运行到这句代码时窗体的默认显示位置Left和Top都还是0窗体显示动画一定是在屏幕左上角出现的在运行了End Sub语句之后窗体就会根据StartUpPosition属性的默认值“1 - 所有者中心”调整显示位置到表格中心。分析过程如下你可以通过F8逐行调试的功能来解决这个问题我们可以看到当代码运行了AnimateWindow语句之后窗体就在屏幕左上角做显示动画了再当你运行了End Sub语句之后窗体又自动平移到了表格中心。其实这个问题的后半部分挺容易理解的因为窗体有一个控制初始显示位置的属性叫做StartUpPosition它的默认值为“1 - 所有者中心”这里的所有者中心指的就是Excel表格的中心。因此无论你怎么移动表格窗口窗体的初始显示位置永远都是表格中心。而且代码永远是在运行了UserForm_Initialize事件的End Sub语句之后窗体被移动到表格中心显示。那前半部分呢为什么窗体会先在屏幕左上角显示呢我们可以这样理解UserForm_Initialize事件在运行时窗体就已经创建好了默认位置就是0, 0只不过还没显示在当运行了End Sub语句之后窗体会因为设置了StartUpPosition属性而被调整到表格中心显示。2. 为什么在UserForm_Activate事件中调用窗体显示动画看不到任何效果这个问题对应的代码长这个样子因为UserForm_Activate事件触发时就已经代表窗体成为活动窗口了即已经显示了。而且AnimateWindow函数明确要求如果对已经显示的窗口进行动画显示那么函数将会调用失败返回零值。所以无法在此事件中调用窗体显示动画。3. 为什么不能在UserForm_Terminate事件中调用窗体隐藏动画这个问题对应的代码长这个样子因为UserForm_Terminate事件触发时窗体就已经被卸载消失了。而且AnimateWindow函数同样明确要求了如果对已经隐藏的窗口进行动画隐藏那么函数将会调用失败返回零值。所以无法在此事件中调用窗体隐藏动画。五、相关文章相关文章https://mp.weixin.qq.com/s/zciGwtJSnIrsqquPQGXeHg