Почему процедура на форме основного проекта срабатывает, а при помещении её в контрол
Есть поцедура (VB6), которая, при вводе текста в комбобокс, автоматом пытается подставлять ближайшее найденное значение. Вобщем, в ремарках всё описано.
Если процедура включена в состав основного проекта и вызывается оттуда, всё работает нормально, но, если поместить её в контрол, то она не отрабатывает. Вызов её вешается на события KeyDown и KeyPress, обрабатываясь следующим образом:
'МАХ обрабатываем введённый символ
On Error GoTo ErrHnd 'МАХ в случае ошибки передаём управление обработчику
If KeyCode = 9 Or KeyCode = 46 Or KeyCode = 8 Or KeyCode = 27 Then
SelectCbx CbAncCntr, vbNullString, 0, True 'МАХ сбросим комбобокс
End If
Exit Sub
ErrHnd: 'МАХ область обработки ошибок
'МАХ передача управления процедуры ведения лога
ErrDescr Err.Number, Err.Description, "FrmAnketa.CbAncCntr_KeyDown Код клавиши " & KeyCode
End Sub
Private Sub CbAncCntr_KeyPress(KeyAscii As Integer)
'МАХ отлавливаем нажатие кнопки пользователем (для подстановки)
On Error GoTo ErrHnd 'МАХ в случае ошибки передаём управление обработчику
If KeyAscii <> 9 And KeyAscii <> 8 And KeyAscii <> 27 And KeyAscii <> 13 Then
SelectCbx CbAncCntr, Chr$(KeyAscii), CbAncCntr.ListIndex, False
End If
KeyAscii = 0 'МАХ стираем символ
Exit Sub
ErrHnd: 'МАХ область обработки ошибок
'МАХ передача управления процедуры ведения лога
ErrDescr Err.Number, Err.Description, "FrmAnketa.CbAncCntr_KeyPress Код клсвиши " & KeyAscii
End Sub
Сама процедура:
'МАХ процедура. которая должна находить в комбобоксе введённый текст и _
подставлять в него значения, ну, короче, понятно (срабатывает, когда чувак _
набирает в комбике текст, а комбик сам под него подставляется) _
Получает на вход комбобокс и символ текста пользователя, текущий лист индекс. _
Опционально получает команду на очистку
On Error GoTo ErrHnd 'МАХ в случае ошибки переходим к собственному обработчику ошибок
Static OldCbx As String 'МАХ хранит комбобокс
Static CbLetter As String 'МАХ хранит текст комбобокса
Dim I As Long 'МАХ счётчик циклов
If Not Refr Then 'МАХ проверяем необходимость рефреша (если комбик, например, теряет фокус)
'МАХ проверка, тот ли комбобокс
If OldCbx = vbNullString Or OldCbx <> Cbx.Name Then
OldCbx = Cbx.Name
CbLetter = vbNullString
End If
CbLetter = CbLetter & Txt 'МАХ создаём поисковый текст
For I = 0 To Cbx.ListCount - 1 'МАХ в цикле ищем текст, начинающийся с введённых символов
Cbx.ListIndex = I 'МАХ устанавливаем лист индекс
If LCase(Left(Trim(Cbx.Text), Len(Trim(CbLetter)))) = LCase(CbLetter) Then
DoEvents
Cbx.ListIndex = I 'МАХ подставляем итем комбобокса
DoEvents
Cbx.Refresh
DoEvents
LisInd = I
Exit For 'МАХ досрочно выходим из цикла
End If
Cbx.ListIndex = LisInd 'МАХ возвращаем лист индекс
Next
Else
'МАХ если рефрешим, сбрасываем все переменные
OldCbx = vbNullString
CbLetter = vbNullString
End If
Exit Sub
ErrHnd: 'МАХ область обработки ошибок
'МАХ передача управления процедуры ведения лога
ErrDescr Err.Number, Err.Description, "FrModGlobalProcedures.SelectCbx Комбобокс " & Cbx.Name & " Текст " & Txt
End Sub
В чём может быть загвоздка?
Все что я вижу, это то что единственным способом процедура SelectCbx может не вызываться, это если только до нее не доходит управление. У тебя в коде процедура SelectCbx стоит в If Then - поставь туда breakpoint и посмотри заходит ли туда программы при выполнении (я думаю что все это ты уже проделал, ты бы написал лучше свои изыскания чтобы мы не предлагали уже испробованные варианты)
ОК. Сейчас я немного сместился от этой задачи. но в середине следующей недели я вернусь к ней и сообщу о том, что смог накопать.
Пока только я отметил одно:
процедура подстановки данных в комбюобокс вклюсена в код контрола, но почему-то по событию KeyPres и KeyDown она не вызывается. Вернее, при дебаге программа входит в неё, а в рантайме - нет.
и если в дебаг окне все будет видно, то можно еще пощупать входящие переменные процедуры, может что-нибудь не то передается...
Добавь в If Then - Debug.Print "Оо, попали"
и если в дебаг окне все будет видно, то можно еще пощупать входящие переменные процедуры, может что-нибудь не то передается...
Не, так делал уже - просто не попадает в процедуру. Я не приложу ума, что же происходит в событиях контрола в рантайме...:{
Не, так делал уже - просто не попадает в процедуру. Я не приложу ума, что же происходит в событиях контрола в рантайме...:{
Так, разобрался. Я, к сожалению, обманул всех, когда написал, что прога не заходит в процедуру. Просто процедура не может работать в случае, если в неё передаётся контрол из массива контролов. Сейчас башка ничего не соображает. Если у кого есть идеи - буду очень рад помощи.
KeyDown и KeyPress одновременно не обрабатываются. Либо KeyDown/KeyUp либо KeyPress. И в твоем случае, на мой взгляд, лучше обрабатывать Change.
Может я что-то путаю, но все-таки...
KeyDown и KeyPress одновременно не обрабатываются. Либо KeyDown/KeyUp либо KeyPress. И в твоем случае, на мой взгляд, лучше обрабатывать Change.
Нет, тут всё правильно и именно так и должно быть (проверено на практике). Проблема в том, как передать в процедуру не единичный контрол. а контрол из массива контролов. Тоесть, если у меня есть комбобоксы Cb1, Cb2, Cb3, я передаю любой из них в процедуру и она работает, а если у иеня массив комбобоксов Cb(0), Cb(1), Cb(2), Cb(3), то процедура отрабатывает только для Cb(0), так как она "не понимает", с каким комбобоксом ей работать.
у тебя в SelectCbx(ByVal Cbx As Object, передается же сам объект, кстати зачем ByVal использовать ?!, не вижу кода как ты передаешь ему объект из массива - и потом массив не может содержать объекты (если не считать вариант с хранением pointer типа long на объекты, но это уже извращение), для этого можно только коллекции использовать
Так, чтобы тебе помочь надо немного разобраться:
у тебя в SelectCbx(ByVal Cbx As Object, передается же сам объект, кстати зачем ByVal использовать ?!, не вижу кода как ты передаешь ему объект из массива - и потом массив не может содержать объекты (если не считать вариант с хранением pointer типа long на объекты, но это уже извращение), для этого можно только коллекции использовать
Правильно! Правильно!
Спасибо Вам ОГРОМНОЕ!
Я-то, дурак, всё перерыл, но на то, что вместо того, чтобы ByRef писать, или опустить параметр, передаю по значению, упустил! МЕСЯЦ перекапывал процедуру, а как передаю параметры, НЕ ПОСМОТРЕЛ НИ РАЗУ!!!:D :D :D
Огромное Вам СПАСИБО!!!!
InvalidateRect vchWnd, 0&, API_TRUE
через что токо не пробывал, ну не обновляет и все тут, потом написал "ByVal 0&" и о чудо:
InvalidateRect vchWnd, ByVal 0&, API_TRUE
наконец-то заработало. Прикол оказался в том что в API функции надо всегда передавать переменные только как ByVal и я это знал. Просто обычно уже при объявлениии функции пишут например:
GetSysColor Lib "user32" (ByVal nIndex As Long)
и по этому в коде уже можно просто писать
GetSysColor(0&) без всякого ByVal - он же уже в объявлении сидит.
А у InvalidateRect я не заметил что объявлении такое:
Declare Function InvalidateRect Lib "user32" (ByVal hwnd As Long, lpRect As Any, ByVal bErase As Long) As Long
lpRect As Any - без ByVal объявление и поэтому надо в коде обязательно писать с ByVal
угар вообщем, 3 дня