Jump to content

IE intercepting Ctrl+F find function or invoking Find via GUI


Go to solution Solved by mpower,

Recommended Posts

I'm trying to intercept the Ctrl+F function in IE so that I can achieve a similar effect of words being highlighted via the input on my gui. To explain better here is my code.

What I want is to basically be able to type stuff into the input box that follows the label "Quick find:" and for any data that partially matches input  on the displayed html page to be highlighted as if I was using Ctrl+F search in IE. You can see the behaviour of Ctrl+F highlight by clicking into the IE object and then pressing Ctrl+F. I would also like for it to auto-scroll to the *best* match data. Essentially same as Ctrl+F in IE.

Place all attachments - the tow PNG files and the HTML file in script folder to get the full effect.

DaleHohm, DaleHohm, DaleHohm,  <---- just trying to summon user DaleHohm who seems to have very good knowledge of IE :P

#include-once
#NoTrayIcon
#AutoIt3Wrapper_Outfile=Example.exe
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_UseX64=n
#include <GDIPlus.au3>
#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <WinAPIEx.au3>
#include <IE.au3>

Global $bAero, $hidden = False, $tuck = False, $tucked = False, $untucked = False, $tucking = False, $untucking = False, $timer = 0, $tdiff = 0, _
$LAYERED_GUI = $WS_EX_LAYERED, $hGUI_child, $hGUI_height = 683
Global Const $hDwmApiDll = DllOpen("dwmapi.dll"), $sChkAero = DllStructCreate("int;")
DllCall($hDwmApiDll, "int", "DwmIsCompositionEnabled", "ptr", DllStructGetPtr($sChkAero))
$bAero = DllStructGetData($sChkAero, 1)
If Not $bAero Then
    $LAYERED_GUI = 0
    $hGUI_height = $hGUI_height - 20
EndIf

$hGUI = GUICreate("", 715, $hGUI_height, -1, 0, $WS_POPUP, $LAYERED_GUI + $WS_EX_TOPMOST, WinGetHandle(AutoItWinGetTitle()))
$hIcon = _WinAPI_GetClassLongEx($hGUI, $GCL_HICON)
_WinAPI_DestroyIcon($hIcon)
_WinAPI_SetClassLongEx($hGUI, $GCL_HICON, 0)
_WinAPI_SetClassLongEx($hGUI, $GCL_HICONSM, 0)

If $bAero Then
    $hGUI_child = GUICreate("", 715-39, 683 - 26, 22,  3, $WS_POPUP, $WS_EX_MDICHILD + $WS_EX_TOPMOST, $hGUI)
    $hGUI_Font = $hGUI_child
Else
    $hGUI_Font = $hGUI
    $hGUI_child = $hGUI
EndIf
GUISetBkColor(0xFFFFFF)
GUISetFont(18, 100, Default, 'Segoe UI', $hGUI_Font, 5)
GUICtrlCreateLabel('Quick find:', 10, 25)
GUICtrlCreateInput('', 150, 20, 100, 35)
$oIE = _IECreateEmbedded()
$oIEobj = GUICtrlCreateObj($oIE, 10, 85, 650, 550)
$oNav = _IENavigate($oIE, @ScriptDir & '/example.html', 0)

$hGUI_child2 = GUICreate("", 112, 50, 280, 645, $WS_POPUP, $LAYERED_GUI + $WS_EX_MDICHILD + $WS_EX_TOPMOST, $hGUI_child)
If Not $bAero Then
    GUISetBkColor(0xE0F2F7)
    $hGUI_Font = $hGUI_child2
    GUISetFont(33, 100, Default, 'Segoe UI', $hGUI_Font, 5)
    GUICtrlCreateLabel(" = ", 0, 0, 112, 50, $SS_CENTER + $SS_CENTERIMAGE)
EndIf
GUISetCursor(0, 1, $hGUI_child2)

If $bAero Then
    _GDIPlus_Startup()
    $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\panel.png')
    SetBitmap($hGUI, $hImage)
    $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\roundbn.png')
    SetBitmap($hGUI_child2, $hImage)
    _GDIPlus_Shutdown()
EndIf


GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")
GUISetState(@SW_SHOW, $hGUI)
If $bAero Then GUISetState(@SW_SHOW, $hGUI_child)
GUISetState(@SW_SHOW, $hGUI_child2)

