xp定时关机软件(xp设置定时关机)

xp定时关机软件(xp设置定时关机)

其实就是怼一个API,一个相对比较底层的API

Private Declare Function SoftModalMessageBox Lib "user32" (pMsgBoxParams As MSGBOXDATA) As Long

这个API当然也不是最底层的API,且这个API并没有在微软官方文档中出现,其实逆向大神自行逆向出来的。

所以以下内容在MSDN是找不到的

首先看这个API的传入参数:

Private Type MSGBOXPARAMS
cbSize As Long
hWndOwner As Long
hInstance As Long
lpszText As Long
lpszCaption As Long
dwStyle As Long
lpszIcon As Long
dwContextHelpId As Long
lpfnMsgBoxCallback As Long
dwLanguageId As Long
End Type
Public Type MSGBOXDATA_Earlier 'Vista及以前的版本
params As MSGBOXPARAMS
pwndOwner As Long
wLanguageId As Long
pidButton As Long
ppszButtonText As Long
cButtons As Long
DefButton As Long
CancelID As Long
Timeout As Long
End Type
Public Type MSGBOXDATA_Later 'Win7及以后的版本
params As MSGBOXPARAMS
unk1 As Long
pwndOwner As Long
wLanguageId As Long
pidButton As Long
ppszButtonText As Long
cButtons As Long
DefButton As Long
CancelID As Long
Timeout As Long
unk2 As Long
unk3(4) As Long
End Type

API传入的参数在低版本(Vista及以前)和高版本中不一样,我们在声明API时可以分别声明,像下面这样,分别声明:

Private Declare Function SoftModalMessageBox_Earlier Lib "user32" Alias "SoftModalMessageBox" (pMsgBoxParams As MSGBOXDATA_Earlier) As Long
Private Declare Function SoftModalMessageBox_Later Lib "user32" Alias "SoftModalMessageBox" (pMsgBoxParams As MSGBOXDATA_Later) As Long

当然也可以偷个懒,直接声明为Any:

Private Declare Function SoftModalMessageBox Lib "user32" (pMsgBoxParams As Any) As Long

只是声明为Any后,传入参数的类型就需要特别注意了,由于是高阶应用,上述对高低版本分别声明的应用我这里就不讲了,请有兴趣的自己看完自行娱乐。

观察以下MSGBOXDATA这个结构体,里面全部是Long,全部是4字节对齐的,这简直是天助我也,这不就是为了让我们用数组来代替结构体吗?O(∩_∩)O哈哈~haha

进入正题,我们封装一个函数,解决以下问题:

1、自定义按钮个数、按钮文本、自动退出时间

2、Windows版本兼容

首先解决版本兼容问题,意味着我们需要识别不同的Windows版本,这个经过再三测试,发现怼的API实际上不靠谱,直接用wmi最可靠

Public Function WindowsVersion() As Long
' Windows 10 100
' Windows 8.1 63
' Windows 8.0 62
' Windows 7 61
' Windows Vista 60
' Windows XP 51
' Windows 2000 50
Dim SystemSet As Object
Dim System As Object
Dim S As String
Dim i As Long
Set SystemSet = GetObject("winmgmts:").InstancesOf("Win32_OperatingSystem")
For Each System In SystemSet
S = System.Version
Next
i = InStr(S, ".")
S = Left$(S, i - 1) & Mid$(S, i + 1)
i = InStr(S, ".")
If i Then S = Left$(S, i - 1)
WindowsVersion = Val(S)
End Function

获取到不同的版本之后,存储到一个全局变量里:

Public Enum WindowsVersion
Earlier
Later
End Enum
Public WinVersion As WindowsVersion

这里为啥无聊定义一个枚举,请自行体会,全部都说完了,就没意思了

然后就可以根据实际情况定义不同的参数(我这里肯定是打算定义数组的)

为了代码可读性,我当然不会直接用数字,还是打算用枚举代替结构体成员位置:

Public Enum eMsgParams
cbSize
hWndOwner
hInstance
lpszText
lpszCaption
dwStyle
lpszIcon
dwContextHelpId
lpfnMsgBoxCallback '回调
dwLanguageId
pwndOwner '从这里开始高版本结构体+1
wLanguageId
pidButton
ppszButtonText
cButtons
DefButton
CancelID
Timeout
unk2_2 = 21 '回调开始位置
unk2_3
unk2_4
End Enum

枚举的特性,印象中以前好像讲过,cbSize=0,不用书写0

hWndOwner=1,以此类推

直到重新定义了unk2_2=21,流水号重新计算

距离主函数出来之前,先发一个Split函数,比VBA库里自带的Split函数快3倍

