Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> То рисует рамку фокуса в ListView, то нет, Работа только с фокусными элементами 
V
    Опции темы
feodorv
Дата 1.8.2013, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Уважаемые форумчане!

Может, кто сталкивался с подобной проблемой. Работаю на чистом WinAPI. Есть диалог с табом, при переключении которого отображается соответствующий ListView через ShowWindow( SW_HIDE/SW_SHOW ). Вседа работал в ListView с выбранными (SELECTED) элементами, но разрешал только один такой элемент. Теперь решил перейти на чисто фокусный элемент (FOCUSED) с тем, чтобы покрасивше можно было его оформить.

Так вот, при одном запуске одной и той же программы ListView рисуется нормально, с прерывистой рамкой у фокусного элемента ListView, а при другом запуске - эта рамка уже не отображется (ни на одном ListView). Если бы не подсветил фокусный элемент другим цветом заднего плана, то и не поймёшь, где там фокус. При этом все клавиши перемещения текущего элемента (Up/Down/PgUp etc) работают исправно, фокус перемещается.

Такое впечатление, что что-то недоинициализировано, и какая-то переменная получает случайное значение, но что именно, не могу понять.

Чуть больше информации
  • При старте программы:
    Код
      INITCOMMONCONTROLSEX ic;
      ZeroMemory( &ic, sizeof(INITCOMMONCONTROLSEX));
      ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
      ic.dwICC = ICC_WIN95_CLASSES;
      InitCommonControlsEx( &ic );
  • ListView имеет фиксированный стиль LVS_REPORT | LVS_SINGLESEL | LVS_OWNERDATA и расширенный стиль LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP
  • На ListView наложена маска обратного вызова
    Код
      ListView_SetCallbackMask( lv, LVIS_SELECTED);
    и при обработке LVN_GETDISPINFO никакому элементу не ставится флаг LVIS_SELECTED
  • В функции диалога идет обработка уведомления NM_CUSTOMDRAW:
    Код
     case NM_CUSTOMDRAW:
        {
          NMLVCUSTOMDRAW *cd = (NMLVCUSTOMDRAW *) nm;
          switch( cd->nmcd.dwDrawStage )
          {
            case CDDS_PREPAINT:
              SetWindowLong( dialog, DWL_MSGRESULT, CDRF_NOTIFYITEMDRAW);
              return TRUE;
            case CDDS_ITEMPREPAINT:
              SetWindowLong( dialog, DWL_MSGRESULT, CDRF_NOTIFYSUBITEMDRAW);
              return TRUE;
            case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
              cd->clrText = getColor( cd->nmcd.dwItemSpec );
              if( (cd->nmcd.uItemState & CDIS_FOCUS) )
                cd->clrTextBk = RGB( 0xee, 0xee, 0xee);
              SetWindowLong( dialog, DWL_MSGRESULT, CDRF_NEWFONT);
              return TRUE;
            default:
              SetWindowLong( dialog, DWL_MSGRESULT, CDRF_DODEFAULT);
          }
          break;
        }
    и уведомления LVN_GETDISPINFO:
    Код

        case LVN_GETDISPINFO:
        {
          LVITEM *item = &((LV_DISPINFO *) nm)->item;
          if( (item->mask & LVIF_TEXT) != 0 )
            item->pszText = getText( item );
          break;
        }
    с возвратом
    Код
       return FALSE;
  • Один из симптомов проблемы - при переключении таба и дальнейшем ShowWindow( oldlv, SW_HIDE) и ShowWindow( newlv, SW_SHOW) фокус ввода остаётся на старом ListView, приходится принудительно делать SetFocus( newlv ).



--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
feodorv
Дата 1.8.2013, 16:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Вставил логгирование в обработчик уведомления NM_CUSTOMDRAW. Выяснил, что один и тот же элемент ListView отрисовывается дважды подряд. Естественно, рамка пропадает, поскольку DrawFocusRect второй раз просто стирает ранее нарисованную рамку:
Цитата
Because DrawFocusRect is an XOR function, calling it a second time with the same rectangle removes the rectangle from the screen. 
Но вопрос остался - почему один и тот же элемент списка ListView отрисовыватся два раза подряд...

Не прав. Когда рамка рисуется, данные тоже запрашиваются 2 раза подряд...

Это сообщение отредактировал(а) feodorv - 1.8.2013, 17:08


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
volatile
Дата 1.8.2013, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Вот здесь что-то похожее на вашу проблему.
Главный вывод из прочитанного: это таки обычное поведение для вендузятины (если вас это успокоит  smile ).
(подозреваю что поведение этой рамки еще слегка варьируется от версии венды)

Ну а выход... может плюнуть на эту рамку и отрисовывать что-то похоже самому?

Добавлено через 8 минут и 41 секунду
Цитата
the focus rectangle shows up if the user got there via the keyboard and not if the user got there some other way

то есть она вообще только при заходе клавиатурой должна отрисовываться. а это  не ваш случай.


PM MAIL   Вверх
feodorv
Дата 1.8.2013, 20:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



volatile, спасибо большое за ответ и ссылку smile 

Цитата(volatile @  1.8.2013,  20:59 Найти цитируемый пост)
а это  не ваш случай

Ничего, зато есть над чем подумать smile 

Цитата(volatile @  1.8.2013,  20:59 Найти цитируемый пост)
Ну а выход... может плюнуть на эту рамку и отрисовывать что-то похоже самому?

