lynfr8 发表于 2010-7-6 16:37:38

内嵌IE不弹出新窗口[新成果+讨论]

目前内嵌IE“target=_blank”类型的链接直接点击会跳出Gui的问题尚未得到有效解决
论坛也有几位坛友提出讨论过,也有一定的进展:
传送门:
http://www.autoitx.com/thread-16652-1-3.html
AU3浏览器- 如何不弹出IE窗口-简单试例
http://www.autoitx.com/forum.php?mod=viewthread&tid=14316&sid=VzAdte
触摸屏浏览器!GUI内嵌IE的几个问题
http://www.autoitx.com/forum.php?mod=viewthread&tid=8144&highlight=%C4%DA%C7%B6
点击内嵌IE的链接后,如何指定一定还要在内嵌IE里来打开这个新页面

翻看了一下帮助文件-AutoIt COM 扩展
其中 IE COM 事件有一个例子[附件下载]


我修改了一下如下:
#include "GUIConstantsEx.au3"
#include <IE.au3>
Dim $Text,$EventName, $Text2
$GUIMain=GUICreate            ( "Event Test",       1000,800 )
$GUIEdit=GUICtrlCreateEdit      ( "Test Log:" & @CRLF,10, 20, 980, 400)
$GUIProg=GUICtrlCreateProgress(                     10,5, 580,10)
GUISetState ()
$oIE = _IECreateEmbedded ()
GUICtrlCreateObj($oIE,0, 421, 980, 350)
$EventObject=ObjEvent($oIE,"IEEvent_","DWebBrowserEvents")
if @error then
   Msgbox(0,"AutoIt COM Test", _
    "ObjEvent: Can't use event interface 'DWebBrowserEvents'. Error code: " & hex(@error,8))
   exit
endif
$URL = "http://www.google.com.hk/"
$oIE.Navigate( $URL )         
sleep(1000)            
GUISwitch ( $GUIMain )
While 1
   $msg = GUIGetMsg()
   If $msg = $GUI_EVENT_CLOSEThen ExitLoop
Wend
$EventObject.Stop   ; 不再接收事件
$EventObject=0      ; 关闭Event Object
$oIE=0            ; 清除内存
GUIDelete ()      
Exit            
Func IEEvent_BeforeNavigate($URL, $Flags, $TargetFrameName, $PostData, $Headers, $Cancel)
    GUICtrlSetData ( $GUIEdit, "BeforeNavigate: " & $URL & " Flags: " & $Flags & " tgframe: " & $TargetFrameName & " Postdat: " & $PostData & " Hdrs: " & $Headers & " canc: " & $Cancel& @CRLF, "append" )
EndFunc
Func IEEvent_ProgressChange($Progress,$ProgressMax)
    If $ProgressMax > 0 Then
      GUICtrlSetData($GUIProg, ($Progress * 100) / $ProgressMax )
    EndIf
EndFunc
Func IEEvent_StatusTextChange($Text)
    GUICtrlSetData ( $GUIEdit, "IE Status text changed to: " & $Text & @CRLF, "append" )
If $Text<>'' Then $Text2=$Text
      If $EventName ='NewWindow' And $Text<>'' Then
$oIE.Navigate( $Text2 )
EndIf
EndFunc
Func IEEvent_PropertyChange( $szProperty)
    GUICtrlSetData ( $GUIEdit, "IE Changed the value of the property: " & $szProperty & @CRLF, "append" )
EndFunc
Func IEEvent_DownloadComplete()
    GUICtrlSetData ( $GUIEdit, "IE has finished a navigation operation" & @CRLF, "append" )
EndFunc
Func IEEvent_NavigateComplete($URL)
    GUICtrlSetData ( $GUIEdit, "IE has finished loading URL: " & $URL & @CRLF, "append" )
EndFunc
Func IEEvent_($EventName)
    GUICtrlSetData ( $GUIEdit, "Uncatched event: " & $EventName & @CRLF, "append" )
    If $EventName ='NewWindow'Then;如果发现有IE新窗口生成
WinKill("");将IE弹出激活的新窗口关闭
$oIE.Navigate( $Text2 );然后在Gui激活捕捉到状态栏显示的最后链接
EndIf
EndFunc



关键是修改了Func IEEvent_($EventName)这一部分
这样虽然可以在GUi打开弹出的新IE窗口链接,
虽然不完美:弹窗还会一闪而过
但总算向完美又迈进了一小步
在这里,如果有比较熟悉IE event或对此问题有兴趣的朋友,不妨跟帖讨论下,有价值的回帖一律重重加分!

