powered by simpleCommunicator - 2.0.55     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Сохранение цвета текста выделенных и hover-итемов в ListView (стиль Explorer)
7 сообщений из 7, страница 1 из 1
Сохранение цвета текста выделенных и hover-итемов в ListView (стиль Explorer)
    #38833309
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну т.е. строчки разноцветные, а не черные.

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    SetWindowTheme(ListView1.Handle, "explorer", vbNullString) 'стиль для Висты-8.1
    Dim LItem As ListViewItem
    For i As Integer = 0 To 9
      LItem = ListView1.Items.Add(New ListViewItem)
      LItem.Text = "Item" & i.ToString
      For j As Integer = 1 To 3
        LItem.SubItems.Add(New ListViewItem.ListViewSubItem) 'добавим пустые SubItems
        LItem.SubItems(j).Text = "Subitem" & i.ToString & "-" & j.ToString
      Next
    Next
    ListView1.Items(0).ForeColor = Color.Blue
    ListView1.Items(1).ForeColor = Color.Green
    ListView1.Items(2).ForeColor = Color.Red
    ListView1.Items(3).ForeColor = Color.Yellow
    ListView1.Items(4).ForeColor = Color.Magenta
    ListView1.Items(5).ForeColor = Color.Violet
    ListView1.Items(6).ForeColor = Color.Gray
    ListView1.Items(7).ForeColor = Color.Orange
    ListView1.Items(8).ForeColor = Color.RoyalBlue
    ListView1.Items(9).ForeColor = Color.Navy
  End Sub



Проблема: цвет Selected-итемов - черный, цвет итемов над которыми скользит мышь - черный.
"explorer" стиль не должен менять цвет.

Хорошо, вылечил классически:
Код: 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.
  Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    Select Case m.Msg
      Case WM_NOTIFY
        'Static lvcd As NMLVCUSTOMDRAW
        Dim lvcd As NMLVCUSTOMDRAW = CType(Marshal.PtrToStructure(m.LParam, GetType(NMLVCUSTOMDRAW)), NMLVCUSTOMDRAW)
        Select Case lvcd.nmcd.hdr.code
          Case NM_CUSTOMDRAW
            Select Case lvcd.nmcd.dwDrawStage
              Case CD_DrawStage.CDDS_PREPAINT
                m.Result = CD_ReturnFlags.CDRF_NOTIFYITEMDRAW
              Case CD_DrawStage.CDDS_ITEMPREPAINT
                Select Case lvcd.nmcd.hdr.hwndFrom 'в смысле какой контрол собрался перерисовываться
                  Case Me.ListView1.Handle
                    lvcd.clrText = ColorTranslator.ToWin32(Me.ListView1.Items(lvcd.nmcd.dwItemSpec).ForeColor)
                    Marshal.StructureToPtr(lvcd, m.LParam, False)
                    Exit Sub
                End Select 'lvcd.nmcd.hdr.hwndFrom
            End Select
        End Select
    End Select

    ' Forward message to base WndProc.
    MyBase.WndProc(m)
  End Sub



Структуры, константы под спойлером.
Код: 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.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
Imports System.Runtime.InteropServices

