前两种方式可以参见:http://dkfdtf.blogbus.com/logs/20284731.html
当我们用 InternetExplorer 或 WebBrowse 对象来保存网页为 mht 格式的本地文件时, 对话框是一定会出现的,不管你如何设置 ExecWB 的第二个参数。但我们可以用程序来模拟用户按键,这样就可以不需要用户的参与了。
问题是 vfp 只能以单线程的方式来运行,而弹出的对话框是个模式对话框,所以你即使想用计时器来异步探测出这个模式窗口也是不可能的,因为他们同处一个进程中的主线程内,模式窗口会暂停计时器的运行。
这样一来我们只有两种方案可选择,一种是做成一个外部 COM 组件,vfp 支持它按多线程来运行;另一种方式就是执行两个进程,其中一个启动 InternetExplorer 并执行保存的动作,另一个则监视模式对话框窗口的出现,一旦发现即执行模拟用户按键的操作。
下面是第二种方案的代码:
1. 先创建一个用来启动 IE 并执行保存操作的 exe 文件创建一个名为 gotourl 的新项目,其中只包含一个 prg 主文件,内容如下:
LPARAMETERS tcUrl && 用来接收要打开的网页地址
_Screen.Visible = .F.
m.oe = NEWOBJECT( 'InternetExplorer.Application' )
m.oe.Navigate( m.tcUrl )
m.oe.Visible = .T.
WAIT WINDOW '' TIMEOUT 2
m.oe.ExecWB( 4, 1, 'c:/aaa.mht' )
然后编译并生成一个名为 gotourl.exe 的文件。
2. 接下来创建一个测试程序,代码如下:
DECLARE Long FindWindowEx IN WIN32API ;
Long hwndParent, Long hwndChildAfter, ;
String lpszClass, String lpszTitle
DECLARE Long Sleep IN WIN32API ;
Long dwMilliseconds
DECLARE Long GetWindowThreadProcessId IN WIN32API ;
Long hWnd, Long @ lpdwProcessId
DECLARE Long AttachThreadInput IN WIN32API ;
Long idAttach, Long idAttachTo, Long fAttach
DECLARE Long keybd_event IN WIN32API ;
Long bVk, Long bScan, Long dwFlags, Long dwExtraInfo
m.cSrc = 'http://www.microsoft.com'
m.cFile = 'c:/ms.mht'
*|* 启动第二个进程( gotourl.exe )并导航到指定的网站
m.cmd = 'gotourl ' + m.cSrc
RUN/N &cmd.
*|* 继续当前进程的运行
*|* 等待模式对话框的出现,并设置 15 秒的超时等待值
m.hWnd = 0
m.nTimeout = SECONDS() + 15
DO WHILE ( 0 == m.hWnd ) AND ( SECONDS() < m.nTimeout )
m.hWnd = FindWindowEx( 0, 0, '#32770', '保存网页' )
Sleep( 100 )
ENDDO
IF ( 0 == m.hWnd )
MESSAGEBOX( '保存网页超时。', 16, '错误' )
ELSE
*|* 找到了另一进程执行 ExecWB 方法产生的模式对话框句柄
ERASE ( m.cFile )
*|* 先获取该对话框窗口的主线程 id,然后将当前线程的输入队列附着到其中
m.hThread = GetWindowThreadProcessId( m.hWnd, 0 )
AttachThreadInput( Application.ThreadId, m.hThread, 1 )
*|* 模拟用户按键:复制要保存的文件路径及名称(ctrl+v),按下保存按钮( alt+s)
_CLIPTEXT = m.cFile
keybd_event( 0x11, 0, 0, 0 ) && Ctrl
keybd_event( 0x56, 0, 0, 0 ) && V
keybd_event( 0x56, 0, 2, 0 )
keybd_event( 0x11, 0, 2, 0 )
keybd_event( 0x12, 0, 0, 0 ) && ALT
keybd_event( 0x53, 0, 0, 0 ) && S
keybd_event( 0x53, 0, 2, 0 )
keybd_event( 0x12, 0, 2, 0 )
*|* 输入队列重新指回当前进程的主线程
AttachThreadInput( Application.ThreadId, m.hThread, 0 )
ENDIF
运行一下看看,C 盘根目录下是否存在这个 mht 文件? 这里不爽的是 ie 和保存对话框窗口还是会出现。如果在 gotourl 中设置 Visible = .F. 虽然可以隐藏 IE 窗口,但这样对话框窗口也会找不到。