powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
27 сообщений из 27, показаны все 2 страниц
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36525132
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как то рассматривал я "умный" вопрос про то как не рисовать точки вокруг слайдера при получении им фокуса(ибо похабство)
/topic/736404&hl=
Код я тогда как бы себе тогда придумал: детский, громоздский, идиотский и т.п.
Нарисовал, так сказать, "пользовательский контрол" (очень показательный кстати пример убийства времени + нуль новых знаний )

Все проще...
Внедряя xp/Vista стили методом манифеста понял что это решается автоматически, т.е. даже при XP-классический стиль кнопки уже не выглядят в точечках: но одно но.

Как правильно заметил Antonariy,
Код: plaintext
Какая-то фигня получается... Если я люблю пользоваться клавиатурой, как я узнаю, что фокус на слайдере? Не солидно.

С манифестом получается так: если я запустил окно мышкой, то все выглядит "прилично".
Если клавиатурой, то "с точками-указателями на фокус".
Все вроде корректно.

Но я наблюдал как делает "нормальное" приложение.
Если вывели окно мышкой, то фокусы не показываются (что красиво ,да и незачем). Но при первом нажатии какого-нибудь "TAB" они сразу появляются и это разумно.

В моем же случае если "точки" изначально не вызвали (запуск с мышки), то они уже не появятся, хоть обожмись клавиатурой. И если на XP по теням рядом с кнопками еще можно понять где находимся(для многих элементов) , то на Висте это понять (где фокус) уже малореально.

Есть идеи, как этот "интерфейс" правильно реализовать?
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36525167
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
http://forum.vingrad.ru/forum/topic-278854.html

Вот еще такое же описание проблемы, но к сожалению не руководство к действию.
Вид/глючность винды, язык программирования, x86/x64 точно ни при чем.
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36525807
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да не мистика какая-то, элементарное приложение
из одной формы + 2 кнопки + чекбокс

+манифест + запускаем мышкой +

не появляется focus rectangle (а он должен появляться при первом нажатии TAB)

и вопросов таких в google много, а ответа не вижу

должна же быть какая-то маленькая хитрость (какая-нибудь API напр. которая активирует отображение этого focus rectangle), ведь если запустить приложение ENTER то все работает...

ну запихну эту API в form_load в конце концов...
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36526523
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не тривиально, но не безнадежно.
http://www.vbmonster.com/Uwe/Forum.aspx/vb/30910/XP-Vista-Visual-Styles-Focus-Rectangle

Решение(рабочее):

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Public Declare Function SendMessage Lib "user32" _
       Alias "SendMessageA" ( _
       ByVal hWnd As Long, _
       ByVal wMsg As Long, _
       ByVal wParam As Long, _
       lParam As Any) As Long

'* These are used in every form to ensure focus rectangle visibility
Public Const WM_CHANGEUISTATE As Long = &H127
Public Const UIS_CLEAR As Integer = &H2
Public Const UISF_HIDEFOCUS As Integer = &H1

Private Sub Form_Load()
   Call SendMessage(Me.hWnd, WM_CHANGEUISTATE, _
       MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), ByVal  0 )
End Sub

Но один вопрос остался.
Как узнать что User принялся за клавиатуру и начал щелкать ТАБами/стрелками? Потому как любителю мышек этот focus rectangle visibility наф... не нужен (и негативно сказывается на зрении и настроении юзера, испытывал на себе),
должно быть так

Код: plaintext
1.
2.
3.
Private_Юзер_TAB_или_чего_там_положено_Первый_Раз_Нажал()
   Call SendMessage(Me.hWnd, WM_CHANGEUISTATE, _
       MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), ByVal  0 )
End Sub

Боюсь KeyPress/Down в общем случае не помогут.
И попытки их прописывать для всех Controls идиотизм и трата времени.
Сабклассить форму?
Если сабклассить то на что реагировать?
Понимаю что опять морока(если сабклассить), но по крайне мере для "ключевых" форм такую роскошь можно позволить.
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36526574
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
глобальный хук на клавиатуру спасёт
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36526784
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Konst_Oneглобальный хук на клавиатуру спасёт
Это как? Намека на элементы кода не дадите?
Совсем "глобально" как бы тоже не надо. Надо в рамках отображаемой формы (окна).

