我没有判断的程序但是我有用API打开和关闭光驱的程序但愿对你有用:
声明API
Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long打开:
retvalue = mciSendString("set CDAudio door open", returnstring, 127, 0)关闭:
retvalue = mciSendString("set CDAudio door closed", returnstring, 127, 0)如果没有用就笑笑算了!! ^)^
声明API
Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long打开:
retvalue = mciSendString("set CDAudio door open", returnstring, 127, 0)关闭:
retvalue = mciSendString("set CDAudio door closed", returnstring, 127, 0)如果没有用就笑笑算了!! ^)^
解决方案 »
- 什么是句柄?
- 谁做过用vb程序控制另外一个程序的按钮。听说用api我弄了很长时间也不好弄
- ACTIVEX控件与DLL问题
- IE的主页莫名其妙地被修改,是不是病毒?用瑞星杀也没有发现病毒。
- 如何得知用户切换到了其他程序,也就是说当前程序失去了焦点?
- 怎么判断ACCESS数据库的某字段值为空?在线等待
- 大侠们快来救命啊!我的怎样在XP下安装手柄?????(300分,详情请入内查看)
- 一个小问题 求助
- 在Vb窗体中,怎样实现动态连接?
- 请问各位高手,VB中如何对类的方法和属性进行封装??
- 请问,VB中的外接程序如何将向已存在的弹出菜单中添加一个自己的命令?
- 在component中找不到microsoft windows common dialog 6.0
执行这句话后cd-rom肯定是关着的想些什么播放软件马?
有知道cd-rom状态的必要吗?
使用MCI命令字符串可以控制CD-ROM的弹出和弹入,VB提供了MCI控件,最初我考虑它应该是支持所有MCI命令的,但经试验未果,最后只能把原始的MCI APIs抬出来(大家可以参考MSDN – MCI Command strings,这里包含了所有MCI控制命令的字符串描述)。这样我们就必须要在项目中添加一个API的声明,为了这个声明对任何模块和窗体都有效,我们要把它放置到模块文件中作为Public声明出现,步骤如下:
1. 在窗体上添加cmdEject和cmdClose两个按钮。
2. 选择工程菜单——添加模块,然后将新添加的模块命名为APIs。
3. 在模块中添加如下声明:Public Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
4. 处理cmdEject的Click事件,加入如下代码:
Dim strSend As String * 80
Dim strRecv As String * 80
strSend = "set cdaudio door open"
mciSendString strSend, strRecv, 80, 0
Debug.Print "Recv = " + strRecv
5. 处理cmdClose的Click事件,加入如下代码:
Dim strSend As String * 80
Dim strRecv As String * 80
strSend = "set cdaudio door closed"
mciSendString strSend, strRecv, 80, 0
Debug.Print "Recv = " + strRecv
这样就可以有效的控制CD-ROM的弹出和弹入了。
(2) 如何感知CD-ROM中的碟片变化
处理WM_DEVICECHANGE消息可以获得碟片变化的信息,比如新的碟片被弹入,或者碟片被从CD-ROM中移除。这些消息由Windows发送到窗体的消息队列中,既然需要拦截窗体消息,我们就必须重建Window Procdure,在这个函数中判断各种到来的消息。重建Windows Procdure所用的API分别为SetWindowLong和CallWindowProc,那么我们在模块APIs中添加声明如下:
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Public Const GWL_WNDPROC = -4&
这些声明很烦,但是原文都可以在Visual Studio中提供的“API阅览器”中找到。
然后我们把窗体过程(Window Procdure)的框架实现:
1. 由于在窗体过程中务必调用默认窗体过程,所以我们有必要保存frmMain的默认窗体过程的入口地址,我们采取全局变量glOldWndProc来存储这个信息,同时使用ghWnd来存储主窗体的句柄:hWnd。
在模块APIs中添加如下声明:
Public glOldWndProc As Long
Public ghWnd As Long
2. 在模块APIs中添加窗体过程的框架代码:
Public Function VbWndProc(ByVal hWnd As Long, ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case uMsg
Case Else
End Select
VbWndProc = CallWindowProc(glOldWndProc, ghWnd, uMsg, wParam, lParam)
End Function
3. 捕捉frmMain的Form_Load事件,在这个事件中完成窗体过程的重新设定。
Private Sub Form_Load()
ghWnd = Me.hWnd ‘保存窗体句柄hWnd
‘设置新的窗体过程,同时保存默认窗体过程的入口地址
glOldWndProc=SetWindowLong(hWnd,GWL_WNDPROC, AddressOf VbWndProc)
End Sub
好,此时似乎已经大功告成(我当时就是这样想的),只需要在窗体过程的SELECT语句中判断消息类型uMsg就可以了。不过我查阅了“API阅览器”,却没有发现WM_DEVICECHANGE的声明,最终在VC中试验出了WM_DEVICECHANGE常量值为537,那么我们在APIs中添加如下常量说明:
Public Const WM_DEVICECHANGE = 537&
同时在Select语句中添加相应的判断:
Select Case uMsg
Case Is = WM_DEVICECHANGE
Debug.Print "WM_DEVICECHANGE"
Debug.Print "wParam = " & wParam
Case Else
End Select
注意出现在Case中的Debug.Print语句,这是VB程序员进行调试的常用方法,使用VB而不用Debug.Assert和Debug.Print是难以想象的,在VC中提供断言以及变量监视的方法就更多一些,甚至类型(比如RTTI)。
这个消息捕捉到了,我们还要继续判断这个消息说明的是碟片被移除还是新碟片被插入,在WINDOWs SDK程序设计标准中这是由wParam参数决定的,定义的宏分别为DBT_DEVICEARRIVAL和DBT_DEVICEREMOVECOMPLETE,但是这两个宏所代表的常量值依然无法在“API阅览器”中找到,而且在VC中也没有相应的宏声明,此时上面CASE语句中的Debug.Print "wParam = " & wParam就发挥了作用,在光盘的插拔过程中通过立即窗口的显示我们可以得知DBT_DEVICEARRIVAL对应的常量为32768,而DBT_DEVICEREMOVECOMPLETE对应的常量为32772。那么我们在模块APIs中再添加对这两个消息的声明(注意,声明中没有使用默认的宏名字):
Public Const CD_REMOVED = 32772
Public Const CD_INSERTED = 32768
然后扩充CASE语句:
Select Case uMsg
Case Is = WM_DEVICECHANGE
Debug.Print "WM_DEVICECHANGE"
Debug.Print "wParam = " & wParam
Select Case wParam
Case Is = CD_REMOVED
MsgBox "CD_REMOVED"
Case Is = CD_INSERTED
MsgBox "CD_INSERTED"
End Select
Case Else
End Select
这样我们就完成了对碟片变化这个事件的捕捉。
写这篇文章主要是由于网友ygrobin问起了是否可以在VB中利用API锁定光驱(就是让光驱变成是不可弹出的)的问题,但是由于本人才疏学浅,还是没能解决,还望同行赐教。2001年12月11日星期二
我不是菜鸟,我们认真一点玩,好不好?:)
Dim tDevVol As DEV_BROADCAST_VOLUME
Dim tmpBuffer As String
……
Case WM_DEVICECHANGE
If wParam = DBT_DEVICEARRIVAL Then ' 检测是否是光驱。
CopyMemory tDevHdr, ByVal lParam, Len(tDevHdr) If tDevHdr.dbcd_devicetype = DBT_DEVTYP_VOLUME Then
CopyMemory tDevVol, ByVal lParam, tDevHdr.dbcd_size With tDevVol
tmpBuffer = String(4, vbNullChar)
PathBuildRoot tmpBuffer, TestDriveBit(.dbcv_unitmask)
If GetDriveType(tmpBuffer) = DRIVE_CDROM Then PlayVCD (tmpBuffer)
End With
End If
End If
……' 获得 WM_DEVICECHANGE 消息中 DEV_BROADCAST_VOLUME 设置的驱动器符号。
Public Function TestDriveBit(ByVal dwValue As Long) As Long
Dim i As Long
For i = 0 To 25
If (dwValue And (2 ^ i)) = (2 ^ i) Then
TestDriveBit = i
Exit For
End If
Next i
End Function
我觉得这种方法虽然可行,却不完美,所以才悬赏 200 分,希望明确获得光驱托盘状态。能够解决的话还可以加分。Come On!
请参考 Windows Media Player SDK用 Player Object 的 playState 属性
===========================================
Syntaxplayer.playState=========================
Possible ValuesThis property is a read-only Number (long).Value State Description
0 Undefined Windows Media Player is in an undefined state.
1 Stopped Playback of the current media clip is stopped.
2 Paused Playback of the current media clip is paused. When media is paused, resuming playback begins from the same location.
3 Playing The current media clip is playing.
4 ScanForward The current media clip is fast forwarding.
5 ScanReverse The current media clip is fast rewinding.
6 Buffering The current media clip is getting additional data from the server.
7 Waiting Connection is established, however the server is not sending bits. Waiting for session to begin.
8 MediaEnded Media has completed playback and is at its end.
9 Transitioning Preparing new media.
10 Ready Ready to begin playing. ==============================================================
Sample:// Test if Windows Media Player is in the playing state.
if (3 == Player.playState)
myText.value = "Windows Media Player is playing!";
else
myText.value = "Windows Media Player is NOT playing!";
就是dir "driver:\*" 出错就弹出光驱。
好像bleem似的,
不用理会里面有没有什么和光驱状态没有需要的文件就弹出光驱要求放入指定盘。
或者象CD播放器一样,乐观选择一下,
如果dir "driver:\*"出错就认为光驱是打开的,然后就执行关闭光驱。
如果没有错就弹出光驱。
自己没有办法,就说“不用那么复杂吧”——什么叫精益求精?只会说废话。200 分这么好拿?
===========================================
请参考 Windows Media Player SDK用 Player Object 的 playState 属性
===========================================
Syntaxplayer.playState=========================
Possible ValuesThis property is a read-only Number (long).Value State Description
0 Undefined Windows Media Player is in an undefined state.
1 Stopped Playback of the current media clip is stopped.
2 Paused Playback of the current media clip is paused. When media is paused, resuming playback begins from the same location.
3 Playing The current media clip is playing.
4 ScanForward The current media clip is fast forwarding.
5 ScanReverse The current media clip is fast rewinding.
6 Buffering The current media clip is getting additional data from the server.
7 Waiting Connection is established, however the server is not sending bits. Waiting for session to begin.
8 MediaEnded Media has completed playback and is at its end.
9 Transitioning Preparing new media.
10 Ready Ready to begin playing. ==============================================================
Sample:// Test if Windows Media Player is in the playing state.
if (3 == Player.playState)
myText.value = "Windows Media Player is playing!";
else
myText.value = "Windows Media Player is NOT playing!";
声明:
Declare Function GetVolumeInformation Lib _
"kernel32" Alias "GetVolumeInformationA" _
(ByVal lpRootPathName As String, _
ByVal lpVolumeNameBuffer As String, _
ByVal nVolumeNameSize As Long, _
lpVolumeSerialNumber As Long, _
lpMaximumComponentLength As Long, _
lpFileSystemFlags As Long, _
ByVal lpFileSystemNameBuffer As String, _
ByVal nFileSystemNameSize As Long) As LongDeclare Function GetDriveType Lib "kernel32" _
Alias "GetDriveTypeA" (ByVal nDrive As String) As LongPublic Const DRIVE_CDROM = 5
使用:
Dim VolName As String, FSys As String, erg As Long
Dim VolNumber As Long, MCM As Long, FSF As Long
Dim Drive As String, DriveType As Long
VolName = Space(127)
FSys = Space(127)
Drive = "F:\" 'Enter the driverletter you want
DriveType& = GetDriveType(Drive$)
erg& = GetVolumeInformation(Drive$, VolName$, 127&, _
VolNumber&, MCM&, FSF&, FSys$, 127&)
Print "分区名称:" & vbTab & VolName$
Print "序列号:" & vbTab & VolNumber&
Print "最大文件名称长:" & vbTab & vbTab & MCM&
Print "文件系统标志:" & vbTab & vbTab & FSF&
Print "文件系统名称:" & vbTab & FSys$
Print "类型:" & vbTab & DriveType&;
'Is the drive a CDROM, if so, check for a CD
If DriveType& = DRIVE_CDROM Then
Print " (CDROM, ";
If erg& = 0 Then
Print "没有 CD )"
Else
Print "有 CD )"
End If
Else
Print " (非 CDROM)"
End If
我还是坚持原来的意见:无解!!
前两天放假,我只有笔记本电脑,没法试(关门必须手推),今天我试了一下win2k的CD唱机,我们来作个实验:cdrom中不要放光碟,并且把门关上,然后启动cd唱机,点击eject,你可以发现,第一次点击,cdrom并无反应,第二次点击,cdrom才开门,然后继续点击,就可以正常实现开关门动作。由此可见,cd唱机实现eject的逻辑:
'首先有一个逻辑变量表示cdrom门的状态,假设为:
dim bolCdOpen 'true开,false关
'eject功能的代码:(其中用到一个函数cd_isready,一个过程cd_eject,写在后面)
private sub cmdEject_Click()if cd_isready() then
cd_eject "open"
bolCdOpen=true
else
eject "close"
cd_end if
bolCdOpen=false
end sub
'判断cdrom是否准备好的函数
private function cd_isready () as boolend
'判断方法上次在你的另一个同样问题的帖子里我已经写了一个functionend function'开关门的过程,实现方法很多人已经讲过了就不抄了
private sub cd_eject(mode as string)
select case lcase(mode)
case 'open''开门case 'close''关门end sub由此可见,win2k的cd唱机也只不过是通过判断cdrom是否准备好来模拟eject,并不能判断光驱门的状态。
>>步骤1----建立新工程,在窗体上放置一个CommandButton按钮.设置其Caption = "打开"
>>步骤2----编写如下代码:Private Declare Function mciSendString Lib "winmm.dll" Alias _
"mciSendStringA" (ByVal lpstrCommand As String, ByVal _
lpstrReturnString As String, ByVal uReturnLength As Long, _
ByVal hwndCallback As Long) As LongPrivate Sub Command1_Click()
Static bOpen As Boolean
Dim strStr As String If Not bOpen Then
Screen.MousePointer = vbHourglass
strStr = "set CDAudio door open"
Command1.Caption = "关闭"
Else
Screen.MousePointer = vbHourglass
strStr = "set CDAudio door closed"
Command1.Caption = "打开"
End If Call mciSendString(strStr, vbNull, 127, 0)
Screen.MousePointer = vbDefault
DoEvents
bOpen = Not bOpen
End Sub>>步骤3----编译运行,点击"打开",光驱弹出;点击"关闭",光驱关上.