pusofalse 发表于 2010-7-27 17:48:15

本帖最后由 pusofalse 于 2010-7-27 17:50 编辑

肯定是鼠标单击在前的,否则通过HOOK鼠标消息没什么意义。#include <WinAPI.au3>
#include <WindowsConstants.au3>

Global $hForeground

$hGUI = GUICreate("Test", 400, 300, -1, -1, Default, $WS_EX_TOPMOST)
GUICtrlCreateButton("Send ""a""", 40, 40, 150, 20)
GUICtrlSetCursor(-1, 0)
$hButton = GUICtrlGetHandle(-1)

$iThreadId = _WinAPI_GetCurrentThreadId()
$hInstance = _WinAPI_GetModuleHandle(0)

$hCBTProc = DllCallBackRegister("_CBTCallBack", "int", "uint;wparam;lparam")
$pCBTProc = DllCallBackGetPtr($hCBTProc)
$hCBTHook = _WinAPI_SetWindowsHookEx(5, $pCBTProc, $hInstance, $iThreadId)

$hMouseProc = DllCallBackRegister("_MouseProc", "int", "uint;wparam;lparam")
$pMouseProc = DllCallBackGetPtr($hMouseProc)
$hMouseHook = _WinAPI_SetWindowsHookEx(14, $pMouseProc, $hInstance, 0)

$hEventProc = DllCallBackRegister("_EventProc", "none", "ptr;dword;hWnd;long;long;dword;dword")
$pEventProc = DllCallBackGetPtr($hEventProc)
$hEventHook = _SetWinEventHook($pEventProc, 1)

GUISetState()
While GUIGetMsg() + 3
WEnd

GUIDelete($hGUI)
_WinAPI_UnhookWindowsHookEx($hCBTHook)
_WinAPI_UnhookWindowsHookEx($hMouseHook)
_UnhookWinEvent($hEventHook)

DllCallBackFree($hCBTProc)
DllCallBackFree($hMouseProc)
DllCallBackFree($hEventProc)

Func _CBTCallBack($iCode, $iwParam, $ilParam)
        Switch $iCode
        Case 5
                If HWnd($iwParam) = $hGUI Then Return 1
        EndSwitch

        Return _WinAPI_CallNextHookEx($hCBTHook, $iCode, $iwParam, $ilParam)
EndFunc        ;==>_CBTCallBack

Func _EventProc($hEventHook, $iEvent, $hWnd, $iObject, $iChild, $iEventThread, $iEventTime)
        If ($iEvent = 0x8005) Then $hForeground = $hWnd
EndFunc        ;==>_EventProc

Func _MouseProc($iCode, $iwParam, $ilParam)
        If ($iCode < 0) Then
                Return _WinAPI_CallNextHookEx($hMouseHook, $iCode, $iwParam, $ilParam)
        EndIf

        Switch $iwParam
        Case $WM_LBUTTONDOWN, $WM_LBUTTONUP, $WM_RBUTTONDOWN, $WM_RBUTTONUP, $WM_MBUTTONDOWN, $WM_MBUTTONUP
                Local $tBuffer, $hWindow

                $tBuffer = DllStructCreate("int X;int Y", $ilParam)
                $hWindow = _WinAPI_WindowFromPoint($tBuffer)
                $tBuffer = 0
                Switch $hWindow
                Case $hGUI
                        Return 1
                Case $hButton
                        If ($iwParam = $WM_LBUTTONUP) Then Send("a")
                        Return 1
                EndSwitch
        EndSwitch
        Return _WinAPI_CallNextHookEx($hMouseHook, $iCode, $iwParam, $ilParam)
EndFunc        ;==>_MouseProc

Func _SetWinEventHook($pCallBack, $iFlags, $iEventMin = 1, $iEventMax = 0x7FFFFFFF, $iProcessId = 0, $iThreadId = 0)
        Local $iResult
        $iResult = DllCall("User32.dll", "ptr", "SetWinEventHook", "uint", $iEventMin, _
                        "uint", $iEventMax, "ptr", 0, "ptr", $pCallBack, "dword", $iProcessId, _
                        "dword", $iThreadId, "uint", $iFlags)
        Return $iResult
EndFunc        ;==>_SetWinEventHook

Func _UnhookWinEvent($hEventHook)
        Local $iResult
        $iResult = DllCall("User32.dll", "int", "UnhookWinEvent", "ptr", $hEventHook)
        Return $iResult
EndFunc        ;==>_UnhookWinEvent

afan 发表于 2010-7-27 17:51:46

肯定是鼠标单击在前的,否则通过HOOK鼠标消息没什么意义。
pusofalse 发表于 2010-7-27 17:48 http://www.autoitx.com/images/common/back.gif


    强大极了~!我就知道这对于P版来说只是小菜~~{:face (301):}

