Jump to content
Sign in to follow this  
Mat

GUIFinder.au3 - V2

Recommended Posts

Mat

My old implementation of a finder control like the one in Au3Info.exe has been pretty popular, so I was having a look to see if it needed any updating... And I want to offer my sincerest apologies to anyone who has used it. The code is so bad I think someone must have hijacked it as surely I can't have been THAT bad. So anyway. Here's how to do it properly.

Reasons why this one is better:

* Found out how to draw the inverted frame like Au3Info does (thanks Jon ;) )

* You can now have as many of them as you want. And they can all have different icons.

* No temporary files for resources, they are loaded straight from the binary.

* There is some code to make sure that you never have frames left behind or not showing. It solves 99% of issues.

* No globals.

* Functions are now properly named.

* My last one returned a dummy which you couldn't use for anything other than events. This one returns a handle

* Doesn't use GUIRegisterMsg, so you can use it with this no problem :)

* ...

The only slight downfall is that, like other UDF controls, GUIGetMsg ignores it. Instead it sends notifications by WM_COMMAND messages (We all know WM_NOTIFY is a bit more work huh?). Right now there are 4, though I can add more easily enough. My favourite example is this:

#include<GUIFinder.au3>

$hGUI = GUICreate("_GUICtrlFinder_GetLastWnd Example", 300, 40)

$hFinder = _GUICtrlFinder_Create($hGUI, 130, 4)

GUISetState()
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

While True
    $iMsg  = GUIGetMsg()
    Switch $iMsg
        Case -3
            ExitLoop
    EndSwitch
WEnd

Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
    Switch _WinAPI_HiWord($wParam)
        Case $FN_WNDCHANGED
            WinSetTitle($hWnd, "", "Handle: " & _GUICtrlFinder_GetLastWnd($lParam))
        Case $FN_STARTUSE
            WinSetTrans($hWnd, "", 150)
        Case $FN_ENDUSE
            WinSetTrans($hWnd, "", 255)
            WinSetTitle($hWnd, "", "_GUICtrlFinder_Create Example")
    EndSwitch
EndFunc   ;==>WM_COMMAND

As you can see, it behaves like a custom control should.

Download

Includes examples + UDF.

For those interested in implementation: It's a custom control, so I register my own window class, which stores information like icons and the last selected window using the "extra" window space, and the GetWindowLongPtr function. Most stuff is handled in the window proc, so GUIRegisterMsg is free for you to use for your own purposes.

Mat

  • Like 2

Share this post


Link to post
Share on other sites
AZJIO

Add color and line thickness in the setting

Global $iPENCOLOR = 0xFF
Global $iPENWIDTH = 2

How do I get the icon was in the tray? I would like to capture that is called from the tray

Share this post


Link to post
Share on other sites
Mat

You could reuse bits of the code, like the handlers for WM_LBUTTONDOWN/UP and WM_MOUSEMOVE and loading resources.

Would be easier to use your own hidden window, and create the tray icon using the winapi, rather than try to use AutoIt's tray item (though it may be possible to use AutoIt's with something like >this). You need a window in order to capture the mouse, I'm not sure if the window has to be visible or not.

I like the idea of doing it directly from the tray though.

Share this post


Link to post
Share on other sites
AZJIO

I want to embed it in >CaptureText to avoid problems on Win7.

Can make the first click activates the cursor, and the second click - let go. To not keep the button pressed.

Share this post


Link to post
Share on other sites
Mat

I'm at work at the moment without AutoIt, and it's a long time since I looked at this code.

What you want should be possible, I'll take a quick look this afternoon when I get home. 

Share this post


Link to post
Share on other sites
czyt

Google code was blocked by GFW.would you please add an attachment?


董小姐,你微笑的时候很美,就像安河桥下,清澈的水...

Share this post


Link to post
Share on other sites
czyt

Thx,Man!

Edited by czyt

董小姐,你微笑的时候很美,就像安河桥下,清澈的水...

Share this post


Link to post
Share on other sites
Mat

This is sort of working. I'm not sure why it's not quite right with the window detection and setting of the cursor. 

#include <WinAPI.au3>
#include <WinAPIShellEx.au3>
#include <APIShellExConstants.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>


Global Const $ICON_ID = 102
Global Const $ICON_MESSAGE = $WM_USER + 1

Global $g__hBackupCursor = 0
Global $g__hLast = 0
Global $g__fIn = False
Global $g__aRect



$hGUI = GUICreate("inactive")
GUISetState()


$idDummy = GUICtrlCreateDummy()



Local $tNID = DllStructCreate($tagNOTIFYICONDATA)