1)Загрузилась без фокусов (если не оговорено иное, т.е. запуск с клавы)
2) Щелкнули (в рамках формы, а не "вообще") характерными клавишами, сработал приведенный код, появились фокусы.
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36526804
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
если только в рамках открытого активного окна, то у него есть свойтво в дизайнере форм:

Код: plaintext
KeyPreview=True

ну а дальше:

Код: plaintext
1.
2.
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
...
End Sub

PS
примеры глобального хука на клавиатуру можно поискать в инете, сам таким не занимался, т.к. считаю, что это неправильный подход
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36526876
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Konst_One,
KeyPreview=True не знал, полезная штука спасибо.

Но проблема в том что
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)

перехватывается системой и не срабатывает, и именно тогда, когда TAB или "стрелочки" переводят фокус к другому элементу, т.е. молчит именно в те моменты когда нам надо чтоб оно "сказало" об этом.

Вот нарисуйте > 1 элемента на чистой форме (чтоб было куда прыгать) и сделайте как предложили:

Код: plaintext
1.
2.
3.
 'KeyPreview=True для формы
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
  msgbox KeyCode
End Sub

Msgbox=9 вы не получите, а оставьте одну кнопку и получите.
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36526902
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
если фокус внутри какого-либо контрола на форме, то естественно нужно обрабатывать уже события этого контрола, поэтому для TAB особый случай, тк у микрософта - это переход фокуса на следующий контрол.
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36526914
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
погуглите на предмет использования этих ф-й:


Код: plaintext
1.
2.
3.
4.
5.
Declare Function GetKeyboardState Lib _ 
        "user32" (pbKeyState As Byte) _ 
        As Long 
Declare Function SetKeyboardState Lib _ 
        "user32" (lppbKeyState As Byte) _ 
        As Long 
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36526933
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По барабану, можете каждую кнопку мучить
Код: plaintext
1.
2.
Private Sub Command1_KeyDown(KeyCode As Integer, Shift As Integer)
    MsgBox KeyCode
End Sub
про tab оно все одно ничего не скажет.

>поэтому для TAB особый случай, тк у микрософта - это переход фокуса на следующий контрол.

о том и речь. И именно это и надо отследить
1) особый случай имел место быть
2) особый случай был инициирован с клавиатуры

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Dim KeyInit  as boolean
KeyInit=false
Private_Особый_Случай(клавиатура as boolean) //перевод фокуса
   If not(KeyInit) then
     If клавиатура then
        Call SendMessage(Me.hWnd, WM_CHANGEUISTATE, _
          MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), ByVal  0 )
        KeyInit=true
     EndIf
  EndIf
End Sub
P.S. Пока писал уже увидел ваше новое сообщение, не пойму правда как эти ф-ции мне помогут, ибо нам нужна информации о событии в окне а не долбеж состояния клавиатуры... но посмотрю конечно.
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36526976
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Konst_Oneпогуглите на предмет использования этих ф-й:
Код: plaintext
1.
2.
3.
4.
5.
Declare Function GetKeyboardState Lib _ 
        "user32" (pbKeyState As Byte) _ 
        As Long 
Declare Function SetKeyboardState Lib _ 
        "user32" (lppbKeyState As Byte) _ 
        As Long 

Такое ощущение что это не оно, тогда уж GetKeyState(TAB)+КакоеОкноВФокусе(), но это уж слишком, примерно то же самое что слайдер в рамку упаковывать чтоб точек не видеть.

Должно быть какое-нибудь более красивое и правильное решение...
Сдается мне, что какая-нибудь простенькая обработка в WinProc формы может отследить желаемое событие.
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36527189
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну в принципе рабочий вариант я нашел.
Только код надо прописывать в событие каждого TAB-значащего контрола на форме.
Считаю сигналом к действию потерю фокуса любым TABstop-элементом вследствии нажимания
TAB; стрелка вверх; стрелка вниз; стрелка вправо; стрелка влево -ничего не упустил?

В тестовом варианте код приведен ниже.
Но у меня на одной форме напр. не 5 контролов а 256++ за счет массивов, из них наверняка сотня для которых код надо писать.
Крыша не съедет?
У меня допустим нет. А у VB?
Если этот код нормальный? (безобидный и не вызовет Crash) Это вопрос #1
то
Можно ли его объединить хотя бы для всех элементов? Это вопрос #2.
Пока воздержусь от "внедрение" в Application.
Мнение экспертов?

