ken0137 发表于 2011-3-11 08:43:13

[已解决]请问当鼠标移到一个窗口上如何在这个窗口周围出现一个闪烁的框(界标线)

本帖最后由 ken0137 于 2011-3-19 13:23 编辑

1、请问当鼠标移到一个窗口上如何出现相应的界标线

是否有范例啊,最好效果最好像afan的“探测窗口控件工具”,

当鼠标移到一个控件或者窗口上,闪烁界标线

happytc 发表于 2011-3-11 09:53:16

用下面三个函数:
_WinAPI_CreateRectRgn()
_WinAPI_CombineRgn()
_WinAPI_SetWindowRgn()
具体的,自己看帮助吧,很容易的

ken0137 发表于 2011-3-11 12:15:02

是否有例子,
还有就是afan的工具里当按住鼠标左键拖动靶心图标至目标窗口,靶心会跟随鼠标移动,这个效果是怎么做的啊

tryhi 发表于 2011-3-11 12:42:50

是否有例子,
还有就是afan的工具里当按住鼠标左键拖动靶心图标至目标窗口,靶心会跟随鼠标移动,这个效果 ...
ken0137 发表于 2011-3-11 12:15 http://www.autoitx.com/images/common/back.gif

这个效果应该是临时改变鼠标形状

happytc 发表于 2011-3-11 13:05:52

是否有例子,
还有就是afan的工具里当按住鼠标左键拖动靶心图标至目标窗口,靶心会跟随鼠标移动,这个效果 ...
ken0137 发表于 2011-3-11 12:15 http://www.autoitx.com/images/common/back.gif

#Include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>
#Include <WindowsConstants.au3>
Global $hwd, $hCursor

$hwd = GUICreate('Mouse')
GUIRegisterMsg($WM_SETCURSOR, 'WM_SETCURSOR')
$OKButton = GUICtrlCreateButton("OK", 100, 100,50, 30)
GUISetState()
While GUIGetMsg() <> -3
        $Ran = Random(100, 116, 1)
        Sleep(250)
        $hCursor = _WinAPI_LoadCursor(_WinAPI_GetModuleHandle(@SystemDir & '\user32.dll'), $Ran)
WEnd

Func WM_SETCURSOR($hWnd, $iMsg, $wParam, $lParam)
        Switch $hWnd
                Case $hwd
                _WinAPI_SetCursor($hCursor)
                Return 1
        EndSwitch
        Return $GUI_RUNDEFMSG
EndFunc

happytc 发表于 2011-3-11 13:07:16

回复 1# ken0137



#include <ProgressConstants.au3>
#include <GuiConstantsEx.au3>
#include <GuiConstants.au3>
#include <ButtonConstants.au3>
#include <BorderConstants.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <TabConstants.au3>
#include <ComboConstants.au3>
#include <Constants.au3>
#include <GDIPlus.au3>
#include <WinApi.au3>
#Include <Misc.au3>



Global $Color = 0x0
While 1
        Sleep(200)
        If $Color = 0xFFFFFF Then
                $Color =0xFF0000
        Else
                $Color = 0xFFFFFF
        EndIf
       
        Global $Struct = DllStructCreate($tagPoint)

        DllStructSetData($Struct, "x", MouseGetPos(0))
        DllStructSetData($Struct, "y", MouseGetPos(1))

        $hWinCtrl = _WinAPI_WindowFromPoint($Struct)
        Local $aCtrlPos = WinGetPos($hWinCtrl)
        GUICreateSquare($aCtrlPos, $aCtrlPos, $aCtrlPos, $aCtrlPos, $Color)

WEnd

Func GUICreateSquare($i_X=-1, $i_Y=-1, $i_W=-1, $i_H=-1, $sColor=0x0)
        $hSquare_GUI = GUICreate("", $i_W, $i_H, $i_X, $i_Y, $WS_POPUP, $WS_EX_TOPMOST+$WS_EX_TOOLWINDOW)
        Local $Frame_Width = 3
       
        GUISetBkColor($sColor)
       
        _GUISetHole($hSquare_GUI, $Frame_Width, $Frame_Width, $i_W - ($Frame_Width * 2), $i_H - ($Frame_Width * 2))
        GUISetState(@SW_SHOWNOACTIVATE, $hSquare_GUI)
EndFunc