afan 发表于 2010-7-27 18:47:16

回复 16# pusofalse


    我这3.3.6.1似乎无法退出,请P版再看看~

pusofalse 发表于 2010-7-27 19:02:22

回复 18# afan


    我现在在用3.3.5.1,没遇到这样的问题。以前在用低版本的au3时,会出现如你所说的不能正常退出的情况,退出时会卡住,并且狂占CPU,我测试了多次,终于发现,对于带GUI界面的程序,如果代码中调用了DllCallBackRegister函数,在退出时必须先GUIDelete、DllCallBackFree才可以,上面的代码就是这样做的。
这是以前在用低版本时遇到的问题,但不知在高版本中也会出现如此情况,我不知道到底怎样做才能彻底解决这个问题,以前没弄明白原因时,总是在紧接着While GUIGetMsg()主循环之后加一句Opt("TrayIconHide", 1)、ProcessClose(@AutoItPid)来强制结束自身进程。如果不在意的话,可以使用这种方法退出。 - -|||
我再看一下。

afan 发表于 2010-7-27 19:07:14

回复 19# pusofalse


    我这测试点击关闭按钮后主循环并未退出,难道GUIGetMsg()也被拦截了?

3mile 发表于 2010-7-27 19:07:36

P大厉害,佩服之极。

pusofalse 发表于 2010-7-27 19:14:14

回复 20# afan


在GUI主界面上点关闭按钮当然是不行的,鼠标单击被拦截并阻止了,GUIGetMsg根本获取不到GUI_EVENT_CLOSE这个消息。
在任务栏上选择右键关闭,这样不会阻止消息。

afan 发表于 2010-7-27 19:18:11

回复 22# pusofalse


    确实如此,而且不用+强制结束进程,一切正常。谢谢啦~

奥斯丁 发表于 2010-7-27 21:49:38

先高兴一下,不过还有问题哦, 窗口弹出来在中间就不能移动了。

afan 发表于 2010-7-27 21:55:40

本帖最后由 afan 于 2010-7-27 21:57 编辑

先高兴一下,不过还有问题哦, 窗口弹出来在中间就不能移动了。
奥斯丁 发表于 2010-7-27 21:49 http://www.autoitx.com/images/common/back.gif


    这个问题可以用判断鼠标位置的方式(或者专门建立一个控件以供点击)来决定是否Hook

奥斯丁 发表于 2010-7-27 22:27:15

这个问题可以用判断鼠标位置的方式(或者专门建立一个控件以供点击)来决定是否Hook
afan 发表于 2010-7-27 21:55 http://www.autoitx.com/images/common/back.gif


    谢谢版主, 不过版主请送佛送到西吧, 俺刚学gui, pusofalse 大大的脚本看起来
有大半犹如天书,还好send(‘a’)还能看懂, 加加减减的修改一下还能应付, 版主
上述的能否把代码都贴上来, 不情之请.......      
    再次谢谢诸位的热心!

afan 发表于 2010-7-27 22:36:54

回复 26# 奥斯丁


    P版的代码都是些高级货,我也看不大懂… 添加点功能进去也许还凑合,不过肯定没有原设计思路的味。。。

奥斯丁 发表于 2010-7-27 23:01:13

{:face (411):} 板凳 {:face (303):}

afan 发表于 2010-7-27 23:24:35

回复 28# 奥斯丁 #include <WinAPI.au3>
#include <WindowsConstants.au3>

Global $hForeground, $_exit = False, $_move = False, $hw_top

$hGUI = GUICreate('Test', 400, 300, -1, -1, 0, $WS_EX_TOPMOST)
GUICtrlCreateButton('Send "a"', 40, 40, 150, 20)
GUICtrlSetCursor(-1, 0)
$hButton = GUICtrlGetHandle(-1)

GUICtrlCreateButton('Exit', 200, 40, 150, 20)
GUICtrlSetCursor(-1, 0)
$hButton1 = GUICtrlGetHandle(-1)

GUICtrlCreateLabel('  按住此处拖动窗口', 100, 80, 150, 15)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetCursor(-1, 9)
$hLabel = GUICtrlGetHandle(-1)

$iThreadId = _WinAPI_GetCurrentThreadId()
$hInstance = _WinAPI_GetModuleHandle(0)

$hCBTProc = DllCallbackRegister('_CBTCallBack', 'int', 'uint;wparam;lparam')
$pCBTProc = DllCallbackGetPtr($hCBTProc)
$hCBTHook = _WinAPI_SetWindowsHookEx(5, $pCBTProc, $hInstance, $iThreadId)

