$GUI_EVENT_PRIMARYDOWN 对应的消息模式应该怎么写?【已解决】
本帖最后由 fenhanxue 于 2018-1-7 12:01 编辑问题背景:
创建的GUI取消了标题栏,自己用lable画了一条标题栏
希望鼠标左键按住标题栏(lable),可以自由拖动GUI窗口的位置
不使用消息模式,代码是这样的:#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>
Global $GUI = GUICreate("", 400, 200, -1, -1,$WS_POPUP)
Global $lable_move = GUICtrlCreateLabel("", 0, 0, 370, 30)
GUICtrlSetBkColor(-1, 0x99D9EA)
Global $lable_close = GUICtrlCreateLabel("关闭", 375, 0, 25, 30)
GUISetState(@SW_SHOW)
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $lable_close
Exit
Case $GUI_EVENT_PRIMARYDOWN
GUI_Move()
EndSwitch
WEnd
Func GUI_Move()
;判断当前鼠标是否在 $lable_move 上方
Local $temp = GUIGetCursorInfo()
If $temp = 0 Then Return
If $temp <> $lable_move Then Return
;获取鼠标和GUI的相对位置
Local $GuiPos = WinGetPos($GUI)
Local $MousePos = MouseGetPos()
Local $PosDiff
$PosDiff = $GuiPos - $MousePos
$PosDiff = $GuiPos - $MousePos
;移动GUI
While _IsPressed("01")
Local $MousePos = MouseGetPos()
WinMove($GUI, "", $MousePos + $PosDiff, $MousePos + $PosDiff)
Sleep(10)
WEnd
EndFunc上述代码可以正常运行
由于au3是单线程,当程序变复杂后,上述代码将会变得不是非常有效。
例如:
假设GUI里有个BUTTON,按了BUTTON,运行一段func ,假设这个func 会耗时10分钟才会完成, 那么在运行这个func期间,GUI窗口是无法拖动的。必须等func运行完后,才能移动GUI。
所有想改成注册消息的模式,
想请教,这里的$GUI_EVENT_PRIMARYDOWN如何变成消息模式?
我试过下面的代码,但是没有效果:#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>
Global $GUI = GUICreate("", 400, 200, -1, -1,$WS_POPUP)
Global $lable_move = GUICtrlCreateLabel("", 0, 0, 370, 30)
GUICtrlSetBkColor(-1, 0x99D9EA)
Global $lable_close = GUICtrlCreateLabel("关闭", 375, 0, 25, 30)
GUISetState(@SW_SHOW)
GUIRegisterMsg($WM_LBUTTONDOWN, "WM_LBUTTONDOWN")
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $lable_close
Exit
EndSwitch
WEnd
Func GUI_Move()
;判断当前鼠标是否在 $lable_move 上方
Local $temp = GUIGetCursorInfo()
If $temp = 0 Then Return
If $temp <> $lable_move Then Return
;获取鼠标和GUI的相对位置
Local $GuiPos = WinGetPos($GUI)
Local $MousePos = MouseGetPos()
Local $PosDiff
$PosDiff = $GuiPos - $MousePos
$PosDiff = $GuiPos - $MousePos
;移动GUI
While _IsPressed("01")
Local $MousePos = MouseGetPos()
WinMove($GUI, "", $MousePos + $PosDiff, $MousePos + $PosDiff)
Sleep(10)
WEnd
EndFunc
Func WM_LBUTTONDOWN($hWndGUI, $MsgID, $WParam, $LParam)
ConsoleWrite(1)
GUI_Move()
EndFunc
回复 1# fenhanxue
http://www.autoit3.cn/forum.php?mod=viewthread&tid=21578&highlight=WM%5C_LBUTTONDOWN
Only windows that have the CS_DBLCLKS style can receive WM_LBUTTONDBLCLK messages, which the system generates whenever the user presses, releases, and again presses the left mouse button within the system's double-click time limit. Double-clicking the left mouse button actually generates a sequence of four messages: WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK, and WM_LBUTTONUP 回复 1# fenhanxue
http://www.autoit3.cn/thread-25676-1-1.html 回复 1# fenhanxue
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>
Opt("GUIOnEventMode", 1)
Global $GUI = GUICreate("", 400, 200, -1, -1,$WS_POPUP)
Global $lable_move = GUICtrlCreateLabel("", 0, 0, 370, 30)
GUICtrlSetBkColor(-1, 0x99D9EA)
Global $lable_close = GUICtrlCreateLabel("??", 375, 0, 25, 30)
GUISetState(@SW_SHOW)
GUISetOnEvent($GUI_EVENT_PRIMARYDOWN, "GUI_Move")
GUICtrlSetOnEvent($lable_close, "GUI_COMMAND")
While 1
WEnd
Func GUI_Move()
;判??前鼠?是否在 $lable_move 上方
Local $temp = GUIGetCursorInfo()
If $temp = 0 Then Return
If $temp <> $lable_move Then Return
;?取鼠?和GUI的相?位置
Local $GuiPos = WinGetPos($GUI)
Local $MousePos = MouseGetPos()
Local $PosDiff
$PosDiff = $GuiPos - $MousePos
$PosDiff = $GuiPos - $MousePos
;移?GUI
While _IsPressed("01")
Local $MousePos = MouseGetPos()
WinMove($GUI, "", $MousePos + $PosDiff, $MousePos + $PosDiff)
Sleep(10)
WEnd
EndFunc
Func GUI_COMMAND()
Switch @GUI_CtrlId
Case $lable_close
Exit
EndSwitch
EndFunc
本帖最后由 fenhanxue 于 2018-1-4 11:10 编辑
回复 4# kk_lee69
这样不行呀,KK
如下述代码,当没有触发$bt的时候,窗口是可以自由拖动的
但是,当$bt 触发后,就不能自由拖动了,必须等$bt所对应的函数运行完才行(下例子中的func other())
所以我想弄个注册消息的方式来实现拖动#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>
Opt("GUIOnEventMode", 1)
Global $GUI = GUICreate("", 400, 200, -1, -1,$WS_POPUP)
Global $lable_move = GUICtrlCreateLabel("", 0, 0, 370, 30)
GUICtrlSetBkColor(-1, 0x99D9EA)
Global $lable_close = GUICtrlCreateLabel("??", 375, 0, 25, 30)
GUISetState(@SW_SHOW)
GUISetOnEvent($GUI_EVENT_PRIMARYDOWN, "GUI_Move")
GUICtrlSetOnEvent($lable_close, "GUI_COMMAND")
#region我添加的
Global $bt = GUICtrlCreateButton('点我',0,50,400,40)
GUICtrlSetOnEvent($bt, "other")
#endregion
While 1
WEnd
#region我添加的
Func other()
GUICtrlSetData($bt,'此时你是无法拖动窗口的,但是我想要此时拖动窗口')
For $i = 1 To 10
Sleep(1000)
ConsoleWrite($i)
Next
GUICtrlSetData($bt,'点我')
EndFunc
#endregion
Func GUI_Move()
;判??前鼠?是否在 $lable_move 上方
Local $temp = GUIGetCursorInfo()
If $temp = 0 Then Return
If $temp <> $lable_move Then Return
;?取鼠?和GUI的相?位置
Local $GuiPos = WinGetPos($GUI)
Local $MousePos = MouseGetPos()
Local $PosDiff
$PosDiff = $GuiPos - $MousePos
$PosDiff = $GuiPos - $MousePos
;移?GUI
While _IsPressed("01")
Local $MousePos = MouseGetPos()
WinMove($GUI, "", $MousePos + $PosDiff, $MousePos + $PosDiff)
Sleep(10)
WEnd
EndFunc
Func GUI_COMMAND()
Switch @GUI_CtrlId
Case $lable_close
Exit
EndSwitch
EndFunc
回复 5# fenhanxue
我覺得應該不可以吧
依照你的範例事實上不管你用哪種方法 當BT 被執行的時候程式都是 是在長時間忙碌
你也知道AU3 是單線程.........所以 怎麼可能 還有其他的 能力 可以去處理 移動...
標準的 可能可以 移動 那是 因為是WINDOWS 在負責 移動的工作 本帖最后由 fenhanxue 于 2018-1-4 12:15 编辑
回复 6# kk_lee69
GUIRegisterMsg可以避开单线程的坑的,只是我对系统消息所掌握的水平实在有限,写不出来,看下面例子:
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>
Opt("GUIOnEventMode", 1)
Global $GUI = GUICreate("", 400, 200, -1, -1,$WS_POPUP)
Global $lable_move = GUICtrlCreateLabel("", 0, 0, 370, 30)
GUICtrlSetBkColor(-1, 0x99D9EA)
Global $lable_close = GUICtrlCreateLabel("??", 375, 0, 25, 30)
GUISetState(@SW_SHOW)
GUICtrlSetOnEvent($lable_close, "GUI_COMMAND")
#region我添加的
Global $bt = GUICtrlCreateButton('点我',0,50,400,40)
GUICtrlSetOnEvent($bt, "other")
#endregion
GUIRegisterMsg($WM_LBUTTONDOWN, "WM_LBUTTONDOWN")
While 1
WEnd
Func WM_LBUTTONDOWN($hWndGUI, $MsgID, $WParam, $LParam)
ConsoleWrite(1)
GUI_Move()
EndFunc
#region我添加的
Func other()
GUICtrlSetData($bt,'此时你是无法拖动窗口的,但是我想要此时拖动窗口')
For $i = 1 To 10
Sleep(1000)
ConsoleWrite($i)
Next
GUICtrlSetData($bt,'点我')
EndFunc
#endregion
Func GUI_Move()
;判??前鼠?是否在 $lable_move 上方
Local $temp = GUIGetCursorInfo()
If $temp = 0 Then Return
;If $temp <> $lable_move Then Return
;?取鼠?和GUI的相?位置
Local $GuiPos = WinGetPos($GUI)
Local $MousePos = MouseGetPos()
Local $PosDiff
$PosDiff = $GuiPos - $MousePos
$PosDiff = $GuiPos - $MousePos
;移?GUI
While _IsPressed("01")
Local $MousePos = MouseGetPos()
WinMove($GUI, "", $MousePos + $PosDiff, $MousePos + $PosDiff)
Sleep(10)
WEnd
EndFunc
Func GUI_COMMAND()
Switch @GUI_CtrlId
Case $lable_close
Exit
EndSwitch
EndFunc上面的例子就可以移动。例子的关键是这一行代码:
GUIRegisterMsg($WM_LBUTTONDOWN, "WM_LBUTTONDOWN")
上述代码,我鼠标如果是左键,按住GUI窗口,是可以捕获到消息,并触发函数
WM_LBUTTONDOWN() 的
但是,当我鼠标如果按住的是 $lable_move 这个控件,则捕获不到 $WM_LBUTTONDOWN 消息,也就没法触发函数
WM_LBUTTONDOWN()
所以我想知道问题出在哪里,如何才能捕获到鼠标按住$lable_move控件 的消息 更精简一点的问题是:
鼠标左键按下(非放开。down 非 up)$lable_move 所对应的Windows消息ID是什么 回复 8# fenhanxue
沒時間測試
你的情況 跟我之前遇到一個類似
重點是 你無法 真正抓到 滑鼠 按下的那個觸發點
下面 可以可是標題 不可以
標題其實是因為 圖片 卡住了
放在圖片 其他 功能循環時候 又不行
所以 癥結點 在於 抓到滑鼠 按下的瞬間
可能要使用 回CALL 的方法
參考一下 下面的 用法
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPIShellEx.au3>
#include <GuiListView.au3>
Opt( "MustDeclareVars", 1 )
Global $idListView, $idAddSingleSel, $idDelSingleSel
Example()
Func Example()
; Create GUI
GUICreate( "ctrl+single-click --> single-click", 420, 200 )
; Create ListView
$idListView = GUICtrlCreateListView( "", 10, 10, 400, 180, $GUI_SS_DEFAULT_LISTVIEW-$LVS_SINGLESEL, $WS_EX_CLIENTEDGE )
_GUICtrlListView_SetExtendedListViewStyle( $idListView, $LVS_EX_DOUBLEBUFFER+$LVS_EX_FULLROWSELECT )
Local $hListView = GUICtrlGetHandle( $idListView )
; Add columns to ListView
_GUICtrlListView_InsertColumn( $idListView, 0, "Column 1", 94 )
_GUICtrlListView_InsertColumn( $idListView, 1, "Column 2", 94 )
_GUICtrlListView_InsertColumn( $idListView, 2, "Column 3", 94 )
_GUICtrlListView_InsertColumn( $idListView, 3, "Column 4", 94 )
; Fill ListView
Local $iItems = 100
For $i = 0 To $iItems - 1
GUICtrlCreateListViewItem( $i & "/Column 1|" & $i & "/Column 2|" & $i & "/Column 3|" & $i & "/Column 4", $idListView )
Next
; Subclass ListView to receive keyboard/mouse messages
Local $pListViewFunc = DllCallbackGetPtr( DllCallbackRegister( "ListViewFunc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr" ) )
_WinAPI_SetWindowSubclass( $hListView, $pListViewFunc, 0, 0 ) ; $iSubclassId = 0, $pData = 0
; Add/del single selection
$idAddSingleSel = GUICtrlCreateDummy()
$idDelSingleSel = GUICtrlCreateDummy()
Local $iItem
; Show GUI
GUISetState( @SW_SHOW )
; Message loop
While 1
Switch GUIGetMsg()
Case $idAddSingleSel
$iItem = GUICtrlRead( $idAddSingleSel )
_GUICtrlListView_SetItemSelected( $idListView, $iItem, True )
_GUICtrlListView_SetItemFocused( $idListView, $iItem )
Case $idDelSingleSel
$iItem = GUICtrlRead( $idDelSingleSel )
_GUICtrlListView_SetItemSelected( $idListView, $iItem, False )
_GUICtrlListView_SetItemFocused( $idListView, $iItem )
Case $GUI_EVENT_CLOSE
ExitLoop
EndSwitch
WEnd
; Cleanup
_WinAPI_RemoveWindowSubclass( $hListView, $pListViewFunc, 0 )
GUIDelete()
EndFunc
Func ListViewFunc( $hWnd, $iMsg, $wParam, $lParam, $iSubclassId, $pData )
If $iMsg <> $WM_LBUTTONDOWN Then Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )
Switch $wParam
Case 0x0001; 0x0001 = MK_LBUTTON (LButton down)
If _GUICtrlListView_GetSelectedCount( $idListView ) Then
Local $aHit = _GUICtrlListView_HitTest( GUICtrlGetHandle( $idListView ), BitAND( $lParam, 0xFFFF ), BitShift( $lParam, 16 ) )
If Not ( @error Or $aHit = -1 ) Then
If _GUICtrlListView_GetItemSelected( $idListView, $aHit ) Then
GUICtrlSendToDummy( $idDelSingleSel, $aHit )
Else
GUICtrlSendToDummy( $idAddSingleSel, $aHit )
EndIf
EndIf
Return 0 ; Disable single-click in ListView to prevent resetting selections
EndIf
Case 0x0009; 0x0009 = MK_LBUTTON (LButton down) + MK_CONTROL (Ctrl down)
Return 0 ; Disable single selections in ListView with ctrl+single-click
EndSwitch
Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )
; Call next function in subclass chain (this forwards messages to main GUI)
#forceref $iSubclassId, $pData
EndFunc
上面範例 要看的是 滑鼠 攔截消息的方法 回复 8# fenhanxue
解決了
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>
Opt("GUIOnEventMode", 1)
Global $GUI = GUICreate("", 400, 200, -1, -1,$WS_POPUP)
Global $lable_move = GUICtrlCreateLabel("", 0, 0, 370, 30)
GUICtrlSetBkColor(-1, 0x99D9EA)
Global $lable_close = GUICtrlCreateLabel("??", 375, 0, 25, 30)
GUISetState(@SW_SHOW)
GUICtrlSetOnEvent($lable_close, "GUI_COMMAND")
GUIRegisterMsg($WM_COMMAND, "MY_WM_COMMAND")
#region我添加的
Global $bt = GUICtrlCreateButton('?我',0,50,400,40)
GUICtrlSetOnEvent($bt, "other")
#endregion
GUIRegisterMsg($WM_LBUTTONDOWN, "WM_LBUTTONDOWN")
While 1
WEnd
Func WM_LBUTTONDOWN($hWndGUI, $MsgID, $WParam, $LParam)
ConsoleWrite(999)
GUI_Move()
EndFunc
#region我添加的
Func other()
GUICtrlSetData($bt,'此?你是?法拖?窗口的,但是我想要此?拖?窗口')
For $i = 1 To 10
Sleep(1000)
ConsoleWrite($i)
Next
GUICtrlSetData($bt,'?我')
EndFunc
#endregion
Func GUI_Move()
;判??前鼠?是否在 $lable_move 上方
Local $temp = GUIGetCursorInfo()
If $temp = 0 Then Return
;If $temp <> $lable_move Then Return
;?取鼠?和GUI的相?位置
Local $GuiPos = WinGetPos($GUI)
Local $MousePos = MouseGetPos()
Local $PosDiff
$PosDiff = $GuiPos - $MousePos
$PosDiff = $GuiPos - $MousePos
;移?GUI
While _IsPressed("01")
Local $MousePos = MouseGetPos()
WinMove($GUI, "", $MousePos + $PosDiff, $MousePos + $PosDiff)
Sleep(10)
WEnd
EndFunc
Func GUI_COMMAND()
Switch @GUI_CtrlId
Case $lable_close
Exit
Case $lable_move
GUI_Move()
EndSwitch
EndFunc
Func MY_WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
Local $nNotifyCode = BitShift($wParam, 16)
Local $nID = BitAND($wParam, 0x0000FFFF)
Local $hCtrl = $lParam
Switch $nID
CASE $lable_move
GUI_Move()
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc 回复 10# kk_lee69
谢谢KK,
奇怪的是为什么$WM_LBUTTONDOWN 消息在控件上无法捕获 回复 11# fenhanxue
其實 AU3 還是單線程 當你移動時迴圈也就停止了...
所以 只是 誰先跑 誰後跑.....
至於 WM_LBUTTONDOWN我也不知道 但是之前就有發現.....
页:
[1]