Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как поменять цвет Scroll Bar в приложении MFC? 
:(
    Опции темы
chipset
Дата 7.4.2005, 21:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4071
Регистрация: 11.1.2003
Где: Seattle, US

Репутация: 27
Всего: 164



Windows имеет два типа скролбаров. Это "встроенные" скролбары, которые мы получаем при использовании оконных стилей WS_HSCROLL и/или WS_VSCROLL, и скролбар контролы, которые фактически являются дочерними окнами и которые можно создавать в пределах окна. Сообщение WM_CTLCOLOR могут посылать только последние.

Естевственно, возникает вопрос, а почему существует два вида скролбаров ? Ответ кроется в истории. Давным давно, когда Windows была ещё очень маленькой, существовала необходимость экономить каждый бит памяти, а окна занимали значительное пространство. Так как почти в каждом окне присутствовали скролбары, то разработчики решили сделать их неотемлемой частью окон. С другой стороны, программистам не понравилось такое решение, так как им больше хотелось работать со скролбарами, как с отдельными окнами. С одной стороны, конечно же встроенные скролбары удобнее в использовании и требуют меньше кода, но с другой имеют меньше настроек, позволяющих менять их внешний вид.

А как насчёт MFC? Поумолчанию, MFC-шный CScrollView использует встроенные скролбары, у которых нельзя менять цвет. Однако, ничего страшного не случится, если мы заставим CScrollView использовать Ваш собственный контрол скролбара. Но перед тем, как мы решим данную задачу, я хочу заметить, что WM_CTLCOLOR позволяет устанавливать только цвет фона, но не цвет стрелки и бегунок. Поэтому, если Вы хотите менять все цвета, то скорее всего WM_CTLCOLOR окажется бесполезным. Позже я постараюсь подкинуть несколько идей по этому поводу, ну а теперь давайте посмотрим, как заставить CScrollView использовать Ваш скролбар вместо встроенного.

Итак, для начала, объявим экземпляры CScroll баров в основном фрейме:

Исходный код:
Код


class CMainFrame : public CFrameWnd {
protected:
 CScrollbar m_wndHScroll;
 CScrollBar m_wndVScroll;
 ...
};





Затем, при создании фрейма, создаём их окна:

Исходный код:
Код


int CMainFrame::OnCreate(...)
{
 ...
 CRect rc(0,0,0,0);
 VERIFY(m_wndSBHorz.Create(WS_VISIBLE|WS_CHILD|SBS_HORZ,
   rc, this, AFX_IDW_HSCROLL_FIRST));
 VERIFY(m_wndSBVert.Create(WS_VISIBLE|WS_CHILD|SBS_VERT,
   rc, this, AFX_IDW_HSCROLL_FIRST+1));
 VERIFY(m_wndSBBox.Create(WS_VISIBLE|WS_CHILD|SBS_SIZEBOX,
   rc, this,-1));
 return 0;
}





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

Как только скролбары созданы, остаётся ещё несколько вещей, о которых необходимо позаботится. Это установить размер скролбаров, обработать уведомления, и получить для них вид (view). Последнее самое простое. CScrollView содержит виртуальную функцию GetScrollBarCtrl, которую можно переопределить.

Исходный код:
Код


CScrollBar* CPictureView::GetScrollBarCtrl(int nBar) const
{
 CWnd* pParent = GetParent();
 UINT nID = AFX_IDW_HSCROLL_FIRST;
 if (nBar==SB_VERT)
   nID++;
 return (CScrollBar*)pParent->GetDlgItem(nID);
}





Она получает управление от родителя используя удобные идентификаторы (ID) AFX_IDW_HSCROLL_FIRST и AFX_IDW_HSCROLL_FIRST+1.

А как же уведомления? Когда пользователь перемещает полосу прокрутки, скролбар посылает WM_HSCROLL или WM_VSCROLL своему родителю, чтобы Вы могли что-нибудь сделать. Это есть очень хорошо, так как если Вы поместите свои скролбары во фрейм, то CFrameWnd уже имеет обработчики OnHScroll и OnVScroll, которые направляют WM_HSCROLL и WM_VSCROLL в вид (view):

// Из winfrm.cpp
Исходный код:

Код

void CFrameWnd::OnHScroll(...)
{  
 CWnd* pActiveView = GetActiveView();
 if (pActiveView != NULL) {
   pActiveView->SendMessage(WM_HSCROLL, ...);
 }
}





Если Ваш вид наследован от CScrollView, то для того, чтобы обработать сообщения прокрутки, ничего делать не надо, так как MFC делает это автоматически!

Теперь о размерах. Это то место, где прийдётся проделать определённую работу. Для того, чтобы всё летало, необходимо управлять позицией скролбаров каждый раз, когда размер фрейма изменяется. Помните, что скролбары, это потомки фрейма а не вида. Обычно, обработка изменения размеров производится в OnSize, однако для фреймовых окон это делается в CFrameWnd::RecalcLayout. Применительно к программе (исходник которой можно скачать ниже) эта функция выглядит так:

//////////////////
// изменение размеров фрейма: перемещение вида и скролбаров
//
Исходный код:
Код


void CMainFrame::RecalcLayout(BOOL bNotify)
{
   CFrameWnd::RecalcLayout();

   CView* pView = GetActiveView();
   if (pView) {
       CRect rc;
       pView->GetWindowRect(&rc);
       ScreenToClient(&rc);

       // shrink view by scrollbars
       int cyHScroll = GetSystemMetrics(SM_CYHSCROLL);
       int cxVScroll = GetSystemMetrics(SM_CXVSCROLL);
       rc.right  -= cxVScroll;
       rc.bottom -= cyHScroll;
       pView->MoveWindow(rc);

       // next, move the scroll bars: horz, vert and box
       rc.left   = rc.right;
       rc.right += cxVScroll;
       m_wndSBVert.MoveWindow(rc);

       rc.left   = 0;
       rc.right -= cxVScroll;
       rc.top    = rc.bottom;
       rc.bottom+= cyHScroll;
       m_wndSBHorz.MoveWindow(rc);

       rc.left = rc.right;
       rc.right+=cxVScroll;
       m_wndSBBox.MoveWindow(rc);
   }
}  }
}





--------------------
Цитата(Jimi Hendrix)
Well, I stand up next to a mountain
And I chop it down with the edge of my hand
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

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


 




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


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

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