powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Headers in ListView: проблема с картинками: высота и перерисовка.
10 сообщений из 10, страница 1 из 1
Headers in ListView: проблема с картинками: высота и перерисовка.
    #36610134
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проблема #1:
Если mscomctl сам вставляет картинки и худо-бедно регулирует высоту, то Comctl этого не делает. Т.е. если на Висте все и так хорошо, на XP-стиле так сказать терпимо, то на классике просто похабно. Высоту явно надо увеличить.
Что-то я уже наискал на тему HD_LAYOUT, но добротных примеров не нашел.
Как изменить headers.height?

Проблема #2:
Видна из рисунка ниже. Проявляется исключительно на классике при использовании манифеста. При применении горизонтального скроллинга картинка уезжает куда надо, а тень ее (верт. полоса справа и слева) остается на прежнем месте.


Здесь видимо потребуются дополнит. объяснения:
1) Я использую для Listview
Код: vbnet
1.
lStyle = lStyle Or LVS_EX_FULLROWSELECT Or LVS_EX_DOUBLEBUFFER


LVS_EX_DOUBLEBUFFER жизненно необходим для
Код: vbnet
1.
SetWindowTheme ListView1.hwnd, StrPtr("explorer"), 0


в случае Висты и достаточно хорош для остальных стилей /систем, т.к. уменьшает мерцалку при перерисовках, но имеет побочный эффект неперерисовки header-ов в принципе, поэтому это надо делать принудительно:
2)
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
 Public Function NewListWindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    'для событий listview
    If (Msg = &HF) Then 'WM_PAINT
        Form1.RedrawHeaders
    end if
...
Public Sub RedrawHeaders()
'    'перерисовка,ибо сам не удосуживается это сделать
    Dim pvHeaderhWnd As Long
        pvHeaderhWnd = SendMessageLong(ListView1.hwnd, LVM_GETHEADER, 0, 0)
        Call RedrawWindow(pvHeaderhWnd, ByVal 0&, ByVal 0&, RDW_INVALIDATE Or RDW_FRAME Or RDW_UPDATENOW)
...


Собственно глюк, нарисованный на картинках выше обусловлен именно этим пунктом и не зависит от LVS_EX_DOUBLEBUFFER, но я вынужден выполнять этот код именно из-за LVS_EX_DOUBLEBUFFER
Я могу не использовать LVS_EX_DOUBLEBUFFER для классики, но тогда при горизонтальном скроллинге header-ы вообще могут "затираться ластиком", т.е. пункт 2 полезен по-любому

3) В принципе я нашел как исправить и это:
(Я назначаю картинки ПОВТОРНО после принудительной перерисовки, тени исчезают, но не дай бог я буду перерисовывать картинку в первом, т.е. нулевом столбце, тогда ничего не сработает)
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Public Sub RedrawHeaders()
'    'перерисовка,ибо сам не удосуживается это сделать
    Dim pvHeaderhWnd As Long
        pvHeaderhWnd = SendMessageLong(ListView1.hwnd, LVM_GETHEADER, 0, 0)
        Call RedrawWindow(pvHeaderhWnd, ByVal 0&, ByVal 0&, RDW_INVALIDATE Or RDW_FRAME Or RDW_UPDATENOW)

    Dim lvFormat As LV_COLUMN
        With lvFormat
            .mask = LVCF_FMT Or LVCF_IMAGE
            .fmt = LVCFMT_IMAGE 'Or LVCFMT_BITMAP_ON_RIGHT   '
            .iImage = 1
        End With
    'Call SendMessage(ListView1.hwnd, LVM_SETCOLUMN, 0, lvFormat)
    Call SendMessage(ListView1.hwnd, LVM_SETCOLUMN, 1, lvFormat)
    Call SendMessage(ListView1.hwnd, LVM_SETCOLUMN, 2, lvFormat)
End Sub


Но теперь "ТЕНИ" появляются в момент MOUSE_UP при раздвижении header-ов.
Ладно, бьем и здесь.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Public Function NewListHeaderWindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
 'Private Const WM_MOUSEUP = &H200
 'для событий listview Header
     If (Msg = &H200) Then 'WM_MOUSEUP 
         Form1.RedrawHeaders
    End If
    NewListHeaderWindowProc = CallWindowProc( _
        OldListHeaderWindowProc, hwnd, Msg, wParam, _
        lParam)
End Function