Func _GUISetHole(ByRef $hWin, $i_X, $i_Y, $i_SizeW, $i_SizeH)
        Local $aWinPos, $Outer_Rgn, $Inner_Rgn, $Wh, $Combined_Rgn
        Local Const $RGN_DIFF = 4
        $aWinPos = WinGetPos($hWin)
       
        $Outer_Rgn = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", 0, "long", 0, "long", $aWinPos, "long", $aWinPos)
        $Inner_Rgn = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", $i_Y, "long", $i_Y, "long", $i_Y + $i_SizeW, "long", $i_Y + $i_SizeH)
        $Combined_Rgn = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", 0, "long", 0, "long", 0, "long", 0)
        DllCall("gdi32.dll", "long", "CombineRgn", "long", $Combined_Rgn, "long", $Outer_Rgn, "long", $Inner_Rgn, "int", $RGN_DIFF)
        DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $hWin, "long", $Combined_Rgn, "int", 1)
EndFunc

131738 发表于 2011-3-11 16:10:50

回复ken0137
happytc 发表于 2011-3-11 13:07 http://autoitx.com/images/common/back.gif[/quote

正想研究这个效果,可以偷懒了,谢谢代码,但还要添加限时代码,老闪也是个问题啊。。。

131738 发表于 2011-3-11 16:15:02


happytc 发表于 2011-3-11 13:05 http://autoitx.com/images/common/back.gif

谢谢修改光标样式的代码!!!

pusofalse 发表于 2011-3-11 19:48:58

巧了,前两天还在研究这个功能。

#include <WinAPI.au3>
#include <Constants.au3>
#include <WindowsConstants.au3>

Global $hHook, $hPrevWnd

$hMouseProc = DllCallBackRegister("_MouseProc", "long", "long;long;ptr")
$pMouseProc = DllCallBackGetPtr($hMouseProc)

$hGUI = GUICreate("FindWindow", 400, 300)

$iFWIcon = GUICtrlCreateIcon("1.ico", -1, 40, 40, 32, 32)

GUICtrlCreateGroup("Window Info", 100, 30, 200, 210)
GUICtrlCreateLabel("Title:", 110, 55, 60, 20)
GUICtrlCreateLabel("Handle:", 110, 85, 60, 20)
GUICtrlCreateLabel("ID:", 110, 115, 60, 20)
GUICtrlCreateLabel("Class:", 110, 145, 60, 20)
GUICtrlCreateLabel("Style:", 110, 175, 60, 20)
GUICtrlCreateLabel("ExStyle:", 110, 205, 60, 20)

$iTitle = GUICtrlCreateInput("", 170, 53, 120, 20)
GUICtrlCreateInput("", 170, 83, 120, 20)
GUICtrlCreateInput("", 170, 113, 120, 20)
GUICtrlCreateInput("", 170, 143, 120, 20)
GUICtrlCreateInput("", 170, 173, 120, 20)
GUICtrlCreateInput("", 170, 203, 120, 20)

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

While 1
        Sleep(100)
WEnd

Func _WndProc($hWnd, $iMsg, $iwParam, $ilParam)
        Switch $iMsg
        Case $WM_COMMAND
                If ($iFWIcon = BitAnd($iwParam, 0xFFFF)) And (0 = BitShift($iwParam, 16)) Then
                        Local $hCursor = _WinAPI_LoadCursorFromFile("3.cur")
                        _WinAPI_SetSystemCursor($hCursor, 0x7F00)
                        _WinAPI_DestroyCursor($hCursor)

                        $hHook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, $pMouseProc, _WinAPI_GetModuleHandle(0))
                        GUICtrlSetImage($iFWIcon, "2.ico")
                EndIf
        Case $WM_SYSCOMMAND
                If (0xF060 = BitAnd($iwParam, 0xFFFF)) Then
                        If $hHook Then _WinAPI_UnhookWindowsHookEx($hHook)

                        GUIDelete($hWnd)
                        DllCallbackFree($hMouseProc)
                        DllCall("User32.dll", "none", "PostQuitMessage", "uint", 0)
                EndIf
        EndSwitch
EndFunc        ;==>_WndProc