Код: 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.
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.
Public Declare Function GetKeyState Lib "user32.dll" (ByVal nVirtKey As Long) As Integer
'---------------------------------------------------------------
Dim bViewFocus As Boolean

Private Sub Form_Load()
    bViewFocus = True
End Sub

Private Sub Option1_LostFocus()
    If bViewFocus Then
        If (GetKeyState(vbKeyTab) <  0 ) Or (GetKeyState(vbKeyLeft) <  0 ) Or _
          (GetKeyState(vbKeyUp) <  0 ) Or (GetKeyState(vbKeyRight) <  0 ) Or (GetKeyState(vbKeyDown) <  0 ) Then
            Call SendMessage(Me.hWnd, WM_CHANGEUISTATE, _
              MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), ByVal  0 )
            bViewFocus = False
        End If
    End If
End Sub
Private Sub Option2_LostFocus()
    If bViewFocus Then
        If (GetKeyState(vbKeyTab) <  0 ) Or (GetKeyState(vbKeyLeft) <  0 ) Or _
          (GetKeyState(vbKeyUp) <  0 ) Or (GetKeyState(vbKeyRight) <  0 ) Or (GetKeyState(vbKeyDown) <  0 ) Then
            Call SendMessage(Me.hWnd, WM_CHANGEUISTATE, _
              MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), ByVal  0 )
            bViewFocus = False
        End If
    End If
End Sub
Private Sub Option3_LostFocus()
    If bViewFocus Then
        If (GetKeyState(vbKeyTab) <  0 ) Or (GetKeyState(vbKeyLeft) <  0 ) Or _
          (GetKeyState(vbKeyUp) <  0 ) Or (GetKeyState(vbKeyRight) <  0 ) Or (GetKeyState(vbKeyDown) <  0 ) Then
            Call SendMessage(Me.hWnd, WM_CHANGEUISTATE, _
              MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), ByVal  0 )
            bViewFocus = False
        End If
    End If
End Sub
Private Sub Command1_LostFocus()
    If bViewFocus Then
        If (GetKeyState(vbKeyTab) <  0 ) Or (GetKeyState(vbKeyLeft) <  0 ) Or _
          (GetKeyState(vbKeyUp) <  0 ) Or (GetKeyState(vbKeyRight) <  0 ) Or (GetKeyState(vbKeyDown) <  0 ) Then
            Call SendMessage(Me.hWnd, WM_CHANGEUISTATE, _
              MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), ByVal  0 )
            bViewFocus = False
        End If
    End If
End Sub
Private Sub Command2_LostFocus()
    If bViewFocus Then
        If (GetKeyState(vbKeyTab) <  0 ) Or (GetKeyState(vbKeyLeft) <  0 ) Or _
          (GetKeyState(vbKeyUp) <  0 ) Or (GetKeyState(vbKeyRight) <  0 ) Or (GetKeyState(vbKeyDown) <  0 ) Then
            Call SendMessage(Me.hWnd, WM_CHANGEUISTATE, _
              MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), ByVal  0 )
            bViewFocus = False
        End If
    End If
End Sub
Private Sub Check1_LostFocus()
    If bViewFocus Then
        If (GetKeyState(vbKeyTab) <  0 ) Or (GetKeyState(vbKeyLeft) <  0 ) Or _
          (GetKeyState(vbKeyUp) <  0 ) Or (GetKeyState(vbKeyRight) <  0 ) Or (GetKeyState(vbKeyDown) <  0 ) Then
            Call SendMessage(Me.hWnd, WM_CHANGEUISTATE, _
              MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), ByVal  0 )
            bViewFocus = False
        End If
    End If
End Sub
Private Sub Combo1_LostFocus()
    If bViewFocus Then
        If (GetKeyState(vbKeyTab) <  0 ) Or (GetKeyState(vbKeyLeft) <  0 ) Or _
          (GetKeyState(vbKeyUp) <  0 ) Or (GetKeyState(vbKeyRight) <  0 ) Or (GetKeyState(vbKeyDown) <  0 ) Then
            Call SendMessage(Me.hWnd, WM_CHANGEUISTATE, _
              MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), ByVal  0 )
            bViewFocus = False
        End If
    End If
End Sub
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36527262
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Собственно, вот "короткий" код:

