Гость
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Как правильно применить стиль к контролу (Parts and States) / 4 сообщений из 4, страница 1 из 1
18.06.2013, 15:48
    #38301838
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно применить стиль к контролу (Parts and States)
Вот здесь
C SysLink контролом кто сталкивался? Как сделать чтоб ссылка не всегда была подчеркнута?
я применил некий стиль к SysLink.

В целом получилось, но я понял что путь не совсем правильный.

Т.е. есть определенные стили
Aero Style Classes, Parts, and States
По сути мне надо:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
Public Const VSCLASS_FLYOUT = "FLYOUT"

Public Enum FLYOUTPARTS 'FLYOUTSTYLEPARTS
  FLYOUT_HEADER = 1
  FLYOUT_BODY = 2
  FLYOUT_LABEL = 3
  FLYOUT_LINK = 4
  FLYOUT_DIVIDER = 5
  FLYOUT_WINDOW = 6
  FLYOUT_LINKAREA = 7
  FLYOUT_LINKHEADER = 8
End Enum

Public Enum LINKSTATES
  FLYOUTLINK_NORMAL = 1
  FLYOUTLINK_HOVER = 2
End Enum



В MSDN описано как применить стиль к уже существующему контролу:
Using Visual Styles with Custom and Owner-Drawn Controls
И приведены некоторые коды,
я пытаюсь разрисовать свой hLinkTest:

Код: 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.
 hLinkTest = CreateTheSysLink(PictureDigits.hwnd, 50, 20, 200, 15, "<A>This is my test SysLink</A>", Me.Font)

  Dim hTheme As Long
  hTheme = OpenThemeData(PictureTheme.hwnd, StrPtr(VSCLASS_FLYOUT))

  'Draw Syslink
  Dim hdc As Long
  hdc = GetDC(hLinkTest)
  DrawMyControl hdc, hLinkTest, hTheme, FLYOUTLINK_NORMAL
  ReleaseDC hLinkTest, hdc
  
  If (hTheme <> 0) Then CloseThemeData hTheme

Private Function DrawMyControl(hdc As Long, hwndSysLink As Long, hTheme As Long, iState As Long)
  Dim rc As RECT, rcContent As RECT
  Dim szSysLinkText As String * 256
  Dim cch As Long 'длина текста без \0
  'Dim SysLinkText As String 'текст в нормальном виде
  Dim hr As Long
  
  GetWindowRect hwndSysLink, rc
  
  ' Get the window's title.
  cch = GetWindowText(hwndSysLink, szSysLinkText, Len(szSysLinkText))
  'SysLinkText = Left$(szSysLinkText, cch)
  If hTheme <> 0 Then
    hr = DrawThemeBackground(hTheme, hdc, FLYOUT_LINK, iState, rc, rc)
    If hr = S_OK Then
      hr = GetThemeBackgroundContentRect(hTheme, hdc, FLYOUT_LINK, iState, rc, rcContent)
        If hr = S_OK Then
          hr = DrawThemeText(hTheme, hdc, FLYOUT_LINK, iState, _
           StrPtr(szSysLinkText), cch, _
           DT_CENTER Or DT_VCENTER Or DT_SINGLELINE, _
           0, rcContent)
        End If
    End If
  Else
    '// Draw the control without using visual styles.
  End If

End Function



Сразу скажу что если тупо взять Picture1.hdc и на него рисовать DrawThemeBackground и DrawThemeText, то все работает.
Но это просто картинка, а у меня ГОТОВЫЙ КОНТРОЛ .

Я не догоняю в каком месте я должен применять этот код к моему hLinkTest.
Если я его исполняю при старте (как тупо пытаюсь понадеявшись на чудо), то я так мыслю он это все быстренько перерисует(что очевидно и происходит).

В MSDN говорится про WM_PAINT (в нижнем примере кода по указанной ссылке).

Код: plaintext
1.
2.
3.
4.
5.
6.
// textColor is a COLORREF whose value has been set according to whether the button is "hot".
// paint is the PAINTSTRUCT whose members are filled in by BeginPaint.
...
    DrawThemeTextEx(theme, paint.hdc, BP_PUSHBUTTON, CBS_UNCHECKEDNORMAL, 
        caption, cch, DT_CENTER | DT_VCENTER | DT_SINGLELINE, 
        &paint.rcPaint, &opts);



Я могу просабклассить hLinkTest и получать WM_PAINT (подозреваю что именно это и надо делать),
но я не могу понять что я в нем должен делать и что оно должно возвращать
Я могу конечно тупо взять hdc = GetDC(hLinkTest) внутри WM_PAINT,
но подозреваю что плевать ему будет на то что я там нарисую внутри WM_PAINT
.
но они откуда-то берут
paint.hdc paint.rcPaint ?
Откуда?
Ведь lparam и wparam в WM_PAINT пустые..
Направьте, где-то я близко, но не догоняю.
Метод так чувствую классный для стилизации чего хочешь.
...
Рейтинг: 0 / 0
18.06.2013, 17:10
    #38301996
Как правильно применить стиль к контролу (Parts and States)
Дмитрий77,

Код: vbnet
1.
// paint is the PAINTSTRUCT whose members are filled in by BeginPaint.
...
Рейтинг: 0 / 0
18.06.2013, 18:01
    #38302085
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно применить стиль к контролу (Parts and States)
13-й квартал,

