Jump to content
pixelsearch

Autoit message vs Windows message

Recommended Posts

Hi everybody :)

First of all, let me paste a part of LarsJ's explanation, found here, it could be related to the issue I'll expose below.

On 4/24/2015 at 1:25 PM, LarsJ said:

A rule is that all Windows messages already queued up e.g. a bunch of CustomDraw notifications, are handled before any AutoIt messages. While these messages are handled the AutoIt message loop is not running.

I'm facing a problem with the following script because :
* each right click on the header displays correctly a header context menu, with correct consolewrite info, even when you don't select any option in the menu :

1516051562_menuheadercommented.png.752826a8c96a75f7d8fc0f6c4ba9128b.png

* each right click on a cell doesn't display the corresponding cell context menu : it appears at 1st right click, then if you don't select anything but right click a 2nd time, no menu appears (it would appear at 3rd click, not at 4th etc...)

1805332330_menucell1st2ndtime.png.e57fb32b7f00ffc78c40db688310b669.png

Here is the full script :

#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <GuiMenu.au3>
#include <WindowsConstants.au3>

Global $g_hListView, $g_hHeader, $g_bHeaderMenu = False, $g_bCellMenu = False, $g_iCounter = 0

Example()

;============================================
Func Example()

    Local $hGUI = GUICreate("Right-click on headers or cells", 400, 200)
    Local $idListView = GUICtrlCreateListView _
        ("       Col 0      |       Col 1|       Col 2|       Col 3", 10, 10, 380, 180)

    $g_hListView = GuiCtrlGetHandle($idListView)
    $g_hHeader = _GUICtrlListView_GetHeader($idListView)

    For $iRow = 0 To 9
        GUICtrlCreateListViewItem( _
            "Row " & $iRow & " / Col 0 |" & _
            "Row " & $iRow & " / Col 1 |" & _
            "Row " & $iRow & " / Col 2 |" & _
            "Row " & $iRow & " / Col 3", $idListView)
    Next

    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
    GUISetState(@SW_SHOW)

    While 1
        If $g_bHeaderMenu Then ; right click on header => Header context menu
            ConsoleWrite($g_iCounter & " HD Main A" & @lf)
            ConsoleWrite("============" & @lf)
            Header_menu()
            ConsoleWrite($g_iCounter & " HD Main B" & @lf)
            ; other code here
            $g_bHeaderMenu = False
        EndIf

        If $g_bCellMenu Then ; right click on any cell => Cell context menu
            ConsoleWrite($g_iCounter & " LV Main A" & @lf)
            ConsoleWrite("============" & @lf)
            Cell_menu()
            ConsoleWrite($g_iCounter & " LV Main B" & @lf)
            ; other code here
            $g_bCellMenu = False
        EndIf

        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                GUIDelete($hGUI)
                Exit
        EndSwitch
    Wend

EndFunc   ;==>Example

;============================================
Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam

    Local $tNMHDR, $hWndFrom, $iIDFrom, $iCode
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $g_hListView
            Switch $iCode
                Case $NM_RCLICK
                    $g_bCellMenu = True
                    $g_iCounter += 1
                    ConsoleWrite($g_iCounter & " LV Notify" & @lf)
            EndSwitch

        Case $g_hHeader
            Switch $iCode
                Case $NM_RCLICK
                    $g_bHeaderMenu = True
                    $g_iCounter += 1
                    ConsoleWrite($g_iCounter & " HD Notify" & @lf)
            EndSwitch

    EndSwitch
    Return $GUI_RUNDEFMSG

EndFunc   ;==>WM_NOTIFY

;============================================
Func Header_menu() ; called by right click on header

    Local $iMenu_Choice = 0
    Local $hMenu = _GUICtrlMenu_CreatePopup()

    _GUICtrlMenu_InsertMenuItem($hMenu, 10, "Header menu", 10)
    _GUICtrlMenu_InsertMenuItem($hMenu, 15, "", 0)
    _GUICtrlMenu_InsertMenuItem($hMenu, 20, "Option 1", 20)
    _GUICtrlMenu_InsertMenuItem($hMenu, 30, "Option 2", 30)

    $iMenu_Choice = _GUICtrlMenu_TrackPopupMenu($hMenu, $g_hHeader, -1, -1, 1, 1, 2)
    _GUICtrlMenu_DestroyMenu($hMenu)

    Switch $iMenu_Choice
        Case 0, 10
        Case 20
        Case 30
    EndSwitch