Код: 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.
'Form1
Private Sub Form_Load()
    StartForm1KeyHook 'а вдруг user любит клавиатуру?
End Sub

Private Sub Form_Unload(Cancel As Integer)
    StopForm1KeyHook 'если user не любит клавиатуру
End Sub
'Module
'========================================
Private Const WH_KEYBOARD =  2 

Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" _
  (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _
  ByVal ncode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Private mlngForm1HookId As Long

Public Sub StartForm1KeyHook()
    mlngForm1HookId = SetWindowsHookEx(WH_KEYBOARD, AddressOf KeyProcForm1, App.hInstance, App.ThreadID)
End Sub

Public Sub StopForm1KeyHook()
    UnhookWindowsHookEx mlngForm1HookId
End Sub

Private Function KeyProcForm1(ByVal ncode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Form1.Caption = wParam  'Chr$(wParam)
    If (wParam = vbKeyTab) Or (wParam = vbKeyLeft) Or (wParam = vbKeyRight) Or (wParam = vbKeyUp) _
      Or (wParam = vbKeyDown) Then
        Call SendMessage(Form1.hWnd, WM_CHANGEUISTATE, _
          MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), ByVal  0 )
        StopForm1KeyHook 'если user любит клавиатуру
        Exit Function
    End If
    KeyProcForm1 = CallNextHookEx(mlngForm1HookId, ncode, wParam, lParam)
End Function

Есть недостатки по сравнению с предыдущим вариантом. В предыдущем варианте
1) программа реагирует только на смену фокуса между элементами
2) и интересуется не клавиатурой ли это вызвано

В этом варианте:
1) программа реагирует на любой ввод с клавиатуры
2) и проверяет не критические(на основании только нашей "базы знаний") ли клавиши там жали
и иногда делает преждевременный вывод (в текстовом поле user может использовать стрелки для редактирования текста).
Хотя анализ "правильной" (но не микрософтовской) проги показал, что она идет по второму пути (неправильному и короткому), Outlook Express же все делает правильно, т.е. как в моем длинном первом варианте.

Т.е. если существует способ записать ( КАК???)
код в виде:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Private Sub Любой_Элемент_of_Form1_LostFocus()
    If bViewFocus Then
        If (GetKeyState(vbKeyTab) <  0 ) Or (GetKeyState(vbKeyLeft) <  0 ) Or _
          (GetKeyState(vbKeyUp) <  0 ) Or (GetKeyState(vbKeyRight) <  0 ) Or (GetKeyState(vbKeyDown) <  0 ) Then
            Call SendMessage(Me.hWnd, WM_CHANGEUISTATE, _
              MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), ByVal  0 )
            bViewFocus = False
        End If
    End If
End Sub
то первый вариант корректнее. Но блин переписывать одно и то же 200 раз кажется будет извращенством и дурным тоном.
...а с другой стороны, опять блин, крутить непрерывно хук, кот. может быть никогда и не выстрелит (хорошо если не в crash варианте), тоже не дело...

Konst_One, спасибо, по сути эти два кода суть реализации ваших двух идей-намеков (оба рабочие).
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36527764
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
да , работу провёл основательную

как я уже писал, я не олюблю глобальные перехваты клавиш, поэтому всё-таки склоняюсь к первому твоему варианту, хоть он и трудоёмкий, но более стабильный.

ещё есть мысль попробовать обращаться к событиям контролов через VBControlExtenter c WithEvents . т.е. попробовать загнать при инициалицации формы все твои контролы в свою коллекцию и присвоить объектной переменной с обработкой событий.

как-то так:

Код: plaintext
Private WithEvents ctl as VBControlExtender

и обрабатывать нужные события этого контрола.
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36528190
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Konst_One,

ну да, начал сейчас внедрять второй метод в Application.
дополняя ваши мысли (да и мои) про стабильность..
Во-первых указанная неточность обработки стрелок.
Во-вторых требует рихтовки в процессе внедрения.
Хук конечно не так чтоб совсем глобальный (если щелкаете табами в окне чужого приложения, то это не перехватывается, тьфу-тьфу).

Но допустим есть главное окно Form1
И окно поднастроек Form2, вызываемое по принципу
Form2.Show 1

Логично предположить что по Form1 юзер ходит мышкой, а в Form2 использует TAB для перехода между текстовыми полями, ибо ввод с клавиатуры все одно требуется.