Func _MouseProc($iCode, $iwParam, $ilParam)
        Switch $iwParam
        Case $WM_MOUSEMOVE
                Local $tPoint = DllStructCreate($tagPOINT, $ilParam)
                Local $hWnd = _WinAPI_WindowFromPoint($tPoint)

                If ($hWnd <> $hPrevWnd) And (@AutoItPid <> WinGetProcess($hWnd)) Then
                        _DrawFrame($hWnd)
                        _DrawFrame($hPrevWnd)

                        GUICtrlSetData($iTitle + 0, WinGetTitle($hWnd))
                        GUICtrlSetData($iTitle + 1, String($hWnd))
                        GUICtrlSetData($iTitle + 2, _WinAPI_GetDlgCtrlId($hWnd))
                        GUICtrlSetData($iTitle + 3, _WinAPI_GetClassName($hWnd))
                        GUICtrlSetData($iTitle + 4, Ptr(_WinAPI_GetWindowLong($hWnd, $GWL_STYLE)))
                        GUICtrlSetData($iTitle + 5, Ptr(_WinAPI_GetWindowLong($hWnd, $GWL_EXSTYLE)))

                        $hPrevWnd = $hWnd
                EndIf
        Case $WM_LBUTTONUP
                _DrawFrame($hPrevWnd)
                _WinAPI_UnhookWindowsHookEx($hHook)

                GUICtrlSetImage($iFWIcon, "1.ico")
                DllCall("User32.dll", "bool", "SystemParametersInfo", "int", 0x57, "int", 0, "int", 0, "dword", 0)

                $hPrevWnd = 0
                $hHook = 0
                Return
        EndSwitch
        Return _WinAPI_CallNextHookEx(0, $iCode, $iwParam, $ilParam)
EndFunc        ;==>_MouseProc

Func _DrawFrame($hWnd)
        If ($hWnd = 0) Then Return 0

        Local $hDC, $hPen, $hRgn, $aPos

        $hDC = _WinAPI_GetWindowDC($hWnd)
        $hPen = _WinAPI_CreatePen(6, 3, 0)
        $hRgn = _WinAPI_CreateRectRgn(0, 0, @DesktopWidth, @DesktopHeight)

        _WinAPI_SelectObject($hDC, $hPen)
        _WinAPI_SelectObject($hDC, _WinAPI_GetStockObject(5))
        _WinAPI_SetROP2($hDC, 6)

        If _WinAPI_GetWindowRgn($hWnd, $hRgn) Then
                _WinAPI_FrameRgn($hDC, $hRgn, $hPen, 3, 3)
        Else
                $aPos = WinGetPos($hWnd)
                If Not IsArray($aPos) Then Return 0
                _WinAPI_Rectangle($hDC, 0, 0, $aPos, $aPos)
        EndIf
        _WinAPI_DeleteObject($hRgn)
        _WinAPI_DeleteObject($hPen)
        _WinAPI_ReleaseDC($hWnd, $hDC)

        Return 1
EndFunc        ;==>_DrawFrame

Func _WinAPI_Rectangle($hDC, $iLeft, $iTop, $iRight, $iBottom)
        Local $iResult

        $iResult = DllCall("Gdi32.dll", "bool", "Rectangle", "hwnd", $hDC, _
                        "long", $iLeft, "long", $iTop, "long", $iRight, "long", $iBottom)
        Return $iResult
EndFunc        ;==>_WinAPI_Rectangle

Func _WinAPI_SetROP2($hDC, $iMode)
        Local $iResult
        $iResult = DllCall("Gdi32.dll", "bool", "SetROP2", "hwnd", $hDC, "dword", $iMode)
        Return $iResult
EndFunc        ;==>_WinAPI_SetROP2

Func _WinAPI_FrameRgn($hDC, $hRgn, $hBrush, $iWidth, $iHeight)
        Local $iResult

        $iResult = DllCall("Gdi32.dll", "bool", "FrameRgn", "hwnd", $hDC, "hwnd", $hRgn, _
                        "hwnd", $hBrush, "long", $iWidth, "long", $iHeight)
        Return $iResult
EndFunc        ;==>_WinAPI_FrameRgn

Func _WinAPI_LoadCursorFromFile($sCursor)
        Local $iResult = DllCall("User32.dll", "hwnd", "LoadCursorFromFile", "str", $sCursor)
        Return $iResult
EndFunc        ;==>_WinAPI_LoadCursorFromFile