EndFunc   ;==>Header_menu

;============================================
Func Cell_menu() ; called by right click on any cell

    Local $iMenu_Choice = 0
    Local $hMenu = _GUICtrlMenu_CreatePopup()

    _GUICtrlMenu_InsertMenuItem($hMenu, 10, "Cell menu", 10)
    _GUICtrlMenu_InsertMenuItem($hMenu, 15, "", 0)
    _GUICtrlMenu_InsertMenuItem($hMenu, 20, "Option 3", 20)
    _GUICtrlMenu_InsertMenuItem($hMenu, 30, "Option 4", 30)

    $iMenu_Choice = _GUICtrlMenu_TrackPopupMenu($hMenu, $g_hListView, -1, -1, 1, 1, 2)
    _GUICtrlMenu_DestroyMenu($hMenu)

    Switch $iMenu_Choice
        Case 0, 10
        Case 20
        Case 30
    EndSwitch

EndFunc   ;==>Cell_menu

What I notice in the compared Console outputs is this :
A ) In case of the header menu, the 2nd right click doesn't trigger immediately the WM_NOTIFY message. See this "yellowed" line in the pic ?

1 HD Main B

It's the part of the main loop that follows the 1st Header_menu() and it's executed when you right-click for the 2nd time.
Immediately after that are triggered :

2 HD Notify
2 HD Main A

B ) In case of the cell menu, why don't we have the same line ?

1 LV Main B

It's not here (and I don't know why), it seems that the 2nd right-click on a cell triggers immediately the WM_NOTIFY message, without ending first the main loop (as it does in case of header menu)

So anyone could explain why these 2 situations are different ?
Thanks

Edited by pixelsearch

Share this post


Link to post
Share on other sites

You're simply using a wrong technique. When detecting events in a Windows message handler (right-click in a WM_NOTIFY message handler) and the corresponding code must be executed in the AutoIt message handler (so the context menu does not block the WM_NOTIFY message handler), you must ensure that all events are sent on to the AutoIt message handler and in proper order. And you need to make sure that the events can consistently wait for the AutoIt message handler to execute the corresponding code. There are many situations that can temporarily interrupt the AutoIt message handler, eg. a pile of Windows messages.

The best way to meet all these requirements (all events, proper order, wait systematically) is to use AutoIt's built-in message handler system, which implements an actual message queue. Ie. use two Dummy controls to send events from the Windows message handler to the AutoIt message handler:

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7

;#AutoIt3Wrapper_UseX64=y

Opt( "MustDeclareVars", 1 )

#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <GuiMenu.au3>
#include <WindowsConstants.au3>

Global $g_hListView, $g_hHeader, $g_idHeaderMenu, $g_idCellMenu

Example()

;============================================
Func Example()

    Local $hGUI = GUICreate("Right-click on headers or cells", 400, 200)
    Local $idListView = GUICtrlCreateListView _
        ("       Col 0      |       Col 1|       Col 2|       Col 3", 10, 10, 380, 180)

    $g_hListView = GuiCtrlGetHandle($idListView)
    $g_hHeader = _GUICtrlListView_GetHeader($idListView)
  
    $g_idHeaderMenu = GUICtrlCreateDummy()
    $g_idCellMenu = GUICtrlCreateDummy()

    For $iRow = 0 To 9
        GUICtrlCreateListViewItem( _
            "Row " & $iRow & " / Col 0 |" & _
            "Row " & $iRow & " / Col 1 |" & _
            "Row " & $iRow & " / Col 2 |" & _
            "Row " & $iRow & " / Col 3", $idListView)
    Next

    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
    GUISetState(@SW_SHOW)

    While 1
        Switch GUIGetMsg()
            Case $g_idHeaderMenu
                Header_menu()

            Case $g_idCellMenu
                Cell_menu()

            Case $GUI_EVENT_CLOSE
                GUIDelete($hGUI)
                Exit
        EndSwitch
    Wend

EndFunc   ;==>Example

