Jump to content

[Half-Solved] Nasty issue with GuiRegisterMsg( wm_lbuttondown )


4ggr35510n
 Share

Recommended Posts

Greetings!

Using GuiRegisterMsg I've registered two functions, as in this simple example below.

And almost immediately I've encounter two major, nasty issues:

- This MSG doesn't work when clicked on Gui Element (such as one of labels)

- It is not capable to recieve wm_lbuttonup from outside the window, even if lbuttondown happend inside window :/

Could you give me some hints and ideas, how should I done it properly, to

a) get msg even in clicked on gui element,

B) get msg from 'outside' the window (if the window is still active!) or at least some way to recognize when and at which position mouse is leaving my gui window?

I'll really appreciate your help!

BR,

4gr

$hGUI = GUICreate("Menu", 400, 300)
    $label = GUICtrlCreateLabel('', 1, 1, 390, 20)
    $label2 = GUICtrlCreateLabel('',1, 100, 390, 20)
    GUISetState()

    ; Register message handlers
    GUIRegisterMsg(0x0201, 'L_down')
    GUIRegisterMsg(0x0202, 'L_up')

    ; Loop until user exits
    Do
    Until GUIGetMsg() = -3


Func L_down($hWnd, $iMsg, $iwParam, $ilParam)
    GUICtrlSetData($label, Dec(StringMid($ilParam, 3, 4)) & '     ' & Dec(StringMid($ilParam, 7, 4)))
    ConsoleWrite('KLIK' & @CRLF)
EndFunc

Func L_up($hWnd, $iMsg, $iwParam, $ilParam)
    GUICtrlSetData($label2, Dec(StringMid($ilParam, 3, 4)) & '     ' & Dec(StringMid($ilParam, 7, 4)))
EndFunc
Edited by 4ggr35510n
Link to comment
Share on other sites

Thank you for answer, AdmiralAlkex!

Very nice script and really useful... But on my (very poor) PC it's taking up to 50% of CPU :[

I've found THIS cool script that receives only mouse events from inside the gui, which solves my first problem :]

Yet neither of those two are able to get WM_MOUSELEAVE message code...

MSDN says that to receive 'mouseleave' you have to make prior call to TrackMouseEvent. I've searched on forum, but there was only one topic about it, which doesn't help me at all ;)

I'm not as advanced to crack it by myself... Could you please help me with this? :]

Edited by 4ggr35510n
Link to comment
Share on other sites

Not released, not necessarily. I just need to know when the mouse leaves gui...

Eh, I don't know how to explain... Run this examples, please:

#include <winapi.au3>

$gui_handle = GUICreate('abba', 700, 400)

Global $pic_X = 600/2
Global $pic_Y = 300/2

Global $mouse_X, $mouse_Y

Global $pic_handle = GUICtrlCreatePic('', $pic_X, $pic_Y, 1, 1)
$bitmap = _WinApi_CreateSolidBitmap($gui_handle, 0xFF00FF, 100, 100)
GUICtrlSendMsg($pic_handle, 0x0172, 0, $bitmap)

GUISetState()


; Register message handlers
GUIRegisterMsg(0x0201, 'Down')
GUIRegisterMsg(0x0202, 'Up')

; Loop until user exits
Do
Until GUIGetMsg() = -3


Func Down($hWnd, $iMsg, $iwParam, $ilParam)
        $mouse_Y = BitShift($iLParam, 16)
        $mouse_X = BitAND($iLParam, 0xFFFF)
EndFunc

Func Up($hWnd, $iMsg, $iwParam, $ilParam)
    $pic_Y -= BitShift($iLParam, 16) - $mouse_Y
    $pic_X -= BitAND($iLParam, 0xFFFF) - $mouse_X
    GUICtrlSetPos($pic_handle, $pic_X, $pic_y)
EndFunc

Basically, the idea is to move image while moving mouse holding LBM.

In spoiler below, there is a version with dynamic moving, using MouseMove, not LButtonDown and Up messages.

Run this please, because I will rather go with this option:

#include <winapi.au3>

$gui_handle = GUICreate('Dynamic Moving Pic With Mouse', 700, 400)

Global $pic_X = 300
Global $pic_Y = 150

Global $mouse_X, $mouse_Y, $do_move = 0

Global $pic_handle = GUICtrlCreatePic('', $pic_X, $pic_Y, 1, 1)
$bitmap = _WinApi_CreateSolidBitmap($gui_handle, 0xFF00FF, 100, 100)
GUICtrlSendMsg($pic_handle, 0x0172, 0, $bitmap)

GUISetState()

; Register message handlers
GUIRegisterMsg(0x0200, 'Move')

; Loop until user exits
Do
Until GUIGetMsg() = -3