Если писать код для Form2 в виде:
Код: plaintext
1.
2.
3.
4.
5.
6.
Private Sub Form_Load() 'Form2
    StartForm2KeyHook 'а вдруг user любит клавиатуру?
End Sub

Private Sub Form_Unload(Cancel As Integer) 'Form2
    StopForm2KeyHook 'если user не любит клавиатуру
End Sub
то в главную Form1 мы вернемся уже с фокусами, т.к. при запуске Form2 хук для Form1 продолжает отслеживать также клавиатуру для Form2

чтоб этого не произошло, надо извращаться

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
Private Sub Form_Load() 'Form2
    StopForm1KeyHook 'чтоб не перехватывалось главным окном
    StartForm2KeyHook 'а вдруг user любит клавиатуру?
End Sub

Private Sub Form_Unload(Cancel As Integer) 'Form2
    StopForm2KeyHook 'если user не любит клавиатуру
    StartForm1KeyHook 'возврат к главному окну
End Sub

Писать 200 блоков кода (и помнить всегда об этом) конечно желания нет.
Хотя если реализуемо то о чем написали, все равно придется писать 200 строк (хоть и не блоков) добавления элементов в коллекцию и (опять же) помнить об этом.

А нельзя сделать как-то так

Код: plaintext
1.
2.
For all element in the form.elements
    element.add to collection
next
Прекрасно понимаю что _lostfocus для label не применим, но оно же никогда и не выполнится, т.е. ошибки не будет

Или тогда уж

Код: plaintext
1.
2.
3.
4.
For all element in the form.elements
    If (есть событие _lostfocus) то
         element.add to collection
    End If
next
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36528219
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
у формы есть коллекция Conntrols:


Код: plaintext
1.
2.
3.
4.
5.
6.
Dim ctl as Control
Dim MyCols as MyNewCollection 'class собственной коллекции


For each ctl in Me.Controls
   MyCols.Add ctl
Next 
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36528395
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну это мы в тупик приехали ( в силу моей увы безграмотности в нек. ключевых вопросах, не люблю и не понимаю слово класс).

1)Во первых тогда мне надо

Код: plaintext
1.
2.
3.
4.
For each ctl in Me.Controls
   If ctl.HaveEvent (lostfocus) then
      MyCols.Add ctl
   end if
Next
ctl после точки ничего не показывает, хотя напр.
MsgBox ctl.Name имена выводит

Что есть HaveEvent (event) и есть ли такое в природе?

2) Во вторых
Dim MyCols as MyNewCollection 'class собственной коллекции
наверно надо писать какой-то модуль класса MyNewCollection,
туда еще чего-то писать, понятия не имею чего
Интуиция подсказывает, что Event=LostFocus согл. потребностям, но понятия не имею как

3) Чего присваивать этой самой VBControlExtender

Попытка сделать "на дурака"
Set Myctl = Me.Controls
провалилась, как и предполагал собственно.

допускаю что
Set Myctl =MyCols
но у меня темный лес в пункте 2.

4)Private WithEvents Myctl As VBControlExtender
Вижу после точки
Myctl.SetFocus
...это хоть немного обнадеживает
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36528429
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ничего страшного в классах и коллекциях нет. по крайней мере это намного проще изысков управления событиями чужих окон через API

ЗЫ
попробуйте Add-In Class Builder и примерчики посмотрите
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36528610
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не ну ё

Ну использую я два класса, посмотрел на них (как на примерчики)

Нарисовал вот эту ересь в качестве MyNewCollection (Class Module)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
Option Explicit
'Для представления элементов в виде коллекции
Dim cElement As New Collection

Public Event LostFocus()

Sub Add(ctl As Control)
    cElement.Add ctl
End Sub
Пытаюсь выполнить код:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Option Explicit
Private WithEvents Myctl As VBControlExtender
Dim MyCols As MyNewCollection 'class собственной коллекции'

Private Sub Form_Load()
  Dim ctl As Control
  For Each ctl In Me.Controls
     MyCols.Add ctl 'Ругается, скотина
  Next
  Set Myctl = MyCols
End Sub

Ругается, скотина, на
MyCols.Add ctl

че-то там Not Set, панимаешь ли.
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36528622
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dim MyCols As New MyNewCollection