Но остается проблема НУЛЕВОГО СТОЛБЦА. При задвигании его влево тень его картинки нас преследует, мои ходы это не решают.

Вообще говоря, резонно задать еще следующий вопрос.
Как отменить действие манифеста применительно к заданному контролу? Он на классике часто ничего не дает (для header-ов то точно), иногда дает глюки.
Иногда хочется скажем чтоб на ListView был FocusRectangle (с точечками даже красивее).

Я конечно могу отменить стиль
Код: vbnet
1.
2.
3.
4.
5.
Private Declare Function DeactivateWindowTheme Lib "uxtheme" _
    Alias "SetWindowTheme" ( _
     ByVal hwnd As Long, _
     Optional ByRef pszSubAppName As String = " ", _
     Optional ByRef pszSubIdList As String = " ") As Long


Но этим я отменяю лишь Vista/XP стиль, но никак не "вредные" деяния манифеста. Типа тема уходит, а тени остаются.
...
Рейтинг: 0 / 0
Headers in ListView: проблема с картинками: высота и перерисовка.
    #36612604
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По поводу высоты самую умную информацию я нашел здесь:
http://forum.sources.ru/index.php?s=1c8d2b146bbf5e9b1646f3ee0a5759bf&showtopic=252062
(в конце самом)
Ну допустим устанавливаю я первый шрифт "10" (что дает нужную высоту в 20 пикселей на классике)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
Private Function HD_Height(hFont As Long, HD_hWnd As Long)
Dim Retv As Long
Dim tHDL As HDLAYOUT
Dim rc As RECT
Dim pwpos As WINDOWPOS
Retv = SendMessage(HD_hWnd, WM_SETFONT, hFont, True)
If Retv Then
    tHDL.lprc = VarPtr(rc)
    tHDL.lpwpos = VarPtr(pwpos)

    Call SendMessage(HD_hWnd, HDM_LAYOUT,  0 , tHDL)
    Height = rc.top
End If
Private Sub SetHeight() 'в Load например
    Dim fnt As IFont
    Dim pvHeaderhWnd As Long
    Set fnt = Me.Font
    fnt.Size =  10 
    pvHeaderhWnd = SendMessageLong(ListView1.hwnd, LVM_GETHEADER,  0 ,  0 )
    HD_Height fnt.hFont, pvHeaderhWnd
...
это работает, но шрифт-то мне нужен "8" (оригинальный)

Автор настолько обрадовался
Код: plaintext
1.
2.
3.
4.
Мона создать два шрифта.
Одним изменять размер, другой использовать для создания образа в контексте
и с помощью BitBlt скопировать в итем хидера.
Все. Тема закрыта.
Всем спасибо! 
что не описал как собственно это сделать. В каком контексте, какой-такой BitBlt? Без примера что имел ввиду не пойму.

Кой-какую информацию можно почерпнуть тут:
http://www.vbaccelerator.com/home/vb/code/controls/s_grid_2/s_grid_2/VB5_SGrid_2_Full_Source_zip_cHeaderControl_cls.asp

Ну накатал я вот такую функцию....
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
Private Function IdealHeaderHeight(m_hWnd As Long) As Long
Dim tHDL As HDLAYOUT
Dim rc As RECT
Dim pwpos As WINDOWPOS
Dim lR As Long
Dim lHeight As Long
Dim cx As Long
Dim cy As Long
   
   tHDL.lprc = VarPtr(rc)
   tHDL.lpwpos = VarPtr(pwpos)
   
   lR = SendMessage(m_hWnd, HDM_LAYOUT,  0 , tHDL)
   lHeight = pwpos.cy
   'MsgBox lHeight
   'ImageList_GetIconSize m_hIml, cx, cy
   cx =  16 
   cy =  16 
   If (lHeight < cy +  4 ) Then
      lHeight = cy +  4 
   End If
   IdealHeaderHeight = lHeight
'//   rc.bottom = rc.top + lHeight
'//   SetWindowPos m_hWnd, 0, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 1
'//   'MoveWindow m_hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 1
'//   InvalidateRect m_hWnd, rc, 0
'//   UpdateWindow m_hWnd
End Function

Ну говорит она мне что тек. высота 17, а идеальная 20. Спасибо, я это итак знаю. Попытки применить все что после строчки IdealHeaderHeight = lHeight типа MoveWindow/InvalidateRect/UpdateWindow глючит безбожно, т.к. очевидно идет борьба с VB-Listview, видимо это вообще не тот путь.