OnAutoItExitRegister('OnAutoItExit')

DllStructSetData($tNID, 'Size', DllStructGetSize($tNID))
DllStructSetData($tNID, 'hWnd', $hGUI)
DllStructSetData($tNID, 'Flags', BitOR($NIF_ICON, $NIF_MESSAGE))

DllStructSetData($tNID, 'CallbackMessage', $ICON_MESSAGE)
DllStructSetData($tNID, 'ID', $ICON_ID)
DllStructSetData($tNID, 'hIcon', __GUICtrlFinder_GetDefaultResources(0))
_WinAPI_ShellNotifyIcon($NIM_ADD, $tNID)

GUIRegisterMsg($ICON_MESSAGE, "IconMessage")
GUIRegisterMsg($WM_MOUSEMOVE, "WinMouseMove")
GUIRegisterMsg($WM_LBUTTONDOWN, "WinLButtonDown")

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch
WEnd


Func WinLButtonDown($hWnd, $iMsg, $wParam, $lParam)
    Local $hLast

    If _TrayFinder_IsFinding($hWnd) Then
        _WinAPI_ReleaseCapture()
        _WinAPI_SetCursor($g__hBackupCursor)

        $hLast = $g__hLast
        If $hLast <> 0 And IsArray($g__aRect) Then
            If $g__fIn Then _WinAPI_PostMessage($hWnd, $iMsg, $wParam, $lParam)


            DllStructSetData($tNID, 'Flags', $NIF_ICON)
            DllStructSetData($tNID, 'hIcon', __GUICtrlFinder_GetDefaultResources(0))
            _WinAPI_ShellNotifyIcon($NIM_MODIFY, $tNID)

            $hDC = _WinAPI_GetDC($hLast)
            If Not $hDC Then Return 0

            DllCall("Gdi32.dll", "int", "SetROP2", "HANDLE", $hDC, "int", 10) ; $R2_NOTXORPEN

            $hPen = _WinAPI_CreatePen($PS_SOLID, 4, 0)
            $hOldPen = _WinAPI_SelectObject($hDC, $hPen)

            DllCall("Gdi32.dll", "int", "Rectangle", "HANDLE", $hDC, "int", 2, "int", 2, "int", $g__aRect[0] - 1, "int", $g__aRect[1] - 1)

            _WinAPI_SelectObject($hDC, $hOldPen)
            _WinAPI_DeleteObject($hPen)
            _WinAPI_ReleaseDC($hLast, $hDC)

            $g__aRect = 0
        EndIf
    EndIf
EndFunc   ;==>WinLButtonDown

Func WinMouseMove($hWnd, $iMsg, $wParam, $lParam)
    Local $hLast

    If _TrayFinder_IsFinding($hWnd) Then
        If $g__fIn Then Return 0
        $g__fIn = True

        Local $tPoint = _WinAPI_GetMousePos()
        $h = _WinAPI_WindowFromPoint($tPoint)
        If $h = 0 Then
            $fIn = False
            Return 0
        EndIf

        $hLast = $g__hLast
        If $h <> $g__hLast Then
            $g__hLast = $h

            If $hLast <> 0 And IsArray($g__aRect) Then
                $hDC = _WinAPI_GetDC($hLast)
                If Not $hDC Then
                    $fIn = False
                    Return 0
                EndIf

                DllCall("Gdi32.dll", "int", "SetROP2", "HANDLE", $hDC, "int", 10) ; $R2_NOTXORPEN

                $hPen = _WinAPI_CreatePen($PS_SOLID, 4, 0)
                $hOldPen = _WinAPI_SelectObject($hDC, $hPen)

                DllCall("Gdi32.dll", "int", "Rectangle", "HANDLE", $hDC, "int", 2, "int", 2, "int", $g__aRect[0] - 1, "int", $g__aRect[1] - 1)

                _WinAPI_SelectObject($hDC, $hOldPen)
                _WinAPI_DeleteObject($hPen)
                _WinAPI_ReleaseDC($hLast, $hDC)
            EndIf

            $g__aRect = WinGetClientSize($h)
            If @error Then
                $fIn = False
                Return 0
            EndIf

            $hDC = _WinAPI_GetDC($h)
            If Not $hDC Then
                $fIn = False
                Return 0
            EndIf

            DllCall("Gdi32.dll", "int", "SetROP2", "HANDLE", $hDC, "int", 10) ; $R2_NOTXORPEN

            $hPen = _WinAPI_CreatePen($PS_SOLID, 4, 0)
            $hOldPen = _WinAPI_SelectObject($hDC, $hPen)

            DllCall("Gdi32.dll", "int", "Rectangle", "HANDLE", $hDC, "int", 2, "int", 2, "int", $g__aRect[0] - 1, "int", $g__aRect[1] - 1)

            _WinAPI_SelectObject($hDC, $hOldPen)
            _WinAPI_DeleteObject($hPen)
            _WinAPI_ReleaseDC($h, $hDC)
        EndIf

        $g__fIn = False
        Return 0
    EndIf

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WinMouseMove


