看板Programming
标 题Re: [VB6 ] 控制外部程式开启档案的方法?
发信站枫桥驿站 (Sun Jan 31 09:02:02 2010)
转信站ptt!news.ntu!ctu-gate!ctu-peer!news.nctu!news.csie.ncyu!news.cs.nthu!M
※ 引述《[email protected]》之铭言:
> ※ [本文转录自 Visual_Basic 看板]
> 作者: SNG () 看板: Visual_Basic
> 标题: [VB6 ] 控制外部程式开启档案的方法?
> 时间: Sat Jan 30 15:43:08 2010
> 请问版友
> 该如何控制外部程式 开启档案呢?
> (不用shell加参数)
> 例如以 Notepad 为例子
> Private Declare Function GetMenu Lib "user32.dll" (ByVal hWnd As Long) As Long
> Private Declare Function SendMessage Lib "user32.dll" Alias _
> "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
> Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" _
> (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
> Private Declare Function GetMenuItemID Lib "user32.dll" (ByVal hMenu As Long, ByVal nPos As Long) As Long
> Private Declare Function GetSubMenu Lib "user32.dll" (ByVal hMenu As Long, ByVal nPos As Long) As Long
> Private Const WM_COMMAND As Long = &H111
> Private Sub Command1_Click()
> Dim hWnd As Long, hMenu As Long, MenuID As Long
> hWnd = FindWindow(vbNullString, "未命名 - 记事本")
> If hWnd <> 0 Then
> hMenu = GetMenu(hWnd)
> hMenu = GetSubMenu(hMenu, 0)
> MenuID = GetMenuItemID(hMenu, 1)
> SendMessage hWnd, WM_COMMAND, MenuID, ByVal 0
> Else
> Shell "notepad", vbNormalFocus
> End If
> End Sub
> 目前遇到的问题是有成功呼叫出 开启旧档的对话视窗 (CommonDialog)
> 但是接下来就卡住了,可以请版友提供一下建议吗?
重点:
1. 将 SendMessage() 改成 PostMessage(). (Windows API)
2. 加 SendKeys 在 PostMessage()後: (VB指令)
SendKeys "C:\WINDOWS\FAQ.TXT" + vbCr, True
语法: SendKeys 讯息文字, 等候回应 (请查VB线上说明)
说明:
SendMessage() 是同步的. 会等到整个动作完成才回来.
开启旧档的功能表动作一直到「对话盒」关闭才算完成, 所以你会卡
在那里.(由於对话盒没有获得新的输入指令, 一直在哪里等. 你必须
手动关掉对话盒, 程式才会返回.)
你的原意是要继续自动的指定档名, 所以不能使用同步的SendMessage(),
因为档名还未指定.(新的讯息)
PostMessage() 是非同步的. 送完立刻回来. 不会等整个动作完成.
因此API 送完功能表执行指令後, 你可以继续再传送新的指令给已打
开的「对话盒」.
第二行 SendKeys() (VB指令) 就是送新的讯息给「对话盒」. 指定
开启的档名. vbCr 是代替你按 Enter (Return) 键. 结果就是出现
开启的资料, 在你的程式执行完後.
注意! VB指令的SendKeys(), 其传送对象是「现行活动的视窗」. 所
以当你以讯息触发笔记本的开启旧档功能表後, 对话盒自动成为活动
视窗. 因此SendKeys()才会找对对象.
如果你的SendKeys()没有正确结果. 要注意的是「开启旧档对话盒」
是否在SendKeys()前已正确开启.
因为执行需要时间. PostMessage() 不会等功能表完成动作才返回,
所以有时候系统太忙, 来不及开对话盒而你的程式早就跑到下一行执
行了, 所以SendKeys()可能会失败.
最简单的指令就是前面标题的「重点」所言. 但是更稳定的控制, 你
要侦测动作是否完成. 使用底下的两种型式来改进:
1. 加Sleep (Windows API)暂停你的VB指令, 等对方完成动作.
Sleep 1500 '傻等1.5秒 (一个够长的时间) 不一定有效或有效率.
SendKeys ...
2. 使用FindWindow() 看看是否视窗已打开. 否则继续睡觉.
cnt = 0
Do until FindWindow(vbNullString, "开启旧档") <> 0
Sleep 100 '每次小睡0.1秒.
cnt = cnt + 1: If cnt = 100 Then Exit Do '避免死当. 等10秒
Loop
'* 未逾时则执行.
If cnt < 100 Then SendKeys "C:\WINDOWS\FAQ.TXT" + vbCr, True
宣告: PostMessage() 和 SendMessage() 只差名称四个字, 其它参数一样.
Private Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" _
(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
注: FindWindow()找 "开启旧档" 还是有不稳定的情况在, 很可能多工状态出
现两个对话框. 最常见的巧合就是你的自动程式背景跑, 你在前景使用笔
记本. 正好程式跑到开笔记本, 而你也打开对话框. 所以傻瓜程式分不出
是哪一个, 因此先後程序错乱产生异常.
请注意这点, 不要用在关键任务中, 虽然机率很小, 但是系统很忙时, 间
隙会变得比你想的还要来得大! 请研究清楚再用.
「绝对不能错」的任务就是「绝对」不能错! 你不会希望军舰因为当机而
被拖回港.
Tommy 99/01/31
[B75628A1:Tom]
--
▄ ◢ ▄▄▄ ▄▄▄ ▄ ▄▄▄
清大资工
█ █◣◢█ █▄█ █▄█ █ █▄▄ tommy 从 61.229.168.125
█ █◥◤█ █ █ █ █▄▄ █▄▄
【枫桥驿站】 telnet://imaple.tw