В принципе, можно жёстко диалогу UISF_HIDEFOCUS поставить, и в CDRF_NOTIFYPOSTPAINT рамку рисовать. Но как-то это неестестественно, что ли)))


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
feodorv
Дата 1.8.2013, 21:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Случай, кстати, явно похожий, только более тонкий)))
Если при старте программы (когда активным становится первый ListView) в диалоге нажать два раза TAB, то прямоугольник фокуса появляется...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
feodorv
Дата 1.8.2013, 21:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Дело точно в установленном флаге UISF_HIDEFOCUS. Поставил на него проверку:
Код

    case WM_INITDIALOG:
      if( !initDialog( hWnd, (struct dialog_data_s *) lParam) ) ((struct dialog_data_s *) lParam)->success = False;
       logMessage( "DialogInit:  focus = %u", SendMessage( hWnd, WM_QUERYUISTATE, 0, 0) & UISF_HIDEFOCUS);
      return TRUE;

    case WM_DESTROY:
      logMessage( "DialogDestroy:  focus = %u", SendMessage( hWnd, WM_QUERYUISTATE, 0, 0) & UISF_HIDEFOCUS);
      finishDialog( hWnd );
      PostQuitMessage( 0 );
      SetWindowLong( hwnd, DWL_MSGRESULT, 0);
      return 0;

И что получил:
Цитата

DialogInit:  focus = 0
...
DialogDestroy:  focus = 1

Кто-то из контролов всё испортил  smile 

Вставил после initDialog в WM_INITDIALOG
Код

     SendMessage( hWnd, WM_CHANGEUISTATE, MAKEWPARAM( UIS_INITIALIZE, 0), 0);

Теперь так:
Цитата

DialogInit:  focus = 1
...
DialogDestroy:  focus = 1

 smile 

Это сообщение отредактировал(а) feodorv - 1.8.2013, 21:28


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
feodorv
Дата 1.8.2013, 22:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Ну, кажись, всё  smile 
Вместо 
Код
     SendMessage( hWnd, WM_CHANGEUISTATE, MAKEWPARAM( UIS_INITIALIZE, 0), 0);
вставил
Код
    SendMessage( hWnd, WM_UPDATEUISTATE, MAKEWPARAM( UIS_CLEAR, UISF_HIDEFOCUS), 0);
и всё починилось)))


Цитата(volatile @  1.8.2013,  20:59 Найти цитируемый пост)
это таки обычное поведение для вендузятины

Да уж. Знаю по собственному опыту))) Да и в свиснутом у Microsoft коде полно комментов типа
Цитата

            //  Fix horrible undocumented hanging problem:  LVN_ENDLABELEDIT
            //  is sent in response to EN_KILLFOCUS

или
Цитата

            // Thus, as a cheap
            // and dirty solution, I check to see if the item I think I have
            // is the same one I had when I made the notify, and if not, I
            // bail.  Don't blame me, I'm just cleaning up the mess.
 smile 


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
feodorv
Дата 1.8.2013, 22:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Опять не прав. Так не починилось.
Оставил WM_CHANGEUISTATE в WM_INITDIALOG, а WM_UPDATEUISTATE послал, когда исчерпалась очередь сообщений диалога.
Танцы с бубнами, forever.


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
volatile
Дата 2.8.2013, 11:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



feodorv, интуитивно чувтвую что - лучше все-же сделать своими руками.
Даже если вы и отладите на своей ОS, не факт что глюк не вылезет на другой.
Они же что-то там подкручивают еще. Еще и темы оформления бывают ... Как это будет там? никто знает...  smile 

В общем я бы сделал подсветку своими руками.
(Ну или клавиатурные комбинации посылайте чтоли, не знаю. но это .. smile .)

PM MAIL   Вверх
feodorv
Дата 2.8.2013, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Цитата(volatile @  2.8.2013,  12:56 Найти цитируемый пост)
Как это будет там? никто знает... 

Да, согласен, "подушка безопасности" нужна)))

Цитата(volatile @  2.8.2013,  12:56 Найти цитируемый пост)
Ну или клавиатурные комбинации посылайте чтоли, не знаю.

Думаю как раз про этот вариант smile 

Цитата(volatile @  2.8.2013,  12:56 Найти цитируемый пост)
но это ..

А чо? Нормальное решение - подождать, пока всё успокоится и нанести ответный удар smile 


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
volatile
Дата 2.8.2013, 23:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Цитата(feodorv @  2.8.2013,  17:14 Найти цитируемый пост)
А чо? Нормальное решение 

ну если оно будет работать, то возможно ...

Может кто что еще посоветует...
Честно говоря, конкретно с этим, я дел не имел, просто почитал тот топик, и мне показалось
что это одно из тех многочисленных мест в венде, где мелкомягкие устроили танцы с бубном.
А это они делать умеют.
Пару раз натыкался на такие места...
Вроде бы уже все нормально, но в последний момент опять что-то вылазило ни с того, ни сего...

 smile 
А вобще писать гуй на чистом винапи... это что-то...  smile 

PM MAIL   Вверх
feodorv
Дата 3.8.2013, 00:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Цитата(volatile @  3.8.2013,  00:10 Найти цитируемый пост)
ну если оно будет работать, то возможно ...

"Поживём - увидим" ©)))

Цитата(volatile @  3.8.2013,  00:10 Найти цитируемый пост)
Честно говоря, конкретно с этим, я дел не имел

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

Цитата(volatile @  3.8.2013,  00:10 Найти цитируемый пост)
А вобще писать гуй на чистом винапи... это что-то...

Это мазохизм!!! Даже не знаю, чем оправдаться. Но вот так сложились обстоятельства smile 


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0953 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.