jmon Posted October 27, 2012 Posted October 27, 2012 (edited) Hello everyone, I am trying to create some labels over some tabs, to kind of highlights tabs. I get the position of the tabs, and move the labels over them. When I use the up-down control to move the tabs, I need to compute the position again. The problem is that in the execution order, the labels are refreshed before the position of the tabs and I don't know how to change that (that creates a sort of delay and the labels don't stick to the tabs because the tabs move after the labels have been refreshed). I found that the WM_NOTIFY -722 is sent when you click on the up-down. Check out the example below, and try to enable the "sleep" at line 101 to see the refresh order. expandcollapse popup#include <StructureConstants.au3> #include <TabConstants.au3> #include <GUIConstantsEx.au3> #include <GuiTab.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <WinAPI.au3> #include <Math.au3> Global $hTab, $GUI _Main() Func _Main() $GUI = GUICreate("Test", 500, 500) $hTab = GUICtrlCreateTab(50, 50, 396, 296) GUISetState() _GUICtrlTab_SetMinTabWidth(GUICtrlGetHandle($hTab), 100) GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") _Tab_Add(0, "Tab 1", 0xFFFF00) ;Tab 1 will be yellow _Tab_Add(1, "Tab 2") _Tab_Add(2, "Tab 3") _Tab_Add(3, "Tab 4", 0x00FF00) ;tab 4 is green _Tab_Add(4, "Tab 5", 0x0000FF) ;tab 5 is blue _Tab_Hightlight(0) _Tab_Hightlight(3) _Tab_Hightlight(4) ; Loop until user exits Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete() EndFunc ;==>_Main Func _Tab_Add($iItem, $sText, $iColor = 0xFF0000) Local $iTab = _GUICtrlTab_InsertItem($hTab, $iItem, $sText) $aRect = _GUICtrlTab_GetItemRect($hTab, $iTab) If Not IsArray($aRect) Then Return SetError(1, 0, 0) $iCtrl = GUICtrlCreateLabel("", $aRect[0], $aRect[1], 100, 2) GUICtrlSetBkColor($iCtrl, $iColor) GUICtrlSetState($iCtrl, $GUI_HIDE + $GUI_DISABLE) _GUICtrlTab_SetItemParam($hTab, $iTab, $iCtrl) EndFunc ;==>_Tab_Add Func _Tab_Hightlight($iTabItem, $bHighlight = True) Local $iCtrl, $aRect If $bHighlight Then ;highlight: $iCtrl = _GUICtrlTab_GetItemParam($hTab, $iTabItem) Local $aPos = ControlGetPos($GUI, '', $hTab) $aRect = _GUICtrlTab_GetItemRect($hTab, $iTabItem) If Not IsArray($aRect) Then Return SetError(1, 0, 0) GUICtrlSetPos($iCtrl, $aPos[0] + $aRect[0], $aPos[1] + $aRect[1]) GUICtrlSetState($iCtrl, $GUI_ONTOP + $GUI_SHOW + $GUI_ENABLE) Return SetError(0, 0, $iCtrl) Else ;un-highlight: $iCtrl = _GUICtrlTab_GetItemParam($hTab, $iTabItem) GUICtrlSetState($iCtrl, $GUI_HIDE + $GUI_DISABLE) Return SetError(0, 0, 1) EndIf EndFunc ;==>_Tab_Hightlight Func _tab_RedrawNotif() Local $aPos = ControlGetPos($GUI, '', $hTab) If @error Then Return SetError(1, 0, 0) Local $iCount = _GUICtrlTab_GetItemCount($hTab) For $i = 0 To $iCount Local $iCtrl = _GUICtrlTab_GetItemParam($hTab, $i) $aRect = _GUICtrlTab_GetItemRect($hTab, $i) If Not IsArray($aRect) Then ContinueLoop Local $x = _Max($aPos[0], $aPos[0] + $aRect[0]) Local $y = $aPos[1] + $aRect[1] Local $w = 100 If $x <= $aPos[0] Then $w = 0 EndIf If $x + $w > $aPos[1] + $aPos[2] Then $w = ($aPos[1] + $aPos[2]) - ($x) EndIf GUICtrlSetPos($iCtrl, $x, $y, $w) ;~ Sleep ( 50 ) ;!! TRY TO ENABLE THIS SLEEP AND SEE THAT THE LABELS ARE UPDATED BEFORE THE TAB Next Return True EndFunc ;==>_tab_RedrawNotif Func WM_NOTIFY($hWndGUI, $MsgID, $wParam, $lParam) Local $tagNMHDR = DllStructCreate("int;int;int;int;int;int;int;ptr;int;int;int;int;int;int;int;int;int;int;int", $lParam) If @error Then Return Local $hWndFrom = DllStructGetData($tagNMHDR, 1) Local $IdFrom = DllStructGetData($tagNMHDR, 2) Local $Event = DllStructGetData($tagNMHDR, 3) ;Appearently this event (-722) is triggered when the user clicks the up-down on the tabs If $Event = -722 Then ConsoleWrite("From : " & $hWndFrom & " idfrom : " & $IdFrom & " event : " & $Event & @CR) _tab_RedrawNotif() Return 1 EndIf Switch $hWndFrom Case GUICtrlGetHandle($hTab) ;From the tab control: Switch $Event Case $NM_RCLICK ;Right click to highlight Local $tPoint = _WinAPI_GetMousePos(True, GUICtrlGetHandle($hTab)) Local $tHitTest = _GUICtrlTab_HitTest(GUICtrlGetHandle($hTab), DllStructGetData($tPoint, 1), DllStructGetData($tPoint, 2)) If Not $tHitTest = -1 Then If $tHitTest[0] <> -1 Then _Tab_Hightlight($tHitTest[0], True) EndIf EndIf Case $TCN_SELCHANGE ;left click or change tab to un-highlight: Local $iItem = _GUICtrlTab_GetCurFocus(GUICtrlGetHandle($hTab)) If $iItem <> -1 Then _Tab_Hightlight($iItem, False) EndIf EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Thanks for your time. PS: I don't want to use the built in function to highlight the tabs because it doesn't work with Uskin dll [EDIT] Solved in post #4 by LarsJ. Edited November 5, 2012 by jmon [center]www.jmontserrat.comFile Sequence UDF - _StringExtractPaths - _StringTrimPattern - GuiCtrlSetOnTop - CalendarUDF[/center]
PhoenixXL Posted October 27, 2012 Posted October 27, 2012 what you are doing is very complicatedtry to draw, paint labels and use them to switch your tab jmon 1 My code: PredictText: Predict Text of an Edit Control Like Scite. Remote Gmail: Execute your Scripts through Gmail. StringRegExp:Share and learn RegExp.Run As System: A command line wrapper around PSEXEC.exe to execute your apps scripts as System (LSA). Database: An easier approach for _SQ_LITE beginners. MathsEx: A UDF for Fractions and LCM, GCF/HCF. FloatingText: An UDF for make your text floating. Clipboard Extendor: A clipboard monitoring tool. Custom ScrollBar: Scroll Bar made with GDI+, user can use bitmaps instead. RestrictEdit_SRE: Restrict text in an Edit Control through a Regular Expression.
jmon Posted November 2, 2012 Author Posted November 2, 2012 Thanks for your help PhoenixXl. I guess that's the only possible solution. [center]www.jmontserrat.comFile Sequence UDF - _StringExtractPaths - _StringTrimPattern - GuiCtrlSetOnTop - CalendarUDF[/center]
Solution LarsJ Posted November 4, 2012 Solution Posted November 4, 2012 (edited) jmon, If you use custom drawn tabs and the WM_DRAWITEM event to position the labels, you will not have any problems with reordering of the tabs. The WM_DRAWITEM event fires after the reordering. The example below looks and works fine (Win XP), but custom drawn tabs doesn't look exactly like system drawn. expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <StructureConstants.au3> #include <GuiTab.au3> Global Const $ODT_TAB = 101 Global Const $ODA_DRAWENTIRE = 0x1 Global Const $ODS_SELECTED = 0x0001 Opt( "MustDeclareVars", 1 ) Global $hGui, $idTab, $hTab, $aPos MainScript() Func MainScript() $hGui = GUICreate("Test", 500, 500) $idTab = GUICtrlCreateTab(50, 50, 400, 296, $TCS_OWNERDRAWFIXED) $hTab = GUICtrlGetHandle($idTab) _GUICtrlTab_SetMinTabWidth($hTab, 100) $aPos = ControlGetPos($hGui, '', $idTab) GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM") GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState() _GUICtrlTab_InsertItem($hTab, 0, "Tab 0") _GUICtrlTab_InsertItem($hTab, 1, "Tab 1") _GUICtrlTab_InsertItem($hTab, 2, "Tab 2") _GUICtrlTab_InsertItem($hTab, 3, "Tab 3") _GUICtrlTab_InsertItem($hTab, 4, "Tab 4") _GUICtrlTab_InsertItem($hTab, 5, "Tab 5") _GUICtrlTab_InsertItem($hTab, 6, "Tab 6") _GUICtrlTab_InsertItem($hTab, 7, "Tab 7") _GUICtrlTab_InsertItem($hTab, 8, "Tab 8") _GUICtrlTab_InsertItem($hTab, 9, "Tab 9") TabHighlight(1, 0xFFFF00) ; tab 1 yellow TabHighlight(4, 0x00FF00) ; tab 4 green TabHighlight(5, 0x0000FF) ; tab 5 blue ; Loop until user exits Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete() EndFunc Func TabHighlight($iTab, $iColor) Local $aDisRect, $aRect, $iCtrl $aDisRect = _GUICtrlTab_GetDisplayRect($hTab) $aRect = _GUICtrlTab_GetItemRect($hTab, $iTab) $iCtrl = GUICtrlCreateLabel("", $aRect[0], $aRect[1], $aRect[2]-$aRect[0]-2, 2) GUICtrlSetBkColor($iCtrl, $iColor) If $aRect[0] < $aDisRect[2] Then GUICtrlSetPos($iCtrl, $aPos[0] + $aRect[0], $aPos[1] + $aRect[1]) GUICtrlSetState($iCtrl, $GUI_ONTOP + $GUI_SHOW + $GUI_ENABLE) Else GUICtrlSetState($iCtrl, $GUI_HIDE + $GUI_DISABLE) EndIf _GUICtrlTab_SetItemParam($hTab, $iTab, $iCtrl) EndFunc Func TabRemoveHighlight() Local $iCount = _GUICtrlTab_GetItemCount($hTab), $iCtrl For $i = 0 To $iCount - 1 $iCtrl = _GUICtrlTab_GetItemParam($hTab, $i) If $iCtrl = 0 Then ContinueLoop GUICtrlSetState($iCtrl, $GUI_HIDE + $GUI_DISABLE) Next EndFunc Func WM_NOTIFY($hWndGUI, $MsgID, $wParam, $lParam) Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) Local $hWndFrom = DllStructGetData($tNMHDR, 1) Local $Event = DllStructGetData($tNMHDR, 3) ;Appearently this event (-722) is triggered when the user clicks the up-down on the tabs If $Event = -722 Then TabRemoveHighlight() Return 1 EndIf Switch $hWndFrom Case $hTab Switch $Event Case $TCN_SELCHANGE Local $iItem = _GUICtrlTab_GetCurFocus(GUICtrlGetHandle($hTab)) If $iItem <> -1 Then TabRemoveHighlight() EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam) Local $tDRAWITEMSTRUCT = DllStructCreate("uint cType;uint cID;uint itmID;uint itmAction;uint itmState;" & _ "hwnd hItm;hwnd hDC;dword itmRect[4];dword itmData", $lParam) If DllStructGetData($tDRAWITEMSTRUCT, "cType") <> $ODT_TAB Then Return $GUI_RUNDEFMSG If DllStructGetData($tDRAWITEMSTRUCT, "itmAction") <> $ODA_DRAWENTIRE Then Return $GUI_RUNDEFMSG Local $itmID = DllStructGetData($tDRAWITEMSTRUCT, "itmID") Local $iCtrl = _GUICtrlTab_GetItemParam($hTab, $itmID) If $iCtrl Then Local $aRect = _GUICtrlTab_GetItemRect($hTab, $itmID) If $aRect[0] > 0 Then GUICtrlSetPos($iCtrl, $aPos[0] + $aRect[0], $aPos[1] + $aRect[1]) GUICtrlSetState($iCtrl, $GUI_ONTOP + $GUI_SHOW + $GUI_ENABLE) EndIf EndIf Local $tBuffer = DllStructCreate("char[256]") DllStructSetData($tBuffer, 1, "Tab " & $itmID) Local $itmText = DllStructGetData($tBuffer, 1) DllStructSetData($tDRAWITEMSTRUCT, "itmRect", DllStructGetData($tDRAWITEMSTRUCT, "itmRect", 1) + 4, 1) DllStructSetData($tDRAWITEMSTRUCT, "itmRect", DllStructGetData($tDRAWITEMSTRUCT, "itmRect", 2) + 4, 2) Local $hDC = DllStructGetData($tDRAWITEMSTRUCT, "hDC") If DllStructGetData($tDRAWITEMSTRUCT, "itmState") = $ODS_SELECTED Then _WinAPI_SetTextColor($hDC, 0x0000FF) ; Red, BGR Else _WinAPI_SetTextColor($hDC, 0x000000) EndIf DllCall("user32.dll", "int", "DrawText", "hwnd", $hDC, "str", $itmText, "int", StringLen($itmText), _ "ptr", DllStructGetPtr($tDRAWITEMSTRUCT, "itmRect"), "int", $DT_LEFT) Return $GUI_RUNDEFMSG EndFunc Lars Edited November 4, 2012 by LarsJ jmon 1 Controls,  File Explorer,  ROT objects,  UI Automation,  Windows Message MonitorCompiled code: Accessing AutoIt variables,  DotNet.au3 UDF,  Using C# and VB codeShell menus: The Context menu,  The Favorites menu. Shell related: Control Panel,  System Image ListsGraphics related: Rubik's Cube,  OpenGL without external libraries,  Navigating in an image,  Non-rectangular selectionsListView controls: Colors and fonts,  Multi-line header,  Multi-line items,  Checkboxes and icons,  Incremental searchListView controls: Virtual ListViews,  Editing cells,  Data display functions
jmon Posted November 5, 2012 Author Posted November 5, 2012 (edited) Thank you Lars ! That's exactly what I was looking for. I was hoping for someone to give me an answer using the WM_DRAWITEM! I had no idea how to use it and it's very powerful.It works on windows 7 ultimate x64Thanks a lot,Jmon[EDIT] Works very well, but still having a problem with uSkin: check out post. Edited November 5, 2012 by jmon [center]www.jmontserrat.comFile Sequence UDF - _StringExtractPaths - _StringTrimPattern - GuiCtrlSetOnTop - CalendarUDF[/center]
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