While 1
    $mPos = MouseGetPos()
    If BitAnd($hidden, $mPos[1] = 0, $timer = 0) Then
        $timer = TimerInit()
        Sleep(10)
    ElseIf $mPos[1] <> 0 Then
        $timer = 0
        $tdiff = 0
    EndIf
    If $timer <> 0 Then $tdiff = TimerDiff($timer)
    If BitAND($hidden, Not $tucked, $mPos[1] <> 0, Not $tucking) Then
        $tuck = True
        $untucking = False
        $tucking = True
        AdlibRegister("TuckAway", 2500)
    ElseIf BitAND($hidden, $tucked, $mPos[1] = 0, Not $untucking, $tdiff > 450) Then
        $tuck = False
        $tucking = False
        $untucking = True
        AdlibRegister("TuckAway")
    ElseIf BitAND($hidden, Not $tucked, $mPos[1] = 0, $tucking) Then
        AdlibUnRegister("TuckAway")
        $tuck = False
        $tucking = False
    EndIf
    $msg = GUIGetMsg(1)
    Switch $msg[1]
        Case $hGUI
            Switch $msg[0]
                Case $GUI_EVENT_CLOSE, $GUI_EVENT_SECONDARYUP
                    Exit
            EndSwitch
        Case $hGUI_child
            Switch $msg[0]
                Case $GUI_EVENT_CLOSE, $GUI_EVENT_SECONDARYUP
                    Exit
            EndSwitch
        Case $hGUI_child2
            Switch $msg[0]
                Case $GUI_EVENT_PRIMARYDOWN
                    If Not $hidden Then
                        HidePanel()
                    Else
                        HidePanel(False)
                    EndIf
            EndSwitch
    EndSwitch
WEnd

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    Switch $wParam
        Case 0x00780000
            $oIE.document.parentwindow.scrollBy(0, -150)
        Case 0xFF880000
            $oIE.document.parentwindow.scrollBy(0, 150)
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func HidePanel($hide = True)
    AdlibUnRegister("TuckAway")
    If $hide Then
        $tucked = False
        $untucked = True
        $hidden = True
        For $i = -1 to -663 Step - 1
            WinMove($hGUI, "", Default, $i)
        Next
    Else
        $tucked = False
        $untucked = False
        $hidden = False
        For $i = -664 to -4 Step 1
            WinMove($hGUI, "", Default, $i)
        Next
    EndIf
EndFunc

Func TuckAway()
    If $tuck Then
        $tucking = False
        $untucked = False
        $tucked = True
        For $i = 663 to 695 Step 1
            WinMove($hGUI, "", Default, -$i)
            Sleep(10)
        Next
    Else
        $untucking = False
        $tucked = False
        For $i = 695 to 663 Step - 1
            WinMove($hGUI, "", Default, -$i)
            Sleep(10)
        Next
    EndIf
    AdlibUnRegister("TuckAway")
EndFunc

Func SetBitmap($hGUI, $hImage, $iOpacity = 255)
    Local $hScrDC, $hMemDC, $hBitmap, $hOld, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend
    $hScrDC = _WinAPI_GetDC(0)
    $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC)
    $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    $hOld = _WinAPI_SelectObject($hMemDC, $hBitmap)
    $tSize = DllStructCreate($tagSIZE)
    $pSize = DllStructGetPtr($tSize)
    DllStructSetData($tSize, "X", _GDIPlus_ImageGetWidth($hImage))
    DllStructSetData($tSize, "Y", _GDIPlus_ImageGetHeight($hImage))
    $tSource = DllStructCreate($tagPOINT)
    $pSource = DllStructGetPtr($tSource)
    $tBlend = DllStructCreate($tagBLENDFUNCTION)
    $pBlend = DllStructGetPtr($tBlend)
    DllStructSetData($tBlend, "Alpha", $iOpacity)
    DllStructSetData($tBlend, "Format", 1)
    _WinAPI_UpdateLayeredWindow($hGUI, $hGUI, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA)
    _WinAPI_ReleaseDC(0, $hScrDC)
    _WinAPI_SelectObject($hMemDC, $hOld)
    _WinAPI_DeleteObject($hBitmap)
    _WinAPI_DeleteDC($hMemDC)
