关于保存网页为 MHTML Document 格式的第三种方式

前两种方式可以参见: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 窗口,但这样对话框窗口也会找不到。

你可能感兴趣的:(Win32API)