Func IconMessage($hWnd, $iMsg, $wParam, $lParam)
    Switch $lParam
        Case $WM_LBUTTONUP
            DllStructSetData($tNID, 'Flags', $NIF_ICON)
            DllStructSetData($tNID, 'hIcon', __GUICtrlFinder_GetDefaultResources(1))
            _WinAPI_ShellNotifyIcon($NIM_MODIFY, $tNID)

            $hCur = __GUICtrlFinder_GetDefaultResources(2)

            _WinAPI_SetCapture($hGUI)
            Sleep(10)
            $g__hBackupCursor = _WinAPI_SetCursor($hCur)

            ConsoleWrite("Hello, World!" & @LF)
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>IconMessage



Func _TrayFinder_IsFinding($hWnd)
    Local $hCap = DllCall("User32.dll", "handle", "GetCapture")
    If @error Then Return False
    Return $hCap[0] = $hWnd
EndFunc   ;==>_TrayFinder_IsFinding

Func OnAutoItExit()
    DllStructSetData($tNID, 'ID', $ICON_ID)
    _WinAPI_ShellNotifyIcon($NIM_DELETE, $tNID)

    __GUICtrlFinder_GetDefaultResources(-1, True)
EndFunc   ;==>OnAutoItExit

Func __GUICtrlFinder_GetDefaultResources($iRes = -1, $fClean = False)
    Local Static $ahRes[3] = [0, 0, 0] ; Full, Empty, Cursor

    If $fClean Then
        _WinAPI_DestroyIcon($ahRes[0])
        _WinAPI_DestroyIcon($ahRes[1])
        DllCall("user32.dll", "int", "DestroyCursor", "ptr", $ahRes[2])

        $ahRes[0] = 0
        Return 0
    ElseIf $ahRes[0] = 0 Then
        Local $bRes, $tRes, $iOffset, $tImg, $aRet

        $bRes = "0x0000010001002020100001000400E8020000160000002800000020000000400000000100040000000000000200000000000000" & _
                "000000100000001000000000000000000080000080000000808000800000008000800080800000C0C0C000808080000000FF0000FF0" & _
                "00000FFFF00FF000000FF00FF00FFFF0000FFFFFF000000000000000000000000000000000000000000000000000000000000000000" & _
                "00FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFF00000FFFFFFFFFFFF000FFFFFFFFF" & _
                "F00FF0FF00FFFFFFFFFF000FFFFFFFFF0FF00000FF0FFFFFFFFF000FFFFFFFF0FFFFF0FFFFF0FFFFFFFF000FFFFFFF0FFFF00000FFF" & _
                "F0FFFFFFF000FFFFFFF0FFFFFF0FFFFFF0FFFFFFF000FFFFFF0F0F0FF000FF0F0F0FFFFFF000FFFFFF0F0F0F0FFF0F0F0F0FFFFFF00" & _
                "0FFFFFF0000000F0F0000000FFFFFF000FFFFFF0F0F0F0FFF0F0F0F0FFFFFF000FFFFFF0F0F0FF000FF0F0F0FFFFFF000FFFFFFF0FF" & _
                "FFFF0FFFFFF0FFFFFFF000FFFFFFF0FFFF00000FFFF0FFFFFFF000FFFFFFFF0FFFFF0FFFFF0FFFFFFFF000FFFFFFFFF0FF00000FF0F" & _
                "FFFFFFFF000FFFFFFFFFF00FF0FF00FFFFFFFFFF000FFFFFFFFFFFF00000FFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000" & _
                "FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000007770CCCCCCC" & _
                "CCCCCCCCCCCCCC07770007070CCCCCCCCCCCCCCCCCCCCC07070007770CCCCCCCCCCCCCCCCCCCCC07770000000000000000000000000" & _
                "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFF" & _
                "FFFFF800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000" & _
                "00800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008" & _
                "000000080000000FFFFFFFFFFFFFFFFFFFFFFFF"

        $tRes = DllStructCreate("byte[" & BinaryLen($bRes) & "]")
        DllStructSetData($tRes, 1, Binary($bRes))

        $iOffset = DllCall("user32.dll", "int", "LookupIconIdFromDirectory", "ptr", DllStructGetPtr($tRes), "int", 1)
        $iOffset = $iOffset[0]

        $tImg = DllStructCreate($tagBITMAPINFO, DllStructGetPtr($tRes) + $iOffset)
        $aRet = DllCall("user32.dll", "handle", "CreateIconFromResource", _
                "ptr", DllStructGetPtr($tImg), _
                "int", DllStructGetData($tImg, "Size"), _
                "int", 1, _
                "int", 0x00030000)
        $ahRes[0] = $aRet[0]

        $bRes = "0x0000010001002020100001000400E80200001600000028000000200000004000000001000400000000000002000000000000000000001000" & _
                "00001000000000000000000080000080000000808000800000008000800080800000C0C0C000808080000000FF0000FF000000FFFF00FF00" & _
                "0000FF00FF00FFFF0000FFFFFF00000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFF" & _
                "FFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FF" & _
                "FFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFF" & _
                "FFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FF" & _
                "FFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFF" & _
                "FFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FF" & _
                "FFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000FFFFFFFFFFFFFFFFFF" & _
                "FFFFFFFFFFF000000000000000000000000000000000007770CCCCCCCCCCCCCCCCCCCCC07770007070CCCCCCCCCCCCCCCCCCCCC070700077" & _
                "70CCCCCCCCCCCCCCCCCCCCC07770000000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
                "00000000000000000000000000000000000000000000FFFFFFFF800000008000000080000000800000008000000080000000800000008000" & _
                "0000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000" & _
                "0000800000008000000080000000800000008000000080000000FFFFFFFFFFFFFFFFFFFFFFFF"

        $tRes = DllStructCreate("byte[" & BinaryLen($bRes) & "]")
        DllStructSetData($tRes, 1, Binary($bRes))

        $iOffset = DllCall("user32.dll", "int", "LookupIconIdFromDirectory", "ptr", DllStructGetPtr($tRes), "int", 1)
        $iOffset = $iOffset[0]

        $tImg = DllStructCreate($tagBITMAPINFO, DllStructGetPtr($tRes) + $iOffset)
        $aRet = DllCall("user32.dll", "handle", "CreateIconFromResource", _
                "ptr", DllStructGetPtr($tImg), _
                "int", DllStructGetData($tImg, "Size"), _
                "int", 1, _
                "int", 0x00030000)
        $ahRes[1] = $aRet[0]


        $bRes = "0x000002000100202000000F0010003001000016000000280000002000000040000000010001000000000080000000000000000000000002" & _
                "0000000200000000000000FFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
                "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
                "00000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" & _
                "FFFFFFFFF83FFFFFE6CFFFFFD837FFFFBEFBFFFF783DFFFF7EFDFFFEAC6AFFFEABAAFFFE0280FFFEABAAFFFEAC6AFFFF7EFDFFFF783DFFFF" & _
                "BEFBFFFFD837FFFFE6CFFFFFF83FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"

        $tRes = DllStructCreate("byte[" & BinaryLen($bRes) & "]")
        DllStructSetData($tRes, 1, Binary($bRes))

        $iOffset = DllCall("user32.dll", "int", "LookupIconIdFromDirectory", "ptr", DllStructGetPtr($tRes), "int", 1)
        $iOffset = $iOffset[0]

        $tImg = DllStructCreate($tagBITMAPINFO, DllStructGetPtr($tRes) + $iOffset)
        $aRet = DllCall("user32.dll", "handle", "CreateIconFromResource", _
                "ptr", DllStructGetPtr($tImg), _
                "int", DllStructGetData($tImg, "Size"), _
                "int", 1, _
                "int", 0x00030000)
        $ahRes[2] = $aRet[0]
    EndIf

    If $iRes < 0 Then Return $ahRes
    Return $ahRes[$iRes]
EndFunc   ;==>__GUICtrlFinder_GetDefaultResources

Share this post


Link to post
Share on other sites
AZJIO

WM_MOUSEMOVE is performed for the current window. Make it transparent on the whole screen.

Switch trigger when you click the tray icon to activate the search.

Activate with $TRAY_EVENT_PRIMARYDOWN

Edited by AZJIO

Share this post


Link to post
Share on other sites
Mat

WM_MOUSEMOVE is performed for the current window. Make it transparent on the whole screen.

Switch trigger when you click the tray icon to activate the search.

Activate with $TRAY_EVENT_PRIMARYDOWN

By capturing the mouse it should always receive the messages, see the code for the original.

Share this post


Link to post
Share on other sites
AZJIO

You can check in the loop

For me the problem is to determine the time of the click. Out of nowhere.

Edited by AZJIO

Share this post


Link to post
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
Sign in to follow this  

×