Jump to content

GUIFinder.au3 - V2


Mat
 Share

Recommended Posts

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

Link to comment
Share on other sites

  • 3 years later...

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.

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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.

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...