lanfengc 发表于 2010-7-6 23:49:48

#include "GUIConstantsEx.au3"
#include <IE.au3>
#include <Misc.au3>
Dim $Text,$Text2="",$URL = "http://www.baidu.com/"
$dll = DllOpen("user32.dll")
$GUIMain=GUICreate            ( "Event Test",       800,600 )
$GUIEdit=GUICtrlCreateEdit      ( "Test Log:" & @CRLF,10, 20, 780, 270)
$StateLab = GUICtrlCreateLabel("Label1", 8, 288, 780, 17)
GUISetState ()
$oIE = _IECreateEmbedded ()
GUICtrlCreateObj($oIE,8, 320, 780, 320)
$EventObject=ObjEvent($oIE,"IEEvent_","DWebBrowserEvents")
if @error then exit Msgbox(0,"错误!","不可使用COM接口 'DWebBrowserEvents'. 错误代码: " & hex(@error,8))
$Timer = DllCallbackRegister("Timer", "int", "hwnd;uint;uint;dword")
$TimerDLL = DllCall($dll, "uint", "SetTimer", "hwnd", 0, "uint", 0, "int", 10, "ptr", DllCallbackGetPtr($Timer))
$oIE.Navigate( $URL )         
sleep(1000)            
GUISwitch ( $GUIMain )
While 1
    $msg = GUIGetMsg()
        If $msg = $GUI_EVENT_CLOSEThen
                $EventObject.Stop   ; 不再接收事件
                $EventObject=0      ; 关闭Event Object
                $oIE=0            ; 清除内存
                GUIDelete ()
                DllCall($dll, "int", "KillTimer", "hwnd", 0, "uint", $TimerDLL)
                DllCallbackFree($Timer)
                DllClose($dll)
                Exit
        EndIf
        ;这里你可以自己检测鼠标点击的是什么控件,按你的要求做相应的响应。
           If _IsPressed("1", $dll) And WinActive($GUIMain) Then
                ;我测试用延迟不管用。必须用MSGBOX断下程序执行。然后才能正常。
      MsgBox(0,"提示", "End Key Pressed",10)
                If $Text2<>"" Then $oIE.Navigate( $Text2 )   
        EndIf
Wend
;其实例子中那么多函数,真正要用到的只有这个。
Func IEEvent_StatusTextChange($Text)
    If $Text<>'' Then GUICtrlSetData ( $GUIEdit, "IE Status text changed to: " & $Text & @CRLF, "append" )
        If $Text<>'' And StringLeft($Text,4)="http" Then $Text2=$Text
        GUICtrlSetData($StateLab,$Text)
EndFunc
Func Timer($hWnd, $uiMsg, $idEvent, $dwTime)
        If WinExists("提示") Then
                WinMove("提示","",@DesktopWidth,@DesktopHeight,0,0,1)
                Send("{Enter}")
        EndIf
EndFunc
完美解决。

lanfengc 发表于 2010-7-6 23:50:47

用到了一个定时器模拟多线程的函数来检测弹出对话框 并将其移走 点确定。

lynfr8 发表于 2010-7-7 00:17:49

用到了一个定时器模拟多线程的函数来检测弹出对话框 并将其移走 点确定。
lanfengc 发表于 2010-7-6 23:50 http://www.autoitx.com/images/common/back.gif


已经非常好了
如果能解决一闪而过的msgbox就更完美了!

lynfr8 发表于 2010-7-7 00:24:11

