С течением времени, когда элементов становится много, появляется вертикальный scroll bar с ползунком, который всегда находится внизу полосы прокрутки. Даже если мне с помощью мыши переместить его наверх, чтобы посмотреть ранее введенные элементы, после очередного InsertItem он все равно опускается вниз. Каким образом я могу поменять такое поведение? Мне необходимо, чтобы ползунок сохранял свою предыдущую позицию (если я переместился наверх, чтобы посмотреть на самый первый элемент, то я там и должен оставаться, вне зависимости от того, добавились ли новые элементы или нет). Пробовал сделать через GetScrollPos и SetScrollPos, не помогает.
Насколько я понял, переменной hSomeItemToBeFocused необходимо присвоить значение, возвращаемое InsertItem, после чего вызывается SetItemState. Если я правильно понял, то у меня это к сожалению не работает.
Если можно, объясните, пожалуйста, цель использования SetItemState со значениями TVIS_SELECTED?
Чтобы было более понятно, покажу свою проблему подробнее:
Итак в Tree Control постепенно появляются различные элементы (тут добавляются ip адреса вместо "New element"): Начало
По мере увеличения их числа (после каждого InsertItem)всегда отображаются последние введенные элементы: Заполнение
Если я хочу посмотреть самый первый элемент — ip 10.0.23.126, то поднимаюсь наверх: В начало
И тут же при следующем InsertItem (он вызывается каждую секунду) мне опять отображается часть дерева с только что появившемся ip: Конец дерева
Таким образом, верхнюю часть дерева я практически не успеваю просмотреть...
Не видя кода, что-то подсказать сложно. Но есть подозрение, что вызов SetScrollPos() кто-то перебивает. Попробуй, ради эксперимента, вызов SetScrollPos() поставить в обработчик PostMessage(). Т.е. сделать что-то вроде:
АФАИК, обработчики post-сообщений вызываются в последнюю очередь, после всех обработчиков send-сообщений (подтверждение сейчас сходу не найду, но практика это показывает). Таким образом, есть надежда, что SetScrollPos() никто не перебьет и он будет вызван самым последним, когда дерево уже окончательно сформировано и все обработчики сделали свое дело.
> Насколько я понял, переменной hSomeItemToBeFocused необходимо присвоить > значение, возвращаемое InsertItem, после чего вызывается SetItemState. Если я > правильно понял, то у меня это к сожалению не работает.
Нет, неправильно понял.
Тебе надо добавлять итемы вниз, а устанавливать текущей какой-то из верхниих.
Например, первый дочерний к корневому.
Хотя я может быть ничего не понял.
> Если можно, объясните, пожалуйста, цель использования SetItemState со значениями > TVIS_SELECTED? >
Ну выбрать другой итем.
> И тут же при следующем InsertItem (он вызывается каждую секунду) мне опять > отображается часть дерева с только что появившемся ip: > Конец дерева <http://files.rsdn.ru/97456/4.jpg>
До инсёрта запоминай текущий выбранный итем. НА который смотрят.
Вставляй, и делай после вставки выбранным его.
> Таким образом, верхнюю часть дерева я практически не успеваю просмотреть...
Не очень ещё понятно как это так ты и вставляешь одновременно итемы,
и пытаешься что-то смотреть. По таймеру что ли это происходит ?
е видя кода, что-то подсказать сложно. Но есть подозрение, что вызов > SetScrollPos() кто-то перебивает.
Да там просто новая вставленая итема наверняка имеет состояние SELECTED , и оно
подматывает само до неё. Можно ещё не создавать с состоянием SELECTED.
> ... > UINT MYAPP_RESTORE_SCROLLBAR_POS_NOTIFY = ::RegisterWindowMessage( _T("MYAPP_RESTORE_SCROLLBAR_POS_NOTIFY" ) );
Зачем применяешь RegisterWindowMessage ?
RegisterWindowMessage нужно только когда регистрируемое сообщение пересылается
между разными приложениями. Для посылки сообщений внутри приложения это не нужно.
И даже вредно, потому что ON_REGISTERED_MESSAGE немного по-другому работает в
MFC, чем простое сообщение.
> АФАИК, обработчики post-сообщений вызываются в последнюю очередь, после всех > обработчиков send-сообщений (подтверждение сейчас сходу не найду, но практика > это показывает).
Они не в последнюю очередь. Они просто в очередь. POST. А SEND обрабатывается
минуя очередь сообщений непосредственно вызовом функции окна, без
постановки сообщения в очередь.
Таким образом, есть надежда, что SetScrollPos() никто не > перебьет и он будет вызван самым последним, когда дерево уже окончательно > сформировано и все обработчики сделали свое дело.
Не, не выйдет. SetScrollPos() -- чисто синхронный вызов.
> Не видя кода, что-то подсказать сложно. Но есть подозрение, что вызов > SetScrollPos() кто-то перебивает. Попробуй, ради эксперимента, вызов > SetScrollPos() поставить в обработчик PostMessage(). Т.е. сделать что-то вроде: > > ... > UINT MYAPP_RESTORE_SCROLLBAR_POS_NOTIFY = ::RegisterWindowMessage( _T("MYAPP_RESTORE_SCROLLBAR_POS_NOTIFY" ) ); > ... > void CMyAppDialog::InsertTreeItem() > { > ... > int nOldPos = m_ctrlTree.GetScrollPos( SB_VERT ); > > m_ctrlTree.InsertItem( L"New element", TVI_ROOT ); > > PostMessage( MYAPP_RESTORE_SCROLLBAR_POS_NOTIFY, 0, ( LPARAM )nOldPos ); > ... > } > > ... > ON_REGISTERED_MESSAGE( MYAPP_RESTORE_SCROLLBAR_POS_NOTIFY, OnRestoreScrollBarPosNotify ) > ... > > void CMyAppDialog::OnRestoreScrollBarPosNotify( WPARAM, LPARAM lp ) > { > m_ctrlTree.SetScrollPos( SB_VERT, lp, TRUE ); > }
А, сорри, выйдет, но не факт, что будет работать. Это отложит вызов SetScrollPos
на потом. Но не факт, что ему поможет.
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Обновление CTreeCtrl
От:
Аноним
Дата:
12.07.12 07:42
Оценка:
Здравствуйте, MasterZiv, Вы писали:
MZ>Не очень ещё понятно как это так ты и вставляешь одновременно итемы, MZ>и пытаешься что-то смотреть. По таймеру что ли это происходит ?
Сейчас покажу. Вот мой код (в упрощенном варианте):
#define ID_TIMER_1 1
HTREEITEM hRoot, hFchild;
...
BEGIN_MESSAGE_MAP(CForexampleDlg, CDialogEx)
...
ON_WM_TIMER() // Для таймера
...
END_MESSAGE_MAP()
...
BOOL CForexampleDlg::OnInitDialog()
{
...
// TODO: Add extra initialization here
hRoot = m_ctrlTree.InsertItem(L"First element", TVI_ROOT);
Test = false;
...
}
...
void CForexampleDlg::OnTimer( UINT uTime) // Обработчик таймера
{
hFchild = m_ctrlTree.InsertItem(L"New element", hRoot);
m_ctrlTree.InsertItem(L"New Fchild", hFchild);
m_ctrlTree.Expand(hRoot, TVE_EXPAND);
m_ctrlTree.Expand(hFchild, TVE_EXPAND); // Если её закомментировать, все работает
}
void CForexampleDlg::OnBnClickedStart()
{
if (!Test)
{
Test=true;
SetTimer(ID_TIMER_1,1000,NULL);
}
else
{
Test=false;
KillTimer(ID_TIMER_1);
}
}
При этом — если не разворачивать ветку с hFchild, то все прекрасно работает.
Для наглядности сделал небольшую анимацию: Gif
Видно, что после 6-го добавления я поднимаюсь наверх к корневому элементу, но 7 InsertItem опять опускает ползунок вниз.
On 07/12/2012 11:42 AM, Аноним 226 wrote:
> MZ>Не очень ещё понятно как это так ты и вставляешь одновременно итемы, > MZ>и пытаешься что-то смотреть. По таймеру что ли это происходит ? > > Сейчас покажу. Вот мой код (в упрощенном варианте):
> При этом — если не разворачивать ветку с hFchild, то все прекрасно работает.
А нафига ж её разворачивать, если она только что вставлена и в ней ничего нет ?
> > Для наглядности сделал небольшую анимацию: Gif <http://files.rsdn.ru/97456/1.gif>
Круто. Все бы так repro делали...
> Видно, что после 6-го добавления я поднимаюсь наверх к корневому элементу, но 7 > InsertItem опять опускает ползунок вниз.
Ну я понял, вставляется, разворачивается и туда прокручивается.
Но всё равно я так и не понял этого:
> MZ>Не очень ещё понятно как это так ты и вставляешь одновременно итемы, > MZ>и пытаешься что-то смотреть.
НАФИГА и вставлять, и пытаться смотреть одновременно ? Вставь ВСЕ, затем
смотри. ЭТо ж тебе не мультики, это TreeCtrl.
Здравствуйте, MasterZiv, Вы писали:
MZ>А нафига ж её разворачивать, если она только что вставлена и в ней ничего нет ?
Как же ничего нет? В ней элемент New hFchild. Если бы я не разворачивал, было бы следующее:Don't expand
MZ>Круто. Все бы так repro делали...
Спасибо
MZ>НАФИГА и вставлять, и пытаться смотреть одновременно ? Вставь ВСЕ, затем MZ>смотри. ЭТо ж тебе не мультики, это TreeCtrl.
В этом то и проблема. По прежним скринам было видно, что вставляются ip адреса, и дерево постоянно пополняется новыми ip, просто в режиме реального времени происходит анализ сети. Дождаться, пока все закончится — не могу, это можно сказать бесконечный процесс... Только лишь из-за этого и возник вопрос — как это можно исправить?
Здравствуйте, Аноним, Вы писали:
А>Ну так получается никаких вариантов нет?
Если через скролл не получается, можно попробовать запоминать преред Expand GetFirstVisibleItem и возвращать через EnsureVisible, обернув в SetRedraw(), ибо будет промигивать.
On 07/13/2012 02:20 PM, Аноним 226 wrote:
> Ну так получается никаких вариантов нет?
Не знаю.
Вообще, плохая идея. Плохой режим работы.
А так ещё можно вместо TreeView использовать ListView (SysListView32 который).
в режиме дерева (там теперь вроде бы есть, а если и нет -- можно самому сделать,
делается).
Вот его можно в виде виртуального ListView делать и там режим такой работы
легде изобразить. По крайней мере я так делал (обновляемые в реальном времени
таблицы). Ну и вообще он помощнее Tree немного, там больше свобод.
Posted via RSDN NNTP Server 2.1 beta
Re[9]: Обновление CTreeCtrl
От:
Аноним
Дата:
25.07.12 07:43
Оценка:
Здравствуйте, MasterZiv, Вы писали:
MZ>On 07/13/2012 02:20 PM, Аноним 226 wrote:
>> Ну так получается никаких вариантов нет?
MZ>Не знаю. MZ>Вообще, плохая идея. Плохой режим работы.
Здравствуйте, Аноним, Вы писали:
А>Ладно, буду пробовать. Спасибо за ответы.
Похоже, что Expand() имеет побочный эфект: перемещает этот элемент в видимую область.
К счастью, вызов этой функции можно избежать, указав EXPANDED в вызове InsertItem().
Вместо