"Мона создать два шрифта" мне больше нравится, только как это "мона". Без примера не знаю.

Есть еще вариант вставлять картинки 16х16, но с полями в один пиксель снизу и сверху(типа реальная высота 14, это нормально смотрится). Но тогда картинки придется очень аккуратно подбирать. Причем сразу становится обидно за Висту, где родной высоты с лихвой хватает.
Ну,б... 6-й контрол же как-то это делает...
===============================================
"ТЕНИ" вокруг картинок.

Код: plaintext
  Call SendMessageLong(pvHeaderhWnd, HDM_SETBITMAPMARGIN, <width>,  0 ) 'HDM_SETBITMAPMARGIN
<width>=5 по умолчанию
Если сделать =0, то тени вообще не будет, но это некрасиво. Остается либо мой вариант, где тень таки остается в нулевой колонке(это не очень бросается), либо выяснять как делать тень "прозрачной".
...
Рейтинг: 0 / 0
Headers in ListView: проблема с картинками: высота и перерисовка.
    #36618838
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77
"ТЕНИ" вокруг картинок.
Код: plaintext
  Call SendMessageLong(pvHeaderhWnd, HDM_SETBITMAPMARGIN, <width>,  0 ) 'HDM_SETBITMAPMARGIN
<width>=5 по умолчанию
Если сделать =0, то тени вообще не будет, но это некрасиво. Остается либо мой вариант, где тень таки остается в нулевой колонке(это не очень бросается), либо выяснять как делать тень "прозрачной".
Тот метод что я привел никуда не годится. Во-первых проблема нулевого столбца. Во-вторых если делать колонки слишком узкими, то тени все равно выезжают где попало. Подозреваю что это как то связано с тем, что Control-5 ни хрена не умеет правильно работать с шириной столбцов.

Если коротко, то это целиком и полностью лечится хитростью.
1. BITMAPMARGIN надо вообще убрать:
Код: plaintext
  Call SendMessageLong(pvHeaderhWnd, HDM_SETBITMAPMARGIN,  0 ,  0 )
2. Но надо добавить прозрачные 5 пикселей в каждую иконку слева и справа, т.е. вместо 16х16 работать с 26х16. Это позволит сохранить желаемый default-внешний вид, т.е. MARGIN-ы прикручиваются на уровне самой картинки, а не ее рамки.
И это полностью решает эту проблему.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
    If IsIDEApp Then
        m_hImlHD = ImageList_Create( 26 ,  16 , ILC_MASK Or ILC_COLOR32,  1 ,  0 )
        ImageList_AddMasked m_hImlHD, LoadResPicture( 201 , vbResBitmap), vbBlue
        ImageList_AddMasked m_hImlHD, LoadResPicture( 202 , vbResBitmap), vbBlue
        ImageList_AddMasked m_hImlHD, LoadResPicture( 203 , vbResBitmap), vbBlue
    Else
        m_hImlHD = ImageList_Create( 26 ,  16 , ILC_MASK Or ILC_COLOR32,  3 ,  0 )
        lngIcon = LoadImage(App.hInstance, MAKEINTRESOURCE( 201 ), IMAGE_ICON,  26 ,  16 , LR_DEFAULTCOLOR)
        ImageList_ReplaceIcon m_hImlHD, - 1 , lngIcon
        lngIcon = LoadImage(App.hInstance, MAKEINTRESOURCE( 202 ), IMAGE_ICON,  26 ,  16 , LR_DEFAULTCOLOR)
        ImageList_ReplaceIcon m_hImlHD, - 1 , lngIcon
        lngIcon = LoadImage(App.hInstance, MAKEINTRESOURCE( 203 ), IMAGE_ICON,  26 ,  16 , LR_DEFAULTCOLOR)
        ImageList_ReplaceIcon m_hImlHD, - 1 , lngIcon
    End If
===========================================
А вот с высотой ничего пока не придумал, кроме как использовать рабочую область иконки 16х14 (естественно иконки надо подбирать более тщательно, на альфа-художника я не тяну, а на таких мелких размерах программы обычно не справляются с перерисовкой).
Попытка использовать более высокую иконку, в отличии от предыдущего случая не фурычит: иконка будет обрезана стандартной высотой header-а.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Headers in ListView: проблема с картинками: высота и перерисовка.
    #38248269
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пытаюсь все-таки разобраться с высотой headers.
М.б. кто подскажет у кого рука набита?

Что надо делать в принципе я понял.
Сабклассить hwndHeader, ловить HDM_LAYOUT и менять pwpos.cy