Module Module1

  Public Const WM_NOTIFY As Integer = &H4E&

  Public Const H_MAX = &HFFFF + 1
  Public Const NM_FIRST = H_MAX
  Public Const NM_CUSTOMDRAW = (NM_FIRST - 12)

  <StructLayout(LayoutKind.Sequential)>
  Public Structure RECT
    Dim Left As Integer
    Dim Top As Integer
    Dim Right As Integer
    Dim Bottom As Integer
  End Structure

  <StructLayout(LayoutKind.Sequential)>
  Public Structure NMHDR
    Dim hwndFrom As IntPtr   ' Window handle of control sending message
    Dim idFrom As IntPtr     ' Identifier of control sending message
    Dim code As UInt16      ' Specifies the notification code
  End Structure

  <StructLayout(LayoutKind.Sequential)>
  Public Structure NMCUSTOMDRAW
    Dim hdr As NMHDR
    Dim dwDrawStage As CD_DrawStage
    Dim hdc As IntPtr
    Dim rc As RECT
    Dim dwItemSpec As Integer
    Dim uItemState As CD_ItemState
    Dim lItemlParam As Integer
  End Structure

  <StructLayout(LayoutKind.Sequential)>
  Public Structure NMLVCUSTOMDRAW
    Dim nmcd As NMCUSTOMDRAW
    Dim clrText As Integer
    Dim clrTextBk As Integer
    Dim iSubItem As Integer
  End Structure

  Public Enum CD_ReturnFlags
    CDRF_DODEFAULT = &H0
    CDRF_NOTIFYPOSTPAINT = &H10
    CDRF_NOTIFYITEMDRAW = &H20
    CDRF_NOTIFYPOSTERASE = &H40
    CDRF_NOTIFYITEMERASE = &H80
    CDRF_NEWFONT = &H2
    CDRF_SKIPDEFAULT = &H4
    CDRF_NOTIFYSUBITEMDRAW = &H20
  End Enum   ' CD_ReturnFlags

  Public Enum CD_DrawStage
    CDDS_PREPAINT = &H1
    CDDS_POSTPAINT = &H2
    CDDS_PREERASE = &H3
    CDDS_POSTERASE = &H4
    CDDS_ITEM = &H10000
    CDDS_ITEMPREPAINT = (CDDS_ITEM Or CDDS_PREPAINT)
    CDDS_ITEMPOSTPAINT = (CDDS_ITEM Or CDDS_POSTPAINT)
    CDDS_ITEMPREERASE = (CDDS_ITEM Or CDDS_PREERASE)
    CDDS_ITEMPOSTERASE = (CDDS_ITEM Or CDDS_POSTERASE)
    CDDS_SUBITEM = &H20000
  End Enum   ' CD_DrawStage

  Public Enum CD_ItemState
    CDIS_SELECTED = &H1          ' The item is selected.
    CDIS_GRAYED = &H2            ' The item is grayed.
    CDIS_DISABLED = &H4          ' The item is disabled.
    CDIS_CHECKED = &H8           ' The item is checked.
    CDIS_FOCUS = &H10            ' The item is in focus.
    CDIS_DEFAULT = &H20          ' The item is in its default state.
    CDIS_HOT = &H40              ' The item is currently under the pointer ("hot").
    CDIS_MARKED = &H80           ' The item is marked. The meaning of this is up to the implementation.
    CDIS_INDETERMINATE = &H100   ' The item is in an indeterminate state.
  End Enum

  Public Declare Unicode Function SetWindowTheme Lib "uxtheme.dll" _
   (ByVal hWnd As IntPtr, ByVal pszSubAppName As String, ByVal pszSubIdList As String) As Integer

End Module



Дефолтный проект .Net 4.5 VS 2013EE.
Я пока еще не решил, но планирую большой проект делать все-таки .Net 2.0 (для совместимости с XP и т.п.)
Конвертанул тест-проект через свойства проекта.
И все - мой фикс сдох, т.е. фикс красит весь текст в черный если с сабклассингом. Ну, .Net-овский Items(0).ForeColor работает, но как указал мне это недостаточно.
Любая другая обратная конвертация хоть бы назад в .Net 4.5 уже не помогает.
Как такое может быть? Как лечить?
Прилагаю картинку с пояснениями.
...
Рейтинг: 0 / 0
Сохранение цвета текста выделенных и hover-итемов в ListView (стиль Explorer)
    #38833311
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прилагаю на всякий случай НЕ испорченный тест-проект.
Т.е. Net 4.5 VS2013EE VB.NET
Который делает вторую картинку.
До того как я его конвертирую в .Net 2.0
Надо чтоб при конвертации функциональность (цвет выделенных и hover итемов) сохранялась.
Запускать надо не ниже Висты со включенными стилями - иначе бессмысленно (я тестировал на 8.1).
...
Рейтинг: 0 / 0
Сохранение цвета текста выделенных и hover-итемов в ListView (стиль Explorer)
    #38833318
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Короче тестанул еще.
После конвертации в .Net2
WinXP- все корректно (там соглашаемся со стандартными цветами при выделении), итемы цветные
Vista, Win 8.1 -некорректно, т.е. сабклассинг делает все итемы черными
Win7 -что интересно, все корректно, т.е. как на второй картинке (итемы цветные и под выделенным тоже)

Что касается оригинального проекта .Net 4.5 -на Висте, 7-ке и 8.1 -везде все корректно
Но на XP то блин работать не будет.

А я люблю чтоб на всех OS один exe-шник хорошо работал. А .Net2 суко глючит на новых.
Можно конечно дублировать файлы: Net 2 -под XP 4.5-под все остальное, инсталлятор разберется, но сильно увеличится размер проекта и это бардак как бы.