;============================================
Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam

    Local $tNMHDR, $hWndFrom, $iCode ; $iIDFrom
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $g_hListView
            Switch $iCode
                Case $NM_RCLICK
                    GUICtrlSendToDummy( $g_idCellMenu )
            EndSwitch

        Case $g_hHeader
            Switch $iCode
                Case $NM_RCLICK
                    GUICtrlSendToDummy( $g_idHeaderMenu )
            EndSwitch

    EndSwitch
    Return $GUI_RUNDEFMSG

EndFunc   ;==>WM_NOTIFY

;============================================
Func Header_menu() ; called by right click on header

    Local $iMenu_Choice = 0
    Local $hMenu = _GUICtrlMenu_CreatePopup()

    _GUICtrlMenu_InsertMenuItem($hMenu, 10, "Header menu", 10)
    _GUICtrlMenu_InsertMenuItem($hMenu, 15, "", 0)
    _GUICtrlMenu_InsertMenuItem($hMenu, 20, "Option 1", 20)
    _GUICtrlMenu_InsertMenuItem($hMenu, 30, "Option 2", 30)

    $iMenu_Choice = _GUICtrlMenu_TrackPopupMenu($hMenu, $g_hHeader, -1, -1, 1, 1, 2)
    _GUICtrlMenu_DestroyMenu($hMenu)

    Switch $iMenu_Choice
        Case 0, 10
        Case 20
        Case 30
    EndSwitch

EndFunc   ;==>Header_menu

;============================================
Func Cell_menu() ; called by right click on any cell

    Local $iMenu_Choice = 0
    Local $hMenu = _GUICtrlMenu_CreatePopup()

    _GUICtrlMenu_InsertMenuItem($hMenu, 10, "Cell menu", 10)
    _GUICtrlMenu_InsertMenuItem($hMenu, 15, "", 0)
    _GUICtrlMenu_InsertMenuItem($hMenu, 20, "Option 3", 20)
    _GUICtrlMenu_InsertMenuItem($hMenu, 30, "Option 4", 30)

    $iMenu_Choice = _GUICtrlMenu_TrackPopupMenu($hMenu, $g_hListView, -1, -1, 1, 1, 2) ; $g_hHeader -> g_hListView
    _GUICtrlMenu_DestroyMenu($hMenu)                                                   ; However, has nothing to do with the issues

    Switch $iMenu_Choice
        Case 0, 10
        Case 20
        Case 30
    EndSwitch

EndFunc   ;==>Cell_menu

This code is the default code for such tasks. It's easy, simple and straightforward code that works well. Why use different code? (The code above can be optimized a lot, but it's probably not that important here.)

Your code is incorrect because it does not implement a proper message handler system that guarantees that all events are handled and in proper order when there is time for it. The issues in your code show this.

The two situations are probably different because there are many more listview notifications than header notifications. The many listview notifications mean that the listview code in the WM_NOTIFY message handler is in poor sync with the code in the AutoIt message handler. The few header notifications mean that the header code is better synchronized between the WM_NOTIFY message handler and the AutoIt message handler.

A piece of coherent code should either be executed in the Windows message handler or in the AutoIt message handler. If the code is split between both message handlers, there is no guarantee that the code will run correctly. The code in the two message handlers is not synchronized in any way. Therefore, an actual queue system that guarantees that events are executed correctly is necessary to send events from the Windows message handler to the AutoIt message handler.


Share this post


Link to post
Share on other sites
22 hours ago, LarsJ said:

This code is the default code for such tasks. It's easy, simple and straightforward code that works well. Why use different code?

I tried to explain in this post why I always preferred the flag option rather than the dummy control in this situation.

In fact, with my code above (flag), it's easy to have exactly the same results as yours (dummy control) and I had this solution in mind when I wrote the 1st post. Instead of this :

If $g_bCellMenu Then
    Cell_menu()
    $g_bCellMenu = False
EndIf

We move 1 line and everything is ok :

If $g_bCellMenu Then
    $g_bCellMenu = False
    Cell_menu() 
EndIf