有一个方法可以解决恼人的msgbox
看代码32-34这几句:#include "GUIConstantsEx.au3"
#include <IE.au3>
#include <Misc.au3>
Dim $Text,$Text2="",$URL = "http://www.google.com.hk/"
$dll = DllOpen("user32.dll")
$GUIMain=GUICreate            ( "Event Test",       800,600 )
$GUIEdit=GUICtrlCreateEdit      ( "Test Log:" & @CRLF,10, 20, 780, 270)
$StateLab = GUICtrlCreateLabel("Label1", 8, 288, 780, 17)
GUISetState ()
$oIE = _IECreateEmbedded ()
GUICtrlCreateObj($oIE,8, 320, 780, 320)
$EventObject=ObjEvent($oIE,"IEEvent_","DWebBrowserEvents")
if @error then exit Msgbox(0,"错误!","不可使用COM接口 'DWebBrowserEvents'. 错误代码: " & hex(@error,8))
$Timer = DllCallbackRegister("Timer", "int", "hwnd;uint;uint;dword")
$TimerDLL = DllCall($dll, "uint", "SetTimer", "hwnd", 0, "uint", 0, "int", 10, "ptr", DllCallbackGetPtr($Timer))
$oIE.Navigate( $URL )         
sleep(1000)            
GUISwitch ( $GUIMain )
While 1
    $msg = GUIGetMsg()
      If $msg = $GUI_EVENT_CLOSEThen
                $EventObject.Stop   ; 不再接收事件
                $EventObject=0      ; 关闭Event Object
                $oIE=0            ; 清除内存
                GUIDelete ()
                DllCall($dll, "int", "KillTimer", "hwnd", 0, "uint", $TimerDLL)
                DllCallbackFree($Timer)
                DllClose($dll)
                Exit
      EndIf
         If _IsPressed("1", $dll) And WinActive($GUIMain) Then
                WinSetOnTop("Event Test", "", 1);设置置顶
      MsgBox(0,"提示", "End Key Pressed",-1000);这样弹出的MsgBox就看不见了,呵呵
                WinSetOnTop("Event Test", "", 0);解除置顶
                If $Text2<>"" Then $oIE.Navigate( $Text2 )   
      EndIf
Wend
Func IEEvent_StatusTextChange($Text)
    If $Text<>'' Then GUICtrlSetData ( $GUIEdit, "IE Status text changed to: " & $Text & @CRLF, "append" )
      If $Text<>'' And StringLeft($Text,4)="http" Then $Text2=$Text
      GUICtrlSetData($StateLab,$Text)
EndFunc
Func Timer($hWnd, $uiMsg, $idEvent, $dwTime)
      If WinExists("提示") Then
                WinMove("提示","",@DesktopWidth,@DesktopHeight,0,0,1)
                Send("{Enter}")
      EndIf
EndFunc不过问题还是存在:msgbox在任务栏还是会一闪而过
依然不够完美

lanfengc 发表于 2010-7-7 08:55:40

一会上班了测试下用SOUNDPLAY或者INETGET这样 的语句让程序等待返回试试。 或者RUNWAIT。

lanfengc 发表于 2010-7-7 08:58:05

对了。另外还有个问题。 。昨天发过帖子后发现的。 不管在IE控件内点什么位置,包括输入框,都会重载页面, 我的想法是检测鼠标指针图标的ID, 判断为手形状才执行IE.NAVIGATE操作。

jhun 发表于 2010-7-7 08:59:44

庸手一个,可耻的坐等成果

newuser 发表于 2010-7-7 09:04:27

回复 2# lanfengc
能给出只显示下半部分窗口的代码吗?就是GUI内嵌网页而不至于点击某连接转到浏览器上去!

lanfengc 发表于 2010-7-7 10:10:13

你说的问题和我自己遇到的问题已解决。 可是又出来个问题。IEEvent_StatusTextChange这个函数对中文支持不好。 链接中含有中文就会出现乱码。我测试的环境是windows 2003 企业版#include "GUIConstantsEx.au3"
#include <IE.au3>
#include <Misc.au3>
#include <WinAPI.au3>
Global Const $HandCursorID=0X0001001F
Dim $Text,$Text2="",$URL = "http://www.baidu.com/"
$dll = DllOpen("user32.dll")
$GUIMain=GUICreate            ( "Event Test",       800,600 )
$GUIEdit=GUICtrlCreateEdit      ( "Test Log:" & @CRLF,10, 20, 780, 270)
$StateLab = GUICtrlCreateLabel("Label1", 8, 288, 780, 17)
GUISetState ()
$oIE = _IECreateEmbedded ()
GUICtrlCreateObj($oIE,8, 320, 780, 320)
$EventObject=ObjEvent($oIE,"IEEvent_","DWebBrowserEvents")
if @error then exit Msgbox(0,"错误!","不可使用COM接口 'DWebBrowserEvents'. 错误代码: " & hex(@error,8))
$Timer = DllCallbackRegister("Timer", "int", "hwnd;uint;uint;dword")
$TimerDLL = DllCall($dll, "uint", "SetTimer", "hwnd", 0, "uint", 0, "int", 100, "ptr", DllCallbackGetPtr($Timer))
$oIE.Navigate( $URL )         
sleep(1000)            
GUISwitch ( $GUIMain )
While 1
    $msg = GUIGetMsg()
        If $msg = $GUI_EVENT_CLOSEThen
                $EventObject.Stop   ; 不再接收事件
                $EventObject=0      ; 关闭Event Object
                $oIE=0            ; 清除内存
                GUIDelete ()
                DllCall($dll, "int", "KillTimer", "hwnd", 0, "uint", $TimerDLL)
                DllCallbackFree($Timer)
                DllClose($dll)
                Exit
        EndIf
        ;这里你可以自己检测鼠标点击的是什么控件,按你的要求做相应的响应。
        $cursor = _WinAPI_GetCursorInfo()
        If $cursor=False Then Exit MsgBox(16,"错误!","获取鼠标信息失败!")
        If $cursor=$HandCursorID Then
                If _IsPressed("1", $dll) And WinActive($GUIMain) Then       
                        ;我测试用延迟不管用。必须用MSGBOX断下程序执行。然后才能正常。
                        WinSetOnTop($GUIMain,"",1)
                        MsgBox(0,"IE内嵌不新建IE窗口", "0",1,WinGetHandle("Program Manager"))
                        WinSetOnTop($GUIMain,"",0)
                        If $Text2<>""Then $oIE.Navigate( $Text2 )   
                EndIf
        EndIf