Думаю опять .Net гадит со своими внутренними кривыми реализациями, что даже API не всегда применить нормально можно (думаю Items.ForeColor где-то дублирует мой "чистый код" типа кто кого).
Могу конечно Items.ForeColor не назначать а цвет писать в Tag итема (как раньше делал), но это здесь не помогает.

Впрочем КОНКРЕТНЫЙ ВОПРОС остался.
Надо чтоб после конвертации приложенного проекта в .Net2 результат на 8.1 был как на моей второй картинке (а не как на нижней).
Общие рассуждения не приветсвую, но если кто придумает/поможет конкретно с этим, буду благодарен.
...
Рейтинг: 0 / 0
Сохранение цвета текста выделенных и hover-итемов в ListView (стиль Explorer)
    #38834921
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все, критикуйте, разрешаю. Устал.
Было вы неплохо понять принцип конвертации C++ типов в .Net.
В VB6 обычно прокатывало As Long + вариации ByVal/ByRef с MoveMemory + укороченные структуры местами типа как в tagNMLVCUSTOMDRAW (с DiSetup это кстати никогда не прокатывает(Имеющийся буфер не подходит для указанной операции) и с Юникодом/не Юникодом бороться обычно тяжеловато).

Marshal.PtrToStructure, Marshal.StructureToPtr -более менее понятно.
DWORD -Integer, int - Integer
Указатели на строки - byval String и главное про A/W и про charset в структурах не забывать...
А вот как со всей многочисленностью
LONG,HWND,DWORD_PTR,COLORREF разбираться безошибочно...
Что-то б типа таблицы умножения где б было, или какой-нибудь "инструмент".

То что собака в этом это я уже догадался напоровшись дважды.
Все остальное что уже наконвертировал из VB6 видимо работает за счет того, что "простые типы", "случайно получилось", "случайно совпало", "случайно неправильные элементы структур не используется".

Аккуратность - 99% залог успеха если используешь API. Знаю.

Критиковать надо вот это:

Код: 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.
 <StructLayout(LayoutKind.Sequential)>
  Public Structure RECT
    Dim Left As Integer
    Dim Top As Integer
    Dim Right As Integer
    Dim Bottom As Integer
  End Structure

  <StructLayout(LayoutKind.Sequential)>
  Public Structure NMHDR
    Dim hwndFrom As IntPtr   ' Window handle of control sending message
    Dim idFrom As IntPtr     ' Identifier of control sending message
    Dim code As UInt16      ' Specifies the notification code
  End Structure

  <StructLayout(LayoutKind.Sequential)>
  Public Structure NMCUSTOMDRAW
    Dim hdr As NMHDR
    Dim dwDrawStage As CD_DrawStage
    Dim hdc As IntPtr
    Dim rc As RECT
    Dim dwItemSpec As Integer
    Dim uItemState As CD_ItemState
    Dim lItemlParam As Integer
  End Structure

  <StructLayout(LayoutKind.Sequential)>
  Public Structure NMLVCUSTOMDRAW
    Dim nmcd As NMCUSTOMDRAW
    Dim clrText As Integer
    Dim clrTextBk As Integer
    Dim iSubItem As Integer
  End Structure



Оригинальный C++ msdn

Код: 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.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
typedef struct _RECT {
  LONG left;
  LONG top;
  LONG right;
  LONG bottom;
} RECT, *PRECT;

typedef struct tagNMHDR {
  HWND     hwndFrom;
  UINT_PTR idFrom;
  UINT     code;
} NMHDR;

typedef struct tagNMCUSTOMDRAWINFO {
  NMHDR     hdr;
  DWORD     dwDrawStage;
  HDC       hdc;
  RECT      rc;
  DWORD_PTR dwItemSpec;
  UINT      uItemState;
  LPARAM    lItemlParam;
} NMCUSTOMDRAW, *LPNMCUSTOMDRAW;

typedef struct tagNMLVCUSTOMDRAW {
  NMCUSTOMDRAW nmcd;
  COLORREF     clrText;
  COLORREF     clrTextBk;
#if (_WIN32_IE >= 0x0400)
  int          iSubItem;
#endif 
#if (_WIN32_IE >= 0x0560)
  DWORD        dwItemType;
  COLORREF     clrFace;
  int          iIconEffect;
  int          iIconPhase;
  int          iPartId;
  int          iStateId;
  RECT         rcText;
  UINT         uAlign;
#endif 
} NMLVCUSTOMDRAW, *LPNMLVCUSTOMDRAW;
...
Рейтинг: 0 / 0
Сохранение цвета текста выделенных и hover-итемов в ListView (стиль Explorer)
    #38835145
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, пока выяснил что в плохом варианте (с .Net2) у меня в NMLVCUSTOMDRAW
clrText попадает в iSubItem ( 8 байт по дороге потерял)