Now both scripts (yours or mine) run the same way, with a right-click making appear the context menu each and every time. And here are the compared ConsoleWrite results between both scripts (after I added a few ConsoleWrite to yours, the ===== lines mean we're in the context menu, waiting). Aren't the ConsoleWrite displays exactly the same ?

....LarsJ       pixelsearch

1 LV Notify     1 LV Notify
1 LV Main A     1 LV Main A
============    ============    
2 LV Notify     2 LV Notify
2 LV Main B     2 LV Main B
2 LV Main A     2 LV Main A
============    ============
3 LV Notify     3 LV Notify
3 LV Main B     3 LV Main B
3 LV Main A     3 LV Main A
============    ============

Now if by "wrong technique", you mean that a flag should not be used in this case (instead of a  dummy control) then the corresponding wiki page should be amended, as it clearly stipulates :

"There are 2 ways we can still run something long and complicated but still leave the handler quickly: either set a flag or action a dummy control."

The point to remember, when using the flag option, is to reset the flag to False asap in the main loop (1st instruction) if we want the script to react in the same way as a dummy control, like this :

#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <GuiMenu.au3>
#include <WindowsConstants.au3>

Global $g_hListView, $g_hHeader, $g_bHeaderMenu = False, $g_bCellMenu = False

Example()

;============================================
Func Example()

    Local $hGUI = GUICreate("Right-click on headers or cells", 400, 200)
    Local $idListView = GUICtrlCreateListView _
        ("       Col 0      |       Col 1|       Col 2|       Col 3", 10, 10, 380, 180)

    $g_hListView = GuiCtrlGetHandle($idListView)
    $g_hHeader = _GUICtrlListView_GetHeader($idListView)

    For $iRow = 0 To 9
        GUICtrlCreateListViewItem( _
            "Row " & $iRow & " / Col 0 |" & _
            "Row " & $iRow & " / Col 1 |" & _
            "Row " & $iRow & " / Col 2 |" & _
            "Row " & $iRow & " / Col 3", $idListView)
    Next

    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
    GUISetState(@SW_SHOW)

    While 1
        If $g_bHeaderMenu Then
            $g_bHeaderMenu = False
            Header_menu()
        EndIf

        If $g_bCellMenu Then
            $g_bCellMenu = False
            Cell_menu()
        EndIf

        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                GUIDelete($hGUI)
                Exit
        EndSwitch
    Wend

EndFunc   ;==>Example

;============================================
Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam

    Local $tNMHDR, $hWndFrom, $iIDFrom, $iCode
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $g_hListView
            Switch $iCode
                Case $NM_RCLICK
                    $g_bCellMenu = True
            EndSwitch

        Case $g_hHeader
            Switch $iCode
                Case $NM_RCLICK
                    $g_bHeaderMenu = True
            EndSwitch

    EndSwitch
    Return $GUI_RUNDEFMSG

EndFunc   ;==>WM_NOTIFY

;============================================
Func Header_menu()

    Local $iMenu_Choice = 0
    Local $hMenu = _GUICtrlMenu_CreatePopup()

    _GUICtrlMenu_InsertMenuItem($hMenu, 10, "Header menu", 10)
    _GUICtrlMenu_InsertMenuItem($hMenu, 15, "", 0)
    _GUICtrlMenu_InsertMenuItem($hMenu, 20, "Option 1", 20)
    _GUICtrlMenu_InsertMenuItem($hMenu, 30, "Option 2", 30)

    $iMenu_Choice = _GUICtrlMenu_TrackPopupMenu($hMenu, $g_hHeader, -1, -1, 1, 1, 2)
    _GUICtrlMenu_DestroyMenu($hMenu)

    Switch $iMenu_Choice
        Case 0, 10
        Case 20
        Case 30
    EndSwitch

EndFunc   ;==>Header_menu

;============================================
Func Cell_menu()

    Local $iMenu_Choice = 0
    Local $hMenu = _GUICtrlMenu_CreatePopup()

    _GUICtrlMenu_InsertMenuItem($hMenu, 10, "Cell menu", 10)
    _GUICtrlMenu_InsertMenuItem($hMenu, 15, "", 0)
    _GUICtrlMenu_InsertMenuItem($hMenu, 20, "Option 3", 20)
    _GUICtrlMenu_InsertMenuItem($hMenu, 30, "Option 4", 30)

    $iMenu_Choice = _GUICtrlMenu_TrackPopupMenu($hMenu, $g_hListView, -1, -1, 1, 1, 2)
    _GUICtrlMenu_DestroyMenu($hMenu)

    Switch $iMenu_Choice
        Case 0, 10
        Case 20
        Case 30
    EndSwitch

EndFunc   ;==>Cell_menu

 

Edited by pixelsearch

Share this post


Link to post
Share on other sites

I've read your thread on "Flag or Dummy control?". The code snippet in first post in the thread is based on left and right click events. The code appears to be copied from some test code. And in test code, you can of course block all the events you want. But the code seems not to be copied from real code used by real users. In real code, you'll never ever block left and right click events. In real code, left click is the primary way to perform user actions eg. to click controls and to navigate. In real code, right click is the primary way to open context menus. In real code, it's extremely rare to block left and right click events thus preventing the corresponding code from being executed.

In real code it's very uncommon to block any Windows messages at all. On the contrary, it's common to be very careful to ensure that all messages that needs a respond in fact are responded and in the correct order corresponding to the order of the messages.

The argument for using the flag variable technique (that messages can be blocked) is not a valid argument in real code.

When you almost never block Windows messages in real code, what's the point in adding extra code to support message blocking? Why not simply omit this extra code that is not being used anyway?

 

On ‎1‎/‎23‎/‎2020 at 6:26 PM, pixelsearch said:

In fact, with my code above (flag), it's easy to have exactly the same results as yours (dummy control) and I had this solution in mind when I wrote the 1st post.

Nevertheless, there were still issues in the code after you made the first post, after you edited the post a day later and before I made my post another day later. The whole reason for the first post seems to be that you failed this easy (as you call it) code.

 

By "wrong technique" I mean that there is nothing in your code that guarantees that all events are sent on to the AutoIt message handler in proper order. Your code does not implement a proper first-in-first-out message queue.

If the code is simple enough then you can almost always make it work. Even if you're using wrong techniques.

Imagine that the flag technique is not just used to handle left and right clicks, but to handle all situations where there is a need to execute longer code sections or blocking code in GUIRegisterMsg() message handlers and maybe even in message handlers implemented through the subclassing technique.

Also imagine that it's advanced code with several thousand code lines. Then you might need a great deal of these flag variables. Then it's possible that multiple flag variables are true at once before the AutoIt main loop handles the events. And there may also be events in the GUIGetMsg() queue. In what order are these events executed?

Your code looks like this:

While 1
  If $bFlagVar1 Then
    ; Code here
  EndIf

  If $bFlagVar2 Then
    ; Code here
  EndIf

  ...

  If $bFlagVar25 Then
    ; Code here
  EndIf

  Switch GUIGetMsg()
    Case $idControl1
      ; Code here

    Case $idControl2
      ; Code here

    ...

    Case $idControl30
      ; Code here

    Case $GUI_EVENT_CLOSE
      GUIDelete($hGUI)
      ExitLoop
  EndSwitch
Wend

If multiple flag variables are true at once, the code is executed in the same order as the If statements. Not necessarily in the order of events. This might be a problem and maybe not.

If there are both flag events and GUIGetMsg() events at the same time, the flag events are always executed before the GUIGetMsg() events (because they come first in the While loop). Also if the GUIGetMsg() events were actually the first events. The events are not necessarily executed in order of the events. This might be a problem and maybe not.

In case of errors due to events being processed in the wrong order, these errors can be extremely difficult to debug. After all, these are not actual code errors, but more errors related to the (wrong) design of the code.

 

The GUICtrlSendToDummy() function supports a state variable this way:

GUICtrlSendToDummy( controlID [, state] )

This state variable is very useful e.g. for left, right, double-click and Enter key presses on listview items, where it can be used to transfer the item index to the GUIGetMsg() event handler. It's probably also possible to implement a state variable with the flag technique. But it requires more code and this further complicates things.

Another problem is that all the If statements at the top of the main loop are always tested. Even when there are no flag events. It may become a performance issue in event intensive code. Placing the If statements in order of most occurrences will not help here. This issue may also be solved with more code. But again this further complicates things.

With the flag variable technique it may be necessary to add some extra code to achieve the same functionality as with the Dummy control technique and the GUICtrlSendToDummy() function.

 

But the main problem with the technique is that it's not possible to ensure that all events are handled in the correct order (in the order of the events).

Why put yourself in a situation where you have to address all these issues when you can handle them all using the Dummy control technique and the GUICtrlSendToDummy() function? This function requires only one line of code and is a very fast internal (built-in) function.

 

And please don't abuse the Wiki pages to make global and general conclusions about code techniques that are simply not documented on these pages. This Wiki page you are referring to is an introduction to the GUIRegisterMsg() function and an idea to solve the problem of long code sections and blocking code in a GUIRegisterMsg() message handler. And nothing else.  It's not a response to all aspects, some of which are quite complicated, by implementing a correct, fast and well-functioning message handler.


Share this post


Link to post
Share on other sites
; taken from https://www.autoitscript.com/forum/topic/201427-ping-discover-local-ips/

Global $_a__WM_NOTIFY[7] = [0]
...
GUIRegisterMsg($WM_NOTIFY, "__WM_NOTIFY")
...
    While 1
        If $_a__WM_NOTIFY[0] Then
            ...
            $_a__WM_NOTIFY[0] = 0
        EndIf
...
Func __WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    If $_a__WM_NOTIFY[0] Then Return $GUI_RUNDEFMSG
    Local $hWndFrom, $iCode, $tNMHDR, $tInfo, $iIDFrom
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $iCode
        Case $NM_CLICK, $NM_DBLCLK, $NM_RCLICK, $LVN_COLUMNCLICK ;, $NM_RDBLCLK
            $tInfo = DllStructCreate($tagNMITEMACTIVATE, $lParam)
            $_a__WM_NOTIFY[1] = $hWndFrom
            $_a__WM_NOTIFY[2] = $iCode
            $_a__WM_NOTIFY[3] = DllStructGetData($tInfo, "Index")
            $_a__WM_NOTIFY[4] = DllStructGetData($tInfo, "SubItem")
            $_a__WM_NOTIFY[5] = DllStructGetData($tInfo, "ActionX")
            $_a__WM_NOTIFY[6] = DllStructGetData($tInfo, "ActionY")
            $_a__WM_NOTIFY[0] = 1
            ;Return 1 ; not to allow the default processing
            ;Return 0         ; allow the default processing
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>__WM_NOTIFY

This is the way I handled that  :) 

