-Ultima- Posted April 18, 2008 Share Posted April 18, 2008 (edited) So, I've got this treeview for which I'm handling NM_DBLCLK through WM_NOTIFY... The thing is, I don't actually want a treeview item to be expanded when I double-click it. In AutoIt 3.2.10.x, it was enough to return some unexpected value in the NM_DBLCLK callback function, but since 3.2.11.x, I haven't been able to override the double-click behavior -- only augment it. Does anyone know how I can work around this, short of toggling the expanded state every time WM_NOTIFY/NM_DBLCLK is called? Here's a test script: expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <TreeViewConstants.au3> #include <StructureConstants.au3> #include <Misc.au3> ;#include <SendMessage.au3> ; NEEDED FOR 3.2.11.x, WON'T WORK WITH 3.2.10.x Opt("GUIOnEventMode", 1) Global $GUIMain_iWidth = 150 Global $GUIMain_iHeight = 100 ; GUI/Controls Global $GUIMain = GUICreate(@AutoItVersion, $GUIMain_iWidth, $GUIMain_iHeight) Global $TreeView = GUICtrlCreateTreeView(5, 5, $GUIMain_iWidth - 10, $GUIMain_iHeight - 10, $TVS_HASBUTTONS + $TVS_HASLINES + $TVS_LINESATROOT + $TVS_NONEVENHEIGHT, $WS_EX_CLIENTEDGE) Global $TreeView_hWnd = GUICtrlGetHandle($TreeView) Global $TreeView_Root = GUICtrlCreateTreeViewItem("ITEM", $TreeView) GUICtrlCreateTreeViewItem("SUBITEM", $TreeView_Root) ; Miscellaneous GUISetOnEvent($GUI_EVENT_CLOSE, "mainExit", $GUIMain) GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState() ; Main Loop While 1 Sleep(1000) WEnd ; Functions Func mainExit() Exit EndFunc Func NM_DBLCLK() ; _GUICtrlTreeView_ToggleItem($TreeView_hWnd) Return 1 EndFunc Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam) Local $tNMHDR = DLLStructCreate($tagNMHDR, $lParam) Switch DllStructGetData($tNMHDR, "hWndFrom") Case $TreeView_hWnd Switch DllStructGetData($tNMHDR, "Code") Case $NM_DBLCLK Return NM_DBLCLK() EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc Func _GUICtrlTreeView_ToggleItem($hWnd) _SendMessage($hWnd, $TVM_EXPAND, $TVE_TOGGLE, _SendMessage($hWnd, $TVM_GETNEXTITEM, $TVGN_CARET, 0, 0, "wparam", "hwnd", "hwnd"), 0, "wparam", "hwnd") EndFunc Edited April 18, 2008 by -Ultima- [ WinINet.au3 | Array.au3 (Optimized) | _UnixTimeParse() ] Link to comment Share on other sites More sharing options...
-Ultima- Posted April 21, 2008 Author Share Posted April 21, 2008 (edited) Hm, it looks to me like it just might be a bug/regression with the AutoIt betas... Take this script as an example: expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <TreeViewConstants.au3> #include <StructureConstants.au3> Opt("GUIOnEventMode", 1) Global $GUIMain_iWidth = 150 Global $GUIMain_iHeight = 100 ; GUI/Controls -------------- Global $GUIMain = GUICreate(@AutoItVersion, $GUIMain_iWidth, $GUIMain_iHeight) Global $TreeView = GUICtrlCreateTreeView(5, 5, $GUIMain_iWidth - 10, $GUIMain_iHeight - 10, $TVS_HASBUTTONS + $TVS_HASLINES + $TVS_LINESATROOT + $TVS_NONEVENHEIGHT, $WS_EX_CLIENTEDGE) Global $TreeView_hWnd = GUICtrlGetHandle($TreeView) GUICtrlCreateTreeViewItem("ITEM", $TreeView) GUICtrlCreateTreeViewItem("SUBITEM", -1) ; Miscellaneous ------------- GUISetOnEvent($GUI_EVENT_CLOSE, "mainExit", $GUIMain) GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState() ; Main Loop ----------------- While 1 Sleep(1000) WEnd ; Functions ----------------- Func mainExit() Exit EndFunc Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam) Local $tNMHDR = DLLStructCreate($tagNMHDR, $lParam) If (DllStructGetData($tNMHDR, "hWndFrom") = $TreeView_hWnd) And (DllStructGetData($tNMHDR, "Code") = $NM_DBLCLK) Then Return 1+Chain1() EndIf Return $GUI_RUNDEFMSG EndFunc ; Callback Function Chain --- Func Chain1() For $i = 0 To 10000 ConsoleWrite("") Next Chain2() EndFunc Func Chain2() For $i = 0 To 10000 ConsoleWrite("") Next Chain3() EndFunc Func Chain3() For $i = 0 To 10000 ConsoleWrite("") Next Chain4() EndFunc Func Chain4() For $i = 0 To 10000 ConsoleWrite("") Next Chain5() EndFunc Func Chain5() For $i = 0 To 10000 ConsoleWrite("") Next ; Return 1 EndFunc As is, it behaves correctly, and the treeview root can't be expanded by double-click. If you modify Chain5() to return *anything*, the whole thing falls apart, and AutoIt decides it wants to handle the message (and expands the treeview root). In fact, if you do return anything, anywhere in the callback function chain, AutoIt decides it wants to handle the message, regardless of what is returned. Regarding the function chain, ignore the For loops. I only added them to demonstrate the fact that it isn't because the function chain is taking too long to return that causes AutoIt to behave wonkily (it's something I considered at first). Can anyone confirm that this a bug? If so, I'll report it to Trac. Aside: The GUIRegisterMsg() documentation needs updating. It's difficult to determine what return value would cause AutoIt to stop handling the message internally. By using 'Return' without any return value the AutoIt internal message handler (if there is one for this message) will NOT be proceed!Yet, an empty return *does* allow AutoIt to continue handling the message. Returning 0 does the same. It seems that it's only when you return a non-zero integer that it stops handling things internally. Edited April 21, 2008 by -Ultima- [ WinINet.au3 | Array.au3 (Optimized) | _UnixTimeParse() ] Link to comment Share on other sites More sharing options...
Siao Posted April 21, 2008 Share Posted April 21, 2008 (edited) I can confirm that something weird is going on with user return values from callbacks in v3.2.11 betas.For example, I believe that this http://www.autoitscript.com/forum/index.ph...amp;hl=listview (posts #3-#7) is related with the problem you describe here. That custom drawn listview example worked in v.3.2.10.0, doesn't work for betas. I thought I figured out the problem, - it looked like internal message proc simply overrides user return value of item prepaint notification with one of it's own for whatever reason - subclassing main GUI "fixed" the problem. Then after some time I decided to submit the bug, and started stripping down the example to the bare minimum. And suddenly, it started "working" again, which got me confused, so I put whole thing aside for a while.Example:expandcollapse popup#include <GuiListView.au3> #include <ListViewConstants.au3> #include <WindowsConstants.au3> #include <GuiConstantsEx.au3> ;custom draw constants for v3.2.10.0 ;~ Global Const $CDDS_ITEM = 0x10000, $CDDS_PREPAINT = 0x1, $CDDS_SUBITEM = 0x20000, $CDDS_ITEMPREPAINT = BitOR($CDDS_ITEM,$CDDS_PREPAINT), _ ;~ $CDRF_NEWFONT = 0x2, $CDRF_NOTIFYITEMDRAW = 0x20, $CDRF_NOTIFYSUBITEMDRAW = 0x20 $hGUI = GUICreate("Listview Custom Draw", 400, 300) $cListView = GUICtrlCreateListView("1|2|3", 2, 2, 394, 268, -1, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT)) GUICtrlCreateListViewItem("a|b|c",$cListView) GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam) Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom") $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") Switch $iIDFrom Case $cListView Switch $iCode Case $NM_CUSTOMDRAW ;~ If Not _GUICtrlListView_GetViewDetails($cListView) Then Return $GUI_RUNDEFMSG Local $tCustDraw = DllStructCreate('hwnd hwndFrom;int idFrom;int code;' & _ 'dword DrawStage;hwnd hdc;long rect[4];dword ItemSpec;int ItemState;dword Itemlparam;' & _ 'dword clrText;dword clrTextBk;int SubItem;' & _ 'dword ItemType;dword clrFace;int IconEffect;int IconPhase;int PartID;int StateID;long rectText[4];int Align', _;winxp or later $lParam), $iDrawStage $iDrawStage = DllStructGetData($tCustDraw, 'DrawStage') Switch $iDrawStage Case $CDDS_PREPAINT ConsoleWrite("$CDDS_PREPAINT" & @CRLF) Return $CDRF_NOTIFYITEMDRAW Case $CDDS_ITEMPREPAINT ConsoleWrite("$CDDS_ITEMPREPAINT" & @CRLF) Return $CDRF_NOTIFYSUBITEMDRAW Case BitOR($CDDS_ITEMPREPAINT, $CDDS_SUBITEM) ConsoleWrite("$CDDS_ITEMPREPAINT+$CDDS_SUBITEM" & @CRLF) Return $CDRF_NEWFONT Case Else EndSwitch EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc;==>WM_NOTIFYWorks with betas - Case BitOR($CDDS_ITEMPREPAINT, $CDDS_SUBITEM) is executed. Then uncomment the line "If Not _GUICtrlListView_GetViewDetails($cListView) Then" and the subitem case isn't getting executed anymore. Edited April 21, 2008 by Siao "be smart, drink your wine" Link to comment Share on other sites More sharing options...
-Ultima- Posted April 21, 2008 Author Share Posted April 21, 2008 Thanks for your confirmation I've reported the bug here. [ WinINet.au3 | Array.au3 (Optimized) | _UnixTimeParse() ] Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now