Func Move($hWnd, $iMsg, $iwParam, $ilParam)
    $mouse_Y_temp = BitShift($iLParam, 16)
    $mouse_X_temp = BitAND($iLParam, 0xFFFF)

    If BitAnd($iwParam, 0x1) Then
        If $mouse_Y_temp <> $mouse_X OR $mouse_X_temp <> $mouse_X Then
            $pic_Y += $mouse_y_temp - $mouse_Y
            $pic_X += $mouse_X_temp - $mouse_X
            $mouse_X = $mouse_X_temp
            $mouse_Y = $mouse_Y_temp
            GUICtrlSetPos($pic_handle, $pic_X, $pic_y)
        EndIf
    Else
        $mouse_X = $mouse_X_temp
        $mouse_Y = $mouse_Y_temp
    EndIf
EndFunc

Yet I don't know how to do 2 things:

- get msg when mouse is leaving gui or when MouseUp is done outside

(its needed only in first case, because mouse move stops automatically on leaving)

-Get windows mouse messages even if clicked on gui element?

(need this anyway for both and this issue is killing me. how to get msg when clicking on gui element, in some simple way, without overloading CPU? ;):))

@EDIT:

I've found a way how to bypass 'not getting msg from gui-element' issue.

Pasted in spoiler below, creating second window and adding 'movement speed' option.

Yet I would like not using this solution in final code, so if someone could give me advice, how to get msg from element, I would be uncommonly thankful, able to create just one, neat and clean window :]

#include <winapi.au3>

$gui_handle = GUICreate('MAPA', 700, 400)

Global $pic_X = 300
Global $pic_Y = 150

Global $mouse_X, $mouse_Y, $do_move = 0

Global $pic_handle = GUICtrlCreatePic('', $pic_X, $pic_Y, 1, 1)
$bitmap = _WinApi_CreateSolidBitmap($gui_handle, 0xFF00FF, 100, 100)
GUICtrlSendMsg($pic_handle, 0x0172, 0, $bitmap)

GUISetState()
Global $_SPEED = 3
$gui_control = GuiCreate('MapControl', 100, 100, 100, 100, Default, 0x00000080)
$p = GUICtrlCreateButton('+',0,0, 20)
$m = GUICtrlCreateButton('-',20,0, 20)
$label = GUICtrlCreateLabel($_SPEED, 40,0, 30,12)
GUIRegisterMsg(0x0200, 'Move')
GUISetState()

While True
    Switch GUIGetMsg()
        Case $p
            $_SPEED += 1
            GUICtrlSetData($label, $_SPEED)
        Case $m
            $_SPEED -= 1
            GUICtrlSetData($label, $_SPEED)
        Case -3
            Exit
    EndSwitch
WEnd


Func Move($hWnd, $iMsg, $iwParam, $ilParam)
    If $hWnd = $gui_control Then
    $mouse_Y_temp = BitShift($iLParam, 16)
    $mouse_X_temp = BitAND($iLParam, 0xFFFF)

    If BitAnd($iwParam, 0x1) Then
        If $mouse_Y_temp <> $mouse_X OR $mouse_X_temp <> $mouse_X Then
            $pic_Y += ($mouse_y_temp - $mouse_Y) * $_SPEED
            $pic_X += ($mouse_X_temp - $mouse_X) * $_SPEED
            $mouse_X = $mouse_X_temp
            $mouse_Y = $mouse_Y_temp
            GUICtrlSetPos($pic_handle, $pic_X, $pic_y)
        EndIf
    Else
        $mouse_X = $mouse_X_temp
        $mouse_Y = $mouse_Y_temp
    EndIf
    EndIf
EndFunc

Edited by 4ggr35510n
Link to comment
Share on other sites

-Get windows mouse messages even if clicked on gui element?

I thought that would be easy, just set a new window proc with SetWindowLong and read the necessary message.

#Include <WinAPI.au3>
#include <Constants.au3> ;For $GWL_WNDPROC
#include <WindowsConstants.au3> ;For $WM_MOUSEMOVE

$gui_handle = GUICreate('Dynamic Moving Pic With Mouse', 700, 400)

Global Const $MK_LBUTTON = 0x0001

$button = GUICtrlCreateButton("Click me!", 100, 100, 50, 30) ;To prove that messages still work

Global $pic_X = 300
Global $pic_Y = 150

Global $mouse_X, $mouse_Y

ConsoleWrite(3 & @CRLF)
Global $pic_handle = GUICtrlCreatePic('', $pic_X, $pic_Y, 1, 1)
$hPic = GUICtrlGetHandle($pic_handle)
$bitmap = _WinApi_CreateSolidBitmap($gui_handle, 0xFF00FF, 100, 100)
GUICtrlSendMsg($pic_handle, 0x0172, 0, $bitmap)
ConsoleWrite(4 & @CRLF)