Public Sub mySplit(Expression$, ResultSplit$(), Optional Delimiter$ = " ")
' By Chris Lucas, cdl1051@earthlink.net, 20011208
Dim C&, SLen&, DelLen&, Tmp&, Results&()
SLen = LenB(Expression) \ 2
DelLen = LenB(Delimiter) \ 2
' Bail if we were passed an empty delimiter or an empty expression
If SLen = 0 Or DelLen = 0 Then
ReDim Preserve ResultSplit(0 To 0)
ResultSplit(0) = Expression
Exit Sub
End If
' Count delimiters and remember their positions
ReDim Preserve Results(0 To SLen)
Tmp = InStr(Expression, Delimiter)
Do While Tmp
Results(C) = Tmp
C = C + 1
Tmp = InStr(Results(C - 1) + 1, Expression, Delimiter)
Loop
' Size our return array
ReDim Preserve ResultSplit(0 To C)
' Populate the array
If C = 0 Then
' lazy man's call
ResultSplit(0) = Expression
Else
' typical call
ResultSplit(0) = Left$(Expression, Results(0) - 1)
For C = 0 To C - 2
ResultSplit(C + 1) = Mid$(Expression, _
Results(C) + DelLen, _
Results(C + 1) - Results(C) - DelLen)
Next C
ResultSplit(C + 1) = Right$(Expression, SLen - Results(C) - DelLen + 1)
End If
End Sub

好,现在就封装目标函数:

Public Function MsgBoxEx(arrText$, strTitle$, strPrompt$, Optional ByVal DefButton As Long = 0, Optional ByVal Timeout As Long = -1, Optional ByVal CancelID As Boolean = True)
Dim md_msg() As Long
Dim lBtn() As Long
Dim sTxt() As String
Dim i&, U&
If WindowsVersion() < 61 Then
WinVersion = Earlier
ReDim md_msg(17) As Long
Else
WinVersion = Later
ReDim md_msg(24) As Long
End If
'arrText = VBA.Split(sTxt, "|") '效率极低
mySplit arrText, sTxt, "|" '不用VBA.Split,效率太低
U = UBound(sTxt)
ReDim lBtn(U) As Long
For i = 0 To U '这里我的按钮定义规则是倒序,最后一个按钮是2
lBtn(i) = U - i + 2 '5 4 3 2,因为必须有2,最后一个按钮为:退出2
Next i
md_msg(eMsgParams.cbSize) = 40 '固定参数
md_msg(eMsgParams.lpszText) = StrPtr(strPrompt) '提示文字
md_msg(eMsgParams.lpszCaption) = StrPtr(strTitle) '标题
md_msg(eMsgParams.dwStyle) = vbYesNo '很奇怪,必须设置这个参数,虽然没用
md_msg(eMsgParams.DefButton + WinVersion) = DefButton - 1 '不以arr的上下标为计数标准,总是从0开始,强行改为从1开始
md_msg(eMsgParams.CancelID + WinVersion) = CancelID '点击关闭按钮时,只能返回2,arrButtonID里必须有2
md_msg(eMsgParams.cButtons + WinVersion) = U + 1 '按钮数
md_msg(eMsgParams.pidButton + WinVersion) = VarPtr(lBtn(0)) 'ButtonID
md_msg(eMsgParams.ppszButtonText + WinVersion) = VarPtr(sTxt(0)) 'Button文字
md_msg(eMsgParams.Timeout + WinVersion) = Timeout '超时时间,默认为无限长
MsgBoxEx = SoftModalMessageBox(md_msg(0))
End Function

其实呢eMsgParams这个枚举是可有可无的

可有,是由于对于代码可读性和可维护性来说,这个必须存在

可无,如果你不打算维护这个函数,那么完全可以将这个函数改成下面这样

Public Function MsgBoxEx(arrText$, strTitle$, strPrompt$, Optional ByVal DefButton As Long = 0, Optional ByVal Timeout As Long = -1, Optional ByVal CancelID As Boolean = True)
Dim md_msg() As Long
Dim lBtn() As Long
Dim sTxt() As String
Dim i&, U&
If WindowsVersion() < 61 Then
WinVersion = Earlier
ReDim md_msg(17) As Long
Else
WinVersion = Later
ReDim md_msg(24) As Long
End If
'arrText = VBA.Split(sTxt, "|") '效率极低
mySplit arrText, sTxt, "|" '不用VBA.Split,效率太低
U = UBound(sTxt)
ReDim lBtn(U) As Long
For i = 0 To U
lBtn(i) = U - i + 2 '5 4 3 2,最后一个按钮为:退出2
Next i
md_msg(0) = 40
md_msg(3) = StrPtr(strPrompt)
md_msg(4) = StrPtr(strTitle)
md_msg(5) = vbYesNo '很奇怪,必须设置这个参数,虽然没用
md_msg(15 + WinVersion) = DefButton - 1 '不以arr的上下标为计数标准,总是从0开始,强行改为从1开始
md_msg(16 + WinVersion) = CancelID '点击关闭按钮时,只能返回2,arrButtonID里必须有2
md_msg(14 + WinVersion) = U + 1 '按钮数
md_msg(12 + WinVersion) = VarPtr(lBtn(0)) 'ButtonID
md_msg(13 + WinVersion) = VarPtr(sTxt(0)) 'Button文字
md_msg(17 + WinVersion) = Timeout '超时时间,默认为无限长
MsgBoxEx = SoftModalMessageBox(md_msg(0))
End Function

