Sign in to follow this  
Followers 0
funkey

WM_NCLBUTTONDOWN does not work like expected

3 posts in this topic

WM_NCLBUTTONDOWN reports on Button up and WM_NCLBUTTONUP reports on double click. What can I do to fix this?

TIA

#Include <Constants.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>

Global $hGui = GUICreate("Costum Titlebar", 500, 300)

Global $hDll = DllCallbackRegister('_WinProc', 'ptr', 'hwnd;uint;long;ptr')
Global $pDll = DllCallbackGetPtr($hDll)
Global $hProc = _WinAPI_SetWindowLong($hGui, $GWL_WNDPROC, $pDll)

GUISetState()

Do
Until GUIGetMsg() = -3

_WinAPI_SetWindowLong($hGui, $GWL_WNDPROC, $hProc)
DllCallbackFree($hDll)

Func _WinProc($hWnd, $iMsg, $wParam, $lParam)
 Local $Res = _WinAPI_CallWindowProc($hProc, $hWnd, $iMsg, $wParam, $lParam)
 Local $hDC = _WinAPI_GetWindowDC($hWnd)
 Local $tRECT = DllStructCreate($tagRect)
 DllStructSetData($tRECT, "Left", 23)
 DllStructSetData($tRECT, "Top", 7)
 DllStructSetData($tRECT, "Right", 500)
 DllStructSetData($tRECT, "Bottom", 25)

    Switch $iMsg
        Case $WM_NCACTIVATE, $WM_NCPAINT
   $hDC = _WinAPI_GetWindowDC($hWnd)
   _WinAPI_SetBkColor($hDC, 0x00FF00)
   _WinAPI_DrawText($hDC, "  " & WinGetTitle($hWnd) & "   ", $tRECT, $DT_LEFT)
   _Winapi_ReleaseDC($hWnd, $hDC)
  Case $WM_NCLBUTTONDOWN
   $x = BitAND($lParam, 0x0000FFFF)
      $y = BitShift($lParam, 16)
   ConsoleWrite("Down at " & $x & "/" & $y & @cr)
  Case $WM_NCLBUTTONUP
   $x = BitAND($lParam, 0x0000FFFF)
      $y = BitShift($lParam, 16)
   ConsoleWrite("Up at " & $x & "/" & $y & @cr)
 EndSwitch
 Return $Res
EndFunc

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

WM_NCLBUTTONDOWN reports on Button up and WM_NCLBUTTONUP reports on double click. What can I do to fix this?

TIA

additional message handling is required to make a custom button work on the titlebar.

1: The WM_NCLBUTTONDOWN message is not passed until mouse capture is released.

2: The WM_NCLBUTTONUP message is posted when the user releases the left mouse button

while the cursor is within the nonclient area of a window.

This message is posted to the window that contains the cursor.

If a window has captured the mouse, this message is not posted.

it helps to use the WinSpector or Window Detective utilities, as they can subclass a window

so you can see what the messages are.

this is just a quick kludge to show a working example,

you need to call systemparaminfo API (I think?) to get the non-client area dimensions.

check the forum for non client area script examples

maybe look at ANYGUI examples, or search 'titlebar'

a point in rect test is used in WM_NCHITTEST to check if the click is on the button,

and a return of HTBORDER to tell the window the border was clicked so we get a WM_NCLBUTTONUP message.

boolean flags used to block keydn/up messages outside of button.

there was some key bounce with the WM_NCLBUTTONUP message being repeated twice,

so I added an additional boolean flag.

if the button is clicked, then the mouse moved off the button and released,

then like a normal button, no WM_NCLBUTTONUP message is sent.

;Author: funkey, modified by rover 2k11
#Include <Constants.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>

Global $tRECT = DllStructCreate($tagRect)
DllStructSetData($tRECT, "Left", 23)
DllStructSetData($tRECT, "Top", 7)
DllStructSetData($tRECT, "Right", 143)
DllStructSetData($tRECT, "Bottom", 25)

Global $tRECTx = DllStructCreate($tagRect);need non-client area dimensions here
DllStructSetData($tRECTx, "Left", 21)
DllStructSetData($tRECTx, "Top", -23)
DllStructSetData($tRECTx, "Right", 140)
DllStructSetData($tRECTx, "Bottom", -5);quick hack to set rect in non-client area

Global $fNCKeyDn = False, $fNCKeyUp = False

Global $hGui = GUICreate("Costum Titlebar", 500, 300)

Global $hDll = DllCallbackRegister('_WinProc', 'ptr', 'hwnd;uint;long;ptr')
Global $pDll = DllCallbackGetPtr($hDll)
Global $hProc = _WinAPI_SetWindowLong($hGui, $GWL_WNDPROC, $pDll)

GUISetState()

Do
Until GUIGetMsg() = -3

_WinAPI_SetWindowLong($hGui, $GWL_WNDPROC, $hProc)
DllCallbackFree($hDll)



Func _WinProc($hWnd, $iMsg, $wParam, $lParam)

    Switch $iMsg
        Case $WM_NCHITTEST;, $wm_
            ;http://msdn.microsoft.com/en-us/library/ms645618(VS.85).aspx
;http://stackoverflow.com/questions/521147/the-curious-problem-of-the-missing-wm-nclbuttonup-message-when-a-window-isnt-max
            Local $tPoint = DllStructCreate($tagPOINT)
            DllStructSetData($tPoint, 1, BitAND($lParam, 0x0000FFFF))
            DllStructSetData($tPoint, 2, BitShift($lParam, 16))
            _WinAPI_ScreenToClient($hWnd, $tPoint)
            If _WinAPI_PtInRect($tRECTx, $tPoint) Then
                $fNCKeyDn = True
                Return $HTBORDER ; tell the window the mouse is clicking on the border so we get a WM_NCLBUTTONUP message
            EndIf
            $fNCKeyDn = False ;required to prevent key down message if titlebar clicked after keyup on button
        Case $WM_NCLBUTTONUP
            If $fNCKeyDn = True And $fNCKeyUp = True Then
                $fNCKeyUp = False
                $x = BitAND($lParam, 0x0000FFFF)
                $y = BitShift($lParam, 16)
                ConsoleWrite("+Up at " & $x & "/" & $y & @cr)
            EndIf
        ;WM_NCLBUTTONDBLCLK: optionally allow fast clicking of button, otherwise some repeated clicks are missed.
        Case $WM_NCLBUTTONDOWN, $WM_NCLBUTTONDBLCLK
            If $fNCKeyDn = True Then
                $fNCKeyUp = True
                $x = BitAND($lParam, 0x0000FFFF)
                $y = BitShift($lParam, 16)
                ConsoleWrite("-Down at " & $x & "/" & $y & @cr)
            EndIf
    EndSwitch

    Local $Res = _WinAPI_CallWindowProc($hProc, $hWnd, $iMsg, $wParam, $lParam)
    Switch $iMsg
        Case $WM_NCACTIVATE, $WM_NCPAINT
           Local $hDC = _WinAPI_GetWindowDC($hWnd)
           _WinAPI_SetBkColor($hDC, 0x00FF00)
           _WinAPI_DrawText($hDC, "  " & WinGetTitle($hWnd) & "   ", $tRECT, $DT_LEFT)
           _Winapi_ReleaseDC($hWnd, $hDC)
    EndSwitch
    Return $Res
EndFunc
Edited by rover

I see fascists...

Share this post


Link to post
Share on other sites

Thank you very much for this. It helped a lot to do what I want.


Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
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
Sign in to follow this  
Followers 0