GUISetState()

ConsoleWrite(1 & @CRLF)
;~ $wProcNew = DllCallbackRegister("_MyWindowProc", "ptr", "hwnd;uint;long;ptr")
;~ $wProcOld = _WinAPI_SetWindowLong($gui_handle, $GWL_WNDPROC, DllCallbackGetPtr($wProcNew)) ;Hijack the AutoIt message pump
ConsoleWrite(2 & @CRLF)

; Loop until user exits
While 1
    Switch GUIGetMsg()
        Case -3
            _WinAPI_SetWindowLong($gui_handle, $GWL_WNDPROC, $wProcOld) ;Maybe isn't necessary here, but better safe than sorry :P
            Exit
        Case $button
            MsgBox(0, "Some title", "Some text")
    EndSwitch
WEnd

Func _MyWindowProc($hWnd, $uiMsg, $wParam, $lParam)
    Static $mouse_X = "", $mouse_Y = ""
    If $uiMsg = $WM_MOUSEMOVE Then
        If $wParam = $MK_LBUTTON Then ;If left button is down
            $iPosX = BitAND($lParam, 0xFFFF) ; Low Word
            $iPosY = BitShift($lParam, 16) ; Hi Word

            $pic_X += $mouse_X -$iPosX
            $pic_Y += $mouse_Y -$iPosY

            If $pic_X < 0 Then $pic_X = 0
            If $pic_Y < 0 Then $pic_Y = 0
            If $pic_X > 600 Then $pic_X = 600
            If $pic_Y > 300 Then $pic_Y = 300

;~             ControlMove($gui_handle, "", $hPic, $pic_X, $pic_y)

            $mouse_X = $iPosX
            $mouse_Y = $iPosY
        EndIf
    EndIf

    ;pass the unhandled messages to default WindowProc
    Return _WinAPI_CallWindowProc($wProcOld, $hWnd, $uiMsg, $wParam, $lParam)
EndFunc   ;==>_MyWindowProc

That was an epic failure, I'm just dead-locking AutoIt.

Someone else must help you with this, I'm beaten ;)

Link to comment
Share on other sites

  • Moderators

4ggr35510n,

Basically, the idea is to move image while moving mouse holding LBM.

Perhaps you cannot do it using the messages you have been using. ;)

Does this help at all - it does seem to do what you want and does not kill my CPU: ;)

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

Global Const $SC_DRAGMOVE = 0xF012

; Create main GUI
$hGUI = GUICreate("Test", 500, 500)

GUISetState()

; Get system values for the GUI borders
Global $iBorder = _WinAPI_GetSystemMetrics(8) ; Border width
Global $iBar = _WinAPI_GetSystemMetrics(4) ; Title bar height
Global $aMain_Pos = WinGetPos($hGUI)

; Create the child GUI
$hGUI_Child = GUICreate("Child", 100, 100, 100, 100, $WS_POPUP, $WS_EX_MDICHILD, $hGUI)

$hPic = GUICtrlCreatePic("", 0, 0, 1, 1)
$hBitMap = _WinApi_CreateSolidBitmap($hGUI_Child, 0xFF00FF, 100, 100)
GUICtrlSendMsg($hPic, 0x0172, 0, $hBitMap)

GUISetState(@SW_SHOW, $hGUI_Child)