Вот я пытаюсь хотя бы распечатать в debug ту .cy что он предлагает:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
Private Type WINDOWPOS
    hwnd As Long
    hWndInsertAfter As Long
    x As Long
    y As Long
    cx As Long
    cy As Long
    Flags As Long
End Type

Private Type HDLAYOUT
  prc As RECT
  pwpos As WINDOWPOS
End Type
'Private Type HDLAYOUT
'  prc As Long
'  pwpos As Long
'End Type

Public Function NewListHeadWindowProc( _
 ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  'для событий listview1 (header)
  Dim Layout As HDLAYOUT
  Dim wPos As WINDOWPOS

  
  If Msg = HDM_LAYOUT Then
    Debug.Print "HDM_LAYOUT"
    MoveMemory ByVal VarPtr(Layout), ByVal lParam, LenB(Layout)
    'MoveMemory wPos, Layout.pwpos, LenB(wPos)
'    Debug.Print Layout.prc & " / " & Layout.pwpos
'    MoveMemory wPos, ByVal Layout.pwpos, LenB(wPos)
    Debug.Print Layout.pwpos.cy
'    Dim the_cy As Long
'    MoveMemory the_cy, ByVal Layout.pwpos.cy, 4
'    Debug.Print the_cy
  End If



И чтобы я ни делал, у меня там выводятся либо ссылки на память, либо нули.
Как я понимаю, Layout.pwpos.cy должен выдавать высоту в пикселях, которую я и должен в сабклассинге поменять на большую.
Но я походу запутался с Ptr-ами и значениями.

HDM_LAYOUT message
lParam
A pointer to an HDLAYOUT structure. The prc member specifies the coordinates of a rectangle, and the pwpos member receives the size and position for the header control within the rectangle.

HDLAYOUT structure
Код: plaintext
1.
2.
3.
4.
typedef struct _HD_LAYOUT {
  RECT      *prc;
  WINDOWPOS *pwpos;
} HDLAYOUT, *LPHDLAYOUT;


prc
Type: RECT*

Structure that contains the coordinates of a rectangle that the header control will occupy.

pwpos
Type: WINDOWPOS*

Structure that receives information about the appropriate size and position of the header control.

На VB6 грамотных примеров на тему процессинга HDM_LAYOUT я не нашел.
М.б. найдется добрый человек кто б помог с этими *, Ptr, MoveMemore, Byval/ByRef, VarPtr и т.д. в данном случае.

Пример на другом языке напр.
Изменение высоты и расположения CHeaderCtrl и высоты строк CListCtrl с помощью сообщений HDM_LAYOUT
Но моя проблема думаю именно в переводе на VB6.
...
Рейтинг: 0 / 0
Headers in ListView: проблема с картинками: высота и перерисовка.
    #38248354
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77На VB6 грамотных примеров на тему процессинга HDM_LAYOUT я не нашел.Я ведь рассказывал, как искать примеры на vb6 , нет? Вторая ссылка.
Не знаю, насколько этот пример грамотен, но это как бы целый header-контрол, не имеющий, правда, отношения к common controls.
...
Рейтинг: 0 / 0
Headers in ListView: проблема с картинками: высота и перерисовка.
    #38248375
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Antonariy,

Да умею я искать, в т.числе так как ты показываешь.
И по этой ссылке вроде как уже был.
Счас буду более внимательно штудировать.

А сам с ходу можешь написать безошибочно структуры и MoveMemory (CopyMemory) для VB6.
Глядя чисто на C-шные определения в MSDN что я привел?
Я попытался, и считаю что в Layout.pwpos.cy я должен для начала "прочесть" высоту header навязывуемую системой.
Но чтоб я не делал, реального числа - предполагаю что-то порядка 19(px) 21(px) я оттуда прочесть не могу.

Т.е
A pointer to an HDLAYOUT structure

Предположение 1:
в lParam лежит Ptr на prc
в lParam+4 лежит Ptr на pwpos

Предположение 2:
начиная с адреса lParam
там подряд лежат prc и pwpos согласно размерностям
RECT и WINDOWPOS

Видимо я запутался в *prc; *pwpos, *LPHDLAYOUT

Если ты хорошо разбираешься в указателях, в указателях на указатели и т.п. то тебе быстрее будет мне написать как правильно (ну да, буду паразитом на этот раз), чем пытаться что-то объяснять.
...
Рейтинг: 0 / 0
Headers in ListView: проблема с картинками: высота и перерисовка.
    #38248405
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Antonariy,

Исходя из того что нарисовано в акселераторе по указанному вами примеру, правильный код должен быть

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
Private Type WINDOWPOS
    hwnd As Long
    hWndInsertAfter As Long
    x As Long
    y As Long
    cx As Long
    cy As Long
    Flags As Long
End Type

Private Type HD_LAYOUT
  prc As RECT
  pwpos As WINDOWPOS
End Type

Public Function NewListHeadWindowProc( _
 ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  Dim tHDL As HD_LAYOUT

  If Msg = HDM_LAYOUT Then
    Debug.Print "HDM_LAYOUT"
    MoveMemory tHDL, ByVal lParam, LenB(tHDL)
    Debug.Print tHDL.pwpos.cy
...чего-то там меняем наверно tHDL.pwpos.cy
    'обратка
    MoveMemory ByVal lParam, tHDL, LenB(tHDL)
...



Но
Debug.Print tHDL.pwpos.cy

распечатывает мне числа по типу
2262368
2401368

что никак не ассоциируется с высотой header порядка 20 пикселей,
а больше смахивает на адреса памяти

Т.е. либо в акселераторе как обычно бред сивой кобылы, либо я неправильно понял/прочитал/осознал то что имеется в виду.
...
Рейтинг: 0 / 0
Headers in ListView: проблема с картинками: высота и перерисовка.
    #38248455
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сдается мне что сабклассить и ковырять HDM_LAYOUT вообще не тот путь.
Идея описанных методов:
1) послать HDM_LAYOUT и получить существующую структуру HDLAYOUT
И в принципе она возвращается (то чего хочу = 17 пикселей на классике)
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Private Sub Command1_Click()
  'MsgBox hwndH
  Dim tHDL As HD_LAYOUT
  Dim rc As RECT
  Dim pwpos As WINDOWPOS

  tHDL.prc = VarPtr(rc)
  tHDL.pwpos = VarPtr(pwpos)

  SendMessage hwndH, HDM_LAYOUT, 0, tHDL
  MsgBox pwpos.cy
...



Ну, в смысле сидеть и караулить это сообщение в самом header не надо

2) А потом как то
To use HDM_LAYOUT to set the initial size and position of a header control, set the initial visibility state of the control so that it is hidden. After sending HDM_LAYOUT to retrieve the size and position values, use the SetWindowPos function to set the new size, position , and visibility state.
(так в msdn написано)

