Что нового

[Элементы GUI] Как реализовать разделительную полосу в Listbox?

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Кто то может сталкивался с реализацией разделителя-группы в Listbox?
На данный момент использую обычный пункт с текстом (------- Separator -------), но хотелось бы это сделать покрасивее, как группу в ListView.


P.S.
ListView не предлагать, интересует именно ListBox.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Вот так получилось:

Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GUIListBox.au3>
#include <WinAPI.au3>

Global Const $ODT_LISTBOX = 2
Global Const $ODA_DRAWENTIRE = 0x1
Global Const $ODA_SELECT = 0x2
Global Const $ODA_FOCUS = 0x4
Global Const $ODS_SELECTED = 0x1
Global Const $ODS_NOACCEL = 0x100
Global Const $ODS_NOFOCUSRECT = 0x200

Global $iLB_LastSelIndx = -1
Global $sSep_RegExp = '^(—+) .*? \1$'


$hGUI = GUICreate("ListBox Separator Demo", 300, 200)

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUIRegisterMsg($WM_MEASUREITEM, "WM_MEASUREITEM")
GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")

$iListBox = GUICtrlCreateList("", 10, 10, 280, 180, BitOR($LBS_HASSTRINGS, $LBS_OWNERDRAWFIXED, $WS_VSCROLL))
$hListBox = GUICtrlGetHandle($iListBox)

For $i = 1 To 10
	If Mod($i, 3) = 0 Then
		_GUICtrlListBox_AddString($iListBox, "———————————————— Separator" & -Mod($i, 4) + 4 & " ————————————————")
	EndIf
	
	_GUICtrlListBox_AddString($iListBox, "String " & $i)
Next

GUISetState()

While 1
	$nMsg = GUIGetMsg()

	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
WEnd

Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
	Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndList
	$hWndListBox = $hListBox
	If Not IsHWnd($hListBox) Then $hWndListBox = GUICtrlGetHandle($hListBox)
	
    $hWndFrom = $ilParam
    $iIDFrom = BitAND($iwParam, 0xFFFF); Low Word
    $iCode = BitShift($iwParam, 16); Hi Word
	
	Switch $hWndFrom
		Case $hWndListBox
			Switch $iCode
				Case $LBN_SELCHANGE ;, $LBN_DBLCLK
					Local $iIndex = _GUICtrlListBox_GetCurSel($hListBox)
					Local $sText = _GUICtrlListBox_GetText($hListBox, $iIndex)
					
					If StringRegExp($sText, $sSep_RegExp) Then
						_GUICtrlListBox_SetCurSel($hListBox, $iLB_LastSelIndx)
					Else
						$iLB_LastSelIndx = $iIndex
					EndIf
			EndSwitch
	EndSwitch
	
	Return $GUI_RUNDEFMSG
EndFunc

Func WM_MEASUREITEM($hWnd, $Msg, $wParam, $lParam)
	Local $CtlType, $tagMEASUREITEMSTRUCT = "UINT CtlType;UINT CtlID;UINT itemID;UINT itemWidth;UINT itemHeight;ULONG_PTR itemData;"
	Local $MEASUREITEMSTRUCT = DllStructCreate($tagMEASUREITEMSTRUCT, $lParam)
	
	$CtlType = DllStructGetData($MEASUREITEMSTRUCT, "CtlType")
	If $CtlType <> $ODT_LISTBOX Then Return $GUI_RUNDEFMSG
	
	;Set height of the item's (text and background)
	DllStructSetData($MEASUREITEMSTRUCT, 5, 15)
	DllStructSetData($MEASUREITEMSTRUCT, 4, DllStructGetData($MEASUREITEMSTRUCT, 4) + 15)
	
	Return
EndFunc

Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
	Local $tagDRAWITEMSTRUCT, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC, $hBrush, $hBrushOld
	
	$tagDRAWITEMSTRUCT = DllStructCreate("uint cType;uint cID;uint itmID;uint itmAction;uint itmState;" & _
		"hwnd hItm;hwnd hDC;int itmRect[4];dword itmData", $lParam)
	If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTBOX Then Return $GUI_RUNDEFMSG
	
	$cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")
	$itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")
	$itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")
	$itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")
	$hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")
	$hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")
	
	Switch $itmAction
		Case $ODA_DRAWENTIRE, $ODA_SELECT
			;get the text to be drawn
			Local $iStringLen = _GUICtrlListBox_GetTextLen($hItm, $itmID)
			Local $itmText = _GUICtrlListBox_GetText($hItm, $itmID)
			Local $iBrushColor = 0XFFFFFF, $iTxtColor = 0x000000
			
			If $itmState = $ODS_SELECTED Or $itmState = BitOR($ODS_SELECTED, $ODS_NOACCEL, $ODS_NOFOCUSRECT) Then
				$iBrushColor = _WinAPI_GetSysColor($COLOR_HIGHLIGHT)
				$iTxtColor = 0xFFFFFF
			EndIf
			
			If StringRegExp($itmText, $sSep_RegExp) Then
				$iBrushColor = 0XFFFFFF
				$iTxtColor = 0XCCCCCC
			EndIf
			
			$hBrush = _WinAPI_CreateSolidBrush($iBrushColor)
			$hBrushOld = _WinAPI_SelectObject($hDC, $hBrush)
			
			_WinAPI_SetTextColor($hDC, $iTxtColor)
			_WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $hBrush)
			_WinAPI_SelectObject($hDC, $hBrushOld)
			_WinAPI_DeleteObject($hBrush)
			_WinAPI_SetBkMode($hDC, 1)
			
			Local $tRECT = DllStructCreate("int Left;int Top;int Right;int Bottom")
			DllStructSetData($tRECT, "Left", DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1) + 5)
			DllStructSetData($tRECT, "Top", DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 2))
			DllStructSetData($tRECT, "Right", DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 3))
			DllStructSetData($tRECT, "Bottom", DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 4))
			
			_WinAPI_DrawText($hDC, $itmText, $tRECT, $DT_LEFT)
			
			Return 1
		Case $ODA_FOCUS
			Return 1
	EndSwitch
	
	Return $GUI_RUNDEFMSG
EndFunc
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Немного обновил пример, теперь разделители выделить нельзя.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Обновил пример ещё немного, среди прочего, теперь цвет выделенного пункта задаётся такой же как и системный ($COLOR_HIGHLIGHT).
 
Верх