Wend
;其实例子中那么多函数,真正要用到的只有这个。
Func IEEvent_StatusTextChange($Text)
    If $Text<>'' And $Text<>'完成' And $Text<>'完毕' Then GUICtrlSetData ( $GUIEdit, "IE Status text changed to: " & $Text & @CRLF, "append" )
      If $Text<>'' And StringLeft($Text,4)="http" Then $Text2=$Text
      GUICtrlSetData($StateLab,$Text)
EndFunc
Func Timer($hWnd, $uiMsg, $idEvent, $dwTime)
        If WinExists("IE内嵌不新建IE窗口") Then
                WinMove("IE内嵌不新建IE窗口","",@DesktopWidth,@DesktopHeight,0,0,1)
                Send("{Enter}")
        EndIf
EndFunc

lanfengc 发表于 2010-7-7 10:13:16

主要是用了_WinAPI_GetCursorInfo() 获取鼠标信息,检测鼠标指针ID为手形才执行检测点击链接操作。 另外,MSGBOX可以通过设置它的父窗口句柄为桌面句柄,任务栏就不会出现一闪而过的窗口了。 代码为MsgBox(0,"IE内嵌不新建IE窗口", "0",1,WinGetHandle("Program Manager")),这个对话框的标题尽量设置的复杂点,防止定时器检测的时候把别的窗口也检测到了,一直对别的窗口发按键。

woeiwoei 发表于 2010-7-7 10:30:45

回复 9# newuser


    代码就在那放着呢。。自己改了 才有意义呀。。

woeiwoei 发表于 2010-7-7 10:32:42

有一个方法可以解决恼人的msgbox
看代码32-34这几句:不过问题还是存在:msgbox在任务栏还是会一闪而过
依 ...
lynfr8 发表于 2010-7-7 00:24 http://www.autoitx.com/images/common/back.gif


    如何关闭里边的网页呢??关闭 不是从新打开。。 about:blank

newuser 发表于 2010-7-7 14:04:39

本帖最后由 newuser 于 2010-7-7 14:18 编辑