Share this post


Link to post
Share on other sites
1 hour ago, LarsJ said:

The whole reason for the first post seems to be that you failed this easy (as you call it) code.

Not at all.
I know for weeks that resetting the flag to False asap will solve the issue and make the cell context menu appear at each right click, even if I choosed not to indicate it in my 1st post. Didn't I give the solution by myself in the 2nd post ?

Concerning the 1st post I edited (1 day before you answered +++)
It was to correct the line you mentioned (I noticed by myself that it was wrong, due to a copy-paste) :

$iMenu_Choice = _GUICtrlMenu_TrackPopupMenu($hMenu, $g_hListView, -1, -1, 1, 1, 2) ; $g_hHeader -> g_hListView (however, has nothing to do with the issues)

There is nothing wrong in modifying a post when no answers have been made, that was the case. I should certainly have written why I modified it, but as you noticed, it has nothing to do with the issue and I noticed that too.

The main reason for the 1st post is based on the fact I hoped someone would point at the fact the flag should be reset earlier and a discussion would have followed that. But the "yellowed" line issue, that one I didn't have any clue about it :

1 HD Main B

That "yellowed" line is the part of code that is executed after the header menu is closed (when no options have been chosen in it). I wanted to know why it appeared only for the header menu (resetting in time the flag, great !) and not for the cell menu (flag not reset => problem)

I discovered this week that, while the header menu is displayed, another right click on the header (keeping the right button down) triggers that "yellowed" line immediately and no other event occurs while the right button is down (no right click notify event)

This behavior isn't found in the cell menu : when you right click on another cell, nothing is triggered (in the script) until you release the right button : that's a big difference between both right clicks (in header or in cell)

Anyway, thanks for the detailed explanations. I'll consider using the dummy control for all the reasons you exposed, especially you made me discover the "state" parameter I never used until now, thanks for that.

GUICtrlSendToDummy( controlID [, state] )

And thanks to argumentum for your code, I'll study that too.

Edited by pixelsearch

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

×
×
  • Create New...