Да вроде понял я это, вот так нарисовал чего хотел
Код: 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.
 Select Case Msg
    Case WM_PAINT
      Form1.TextDebug.Text = Form1.TextDebug.Text & vbCrLf & "WM_PAINT(MyLink)"
      Dim tPS As PAINTSTRUCT  ' PaintStruct used in painting
      Dim the_hdc As Long
      Dim hTheme As Long
      Dim szSysLinkText As String * 256
      Dim cch As Long 'длина текста без \0
      Dim SysLinkText As String 'текст в нормальном виде
      Dim hr As Long
      Dim rcContent As RECT
      
      Form1.TextDebug.Text = Form1.TextDebug.Text & vbCrLf & hwnd & "/" & Form1.hLinkTest
      
      hTheme = OpenThemeData(hwnd, StrPtr(VSCLASS_FLYOUT))
      If hTheme <> 0 Then
        the_hdc = BeginPaint(hwnd, tPS)
'        cch = GetWindowText(hwnd, szSysLinkText, Len(szSysLinkText))
'        SysLinkText = Left$(szSysLinkText, cch)
         SysLinkText = "Change date and time settings..."
'        hr = DrawThemeBackground(hTheme, tPS.hdc, FLYOUT_LINK, FLYOUTLINK_NORMAL, tPS.rcPaint, tPS.rcPaint)
'        If hr = S_OK Then
'          hr = GetThemeBackgroundContentRect(hTheme, tPS.hdc, FLYOUT_LINK, FLYOUTLINK_NORMAL, tPS.rcPaint, rcContent)
'          If hr = S_OK Then
            hr = DrawThemeText(hTheme, tPS.hdc, FLYOUT_LINK, FLYOUTLINK_NORMAL, _
             StrPtr(SysLinkText), -1, _
             DT_LEFT Or DT_VCENTER Or DT_SINGLELINE, _
             0, tPS.rcPaint)
'          End If
'        End If
        EndPaint hwnd, tPS
        CloseThemeData hTheme
      End If



Но, блин не совсем то это.
Я хочу ПРИМЕНИТЬ СТИЛЬ К КОНТРОЛУ, а не НАРИСОВАТЬ СТИЛЬ ВМЕСТО КОНТРОЛА (пусть бы и тот который надо).
Разницу чувствуете?

Т.е. данный код рисует мне текст ссылки. Да, как надо, неподчеркнутый. Могу сделать подчеркнутый, забабахав FLYOUTLINK_HOVER.
Но при этом.
1) Фон рисовать самому. Т.е. прозрачным например через WM_CTLCOLORSTATIC он его уже не делает
2) Точечки Focus Rectangle не рисуются.

Т.е. мне в данном случае надо изменить
только свойства шрифта существующей надписи ссылки
в SysLink на FLYOUTLINK_NORMAL (если мышка наведена) или на FLYOUTLINK_HOVER (если не наведена).

А я вместо этого рисую сам, пусть бы и в правильном стиле.

Т.е. нужно что-то типа SetWindowTheme (sysLink, веди себя как положено для FLYOUTLINK)
Нет идей?
...
Рейтинг: 0 / 0
19.06.2013, 06:14
    #38302517
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно применить стиль к контролу (Parts and States)
Короче задолбался я с этим разбираться.
Я конечно могу полностью рисовать SysLink через WM_PAINT,
чего там рисовать
мышка пришла - рисуем FLYOUT_LINK, FLYOUTLINK_HOVER
мышка ушла - рисуем FLYOUT_LINK, FLYOUTLINK_NORMAL

Только вот с фокусом беда будет - мало того что его надо рисовать ручками, т.к. еще и отслеживать, когда он должен быть, а когда нет.
Еще и фон рисовать в WM_PAINT.
А ну как "тематический шрифт" не совпадет с оригинальным. Тогда еще и курсор с изображением руки будет не по тому месту елозить.

Слишком много работы.

Более красивым решением было бы узнать свойства шрифта FLYOUTLINK_HOVER/FLYOUTLINK_NORMAL и подсунуть этот шрифт контролу. Есть там ф-ция, но задолбаешься ее структуру в IFont переводить.
А единственное место где можно подсунуть Font чтобы нерисованная SysLink его съела - это NM_CUSTOMDRAW и кушает она именно IFont через SelectObject.

Так что остановился на своем варианте . Понятно, что скармливается подчеркнутый или неподчеркнутый Segoe UI 9 а цвет там стандартный для Syslink.

Подсвечивание с LIS_HOTTRACK можно убрать, не стильно это.
Для того чтоб сгенерировать WM_PRINT и NM_CUSTOMDRAW достаточно при захвате отпускании мыши делать код
Код: vbnet
1.
     RedrawWindow hwnd, ByVal 0&, ByVal 0&, RDW_INVALIDATE Or RDW_FRAME Or RDW_UPDATENOW


Странно, что UpdateWindow это не делает.

Ну и коль скоро я делаю фоном для SysLink
Код: vbnet
1.
    DrawThemeBackground hTheme, hdcDst, FLYOUT_LINKAREA, 0, rc, rc


то надо запихнуть этот фон в IPictureDisp, присвоить это PictureBox на кот. надятся Syslink
и подрисовывать фон этих SysLink через WM_CTLCOLORSTATIC.
Иначе на Win8 фон SysLink не совпадет с FLYOUT_LINKAREA и это заметно. На 7-ках и Вистах прокатывает без этого - там обычный Button Face.

Было бы конечно проще если б было можно просто забацать

Код: vbnet
1.
  SetWindowTheme hSysLink, StrPtr("Flayout"), 0 '



Или все-таки есть такие волшебные сим-симы?

но к сожалению в таблице стилей :
http://ukintel.deviantart.com/art/Vista-Visual-Style-Classes-87482323
есть
Код: vbnet
1.
2.
00E: FlyoutStyle
0F8: Flyout


но нет
Flyout::Syslink
и т.п.

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


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