а в clrText сидит походу dwItemSpec( 8 байт потерял до него значит)

при этом dwDrawStage на своем месте кажется

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
    Dim hdc As IntPtr
    Dim rc As RECT
??? что тут не так? 
LONG это походу тот же Integer, не?

  <StructLayout(LayoutKind.Sequential)>
  Public Structure RECT
    Dim Left As Integer
    Dim Top As Integer
    Dim Right As Integer
    Dim Bottom As Integer
  End Structure
...
Рейтинг: 0 / 0
Сохранение цвета текста выделенных и hover-итемов в ListView (стиль Explorer)
    #38835195
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот так вроде почти правильно (по крайней мере заработало)

Код: 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.
  <StructLayout(LayoutKind.Sequential)>
  Public Structure RECT
    Dim Left As Integer
    Dim Top As Integer
    Dim Right As Integer
    Dim Bottom As Integer
  End Structure

  <StructLayout(LayoutKind.Sequential)>
  Public Structure NMHDR
    Dim hwndFrom As IntPtr   ' Window handle of control sending message
    Dim idFrom As UIntPtr 'IntPtr    ' Identifier of control sending message
    Dim code As UInt16      ' Specifies the notification code
  End Structure

  <StructLayout(LayoutKind.Sequential)>
  Public Structure NMCUSTOMDRAW
    Dim hdr As NMHDR
    Dim dwDrawStage As CD_DrawStage
    Dim hdc As IntPtr
    Dim rc As RECT
    Dim dwItemSpec As IntPtr
    Dim uItemState As CD_ItemState
    Dim lItemlParam As IntPtr
  End Structure

  <StructLayout(LayoutKind.Sequential)>
  Public Structure NMLVCUSTOMDRAW
    Dim nmcd As NMCUSTOMDRAW
    Dim clrText As Integer
    Dim clrTextBk As Integer
    Dim iSubItem As Integer
  End Structure



Но с т.зр. полной корректности смущает:
1) Надо делать для обращения к итему:
Код: vbnet
1.
lvcd.clrText = ColorTranslator.ToWin32(Me.ListView1.Items(CType(lvcd.nmcd.dwItemSpec, Integer)).ForeColor)


2) Dim code As UInt16 в NMHDR, а иначе не работает - похоже на "подтасовку"


Вот эти двое:

UINT code
UINT
An unsigned INT. The range is 0 through 4294967295 decimal.

This type is declared in WinDef.h as follows:

typedef unsigned int UINT;
--
UINT_PTR idFrom;
Код: plaintext
1.
2.
3.
4.
5.
#if defined(_WIN64)
 typedef unsigned __int64 UINT_PTR;
#else
 typedef unsigned int UINT_PTR;
#endif



Есть идеи?
...
Рейтинг: 0 / 0
Сохранение цвета текста выделенных и hover-итемов в ListView (стиль Explorer)
    #38835381
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не ну фигня какая-то.

Код: plaintext
1.
2.
3.
4.
5.
typedef struct tagNMHDR {
  HWND     hwndFrom;
  UINT_PTR idFrom;
  UINT     code;
} NMHDR;


Код: vbnet
1.
2.
3.
4.
5.
6.
  <StructLayout(LayoutKind.Sequential)>
  Public Structure NMHDR
    Dim hwndFrom As IntPtr   ' Window handle of control sending message
    Dim idFrom As UIntPtr 'IntPtr    ' Identifier of control sending message
    Dim code As UInt16      ' Specifies the notification code
  End Structure


UInt16 -это 2 -байта при любых раскладках (соотв. as Integer в VB6), а по другому он не хочет.
Т.е. в .Net это работает с жестким интервалом 2 байта между idFrom и code

Но в VB6 это работало с as Long как часы (дельта= 4 байта).

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
' The NMHDR structure contains information about a notification message. The pointer
' to this structure is specified as the lParam member of the WM_NOTIFY message.
Public Type NMHDR
  hwndFrom As Long   ' Window handle of control sending message
  idFrom As Long     ' Identifier of control sending message
  code  As Long      ' Specifies the notification code
End Type



Если работает- не трогай, то я это осилил, но непонятка сия таки бесит.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Сохранение цвета текста выделенных и hover-итемов в ListView (стиль Explorer)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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