找回密码
 加入
搜索
查看: 2232|回复: 11

[AU3基础] $GUI_EVENT_PRIMARYDOWN 对应的消息模式应该怎么写?【已解决】

  [复制链接]
发表于 2018-1-3 20:43:00 | 显示全部楼层 |阅读模式
本帖最后由 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[4] <> $lable_move Then Return
                
                ;获取鼠标和GUI的相对位置
                Local $GuiPos = WinGetPos($GUI)
                Local $MousePos = MouseGetPos()
                Local $PosDiff[2]
         $PosDiff[0] = $GuiPos[0] - $MousePos[0]
         $PosDiff[1] = $GuiPos[1] - $MousePos[1]


                ;移动GUI
        While _IsPressed("01")
                        Local $MousePos = MouseGetPos()
                        WinMove($GUI, "", $MousePos[0] + $PosDiff[0], $MousePos[1] + $PosDiff[1])
                        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[4] <> $lable_move Then Return
                
                ;获取鼠标和GUI的相对位置
                Local $GuiPos = WinGetPos($GUI)
                Local $MousePos = MouseGetPos()
                Local $PosDiff[2]
         $PosDiff[0] = $GuiPos[0] - $MousePos[0]
         $PosDiff[1] = $GuiPos[1] - $MousePos[1]


                ;移动GUI
        While _IsPressed("01")
                        Local $MousePos = MouseGetPos()
                        WinMove($GUI, "", $MousePos[0] + $PosDiff[0], $MousePos[1] + $PosDiff[1])
                        Sleep(10)
                WEnd
EndFunc
        
        
        
Func WM_LBUTTONDOWN($hWndGUI, $MsgID, $WParam, $LParam)
        ConsoleWrite(1)
        GUI_Move()
EndFunc
        
发表于 2018-1-4 09:39:34 | 显示全部楼层
回复 1# fenhanxue

http://www.autoit3.cn/forum.php? ... t=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
发表于 2018-1-4 10:10:34 | 显示全部楼层
发表于 2018-1-4 10:28:36 | 显示全部楼层
回复 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[4] <> $lable_move Then Return
                
                ;?取鼠?和GUI的相?位置
                Local $GuiPos = WinGetPos($GUI)
                Local $MousePos = MouseGetPos()
                Local $PosDiff[2]
         $PosDiff[0] = $GuiPos[0] - $MousePos[0]
         $PosDiff[1] = $GuiPos[1] - $MousePos[1]


                ;移?GUI
        While _IsPressed("01")
                        Local $MousePos = MouseGetPos()
                        WinMove($GUI, "", $MousePos[0] + $PosDiff[0], $MousePos[1] + $PosDiff[1])
                        Sleep(10)
                WEnd
EndFunc
        


Func GUI_COMMAND()
    Switch @GUI_CtrlId

                Case $lable_close
                         Exit
        EndSwitch
EndFunc                
        
 楼主| 发表于 2018-1-4 11:07:33 | 显示全部楼层
本帖最后由 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[4] <> $lable_move Then Return
                
                ;?取鼠?和GUI的相?位置
                Local $GuiPos = WinGetPos($GUI)
                Local $MousePos = MouseGetPos()
                Local $PosDiff[2]
         $PosDiff[0] = $GuiPos[0] - $MousePos[0]
         $PosDiff[1] = $GuiPos[1] - $MousePos[1]
 
 
                ;移?GUI
        While _IsPressed("01")
                        Local $MousePos = MouseGetPos()
                        WinMove($GUI, "", $MousePos[0] + $PosDiff[0], $MousePos[1] + $PosDiff[1])
                        Sleep(10)
                WEnd
EndFunc
        
 
 
Func GUI_COMMAND()
    Switch @GUI_CtrlId
 
                Case $lable_close
                         Exit
        EndSwitch
EndFunc
发表于 2018-1-4 11:52:28 | 显示全部楼层
回复 5# fenhanxue

我覺得應該不可以吧

依照你的範例  事實上  不管你用哪種方法 當BT 被執行的時候  程式都是 是在長時間忙碌

你也知道  AU3 是單線程.........  所以 怎麼可能 還有其他的 能力 可以去處理 移動...

標準的 可能可以 移動   那是 因為  是WINDOWS 在負責 移動的工作
 楼主| 发表于 2018-1-4 12:12:57 | 显示全部楼层
本帖最后由 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[4] <> $lable_move Then Return
                
                ;?取鼠?和GUI的相?位置
                Local $GuiPos = WinGetPos($GUI)
                Local $MousePos = MouseGetPos()
                Local $PosDiff[2]
         $PosDiff[0] = $GuiPos[0] - $MousePos[0]
         $PosDiff[1] = $GuiPos[1] - $MousePos[1]
 
 
                ;移?GUI
        While _IsPressed("01")
                        Local $MousePos = MouseGetPos()
                        WinMove($GUI, "", $MousePos[0] + $PosDiff[0], $MousePos[1] + $PosDiff[1])
                        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控件 的消息

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
 楼主| 发表于 2018-1-4 12:22:22 | 显示全部楼层
更精简一点的问题是:

鼠标左键按下(非放开。down   非 up)$lable_move 所对应的  Windows消息ID  是什么
发表于 2018-1-4 13:26:05 | 显示全部楼层
回复 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 )[0]

  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[0] = -1 ) Then
          If _GUICtrlListView_GetItemSelected( $idListView, $aHit[0] ) Then
            GUICtrlSendToDummy( $idDelSingleSel, $aHit[0] )
          Else
            GUICtrlSendToDummy( $idAddSingleSel, $aHit[0] )
          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 )[0]
  ; Call next function in subclass chain (this forwards messages to main GUI)
  #forceref $iSubclassId, $pData
EndFunc


上面範例 要看的是 滑鼠 攔截消息的方法
发表于 2018-1-4 14:21:19 | 显示全部楼层
回复 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[4] <> $lable_move Then Return
                
                ;?取鼠?和GUI的相?位置
                Local $GuiPos = WinGetPos($GUI)
                Local $MousePos = MouseGetPos()
                Local $PosDiff[2]
         $PosDiff[0] = $GuiPos[0] - $MousePos[0]
         $PosDiff[1] = $GuiPos[1] - $MousePos[1]


                ;移?GUI
        While _IsPressed("01")
                        Local $MousePos = MouseGetPos()
                        WinMove($GUI, "", $MousePos[0] + $PosDiff[0], $MousePos[1] + $PosDiff[1])
                        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  
 楼主| 发表于 2018-1-4 17:16:41 | 显示全部楼层
回复 10# kk_lee69


    谢谢KK,

奇怪的是为什么  $WM_LBUTTONDOWN 消息在控件上无法捕获
发表于 2018-1-4 17:20:09 | 显示全部楼层
回复 11# fenhanxue

其實 AU3 還是單線程   當你  移動時  迴圈也就停止了...
所以 只是 誰先跑 誰後跑.....

至於 WM_LBUTTONDOWN  我也不知道    但是之前就有發現.....
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-11-16 20:51 , Processed in 0.077666 second(s), 20 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表