Баннерная сеть

Личный кабинет

Имя

Пароль

Запомнить меня


Забыли пароль?
Зарегистрироваться

  2008-11-04 11:42
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);

}

} }

}
Быстрый переход
  • Company
  • Overview
  • Facts and Figures
  • Why Us
  • Testimonials
  • Careers
  • Capabilities
  • Technology Centers
  • Microsoft .NET
  • Java EE
  • PHP
  • AJAX
  • Skill Set
  • Domain Expertise
  • Web 2.0
  • Rich Internet Applications
  • Business Continuity
  • Quality Management
  • Methodology
  • Services
  • Advanced Web Development
  • Web Application Development
  • Web and Enterprise Portal Development
  • Website Design and Development
  • Web-based Database Programming
  • Web-enabling Legacy Applications
  • Opensource Software Customization
  • Business Application Development
  • Content and Document Management
  • Secure Intranets / Extranets
  • Customer Relationship Management
  • Workflow Management
  • Supply Chain Management
  • Interactive Learning
  • Independent QA and Testing
  • Application Security Consulting
  • Graphic Design / Multimedia
  • Maintenance and Support
  • Outsourcing
  • Outsourcing Overview
  • Dedicated Teams
  • Security and IP Protection
  • Engagement Models
  • Portfolio
  • By Business Domain
  • Corporate / Info Websites
  • Communities and Networks
  • B2B / B2C Internet Portals
  • Retail / Ecommerce
  • Media Distribution
  • Workflow Management
  • Customer Management
  • Enterprise Collaboration
  • Supply Chain Management
  • eLearning / Online Training
  • By Technology Focus
  • Microsoft .NET
  • Java EE
  • PHP
  • By Solution Type
  • Websites
  • Web Applications
  • Enterprise Solutions
  • Contact
  • Contact Form
  • Get Free Evaluation
  • Call Me Back
  • Contact Info
  • Map