и это только начало пути
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36528700
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А, во как, ну тогда
Set Myctl = MyCols =>Type Mismatch
Може ну его... энтот путь
Может, согласно классикам лучше "Мы пойдем другим путем..." ?

Konst_One, ну если знаете, не томите.. не думаю что там больше нескольких строчек кода...
фраза "начало пути" меня правда пугает
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36529464
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да нет, в баню наверно, пусть будет второй метод.
Старался, накатал этот класс, как сумел:

Вот отсюда чуть содрал:
http://vbcity.com/forums/t/31429.aspx

Код: 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.
42.
43.
44.
45.
46.
47.
48.
49.
'ClassFocus
Option Explicit

Public Parent As Form
Public WithEvents CheckBox As CheckBox
Public WithEvents ComboBox As ComboBox
Public WithEvents CommandButton As CommandButton
Public WithEvents ListView As ListView
Public WithEvents OptionButton As OptionButton
Public WithEvents TextBox As TextBox
Public WithEvents TreeView As TreeView

Private Sub CheckBox_LostFocus()
    Parent.FocusRectangles
End Sub

Private Sub ComboBox_LostFocus()
    Parent.FocusRectangles
End Sub

Private Sub CommandButton_LostFocus()
    Parent.FocusRectangles
End Sub

Private Sub ListView_LostFocus()
    Parent.FocusRectangles
End Sub

Private Sub OptionButton_LostFocus()
    Parent.FocusRectangles
End Sub

Private Sub TextBox_LostFocus()
    Parent.FocusRectangles
End Sub

Private Sub TreeView_LostFocus()
    Parent.FocusRectangles
End Sub

Public Sub Class_Terminate()
    Set Parent = Nothing
    Set CheckBox = Nothing
    Set ComboBox = Nothing
    Set CommandButton = Nothing
    Set ListView = Nothing
    Set OptionButton = Nothing
    Set TextBox = Nothing
    Set TreeView = Nothing
End Sub

Делаем так:
Код: 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.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
Option Explicit

Private TBEvents() As ClassFocus

Private Sub Form_Load()
    Dim Ctr As Control, Count As Long
    For Each Ctr In Me.Controls
        If (TypeOf Ctr Is CheckBox) Or (TypeOf Ctr Is ComboBox) Or (TypeOf Ctr Is CommandButton) Or _
          (TypeOf Ctr Is ListView) Or (TypeOf Ctr Is OptionButton) Or (TypeOf Ctr Is TextBox) Or _
          (TypeOf Ctr Is TreeView) Then
            ReDim Preserve TBEvents(Count)
            Set TBEvents(Count) = New ClassFocus
            Set TBEvents(Count).Parent = Me
            If (TypeOf Ctr Is CheckBox) Then
                Set TBEvents(Count).CheckBox = Ctr
            ElseIf (TypeOf Ctr Is ComboBox) Then
                Set TBEvents(Count).ComboBox = Ctr
            ElseIf (TypeOf Ctr Is CommandButton) Then
                Set TBEvents(Count).CommandButton = Ctr
            ElseIf (TypeOf Ctr Is ListView) Then
                Set TBEvents(Count).ListView = Ctr
            ElseIf (TypeOf Ctr Is OptionButton) Then
                Set TBEvents(Count).OptionButton = Ctr
            ElseIf (TypeOf Ctr Is TextBox) Then
                Set TBEvents(Count).TextBox = Ctr
            ElseIf (TypeOf Ctr Is TreeView) Then
                Set TBEvents(Count).TreeView = Ctr
            End If
            Count = Count +  1 
        End If
    Next
    Set Ctr = Nothing
    Form2.Visible = True
End Sub

Sub FocusRectangles()
    Dim i As Integer
    'если user любит клавиатуру
    If (GetKeyState(vbKeyTab) <  0 ) Or (GetKeyState(vbKeyLeft) <  0 ) Or _
      (GetKeyState(vbKeyUp) <  0 ) Or (GetKeyState(vbKeyRight) <  0 ) Or (GetKeyState(vbKeyDown) <  0 ) Then
        MsgBox "ok"
        Call SendMessage(Me.hWnd, WM_CHANGEUISTATE, _
          MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), ByVal  0 )
    End If
    For i =  0  To Count -  1 
        TBEvents(i).Class_Terminate
    Next i
End Sub

