Friday, August 19, 2016

[AutoIT] Di chuyển Form không cần thanh Caption

 

 Di chuyển Form không cần thanh Caption

Như các bạn đã biết thông thường chúng ta di chuyển một cửa sổ bằng cách kích chuột vào thanh tiêu đề caption và nắm kéo. Nếu cửa sổ không có thanh tiêu đề ví dụ bạn tạo GUI với style là POPUP chẳng hạn thì sao? Hôm nay mình sẽ hướng dẫn các bạn cách để di chuyển một cửa sổ mà không cần đến thanh Caption bất kể cửa sổ đó có thanh Caption hay không :) Let’s go!


Lưu ý các ví dụ trong này đều sử dụng phím tắt là phím "Escape" để thoát chương trình nhé!
Cách 1: Sử dụng style: $GUI_WS_EX_PARENTDRAG
Tư duy của phương pháp này như sau: Tại những nơi mà bạn muốn có thể kéo thả được thì bạn chỉ cần áp cho nó style: $GUI_WS_EX_PARENTDRAG. Áp dụng style này với các đối tượng như Label, hoặc Picture. Khi đó khi bạn kích và giữ chuột ở những vị trí này bạn sẽ có thể di chuyển Form như khi bạn kích vào thanh Caption.
Bạn xem ví dụ sau:
 #include <GuiconstantsEx.au3>
 #include <WindowsConstants.au3>
 
 HotKeySet("{ESC}", "On_Exit")
 
 $hGUI = GUICreate("X", 100, 100, -1, -1, $WS_POPUP)
 GUISetBkColor(0xFF0000, $hGUI)
 $hLabel = GUICtrlCreateLabel("", 0, 0, 100, 50, -1, $GUI_WS_EX_PARENTDRAG)
 GUICtrlSetBkColor(-1, 0x00FF00)
 ;GUICtrlSetState(-1, $GUI_DISABLE)
 $hButton = GUICtrlCreateButton("Test", 10, 35, 80, 30)
 GUISetState()
 
 While 1
     Switch GUIGetMsg()
         Case $hButton
             On_Button()
     EndSwitch
 WEnd
 
 Func On_Button()
     MsgBox(0, "Hi", "Button Pressed")
 EndFunc   ;==>On_Button
 
 Func On_Exit()
     Exit
 EndFunc   ;==>On_Exit
Form này được để style là: $WS_POPUP do đó nếu thông thường bạn sẽ không thể nào di chuyển nó được nhưng ở đây chúng ta đã tạo ra một Label mà vị trí Label này ở trên giống vị trí thanh Caption nên khi click và giữ chuột bạn hoàn thoàn có thể di chuyển nó! Bạn có thể làm tương tự với đối tượng Picture nhé!

Cách 2: Trả về kết quả $SC_DRAGMOVE lại cho windows
Ở đây chúng ta sẽ gửi lại cho windows 1 thông điệp khi mà chuột được nhấn giữ để thay đổi vị trí windows khi mà ta kéo chuột di chuyển. Ưu điểm của cách này là bạn có thể nhấn giữ chuột và thay đổi vị trí windows tại vị trí bất kỳ trên Form. Và theo mình đây cũng là cách nhanh nhất nhé! Tuy nhiên hằng số sử dụng trong này là số hexa: $F012 là một điểm rất đặc biệt đây là một hằng số không công bố trong bất cứ tài liệu nào của Microsoft trong các thư viện win32API và cũng chẳng ai hiểu được tại sao nó lại có tác dụng như vậy! :))
Code mẫu:
 ; Original code - martin
 #include <GuiconstantsEx.au3>
 #include <WindowsConstants.au3>
 #include <SendMessage.au3>
 
 Global Const $SC_DRAGMOVE = 0xF012
 
 HotKeySet("{ESC}", "On_Exit")
 
 $hGUI = GUICreate("X", 100, 100, -1, -1, $WS_POPUP)
 GUISetBkColor(0x00FF00, $hGUI)
 $hButton = GUICtrlCreateButton("Test", 10, 35, 80, 30)
 GUISetState()
 
 While 1
     Switch GUIGetMsg()
         Case $GUI_EVENT_PRIMARYDOWN
             _SendMessage($hGUI, $WM_SYSCOMMAND, $SC_DRAGMOVE, 0)
         Case $hButton
             On_Button()
     EndSwitch
 WEnd
 
 Func On_Button()
     MsgBox(0, "Hi", "Button Pressed")
 EndFunc   ;==>On_Button
 
 Func On_Exit()
     Exit
 EndFunc   ;==>On_Exit