Но с этим походу задница, в которую уже тыкался 3 года назад.
8729101

Походу придется опять забить, а жаль.
Ну как-то делают же это на "других языках"....м.б. из-за глючности VB-шной реализации.
Но рисовать Listview целиком через API желания точно нет.
Или правда шрифтом подтасовывать, а текст как-то через hdc стандартным шрифтом накалякать?
Кстати как? Если сделаю SETFONT, то любой TextOut будет тем же шрифтом рисовать.
Хотя поиграться наверно можно...
...
Рейтинг: 0 / 0
Headers in ListView: проблема с картинками: высота и перерисовка.
    #38250797
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все-таки воспользовался "идеей 2-х шрифтов".
1) Запоминаем "родной шрифт"

Код: vbnet
1.
2.
3.
4.
5.
Public fnt_LV As IFont 'родной шрифт Listview, которым пишем в заголовках headers через CustomDraw

Private Sub Form_Load()
  Set fnt_LV = Form1.ListView1.Font
...


2) Для Headers в Listview устанавливаем свой (большой) шрифт, напр. так чтоб не мучиться:
Код: vbnet
1.
2.
3.
4.
  Dim fntHD As IFont
  Set fntHD = LabelHDFont.Font
  SendMessage hwndH, WM_SETFONT, fntHD.hFont, ByVal 0
  Set fntHD = Nothing

Например MS Sans Serif 12 автовыставит высоту header в 24 пикселя (вместо 17 на классике либо 19 с Segoe UI 9 на Висте)

