news 2026/6/22 23:53:42

【UserForm】窗体の显隐动画

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【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 Sub

2. 窗体隐藏动画

你要在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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/8 22:46:11

i.MX 8M Mini到8M Nano硬件兼容性设计实战指南

1. 项目概述&#xff1a;从i.MX 8M Mini到8M Nano的硬件设计迁移在嵌入式硬件开发领域&#xff0c;尤其是基于NXP i.MX系列这类高性能应用处理器的项目中&#xff0c;我们常常面临一个现实挑战&#xff1a;如何在产品迭代或成本优化时&#xff0c;平滑地从一款处理器迁移到另一…

作者头像 李华
网站建设 2026/6/11 15:58:33

嵌入式5G模块集成实战:从硬件连接到内核驱动与网络拨号全解析

1. 项目概述与核心价值在当前的嵌入式系统开发浪潮中&#xff0c;设备对高速、低延迟无线连接的需求日益迫切。无论是工业物联网网关、车载信息娱乐系统&#xff0c;还是边缘计算节点&#xff0c;5G技术都成为了实现其“永远在线、高速互联”愿景的关键。然而&#xff0c;将一颗…

作者头像 李华
网站建设 2026/6/8 22:37:29

SolonCode 更新:全中文驱动数字员工,Web 设置、对话配置等功能升级!

杭州无耳科技有限公司研发的企业级终端编码智能体 SolonCode 迎来更新&#xff0c;围绕设置即用、安全管控、体验打磨展开&#xff0c;带来多项功能升级。 SolonCode 简介 SolonCode 是全中文驱动的数字员工&#xff0c;能自主理解需求、编写代码。它不挑模型和平台&#xff0c…

作者头像 李华