Cách 3: Gửi thông điệp: $WM_NCLBUTTONDOWN
Trong cách này chúng ta sẽ phát hiện khi nào mà chuột trái được nhấn và chúng ta sẽ gửi lại thông điệp cho windows $WM_NCLBUTTONDOWN khiến cho widows nhầm tưởng rằng con trỏ chuột đang ở vị trí thanh Caption và sẽ di chuyển cửa sổ windows!
Code mẫu:
 #include <GuiconstantsEx.au3>
 #include <WindowsConstants.au3>
 #include <SendMessage.au3>
 
 HotKeySet("{ESC}", "On_Exit")
 
 $hGUI = GUICreate("X", 100, 100, -1, -1, $WS_POPUP)
 GUISetBkColor(0x00FF00, $hGUI)
 $hButton = GUICtrlCreateButton("Test", 10, 35, 80, 30)
 GUISetState()
 
 While 1
     Switch GUIGetMsg()
         Case $GUI_EVENT_PRIMARYDOWN
             On_Drag()
         Case $hButton
             On_Button()
     EndSwitch
 WEnd
 
 Func On_Drag()
     Local $aCurInfo = GUIGetCursorInfo($hGUI)
     If $aCurInfo[4] = 0 Then ; Mouse not over a control
         DllCall("user32.dll", "int", "ReleaseCapture")
         _SendMessage($hGUI, $WM_NCLBUTTONDOWN, $HTCAPTION, 0)
     EndIf
 EndFunc   ;==>On_Drag
 
 Func On_Exit()
     Exit
 EndFunc   ;==>On_Exit
 
 Func On_Button()
      MsgBox(0, "Hi", "Button Pressed")
 EndFunc   ;==>On_Button

Cách 4: Gửi cho windows thông điệp: $WM_NCHITTEST
Như bạn đã biết khi chuột di chuyển vào các vị trí đặc biệt như trên caption, trên menu, trên nút nhấn min, max, close... Windows gửi thông điệp $WM_NCHITTEST để ta kiểm tra và xử lý. Nếu bạn kích chuột trái vào một điểm bất kì trên Form, đón bắt thông điệp $WM_NCHITTEST và trả về kết quả $HTCAPTION Windows sẽ lầm tưởng là bạn đang nắm chuột vào thanh tiêu đề caption cho nên sẽ tự động di chuyển Form theo ý của bạn. Trong code mẫu này có đoạn kiểm tra xem vị trí con trỏ chuột có đang nhỏ hơn 50 pixels nếu có thì sẽ trả về thông điệp $HTCAPTION nếu bạn muốn di chuyển ở vị trí nào cũng được thì hãy bỏ đoạn check này đi nhé!
Code mẫu:
 #include <GuiconstantsEx.au3>
 #include <WindowsConstants.au3>
 #include <SendMessage.au3>
 
 HotKeySet("{ESC}", "On_Exit")
 
 $hGUI = GUICreate("X", 100, 100, -1, -1, $WS_POPUP)
 GUISetBkColor(0x00FF00, $hGUI)
 GUICtrlCreateLabel("", 0, 50, 100, 50)
 GUICtrlSetBkColor(-1, 0xFF0000)
 GUICtrlSetState(-1, $GUI_DISABLE)
 $hButton = GUICtrlCreateButton("Test", 10, 35, 80, 30)
 GUISetState()
 
 GUIRegisterMsg($WM_NCHITTEST, "_MY_NCHITTEST")
 
 While 1
     Switch GUIGetMsg()
         Case $hButton
             On_Button()
     EndSwitch
 WEnd
 
 ; Original code - Prog@ndy
 Func _MY_NCHITTEST($hWnd, $uMsg, $wParam, $lParam)
     Switch $hWnd
         Case $hGUI
             Local $aPos = WinGetPos($hWnd) ; Check if mouse is over top 50 pixels
             If Abs(BitAND(BitShift($lParam, 16), 0xFFFF) - $aPos[1]) < 50 Then Return $HTCAPTION
     EndSwitch
     Return $GUI_RUNDEFMSG
 EndFunc   ;==>_MY_NCHITTEST
 
 Func On_Button()
     MsgBox(0, "Hi", "Button Pressed")
 EndFunc   ;==>On_Button
 
 Func On_Exit()
     Exit
 EndFunc   ;==>On_Exit

Trên đây là những kinh nhiệm mà mình thấy hay và mong muốn nó sẽ giúp ích cho các bạn!
Nguồn: https://www.autoitscript.com/wiki/Moving_and_Resizing_PopUp_GUIs

Pass giải nén(nếu có) :http://nothing1010.blogspot.com
 Lưu ý với các bạn là blog của mình sử dụng WinRar 5 để nén nên các bạn phải dùng WinRar5 để giải nén nhé! Nếu bạn nào chưa có thì có thể vào ĐÂY để tải và cài đặt bản mới nhất nhé!

1 comment:
Write nhận xét