EndFunc

post-75824-0-31431000-1426306989_thumb.p

post-75824-0-39860600-1426306990.png

example.html

Edited by mpower
Link to comment
Share on other sites

Okay so what I'm thinking is to have a WM_COMMAND function detect when my input has focus and then it can send Ctrl+F to the embedded IE object. I can then look at hiding IE's "Find" window and send any input from the GUI input to the "Find" window input.

However the problem I have is that I can't seem to Send CTRL+F to the embedded IE object. 

I have searched the forums and found some working code to send keys to an embedded object however I found one peculiarity that ControlSend actions only seem to work if the GUI doesn't have focus.

Here's the example code:

#include <IE.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

$oIE = _IECreateEmbedded()
$hGUI = GUICreate("myWindow", 800, 600, (@DesktopWidth - 640) / 2, (@DesktopHeight - 580) / 2, _
        $WS_OVERLAPPEDWINDOW + $WS_VISIBLE + $WS_CLIPSIBLINGS)
$GUIActiveX = GUICtrlCreateObj($oIE, 0, 0, 800, 600)
GUISetState()

_IENavigate($oIE, "http://www.autoitscript.com/forum/index.php")

$hHandle = ControlGetHandle("", "", "[CLASS:Internet Explorer_Server; INSTANCE:1]")

For $i = 1 To 10

    ConsoleWrite("sending command:" & ControlSend($hHandle, 0, 0, "{DOWN}") & @CRLF)
    Sleep(1000)

Next

Notice that if you click out of the GUI the page scrolls down, however if you activate the GUI it does not. I wonder why...

To see what I mean, run the above script and watch the Console. It should say "sending command:1" meaning that the sending of down key has succeeded. However the page will not be scrolling down.

If, whilst the loop is running, you click outside of the main GUI you will notice that the page will start scrolling. Once the GUI is back in focus however the scrolling stops.

Bizarre.

How does one send keys (e.g. CTRL+F) to an embedded IE object without having to lose GUI focus?

Edited by mpower
Link to comment
Share on other sites

Okay I've totally re-thought the way I am approaching this and realised that I was overcomplicating things.

Instead I am now using standard method .Find to find a match on the page, highlight a match and scroll the document view to the match location.

Now - just have to figure out a way to highlight multiple results!

Here's the code which can do single item searching/highlighting and scrolling to said item:

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

Func WM_COMMAND($hWnd, $msg, $wParam, $lParam)
    Local $iCode = BitShift($wParam, 16)
    Local $nIDFrom = BitAND($wParam, 0xFFFF)

    Switch $hWnd
        Case $hGUI_child
            Switch $nIDFrom
                Case $qsInput
                    Switch $iCode
                        Case $EN_CHANGE
                            _IESearchText($oIE, GUICtrlRead($qsInput))
                    EndSwitch
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func _IESearchText($oIE, $sFindText)
    $oRange = $oIE.document.body.createTextRange()
    If $oRange.FindText($sFindText) Then
        $oRange.Select()
        $oIE.scrollIntoView()
    Else
        $oIE.document.execCommand("Unselect")
    EndIf
EndFunc
Edited by mpower
Link to comment
Share on other sites

  • Solution

Okay I think I'm satisfied with my code now - I can search for a single value but then press Enter to continue search to find the next value. This is good enough for me.

Final sample code for those interested:
 

#include-once
#NoTrayIcon
#AutoIt3Wrapper_Outfile=Example.exe
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_UseX64=n
#include <GDIPlus.au3>
#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <WinAPIEx.au3>
#include <IE.au3>
#include <Array.au3>

Global $bAero, $hidden = False, $tuck = False, $tucked = False, $untucked = False, $tucking = False, $untucking = False, $timer = 0, $tdiff = 0, _
$LAYERED_GUI = $WS_EX_LAYERED, $hGUI_child, $hGUI_height = 683, $find = False, $qsInfocus = False
Global Const $hDwmApiDll = DllOpen("dwmapi.dll"), $sChkAero = DllStructCreate("int;")
DllCall($hDwmApiDll, "int", "DwmIsCompositionEnabled", "ptr", DllStructGetPtr($sChkAero))
$bAero = DllStructGetData($sChkAero, 1)
If Not $bAero Then
    $LAYERED_GUI = 0
    $hGUI_height = $hGUI_height - 20