3) Через CUSTOM DRAW, там же где я делаю прозрачность header-ов дополнительно меняем шрифт на зарезервированный родной.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
'для событий ListView1
Public Function NewListView1WindowProc _
  (ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
 ...
  Select Case Msg
   Case WM_NOTIFY:
     MoveMemory uNMHDR, ByVal lParam, Len(uNMHDR)
     Select Case uNMHDR.code
       Case NM_CUSTOMDRAW
         'Debug.Print "NM_CUSTOMDRAW"
         Static lvcd As NMCUSTOMDRAW
         MoveMemory lvcd, ByVal lParam, Len(lvcd)   ' every structs' member is a Long
         Select Case lvcd.dwDrawStage
           ' ====================================================
           Case CDDS_PREPAINT
             ' Tell the listview we want CDDS_ITEMPREPAINT for each item
             NewListView1WindowProc = CDRF_NOTIFYITEMDRAW
             Exit Function
             ' ====================================================
           Case CDDS_ITEMPREPAINT
             'Debug.Print lvcd.dwItemSpec
             DrawListViewHeader lvcd.hdc, lvcd.hdr.hwndFrom
             NewListView1WindowProc = CDRF_NEWFONT
             Exit Function
           Case Else
         End Select
       Case Else
     End Select


Public Sub DrawListViewHeader(the_hdc As Long, the_hwnd As Long)
  Dim rc As RECT
  Dim tPt As POINTAPI
  Dim hbmDstOld As Long
  
  SetBkMode the_hdc, TRANSPARENT
  SetTextColor the_hdc, vbWhite
  SetBkColor the_hdc, CLR_NONE
  
  hbmDstOld = SelectObject(the_hdc, hbshBackDigits)
  GetWindowRect the_hwnd, rc
  tPt.x = rc.Left
  tPt.y = rc.Top
  MapWindowPoints 0, Form1.PictureDigits.hwnd, tPt, 2
  rc.Left = tPt.x
  rc.Top = tPt.y
  SetBrushOrgEx the_hdc, -rc.Left, -rc.Top, tPt

  Dim rRB As RECT
  GetClientRect the_hwnd, rRB

  PatBlt the_hdc, 0, 0, (rRB.Right - rRB.Left), (rRB.Bottom - rRB.Top), PATCOPY
  'на XP CustomDraw текст не выравнивается по центру по вертикали, иконку тоже смещаем вверх
  'на >=Vista текст автовыравнивается по центру по вертикали, иконку тоже рисуем по центру
  If Form1.ListView1.ColumnHeaders(1).Tag = 1 Then
    DrawIconEx the_hdc, 6, IIf(IsWinVista, (rRB.Bottom - rRB.Top - 12) / 2, 3), lngIconAscending, 12, 12, 0, 0, DI_NORMAL
  Else
    DrawIconEx the_hdc, 6, IIf(IsWinVista, (rRB.Bottom - rRB.Top - 12) / 2, 3), lngIconDescending, 12, 12, 0, 0, DI_NORMAL
  End If

  SelectObject the_hdc, hbmDstOld
  
  SelectObject the_hdc, fnt_LV.hFont
  'SetTextAlign -не помогает на XP, а на >=Vista текст выравнивается автоматом
  'SetTextAlign the_hdc, TA_RTLREADING 'TA_LEFT 'Or TA_CENTER
  
End Sub


Ну собственно и все.
...
Рейтинг: 0 / 0
Headers in ListView: проблема с картинками: высота и перерисовка.
    #38250825
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну вот еще скриншот.
Единственная проблема:
на "вистах" происходит автовыравнивание CustomDraw шрифта по вертикали (проблема отсутствует),

на XP автовыравнивания не происходит (проблемка!!!), т.е. высота headers -увеличена, но текст смещен вверх (от верхнего края родного шрифта).
Как пофиксить не знаю, вариант с TextOut на hdc мне не нравится, т.к. текст тогда "не прыгает" вместе с нажатием кнопки.

Но в принципе, на Вистах это смотрится прилично (родная "тематическая" высота header - при отключенной теме!!! - иначе прощай прозрачность). Собственно, ориентируем давно уже все красивости на Висту...
А что касается XP, метод позволяет "чуть" увеличить высоту header на классике (обычные серые headers без прозрачности), чтобы не "лепились" рисунки 16х16 - т.е. по сути это решает вопрос над которым бился 3 года назад.

Ну, и еще в этом примере прозрачность headers только для случая одной застопоренной колонки.
Если столбцов несколько (обычный вариант), то надо усложнять код, т.е. высчитывать координаты каждого item по отдельности и рисовать кусками - и непонятно получится ли.

Но для приведенного случая прозрачность я сделал, больше пока не надо.
А с высотой и подтасовкой шрифтов справедливо для любого к-ва столбцов.
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Headers in ListView: проблема с картинками: высота и перерисовка.
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]