$hMouseProc = DllCallbackRegister('_MouseProc', 'int', 'uint;wparam;lparam')
$pMouseProc = DllCallbackGetPtr($hMouseProc)
$hMouseHook = _WinAPI_SetWindowsHookEx(14, $pMouseProc, $hInstance, 0)

$hEventProc = DllCallbackRegister('_EventProc', 'none', 'ptr;dword;hWnd;long;long;dword;dword')
$pEventProc = DllCallbackGetPtr($hEventProc)
$hEventHook = _SetWinEventHook($pEventProc, 1)

GUISetState(@SW_SHOWNOACTIVATE)
While GUIGetMsg() + 3
        If $_exit Then ExitLoop
        If $_move = True Then
                $hw_top = _WinAPI_GetForegroundWindow()
                GuiMove($hGUI)
                $_move = False
        EndIf
WEnd
_exit()

Func _exit()
        GUIDelete($hGUI)
        _WinAPI_UnhookWindowsHookEx($hCBTHook)
        _WinAPI_UnhookWindowsHookEx($hMouseHook)
        _UnhookWinEvent($hEventHook)
        DllCallbackFree($hCBTProc)
        DllCallbackFree($hMouseProc)
        DllCallbackFree($hEventProc)
        GUIDelete($hGUI)
EndFunc   ;==>_exit

Func _CBTCallBack($iCode, $iwParam, $ilParam)
        Switch $iCode
                Case 5
                        If HWnd($iwParam) = $hGUI Then Return 1
        EndSwitch
        Return _WinAPI_CallNextHookEx($hCBTHook, $iCode, $iwParam, $ilParam)
EndFunc   ;==>_CBTCallBack

Func _EventProc($hEventHook, $iEvent, $hWnd, $iObject, $iChild, $iEventThread, $iEventTime)
        If ($iEvent = 0x8005) Then $hForeground = $hWnd
EndFunc   ;==>_EventProc

Func _MouseProc($iCode, $iwParam, $ilParam)
        If $_move = False Then
                If ($iCode < 0) Then Return _WinAPI_CallNextHookEx($hMouseHook, $iCode, $iwParam, $ilParam)
                Switch $iwParam
                        Case $WM_LBUTTONDOWN, $WM_LBUTTONUP, $WM_RBUTTONDOWN, $WM_RBUTTONUP, $WM_MBUTTONDOWN, $WM_MBUTTONUP
                                Local $tBuffer = DllStructCreate('int X;int Y', $ilParam)
                                Local $hWindow = _WinAPI_WindowFromPoint($tBuffer)
                                $tBuffer = 0
                                Switch $hWindow
                                        Case $hGUI
                                                Return 1
                                        Case $hButton
                                                If ($iwParam = $WM_LBUTTONUP) Then Send('a')
                                                Return 1
                                        Case $hButton1
                                                $_exit = True
                                                Return 1
                                        Case $hLabel
                                                $_move = True
                                                Return 1
                                EndSwitch
                EndSwitch
        EndIf
        Return _WinAPI_CallNextHookEx($hMouseHook, $iCode, $iwParam, $ilParam)

EndFunc   ;==>_MouseProc

Func _SetWinEventHook($pCallBack, $iFlags, $iEventMin = 1, $iEventMax = 0x7FFFFFFF, $iProcessId = 0, $iThreadId = 0)
        Local $iResult
        $iResult = DllCall('User32.dll', 'ptr', 'SetWinEventHook', 'uint', $iEventMin, _
                        'uint', $iEventMax, 'ptr', 0, 'ptr', $pCallBack, 'dword', $iProcessId, _
                        'dword', $iThreadId, 'uint', $iFlags)
        Return $iResult
EndFunc   ;==>_SetWinEventHook

Func _UnhookWinEvent($hEventHook)
        Local $iResult
        $iResult = DllCall('User32.dll', 'int', 'UnhookWinEvent', 'ptr', $hEventHook)
        Return $iResult
EndFunc   ;==>_UnhookWinEvent

Func GuiMove($hGUI)
        MouseDown('left')
        Local $PY, $a_R, $PM = MouseGetPos(), $PW = WinGetPos($hGUI, '')
        $PY = $PW - $PM
        $PY = $PW - $PM
        While 1
                $a_R = DllCall('user32.dll', "short", "GetAsyncKeyState", "int", '0x01')
                If @error Then Return 0
                If Not BitAND($a_R, 0x8000) Then ExitLoop
                $PM = MouseGetPos()
                WinMove($hGUI, '', $PM + $PY, $PM + $PY)
                Sleep(5)
        WEnd
        WinActivate($hw_top)
EndFunc   ;==>GuiMove

奥斯丁 发表于 2010-7-28 11:20:24

3q!完美。。。。。。。。。。。
页: 1 [2] 3
查看完整版本: [已解决]如何能使窗口可以响应点击(控件),而窗体不被激活