EndIf

$hGUI = GUICreate("", 715, $hGUI_height, -1, 0, $WS_POPUP, $LAYERED_GUI + $WS_EX_TOPMOST, WinGetHandle(AutoItWinGetTitle()))
$hIcon = _WinAPI_GetClassLongEx($hGUI, $GCL_HICON)
_WinAPI_DestroyIcon($hIcon)
_WinAPI_SetClassLongEx($hGUI, $GCL_HICON, 0)
_WinAPI_SetClassLongEx($hGUI, $GCL_HICONSM, 0)

If $bAero Then
    $hGUI_child = GUICreate("", 715-39, 683 - 26, 22,  3, $WS_POPUP, $WS_EX_MDICHILD + $WS_EX_TOPMOST, $hGUI)
    $hGUI_Font = $hGUI_child
Else
    $hGUI_Font = $hGUI
    $hGUI_child = $hGUI
EndIf
GUISetBkColor(0xFFFFFF)
GUISetFont(18, 100, Default, 'Segoe UI', $hGUI_Font, 5)
$qsLabel = GUICtrlCreateLabel('Quick find:', 10, 25)
$qsInput = GUICtrlCreateInput('', 150, 20, 100, 35)
$oIE = _IECreateEmbedded()
$oIEobj = GUICtrlCreateObj($oIE, 10, 85, 650, 550)
$oNav = _IENavigate($oIE, @ScriptDir & '/contactlist.html', 0)
$hENTER = GUICtrlCreateDummy()
Dim $AccelKeys[1][2]=[["{ENTER}", $hENTER]]
GUISetAccelerators($AccelKeys)

$hGUI_child2 = GUICreate("", 112, 50, 280, 645, $WS_POPUP, $LAYERED_GUI + $WS_EX_MDICHILD + $WS_EX_TOPMOST, $hGUI_child)
If Not $bAero Then
    GUISetBkColor(0xE0F2F7)
    $hGUI_Font = $hGUI_child2
    GUISetFont(33, 100, Default, 'Segoe UI', $hGUI_Font, 5)
    GUICtrlCreateLabel(" = ", 0, 0, 112, 50, $SS_CENTER + $SS_CENTERIMAGE)
EndIf
GUISetCursor(0, 1, $hGUI_child2)

If $bAero Then
    _GDIPlus_Startup()
    $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\panel.png')
    SetBitmap($hGUI, $hImage)
    $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\roundbn.png')
    SetBitmap($hGUI_child2, $hImage)
    _GDIPlus_Shutdown()
EndIf


GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUISetState(@SW_SHOW, $hGUI)
If $bAero Then GUISetState(@SW_SHOW, $hGUI_child)
GUISetState(@SW_SHOW, $hGUI_child2)

While 1
    $mPos = MouseGetPos()
    If BitAnd($hidden, $mPos[1] = 0, $timer = 0) Then
        $timer = TimerInit()
        Sleep(10)
    ElseIf $mPos[1] <> 0 Then
        $timer = 0
        $tdiff = 0
    EndIf
    If $timer <> 0 Then $tdiff = TimerDiff($timer)
    If BitAND($hidden, Not $tucked, $mPos[1] <> 0, Not $tucking) Then
        $tuck = True
        $untucking = False
        $tucking = True
        AdlibRegister("TuckAway", 2500)
    ElseIf BitAND($hidden, $tucked, $mPos[1] = 0, Not $untucking, $tdiff > 450) Then
        $tuck = False
        $tucking = False
        $untucking = True
        AdlibRegister("TuckAway")
    ElseIf BitAND($hidden, Not $tucked, $mPos[1] = 0, $tucking) Then
        AdlibUnRegister("TuckAway")
        $tuck = False
        $tucking = False
    EndIf
    $msg = GUIGetMsg(1)
    Switch $msg[1]
        Case $hGUI
            Switch $msg[0]
                Case $GUI_EVENT_CLOSE, $GUI_EVENT_SECONDARYUP
                    Exit
            EndSwitch
        Case $hGUI_child
            Switch $msg[0]
                Case $GUI_EVENT_CLOSE, $GUI_EVENT_SECONDARYUP
                    Exit
                Case $hENTER
                    If $qsInfocus Then _IESearchText($oIE, GUICtrlRead($qsInput), 1)
            EndSwitch
        Case $hGUI_child2
            Switch $msg[0]
                Case $GUI_EVENT_PRIMARYDOWN
                    If Not $hidden Then
                        HidePanel()
                    Else
                        HidePanel(False)
                    EndIf
            EndSwitch
    EndSwitch
