Есть строка, которую надо отобразить на диалоге в виде бегущей строки. Символы появляются справа налево. В каком контроле лучше всего это сделать ? Пытался CEdit, да что то не могу найти некоторых фич которые нужны.
Кто нибудь делал подобное? Работаю с MFC
Спасибо
бегущая строка
-
- Уже с Приветом
- Posts: 2013
- Joined: 16 Mar 2002 10:01
- Location: New York City
-
- Уже с Приветом
- Posts: 144
- Joined: 05 Mar 2001 10:01
Kогда-то попадалась ActiveX-компонента, отображающая "навороченную" бегущую строку, но не помню где.
Ну а если уж самопально на коленке, то проще всего наверное использовать onTimer(). Контрол может быть любой, отображающий текст, вот, например, эскиз функциональной части для CStatic (IDC_RUNSTR):
void CMyDlg::OnTimer(UINT nIDEvent)
{
m_runString = myLongString.Right(myLongStringLength - shiftValue);
if ((++shiftValue)==myLongStringLength ) shiftValue = 0;
InvalidateRect(&rectString);
UpdateData(false);
CDialog::OnTimer(nIDEvent);
}
при этом
void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
<...skip...>
DDX_Control(pDX, IDC_RUNSTR, m_runStringCtrl);
DDX_Text(pDX, IDC_RUNSTR, m_runString);
<...skip...>
}
BOOL CrunStrDlg::OnInitDialog()
{
<...skip...>
shiftValue = 0;
m_runStringCtrl.GetClientRect(&rectString);
myLongString= CString(" ")+myLongString; // количество пробелов подбирается экспериментально
// (или вычисляется, исходя из размера контрола и размеров шрифта) так,
// чтобы строчка "появлялась" с правой стороны контрола
// ( не получается вставить в сообщение больше одного пробела )
myTimerID = SetTimer(1, 100, 0);
<...skip...>
}
Успехов.
Ну а если уж самопально на коленке, то проще всего наверное использовать onTimer(). Контрол может быть любой, отображающий текст, вот, например, эскиз функциональной части для CStatic (IDC_RUNSTR):
void CMyDlg::OnTimer(UINT nIDEvent)
{
m_runString = myLongString.Right(myLongStringLength - shiftValue);
if ((++shiftValue)==myLongStringLength ) shiftValue = 0;
InvalidateRect(&rectString);
UpdateData(false);
CDialog::OnTimer(nIDEvent);
}
при этом
void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
<...skip...>
DDX_Control(pDX, IDC_RUNSTR, m_runStringCtrl);
DDX_Text(pDX, IDC_RUNSTR, m_runString);
<...skip...>
}
BOOL CrunStrDlg::OnInitDialog()
{
<...skip...>
shiftValue = 0;
m_runStringCtrl.GetClientRect(&rectString);
myLongString= CString(" ")+myLongString; // количество пробелов подбирается экспериментально
// (или вычисляется, исходя из размера контрола и размеров шрифта) так,
// чтобы строчка "появлялась" с правой стороны контрола
// ( не получается вставить в сообщение больше одного пробела )
myTimerID = SetTimer(1, 100, 0);
<...skip...>
}
Успехов.
-
- Уже с Приветом
- Posts: 2013
- Joined: 16 Mar 2002 10:01
- Location: New York City
-
- Уже с Приветом
- Posts: 1976
- Joined: 08 Jun 1999 09:01
- Location: SPb -> SFBA -> Beaverton, OR
uniqueman wrote:спасибо. сделал наподобие этого. За контрол взял CRichEdit.
Только вот проблема. Функция обновления вызывается каждые 50 миллисекунд, чтобы скорость строки была приемлимой. Но тогда появляется раздражающее моргание из за частого вызова UpdateData.
Есть ли способ сгладить это моргание ?
Спасбо
Рисуйте в memory bitmap, а потом копируйте на экран нужные куски. Будет без мерцания и scrolling можно сделать плавным, т.е. не дергать текст сразу на символ в сторону, а попиксельно ( за счет немного большей загрузки CPU ). Если не хочется заморачиваться, сделайте ctrlEdit.SetRedraw( FALSE ) до перерисовки и ctrlEdit.SetRedraw( TRUE ); ctrlEdit.Invalidate( NULL ); ctrlEdit.UpdateWindow() после ( писал по памяти, проверьте аргументы методов! )
-
- Уже с Приветом
- Posts: 2013
- Joined: 16 Mar 2002 10:01
- Location: New York City
http://www.codeproject.com/staticctrl/t ... print=true
вот здесь нашел что то подобное. DenisM, если несложно, посмотрите сорс. Вы это имели в виду. ? В этом примере все равно мерцает довольно сильно, когда скорость прокрутки где то насередине (ползунок).
вот здесь нашел что то подобное. DenisM, если несложно, посмотрите сорс. Вы это имели в виду. ? В этом примере все равно мерцает довольно сильно, когда скорость прокрутки где то насередине (ползунок).
-
- Уже с Приветом
- Posts: 1976
- Joined: 08 Jun 1999 09:01
- Location: SPb -> SFBA -> Beaverton, OR
uniqueman wrote:http://www.codeproject.com/staticctrl/ticker.asp?print=true
вот здесь нашел что то подобное. DenisM, если несложно, посмотрите сорс. Вы это имели в виду. ? В этом примере все равно мерцает довольно сильно, когда скорость прокрутки где то насередине (ползунок).
Ага, я посмотрел, у меня верхний ticker тоже заметно мерцает. Можно попробовать уменьшить мерцание, перенеся CPaintDC к последнему BitBlt в OnPaint(). Вообще для максимизации скорости отрисовки лучше всего в OnPaint() только делать BitBlt из memory bitmap на screen. А всю подготовительную работу ( относительно долгую ) проводить заранее.
-
- Уже с Приветом
- Posts: 2013
- Joined: 16 Mar 2002 10:01
- Location: New York City
-
- Уже с Приветом
- Posts: 1976
- Joined: 08 Jun 1999 09:01
- Location: SPb -> SFBA -> Beaverton, OR
uniqueman wrote:вот такой еще вопрос.
в качестве контнейнера для строки использую CRichEdit контрол. Мне надо разные части бегущей строки рисовать разным цветом. Как это возможно сделать быстро ? Вроде слышал что CRichEdit позволяет это легко делать, однако не могу найти как
Спасибо
Я делал так: создал шаблон в WordPad, где установил все необходимые мне аттрибуты для каждого участка текста. Вместо собственно информативного текста были вставлены метки %1, %2 etc. А потом на runtime просто заменял эти метки на нужный мне текст. То же самое можно сделать с аттрибутами. Ну если очень хочется большого геммороя, можно разобраться в формате RTF ( ~150 страниц описания, см. www.wotsit.org ), генерить его из Ваших данных по мере надобности и запихивать в RichEdit.
-
- Уже с Приветом
- Posts: 2013
- Joined: 16 Mar 2002 10:01
- Location: New York City
Я делал так: создал шаблон в WordPad, где установил все необходимые мне аттрибуты для каждого участка текста. Вместо собственно информативного текста были вставлены метки %1, %2 etc. А потом на runtime просто заменял эти метки на нужный мне текст. То же самое можно сделать с аттрибутами.
не совсем понял каким образом получается текст разного цвета
-
- Мистер Привет 2015
- Posts: 7606
- Joined: 26 Mar 2002 10:01
- Location: San Diego
uniqueman wrote:в качестве контнейнера для строки использую CRichEdit контрол.
Таки решили не использовать битмапы для строки? Зря, зря Такой плавности как там, при помощи Rich Edit не достигнуть.
uniqueman wrote: Мне надо разные части бегущей строки рисовать разным цветом. Как это возможно сделать быстро ? Вроде слышал что CRichEdit позволяет это легко делать, однако не могу найти как
Так надо быстро или легко? Я в свое время просто делал selection участка, который надо было выводить нужным цветом а потом менял аттрибуты символов в этом selection
Code: Select all
CHARFORMAT cf;
cf.crTextColor = RGB(255, 0, 0);
cf.dwMask = CFM_COLOR;
cf.dwEffects = 0;
m_RichEdit->SetSelectionCharFormat(cf);
olley
-
- Уже с Приветом
- Posts: 2013
- Joined: 16 Mar 2002 10:01
- Location: New York City
Таки решили не использовать битмапы для строки? Зря, зря Такой плавности как там, при помощи Rich Edit не достигнуть.
согласен, но в последний момент тех. задание изменилось (ой как я это ненавижу ). Надо вместо бегущей строки просто добавлять новые данные в конец текущей. Никакого скрола не надо. единственное что пришлось выдумать - обрезать строку слева, когда текст уже не влазит.
Так надо быстро или легко? Я в свое время просто делал selection участка, который надо было выводить нужным цветом а потом менял аттрибуты символов в этом selectionCode: Select all
CHARFORMAT cf;
cf.crTextColor = RGB(255, 0, 0);
cf.dwMask = CFM_COLOR;
cf.dwEffects = 0;
m_RichEdit->SetSelectionCharFormat(cf);
надо без гемора всякого с GDI если можно Сейчас текст выводится вот так..
// запоминаем пришешие данные..
string sTemp = sHouse + ":" + sData;
// добавляем данные к текущей строке
sTickerString += sTemp;
// если длина текущей строки превышает предел, то вырезаем из текущей строки подстроку, захыватывая последние данные.
if (sTickerString.length() > 150)
{
sTickerString = sTickerString.substr(sTemp.length(), sTickerString.length() - sTemp.length());
}
// выводим на контрол
m_editRichTicker.SetWindowText (sTickerString.c_str());
мне в какой то момент надо делать часть sData либо зеленой либо красной (в зависимости от знака данных). Как это сделать?
-
- Мистер Привет 2015
- Posts: 7606
- Joined: 26 Mar 2002 10:01
- Location: San Diego
uniqueman wrote:мне в какой то момент надо делать часть sData либо зеленой либо красной (в зависимости от знака данных). Как это сделать?
Если объяснять на пальцах, то сделайте так:
1. Сохранить текущее выделение GetSel()
2. Выделить ту часть текста, в которой данные из sData. Используйте для этого SetSel()
3. Изменить цвет выделенного текста - SetSelectionCharFormat()
4. Вернуть выделение к тому виду, каким оно было до шага 2 - SetSel()
Это то, что я могу вспомнить навскидку. Да, чтобы эти выделения не мерцали, сделайте richEdit->SetRedraw(FALSE); до всех операций и richEdit->Invalidate(); - после.
У меня работало и вроде не мерцало Это был обновляющийся разноцветный лог. Правда я писал в окно через потоки (StreamIn()), а не через SetWindowText(). Но думаю, что для однострочного контрола это не принципиально.
olley