调用示例:

MsgBoxEx “我的按钮|你的按钮|她的按钮|取消”, “一起摇摆”, “女士优先,默认选她”, 3, , False

不显示关闭叉叉,不设定第3个参数,等待用户选择,直接按Enter,返回3

xp定时关机软件(xp设置定时关机)

测试1

MsgBoxEx “我的按钮|你的按钮|她的按钮|取消”, “一起摇摆”, “女士优先,默认选她”, 3, 6000, True

显示关闭叉叉,6000ms=6s后自动退出,自动退出时返回32000,点关闭和点取消都返回2

xp定时关机软件(xp设置定时关机)

测试2

以上,如果在应用时可以这样写:

Dim var&
var = MsgBoxEx("我的按钮|你的按钮|她的按钮|取消", "一起摇摆", "女士优先,默认选她", 3, 6000, True)
Select Case var
Case 32000 '未选择,自动退出
Case 2 '取消
Case 3 '她的按钮
Case 4 '你的按钮
Case 5 '我的按钮
End Select
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 44400@trc20.tw 举报,一经查实,本站将立刻删除。
(0)

相关推荐

  • win10创意者更新(win10秋季创意者更新build)

    IT之家11月29日消息 AdDuplex今天发布了最新的11月份Windows设备生态报告,在经过1个多月的发布和推送后,Windows 10创意者更新秋季版(1709)在整个W…

    2023年9月10日
    5
  • 电脑怎么把电影剪辑成短片(爱剪辑的使用方法)

    随着自媒体的火爆越来越多的人加入到了这个行业中来,那么其中不乏一些热衷于制作短视频的朋友,大家平时看到一些精彩的电影或是电视剧的片段都是通过剪辑做出来了,今日头条官方也在讲短视频就…

    2023年8月20日
    27
  • win7桌面图标怎么变小(win7桌面图标变小了)

    手机桌面千千万,你的最好看 教你打造个性化桌面 手机使用时间长了 单一的桌面图标看腻了? 那小O强烈推荐OPPO手机上这个功能 —— 桌面风格图标 让你不用更换手机主题 也能拥有独…

    2023年9月10日
    5
  • 如何使用PDO连接数据库(pdo连接数据库方法)

    在PHP开发中,连接数据库是常见的操作之一。PDO是PHP提供的一种数据库抽象层,可以方便地连接和操作各种类型的数据库。下面是使用PDO连接数据库的步骤(需要打开PDO相关的配置)…

    2023年7月25日
    27
  • Excel转Word怎么转换(分享两种方法)

    怎么把Excel表格转换成Word文档来使用呢?大家在日常办公中对Excel的使用频率也会挺高的,需要制作表格来记录信息。但是在很多情况下,我们需要将表格中的内容做成Word文档来…

    2023年7月13日
    33
  • daemontoolslite(daemontools)

    磁盘镜像包括了整个磁盘卷的文件或者是全部的存储设备的数据,比如说硬盘,光盘(DVD,CD,蓝光光碟),磁带机,USB闪存,软盘。一个完整的磁盘镜像应该包含与原来的存储设备上一样完整…

    4天前
    3
  • cad2010激活码(cad2007激活码)

    1、下载完安装包,右键解压,注意解压路径不要有中文,可以参考我的路径。(尽量别放C盘) 2、找到解压文件,点击Setup 3、点击安装 4、我接受,下一步 5、更改安装路径,同样的…

    2天前
    2
  • rar 密码破解(rar文件密码怎么解除)

    找回RAR/ZIP密码、在线RAR/ZIP解密、RAR/ZIP压缩包解密,具体步骤如下:一、百度搜索“密码帝官网”;二、点击“立即开始”,进入用户中心;三、上传文件,一步搞定。简单…

    2023年9月9日
    8
  • boot启动项设置(华硕boot启动项设置)

    使用光盘安装系统已经越来越少,现在取而代之的是更加方便快速的U盘装机方式,要使用U盘装系统,除了制作U教授U盘启动盘之外,还需设置电脑开机从U盘引导启动进入系统安装界面。现在大多数…

    12小时前
    1
  • 图片压缩方法有哪些(图片压缩怎么弄)

    图片压缩方法有哪些?图片压缩是一种非常重要的技术,可以通过减少图片文件大小来节省存储空间和提高加载速度。为了实现最佳效果,你可以使用多种方法来压缩图像,总之,图片压缩是一种非常实用…

    2023年7月12日
    35

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注