WEnd

Func WM_COMMAND($hWnd, $msg, $wParam, $lParam)
    Local $iCode = BitShift($wParam, 16)
    Local $nIDFrom = BitAND($wParam, 0xFFFF)

    Switch $hWnd
        Case $hGUI_child
            Switch $nIDFrom
                Case $qsInput
                    Switch $iCode
                        Case $EN_CHANGE
                            _IESearchText($oIE, GUICtrlRead($qsInput), 0)
                        Case $EN_SETFOCUS
                            $qsInfocus = True
                        Case $EN_KILLFOCUS
                            $qsInfocus = False
                    EndSwitch
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func _IESearchText($oIE, $sFindText, $fNext = 0)
    $docRange = $oIE.document.body.createTextRange()
    $docRange.execCommand("backColor", false, "#ffffff");
    If $sFindText <> '' Then
        If $fNext = 0 Then
            Global $oRange = $oIE.document.body.createTextRange()
        Else
            $oRange.moveStart("character")
        EndIf
        If $oRange.FindText($sFindText) Then
            $oRange.execCommand("backColor", false, "fdee00");
            $oRange.scrollIntoView()
        Else
            $oRange = $oIE.document.body.createTextRange()
        EndIf
    Else
        $oIE.document.parentwindow.scroll(0)
    EndIf
EndFunc

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    Switch $wParam
        Case 0x00780000
            $oIE.document.parentwindow.scrollBy(0, -150)
        Case 0xFF880000
            $oIE.document.parentwindow.scrollBy(0, 150)
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func HidePanel($hide = True)
    AdlibUnRegister("TuckAway")
    If $hide Then
        $tucked = False
        $untucked = True
        $hidden = True
        For $i = -1 to -663 Step - 1
            WinMove($hGUI, "", Default, $i)
        Next
    Else
        $tucked = False
        $untucked = False
        $hidden = False
        For $i = -664 to -4 Step 1
            WinMove($hGUI, "", Default, $i)
        Next
    EndIf
EndFunc

Func TuckAway()
    If $tuck Then
        $tucking = False
        $untucked = False
        $tucked = True
        For $i = 663 to 695 Step 1
            WinMove($hGUI, "", Default, -$i)
            Sleep(10)
        Next
    Else
        $untucking = False
        $tucked = False
        For $i = 695 to 663 Step - 1
            WinMove($hGUI, "", Default, -$i)
            Sleep(10)
        Next
    EndIf
    AdlibUnRegister("TuckAway")
EndFunc

Func SetBitmap($hGUI, $hImage, $iOpacity = 255)
    Local $hScrDC, $hMemDC, $hBitmap, $hOld, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend
    $hScrDC = _WinAPI_GetDC(0)
    $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC)
    $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    $hOld = _WinAPI_SelectObject($hMemDC, $hBitmap)
    $tSize = DllStructCreate($tagSIZE)
    $pSize = DllStructGetPtr($tSize)
    DllStructSetData($tSize, "X", _GDIPlus_ImageGetWidth($hImage))
    DllStructSetData($tSize, "Y", _GDIPlus_ImageGetHeight($hImage))
    $tSource = DllStructCreate($tagPOINT)
    $pSource = DllStructGetPtr($tSource)
    $tBlend = DllStructCreate($tagBLENDFUNCTION)
    $pBlend = DllStructGetPtr($tBlend)
    DllStructSetData($tBlend, "Alpha", $iOpacity)
    DllStructSetData($tBlend, "Format", 1)
    _WinAPI_UpdateLayeredWindow($hGUI, $hGUI, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA)
    _WinAPI_ReleaseDC(0, $hScrDC)
    _WinAPI_SelectObject($hMemDC, $hOld)
    _WinAPI_DeleteObject($hBitmap)
    _WinAPI_DeleteDC($hMemDC)
EndFunc
Edited by mpower
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...