回复 12# woeiwoei
这是我的理解,但还是不懂,我想把EDIT控件给屏蔽了不就看不到EVENT LOG了吗?但该怎么做呢?确实水平有限,他里面的2个函数我都没看懂,能在帮助把该代码的编写思路给理清一下吗?#include "GUIConstantsEx.au3"
#include "GUIConstantsEx.au3"
#include <IE.au3>
#include <Misc.au3>
#include <WinAPI.au3>
Global Const $HandCursorID=0X0001001F
Dim $Text,$Text2="",$URL = "http://www.baidu.com/"
$dll = DllOpen("user32.dll");打开指定的DLL文件以供DllCall()函数调用
$GUIMain=GUICreate            ( "Event Test",       800,600 );创建主窗口
$GUIEdit=GUICtrlCreateEdit      ( "Test Log:" & @CRLF,10, 20, 780, 270);在主窗口上创建一个Edit控件
;这个Edit控件应该是显示事件的日志信息
$StateLab = GUICtrlCreateLabel("Label1", 8, 288, 780, 17) ;在主窗口上创建一个静态标签控件
;这个标签难道是:当鼠标在不同的连接地址移动时,获得连接地址上的文字?
GUISetState () ;显示当前窗口
$oIE = _IECreateEmbedded ();创建一个适合于内嵌在AU3的图形化界面的浏览器对象,该图形化界面必须是由GUICtrlCreateObj()建立
GUICtrlCreateObj($oIE,8, 320, 780, 320) ;创建适合浏览器对象内嵌的图形化界面
$EventObject=ObjEvent($oIE,"IEEvent_","DWebBrowserEvents") ;包含一个已经得到的对象(object)的事件句柄
;IEEvent函数前缀,用来处理收到的事件
;DWebBrowserEvents 接口名称
if @error then exit Msgbox(0,"错误!","不可使用COM接口 'DWebBrowserEvents'. 错误代码: " & hex(@error,8))
$Timer = DllCallbackRegister("Timer", "int", "hwnd;uint;uint;dword")
;DllCallbackRegister() 创建一个用户自定义的回调函数
;语法:DllCallbackRegister ( "函数名", "返回类型", "参数" )
$TimerDLL = DllCall($dll, "uint", "SetTimer", "hwnd", 0, "uint", 0, "int", 100, "ptr", DllCallbackGetPtr($Timer))
;DllCall() 调用指定Dll文件里面的函数
;语法 :DllCall ( "dll", "返回值类型", "函数名称" [, "类型1", 参数1[, "类型n", 参数n]] )
;DllCallbackGetPtr($Timer) 返回回调函数的指针,可以用于传递给一个WIN32 API
$oIE.Navigate( $URL ) ;打开指定连接地址         
sleep(1000)            
GUISwitch ( $GUIMain );切换用于GUI函数“当前”的窗口
While 1
    $msg = GUIGetMsg()
      If $msg = $GUI_EVENT_CLOSEThen
                $EventObject.Stop   ; 不再接收事件
                $EventObject=0      ; 关闭Event Object
                $oIE=0            ; 清除内存
                GUIDelete ()
                DllCall($dll, "int", "KillTimer", "hwnd", 0, "uint", $TimerDLL)
                DllCallbackFree($Timer) ;清除先前由DllCallbackRegister()创建的句柄
                DllClose($dll) ;将先前打开的User32.dll文件关闭
                Exit
      EndIf
      ;这里你可以自己检测鼠标点击的是什么控件,按你的要求做相应的响应。
      $cursor = _WinAPI_GetCursorInfo()
      If $cursor=False Then Exit MsgBox(16,"错误!","获取鼠标信息失败!")
      If $cursor=$HandCursorID Then
                If _IsPressed("1", $dll) And WinActive($GUIMain) Then      
                        ;_IsPressed("1", $dll) 检查按键是否被按下,1表示按下,反之0。
                                                ;我测试用延迟不管用。必须用MSGBOX断下程序执行。然后才能正常。
                        WinSetOnTop($GUIMain,"",1)
                                                ;设定指定窗口总是在顶层,1表示在顶层
                                                ;语法:WinSetOnTop ( "窗口标题", "窗口文本", 标志 )
                        MsgBox(0,"IE内嵌不新建IE窗口", "0",1,WinGetHandle("Program Manager"))
                        WinSetOnTop($GUIMain,"",0)
                        If $Text2<>""Then $oIE.Navigate( $Text2 )   
                EndIf
      EndIf
Wend
;其实例子中那么多函数,真正要用到的只有这个。
Func IEEvent_StatusTextChange($Text)
    If $Text<>'' And $Text<>'完成' And $Text<>'完毕' Then GUICtrlSetData ( $GUIEdit, "IE Status text changed to: " & $Text & @CRLF, "append" )
      If $Text<>'' And StringLeft($Text,4)="http" Then $Text2=$Text
      GUICtrlSetData($StateLab,$Text)
EndFunc
Func Timer($hWnd, $uiMsg, $idEvent, $dwTime)
      If WinExists("IE内嵌不新建IE窗口") Then
                WinMove("IE内嵌不新建IE窗口","",@DesktopWidth,@DesktopHeight,0,0,1)
                Send("{Enter}")
      EndIf
EndFunc

C.L 发表于 2010-7-7 15:23:30

非常不错,学习了
页: [1] 2 3
查看完整版本: 内嵌IE不弹出新窗口[新成果+讨论]