Func _WinAPI_SetSystemCursor($hCursor, $iSystemCursor)
        Local $iResult = DllCall("User32.dll", "bool", "SetSystemCursor", "hwnd", $hCursor, "dword", $iSystemCursor)
        Return $iResult
EndFunc        ;==>_WinAPI_SetSystemCursor

Func _WinAPI_DestroyCursor($hCursor)
        Local $iResult = DllCall("User32.dll", "bool", "DestroyCursor", "hwnd", $hCursor)
        Return $iResult
EndFunc        ;==>_WinAPI_DestroyCursor

附件中包含相关图片。

ken0137 发表于 2011-3-12 14:26:15

回复 9# pusofalse
回复 6# happytc


哇哦,谢谢“happytc”和“pusofalse”精彩的回复,根据这两份代码,基本上可以实现afan的工具的效果了。
就像131738说的,要添加时限代码,这样就完美了。
还还有我想到了,可以做这么一个鼠标点击效果,那就是,当鼠标移到一个窗口的某个位置,
点击左键,先在窗口边框上出现一个界标线,闪两下,再在鼠标周围出现一个小的框,再闪两下,
最后在鼠标点击的位置出现一个点,闪两下,这样的效果不错诶。

ken0137 发表于 2011-3-20 15:29:28

本帖最后由 ken0137 于 2011-3-20 15:31 编辑

不能编辑帖子了,在这里总结吧,我是菜鸟,对happytc的做个注释吧

#include <ProgressConstants.au3>
#include <GuiConstantsEx.au3>
#include <GuiConstants.au3>
#include <ButtonConstants.au3>
#include <BorderConstants.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <TabConstants.au3>
#include <ComboConstants.au3>
#include <Constants.au3>
#include <GDIPlus.au3>
#include <WinApi.au3>
#Include <Misc.au3>



Global $Color = 0x0
While 1
      Sleep(200)
      If $Color = 0xFFFFFF Then
                $Color =0x000000
      Else
                $Color = 0xFFFFFF
      EndIf
      ;创建一个 C/C++ 样式的数据结构供 DllCall 使用. DllStructCreate ( "数据结构" [,指针] )
      Global $Struct = DllStructCreate($tagPoint)
                ;设置数据结构(struct)中部分元素的数据.DllStructSetData ( 数据结构, 元素, 值 [, 索引 ] )
      DllStructSetData($Struct, "x", MouseGetPos(0));获取当前鼠标的屏幕绝对坐标x位置.
      DllStructSetData($Struct, "y", MouseGetPos(1));获取当前鼠标的屏幕绝对坐标y位置.
                ;返回当前坐标windowns窗口的句柄,例如返回值为0x0016035A,这里的窗口为所要捕捉的程序界面中的窗口,即控件
      $hWinCtrl = _WinAPI_WindowFromPoint($Struct)
                ;获取指定窗口的坐标位置(绝对坐标)和大小等属性.WinGetPos ( "窗口标题" [, "窗口文本"] )
      Local $aCtrlPos = WinGetPos($hWinCtrl)
                ;自定义界标线函数,开始画框
      GUICreateSquare($aCtrlPos, $aCtrlPos, $aCtrlPos, $aCtrlPos, $Color)
               
WEnd

Func GUICreateSquare($i_X=-1, $i_Y=-1, $i_W=-1, $i_H=-1, $sColor=0x0)
        ;创建窗体,
        ;$WS_POPUP,创建一个弹出式窗口.
        ;$WS_EX_TOPMOST,使带有此样式的窗口放置在所有非顶层窗口之上,而且即使在该窗口失去激活状态时还总是保持在它们之上.即置顶效果
        ;$WS_EX_TOOLWINDOW,创建一个工具窗口,工具窗口在任务栏上不显示按钮,用户按下热键 Alt+Tab 后在弹出的对话框中也不会显示它的图标
        ;即无边框,无系统栏,
      $hSquare_GUI = GUICreate("", $i_W, $i_H, $i_X, $i_Y, $WS_POPUP, $WS_EX_TOPMOST+$WS_EX_TOOLWINDOW)
                ;设置边框宽度
      Local $Frame_Width = 3
      ;设置背景颜色
      GUISetBkColor($sColor)
      ;画框
                ;_GUISetHole($hSquare_GUI, $Frame_Width, $Frame_Width, $i_W - ($Frame_Width * 2), $i_H - ($Frame_Width * 2))
                _GUISetHoleWinAPI($hSquare_GUI, $Frame_Width, $Frame_Width, $i_W - ($Frame_Width * 2), $i_H - ($Frame_Width * 2))
                ;@SW_SHOWNOACTIVATE令指定窗口以其上一次的大小和位置显示
      GUISetState(@SW_SHOWNOACTIVATE, $hSquare_GUI)
               