Private Sub Form_Unload(Cancel As Integer)
    'если user не любит клавиатуру
    Dim i As Integer
    For i =  0  To Count -  1 
        TBEvents(i).Class_Terminate
    Next i
End Sub

Супер, блин:
Sub FocusRectangles() - срабатывает на потерю фокусов всеми перечисленными типами элементов (не так уж много типов).

А конструкция
If (GetKeyState(vbKeyTab) < 0) Or (GetKeyState(vbKeyLeft) < 0) Or _
(GetKeyState(vbKeyUp) < 0) Or (GetKeyState(vbKeyRight) < 0) Or (GetKeyState(vbKeyDown) < 0)

не срабатывает : кто-то чего-то перехватил, кто-то чего-то не успел:
все, весь труд коту под хвост, ибо та фишка ради которой все делалось не работает.

Зол как собака. Проделать такой путь, чтобы опять прийти к той же свинье, которая жрет ТАБы и стрелки, т.е. именно необходимый "особый случай".


Думаю пусть будет второй метод. Лучшее враг хорошего.
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36529565
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все, разобрался.
Код: plaintext
1.
2.
        For i =  0  To Count -  1 
            TBEvents(i).Class_Terminate
        Next i
Тороплюсь прибивать классы, плюю в колодец раньше чем достану из него стакан воды.
А ведь сам упрекал 2 года назад одного оч. уважаемого C++ разработчика с мировым именем год назад в том что убивает объект раньше чем объект возвращает результат, причем человека год пришлось убеждать в том что прав я а не он.

Так работает:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
Dim bViewFocus As Boolean

Private Sub Form_Load()
...
    bViewFocus = True


...
Sub FocusRectangles()
    'если user любит клавиатуру
    If bViewFocus Then
        If (GetKeyState(vbKeyTab) <  0 ) Or (GetKeyState(vbKeyLeft) <  0 ) Or _
          (GetKeyState(vbKeyUp) <  0 ) Or (GetKeyState(vbKeyRight) <  0 ) Or (GetKeyState(vbKeyDown) <  0 ) Then
            Call SendMessage(Me.hWnd, WM_CHANGEUISTATE, _
              MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), ByVal  0 )
              bViewFocus = False
        End If
    End If
End Sub

Искренне надеюсь что классы ресурсов не жрут и не стреляют. Так? Тогда пусть болтаются.
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36529815
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не могу понять, зачем в формах
Option Explicit
все кому не лень лепят.

В модуле да, всегда ставлю.
А в форме по традиции не ставлю,
еще сломается чего нибудь.
На работу кодов это вроде не влияет.

P.S. По теме: на вооружение взял все-таки свой крайний вариант, внедряем-с потихоньку.
"Второй" вариант с хуком клавиатуры везде где успел уже впихнуть, отключил. (Основная мотивировка все-таки: ложное срабатывание на стрелки)

Konst_One спасибо, екстендер конечно ну его, но идею вашу кажется реализовал.
Еще конечно чуть беспокоит то, что в моем варианте в экземпляре класса всегда куча пустых Public WithEvents (кроме одного) и бесчисленное множество экземпляров (по числу элементов) постоянно "на взводе".

И надо ли их убивать при form_unload
На Terminate я кстати забил и просто пишу
Код: plaintext
1.
2.
3.
4.
5.
6.
Private Sub Form_Unload(Cancel As Integer)
    Dim i As Integer
    For i =  0  To Count -  1 
        On Error Resume Next
        Set TBEvents(i) = Nothing
    Next i
End Sub
Ну т.е. задачу считаю порешенной, комментарии приветствуются.
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36530148
Фотография Игорь Горбонос
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
> Автор: Дмитрий77
> Не могу понять, зачем в формах
> Option Explicit
> все кому не лень лепят.

Потому, что у него одно предназначение, заставлять программиста явно объявлять переменные.

> В модуле да, всегда ставлю.
> А в форме по традиции не ставлю,
> еще сломается чего нибудь.

Это правильно, сломатся может на раз, потом долго разгребать

> На работу кодов это вроде не влияет.

Только тем что заставит тебя объявить все переменные явно


Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
    #36530201
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nothing экземпляру класса вполне достаточно
...
Рейтинг: 0 / 0
27 сообщений из 27, показаны все 2 страниц
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Клавиатурный "фокус" при использовании xp/Vista стилей (с манифестом)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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