Announcement

Collapse
No announcement yet.

WM_NCHITTEST & mouse click

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • WM_NCHITTEST & mouse click

    Hi, all -

    When user clicks a caption I need to prevent all further system actions.
    But I should understand a reason of this message (mouse moved/pressed or released).
    With coordinates all is clear, but can't find a function, which retrieves current mouse buttons' state or something else, which helps to understand a reason of WM_NCHITTEST.

    Any ideas ?

    ------------------
    E-MAIL: [email protected]

  • #2
    It's in the params.

    Or do you mean something else?

    When you click with them mouse on the window border, hittest will give a diff. number in the wParam or lParam.


    ------------------
    [email protected]
    hellobasic

    Comment


    • #3
      and GetKeyState( VK...mouse ) determins state..


      ------------------
      [email protected]
      hellobasic

      Comment


      • #4
        Edwin --
        I don't see that %WM_NCHITTEST gives any information about pressed or released.
        wparam is not used, lparam - coordinates of cursor.
        Get(Async)KeyState - yes, this helps.
        Thanks.

        ------------------
        E-MAIL: [email protected]

        Comment


        • #5
          MSDN:

          The lParam parameter of the WM_NCHITTEST message contains the screen coordinates of the cursor hot spot. The DefWindowProc function examines the coordinates and returns a hit-test value that indicates the location of the hot spot. The hit-test value can be one of the following values.

          2nd:

          Return Values
          The return value of the DefWindowProc function is one of the following values, indicating the position of the cursor hot spot.

          Or:

          %WM_NCLBUTTONDOWN ??



          ------------------
          [email protected]
          hellobasic

          Comment


          • #6
            Edwin --
            Situation is following. A client part of console window is placed inside "parent" GUI, where are placed "buttons".
            Strictly saying, it's not child - parent, it's two top-level windows.

            Caption of GUI is owner-drawn and shows a state of console, not own.
            Because regional settings could be non-russian, "official" title (SetWindowText) includes latin letters only.
            Meanwhile on the screen I show Russian text.
            GUI window has no even WS_SYSMENU style. But user sees buttons on the caption.

            If to process any HITTEST, GUI window will be activated.
            (note that w/o HITTEST not possible to retrieve NCLBUTTONDOWN).

            If GUI window is activated, occurs some unhappy things.
            Finally all is redrawn, console receives focus again, but before caption becomes "inactive", grayed, with English text and w/o buttons.
            Short time, but not nice view for eyes.

            ------------------
            E-MAIL: [email protected]

            Comment


            • #7
              Semen;

              WM_NCHITTEST is used by windows to "poll" the window to find out
              where the mouse was when the button is clicked.

              Depending on where the mouse was when the button was pushed down,
              one of two messages will be sent to the window.

              If WM_NCHITTEST returns a value indicating that the mouse was
              clicked in the windows client area, then the WM_LBUTTONDOWN message
              is generated. If WM_NCHITTEST returns a value indicating the mouse
              was somewhere in the Titlebar or border, then the WM_NCLBUTTONDOWN
              message is generated.

              When the WM_NCLBUTTONDOWN message is sent a value is sent that
              indicates "where" the mouse is:

              HTBORDERHTBOTTOM
              HTBOTTOMLEFT
              HTBOTTOMRIGHT
              HTCAPTION
              HTCLIENT
              HTERROR
              HTGROWBOX
              HTHSCROLL
              HTLEFT
              HTMENU
              HTNOWHERE
              HTREDUCE
              HTRIGHT
              HTSIZE
              HTSYSMENU
              HTTOP
              HTTOPLEFT
              HTTOPRIGHT
              HTTRANSPARENT
              HTVSCROLL
              HTZOOM

              By returning a "false" value for the WM_NCHITTEST message, you can "fool"
              Windows into thinking the mouse was clicked somewhere else other than
              where it really was.

              By returning the HTCLIENT value you can make the Window think it didn't
              click on the Titlebar.

              You can use the DefWindowProc function to get the proper value to return
              and then "change" it if you like and then return that value back to
              the Window procedure.

              I have done this with windows that are subclassed in Window Procedures,
              but I am not sure how you handle this with DDT and Dialog procedures.




              ------------------
              Chris Boss
              Computer Workshop
              Developer of "EZGUI"
              http://cwsof.com
              http://twitter.com/EZGUIProGuy

              Comment


              • #8
                Semen,
                To figure out why you received a WM_NCHITTEST you have to call DeferWindowProc
                and check the return value.
                Code:
                CASE %WM_NCHITTEST
                  lRet = DefWindowProc(hWnd, lMsg, wParam, lParam)
                  lRet will be equal to HTBORDER, HTCLIENT etc.
                The following MSDN article may be of some help. This article discusses when
                to draw. The concole window is an interesting twist though.

                Article ID: Q99046. How to Draw a Custom Window Caption.

                ------------------
                Dominic Mitchell
                Dominic Mitchell
                Phoenix Visual Designer
                http://www.phnxthunder.com

                Comment


                • #9
                  Chris --
                  Do you know return value for HITTEST, which allows do not activate top-level window, which was not foreground ?

                  I tried NOWHERE and similar, but can't avoid NCACTIVATE.
                  Of course, I can try to recognize a reason of NCACTIVATE and to refuse from it, but I'm a little afraid to ignore events, which really should be accepted.

                  I hoped also that processing WM_MOUSEACTIVATE helps. But it was not so (I could not avoid repainting of caption).

                  Just now I do following: in HITTEST (w/o DefWindowProc to avoid NCACTIVATE) I return NOWHERE.
                  When HITTEST occurs, I understand that left button is pressed under fictive button in caption (using GetAsyncKeyState).
                  SetCapture. Then control further NC_MOUSEMOVE, NC_LBUTTONUP. If button is released or cursor is outside fictive button - ReleaseCapture.

                  More or less works, but, of course, I'll prefer classic NC_LBUTTONDOWN/UP.

                  Dominic --
                  to draw custom caption is not a problem for me.
                  For me is a problem to avoid following sequence, when user clicks my fictive button:
                  I draw caption - Windows redraws - I redraw again.

                  BTW on codeguru in C_section it possible to find enough extended samples.


                  ------------------
                  E-MAIL: [email protected]

                  Comment


                  • #10
                    What Dominic pointed out is what i meant.

                    And,, if you try to prevent having the window getting the focus, forget that, i tried it severly.
                    Don't quite know if this is what you need.

                    Functions described above are the correct ones.



                    ------------------
                    [email protected]
                    hellobasic

                    Comment


                    • #11
                      Ok, guys.
                      I tested some additional methods, but all of them have problems somewhere.

                      Because too difficult to take fragment from real app, I decided to build a sample from "HelloWin".
                      In real program console has no non-client part, I dispatch messages by another way, there is pernanent monitoring of console state and so on.
                      But I think that for our discussion it's not important.

                      So, how to avoid "Ah!" ?
                      Code:
                         #Dim All
                         #Register None
                         #Include "WIN32API.INC"
                      
                         Global hWndConsole As Long
                         '================================
                         Sub CPrint (SOut As String)
                            Static hConsoleOutput As Long, cWritten As Long
                            If hConsoleOutput = 0 Then hConsoleOutput = GetStdHandle(-11&)
                            WriteConsole hConsoleOutput, ByCopy sOut + $CrLf, Len(sOut) + 2, cWritten, ByVal 0&
                         End Sub
                      
                         
                         Function WndProc (ByVal hWnd As Long, ByVal wMsg As Long, _
                                           ByVal wParam As Long, ByVal lParam As Long) Export As Long
                                           
                            Select Case wMsg
                               Case %WM_NCHITTEST
                                    
                                  'Function = DefWindowProc(hWnd, wMsg, wParam, lParam)
                                  'CPrint "%WM_NCHITTEST"
                                  'Function = %HTCLIENT: Exit Function ' NOWHERE ?
                                  
                               Case %WM_NCLBUTTONDOWN:
                                    SetForegroundWindow hWndConsole
                                    CPrint "%WM_NCLBUTTONDOWN": Function = 0: Exit Function
                                    
                               Case %WM_ACTIVATE: If wParam Then SetForegroundWindow hWndConsole
                                    
                               Case %WM_NCLBUTTONUP:
                                    SetForegroundWindow hWndConsole
                                    CPrint "%WM_NCLBUTTONUP": Function = 0: Exit Function
                                    
                               Case %WM_NCACTIVATE, %WM_NCPAINT
                                  CPrint "Ah !!!"
                                  
                               Case %WM_DESTROY      : PostQuitMessage 0: Function = 0: Exit Function
                            End Select
                            
                            Function = DefWindowProc(hWnd, wMsg, wParam, lParam)
                         End Function
                      
                         Function WinMain (ByVal hInstance As Long, ByVal hPrevInstance As Long, _
                            lpCmdLine As Asciiz Ptr, ByVal iCmdShow As Long) As Long
                      
                            AllocConsole
                            SetConsoleTitle "Hren znaet chto": Sleep 100
                            
                            hWndConsole = FindWindow ("", "Hren znaet chto")
                            
                            SetForegroundWindow hWndConsole
                                  
                            Local Msg         As tagMsg
                            Local wndclass    As WndClassEx
                            Local szAppName   As Asciiz * 80
                            Local hWnd        As Long
                      
                            szAppName              = "Test"
                            wndclass.cbSize        = SizeOf(WndClass)
                            wndclass.style         = %CS_HREDRAW Or %CS_VREDRAW
                            wndclass.lpfnWndProc   = CodePtr(WndProc)
                            wndclass.hInstance     = hInstance
                            wndclass.hCursor       = LoadCursor( %NULL, ByVal %IDC_ARROW )
                            wndclass.hbrBackground = GetStockObject( %WHITE_BRUSH )
                            wndclass.lpszClassName = VarPtr( szAppName )
                            wndclass.hIconSm       = LoadIcon( hInstance, ByVal %IDI_APPLICATION )
                      
                            RegisterClassEx wndclass
                      
                            hWnd = CreateWindow(szAppName, "Place for a message", %WS_CLIPCHILDREN Or %WS_CLIPSIBLINGS, _
                                %CW_USEDEFAULT, %CW_USEDEFAULT, %CW_USEDEFAULT, %CW_USEDEFAULT, _
                                 %NULL, %NULL, hInstance, ByVal %NULL)
                            SetParent hWndConsole, hWnd
                            SetForegroundWindow hWnd
                            ShowWindow hWnd, iCmdShow
                            UpdateWindow hWnd
                            SetForegroundwindow hWndConsole
                            While GetMessage(Msg, %NULL, 0, 0)
                               TranslateMessage Msg
                               DispatchMessage Msg
                            Wend
                            Function = msg.wParam
                         End Function  ' WinMain
                      ------------------
                      E-MAIL: [email protected]

                      Comment


                      • #12
                        Semen,
                        I tried your code and was able to prevent the reception of WM_NCACTIVATE and
                        WM_NCPAINT messages by using the WM_MOUSEACTIVATE message. Return either
                        MA_NOACTIVATE or MA_NOACTIVATEANDEAT. One caveat. You will receive an initial
                        "Ah !!!" but none afterwards.
                        Code:
                        Function WndProc (ByVal hWnd As Long, ByVal wMsg As Long, _
                                          ByVal wParam As Long, ByVal lParam As Long) Export As Long
                                          
                           Select Case wMsg
                              CASE %WM_MOUSEACTIVATE
                        
                              FUNCTION = %MA_NOACTIVATE
                              EXIT FUNCTION
                        Oops! Just read you did not like WM_MOUSEACTIVATE. Oh well back to the drawing
                        board(maybe on the weekend). In WM_NCPAINT have you tried the following-
                        Code:
                        CASE %WM_NCPAINT
                          ' Set the caption to empty to avoid Windows-initiated caption bar drawing
                          SetWindowText hWnd, CHR$(0)
                          DefWindowProc hWnd, lMsg, wParam, lParam
                          ' Draw you custom caption here
                        [This message has been edited by Dominic Mitchell (edited October 13, 2000).]
                        Dominic Mitchell
                        Phoenix Visual Designer
                        http://www.phnxthunder.com

                        Comment


                        • #13
                          Uff.. It looks that now it works correctly everywhere.

                          Before I tried to use MOUSEACTIVATE in another than in sample configuration.

                          Thanks, guys for assistant. Finally works following:

                          I do not touch HITTEST.
                          In NCLBUTTONDOWN/UP make console foreground again and refuse from event.
                          In MOUSEACTIVATE refuse from activation.

                          Enough "clean". One not good moment - to detect BUTTONUP, which can occurs outside GUI window (for example, in console), I added a timer and control cursor position.
                          If outside fictive button - means "deactivate" pressing.

                          PS.
                          Dominic --
                          1) I saw that you corrected your message.
                          I think that MOUSEACTIVATE didn't help, because it was not SetForeground hWndConsole in NCLBUTTONDOWN.

                          2) Are you sure that Windows willn't repaint caption if to set CHR$(0) ?
                          Plus this caption is visible in Task Bar.
                          If to return then previous text, as I understand, occurs WM_SETTEXT and all begins again.

                          ------------------
                          E-MAIL: [email protected]

                          [This message has been edited by Semen Matusovski (edited October 13, 2000).]

                          Comment


                          • #14
                            Semen,
                            Glad to see you found a satisfactory solution to your problem.
                            That empty caption snippet is something I thought you might
                            want to try. That is something I will have to test when I get
                            a chance. A long time ago I realized that some of the articles in
                            the MS Win32 knowledge base should be taken with a grain of salt.

                            ------------------
                            Dominic Mitchell
                            Dominic Mitchell
                            Phoenix Visual Designer
                            http://www.phnxthunder.com

                            Comment

                            Working...
                            X