EndFunc

Func _GUISetHole(ByRef $hWin, $i_X, $i_Y, $i_SizeW, $i_SizeH)
      Local $aWinPos, $Outer_Rgn, $Inner_Rgn, $Wh, $Combined_Rgn
      Local Const $RGN_DIFF = 4
      $aWinPos = WinGetPos($hWin)
      ;创建一个坐标,left:0;top:0;right:$aWinPos;bottom:$aWinPos的矩形区域,这个外框
      $Outer_Rgn = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", 0, "long", 0, "long", $aWinPos, "long", $aWinPos)
                ;创建一个坐标,left:$i_Y;top:$i_Y;right:$i_Y ; $i_SizeW;bottom:$i_Y + $i_SizeH的矩形区域,这个内框
      $Inner_Rgn = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", $i_Y, "long", $i_Y, "long", $i_Y + $i_SizeW, "long", $i_Y + $i_SizeH)
                ;创建一个坐标,left:0;top:0;right:0 ;bottom:0的矩形区域
      $Combined_Rgn = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", 0, "long", 0, "long", 0, "long", 0)
                ;合并区域,参数$RGN_DIFF意思是合并产生的区域为$Outer_Rgn有而 $Inner_Rgn没有的区域
      DllCall("gdi32.dll", "long", "CombineRgn", "long", $Combined_Rgn, "long", $Outer_Rgn, "long", $Inner_Rgn, "int", $RGN_DIFF)
                ;设置区域,显示结果,至此出现一个框,边框0.2s变换一下
      DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $hWin, "long", $Combined_Rgn, "int", 1)
EndFunc
       
Func _GUISetHoleWinAPI(ByRef $hWin, $i_X, $i_Y, $i_SizeW, $i_SizeH)
        Local $aWinPos, $Outer_Rgn, $Inner_Rgn, $Wh, $Combined_Rgn
        ;Local Const $RGN_DIFF = 4
        $aWinPos = WinGetPos($hWin)
        ;创建一个坐标,left:0;top:0;right:$aWinPos;bottom:$aWinPos的矩形区域,这个外框
        $outer_rgn = _WinAPI_CreateRectRgn(0, 0, $aWinPos, $aWinPos)
        ;创建一个坐标,left:$i_Y;top:$i_Y;right:$i_Y ; $i_SizeW;bottom:$i_Y + $i_SizeH的矩形区域,这个内框
        $inner_rgn = _WinAPI_CreateRectRgn($i_x, $i_y, $i_x + $i_sizew, $i_y + $i_sizeh)
        ;创建一个坐标,left:0;top:0;right:0 ;bottom:0的矩形区域
        $combined_rgn = _WinAPI_CreateRectRgn(0, 0, 0, 0)
        ;合并区域,参数$RGN_DIFF意思是合并产生的区域为$Outer_Rgn有而 $Inner_Rgn没有的区域
        _WinAPI_CombineRgn($combined_rgn, $outer_rgn, $inner_rgn, $RGN_DIFF)
        _WinAPI_DeleteObject($outer_rgn)
        _WinAPI_DeleteObject($inner_rgn)
        ;设置区域,显示结果,至此出现一个框,边框0.2s变换一下
        _WinAPI_SetWindowRgn($hWin, $Combined_Rgn)
EndFunc

此代码演示了API函数的应用,
缺点是
CPU占用率高,
边框为红白交替,而不是红,透明色,交替

magus 发表于 2011-4-27 11:23:21

一个贴子三份代码,精华啊...

iamwonvy 发表于 2011-5-23 18:36:29

我也正要这个功能 谢谢了

风行者 发表于 2011-12-5 22:17:45

很久没出现这样的好帖子了,留个记号

penguinl 发表于 2011-12-24 09:24:32

捡到宝贝了,感谢各位的代码!
页: [1] 2
查看完整版本: [已解决]请问当鼠标移到一个窗口上如何在这个窗口周围出现一个闪烁的框(界标线)