; Look for the child moving
GUIRegisterMsg($WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING")

While 1
    ; Use the advanced parameter to distinguish between GUIs
    $aMsg = GUIGetMsg(1)
    Switch $aMsg[1]
        Case $hGUI
            Switch $aMsg[0]
                Case $GUI_EVENT_CLOSE
                    Exit
            EndSwitch
        Case $hGUI_Child
            Switch $aMsg[0]
                ; If the mouse is down on the child
                Case $GUI_EVENT_PRIMARYDOWN
                    ; Tell the GUI to drag
                    _SendMessage($hGUI_Child, $WM_SYSCOMMAND, $SC_DRAGMOVE, 0)
            EndSwitch
    EndSwitch

WEnd

; Handler for the child moving
Func WM_WINDOWPOSCHANGING($hWnd, $Msg, $wParam, $lParam)

    ; If it the child sending the message
    If $hWnd = $hGUI_Child Then

        ; Get main GUI position and calculate current min and max positions for child
        $aMain_Pos = WinGetPos($hGUI)
        Local $iY_Min = $aMain_Pos[1] + $iBorder + $iBar
        Local $iY_Max = $aMain_Pos[1] + $iBorder + $iBar + 400
        Local $iX_Min = $aMain_Pos[0] + $iBorder
        Local $iX_Max = $aMain_Pos[0] + $iBorder + 400

        ; Get current child position
        Local $stWinPos = DllStructCreate("uint;uint;int;int;int;int;uint", $lParam)
        Local $iLeft = DllStructGetData($stWinPos, 3)
        Local $iTop = DllStructGetData($stWinPos, 4)
        Local $iWidth = DllStructGetData($stWinPos, 5)
        Local $iHeight = DllStructGetData($stWinPos, 6)

        ; Adjust as necessary to remain within the limits we set
        If $iLeft < $iX_Min Then DllStructSetData($stWinPos, 3, $iX_Min)
        If $iLeft > $iX_Max Then DllStructSetData($stWinPos, 3, $iX_Max)
        If $iTop < $iY_Min  Then DllStructSetData($stWinPos, 4, $iY_Min)
        If $iTop > $iY_Max  Then DllStructSetData($stWinPos, 4, $iY_Max)

    EndIf

EndFunc

I hope that you find it useful - even if it uses a very different technique to move the image. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

  • 1 month later...

Something like solved:

OnAutoItExitRegister('OnAutoitExit')

Global Const $tagPOINT = "int X;int Y"
Global Const $MSLLHOOKSTRUCT = $tagPOINT & ";dword mouseData;dword flags;dword time;ulong_ptr dwExtraInfo"


Global $hKey_Proc = DllCallbackRegister("MouseProc", "int", "int;ptr;ptr")

Global $hM_Module = DllCall("kernel32.dll", "hwnd", "GetModuleHandle", "ptr", 0)

Global $hM_Hook, $ptX = 0, $ptY = 0
Global $labX = 150, $labY = 150

Global $hGUI = GUICreate('Test', 75/100 * @DesktopWidth, 75/100 * @DesktopHeight)
Global $label = GUICtrlCreateLabel('MOVE ME!', $labX, $labY, 300, 300, BitOR(0x0200, 0x01) )
GUICtrlSetBkColor(-1, 0xFF00FF)
GUICtrlSetFont(-1, 22, 1200)
GUIRegisterMsg(0x0006, 'MouseHook_Manage')      ; WM_ACTIVATE
GUISetState()



Do
Until GuiGetMsg() = -3

Func MouseProc($nCode, $wParam, $lParam)
    Local $info, $x, $y

    Switch $wParam
        Case 0x0201
            $info = DllStructCreate($MSLLHOOKSTRUCT, $lParam)
            $ptX = DllStructGetData($info, 1)
            $ptY = DllStructGetData($info, 2)
            ConsoleWrite($ptX & '    ' & $ptY & @CRLF)
        Case 0x0202
            ;ConsoleWrite($labX & '    ' & $labY & @CRLF)
            $info = DllStructCreate($MSLLHOOKSTRUCT, $lParam)
            $x = DllStructGetData($info, 1)
            $y = DllStructGetData($info, 2)
            ConsoleWrite($x & '     ' & $y & @CRLF)
            $difx = $x - $ptX
            $dify = $y - $ptY
            $labX += $difx
            $labY += $dify
            ConsoleWrite($difx & '     ' & $dify & @CRLF)
            ControlMove($hGUI, '', $label, $labX, $labY)
    EndSwitch

EndFunc

Func MouseHook_Manage($hWND, $some_shit, $wActiveState)
    If $hGUI = $hWND Then
        Switch StringRight($wActiveState, 1)
            Case 0
                DllCall("user32.dll", "int", "UnhookWindowsHookEx", "hwnd", $hM_Hook[0])
                $hM_Hook[0] = 0
            Case 1
                $hM_Hook = DllCall("user32.dll", "hwnd", "SetWindowsHookEx", "int", 14, "ptr", DllCallbackGetPtr($hKey_Proc), "hwnd", $hM_Module[0], "dword", 0)
            Case 2
                $hM_Hook = DllCall("user32.dll", "hwnd", "SetWindowsHookEx", "int", 14, "ptr", DllCallbackGetPtr($hKey_Proc), "hwnd", $hM_Module[0], "dword", 0)
        EndSwitch
    EndIf
EndFunc

Func OnAutoItExit()
    DllCall("user32.dll", "int", "UnhookWindowsHookEx", "hwnd", $hM_Hook[0])
    $hM_Hook[0] = 0
    DllCallbackFree($hKey_Proc)
    $hKey_Proc = 0
EndFunc

No child-window, you can move label/picture by clicking on it... Quite works. But:

If anyone has an idea how to cut off the MouseHook_Menage function (detecting gui window [dis]activated; since I can't make $WH_MOUSE work properly :graduated: ) - I'll appreciate your thoughts in this topic:

Thank very much every one for help!

PS Moving control only on WM_LBUTTONUP message is intended (slow, old and ugly CPU). You can easily change script to move every time it receives WM_MOUSEMOVE message... If you want to continue such a useless thing :( ;]

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...