Jump to content

Create labels over tabs and follow tabs on up-down click (SOLVED)


jmon
 Share

Go to solution Solved by LarsJ,

Recommended Posts

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.

#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 by jmon
Link to comment
Share on other sites

what you are doing is very complicated

try to draw, paint labels and use them to switch your tab

;)

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.

Link to comment
Share on other sites

  • Solution

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.

#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 by LarsJ
Link to comment
Share on other sites

Thank you Lars ! :thumbsup:

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 x64

Thanks a lot,

Jmon

[EDIT]

Works very well, but still having a problem with uSkin: check out post.

Edited by jmon
Link to comment
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
 Share

×
×
  • Create New...