Студия web-дизайна Хостмэйк
Наши работыКонтактыО компанииОтзывыГлоссарийСтатьи

Реализация стиля Office XP

Статьи Программирование на С/С++

ToolBarXP

Недавно я пытался найти в сети ToolBar-элемент в стиле Office XP. Поиски мои
не увенчались успехом - все элементы были либо сложны в встраивании в проект,
либо платны. Тогда я принял отчаянные меры - написал сам... А, как оказалось, в
написании тулбара не было оссобенных проблем. Вот как я сделал.

Создал MFC SDI проект с именем StyleXP. С помощью ClassWizard'а добавил новый
класс CToolBarXP, наследованный от CToolBar (CToolBar в списке нет, но я выбрал
CToolBarCtrl и вручную изменил имя предка). Дальше встал вопрос: "Какие функции
перегружать?". Просмотрев весь предоставленный список в ClassWizard'е, я выбрал
WM_PAINT. Долго я с ним провозился, но таки вышло вот что:


void
CToolBarXP::OnPaint()

{

    CPaintDC dc(this); //
device context for painting




    // TODO: Add your message handler code here

    CRect rt, rItem;

    COLORREF face, shdw, cbtn;

    BYTE r,g,b;

    WORD BtnLength;

    // Берём клиентскую область эл-та

    GetClientRect(rt);

    // Выщитываем цвет бэк-граунда(для пущей красоты

    // я решил слегка отклониться от стандартного цвета).


    face = GetSysColor(COLOR_3DFACE);

    r = GetRValue(face)+10;

    g = GetGValue(face)+10;

    b = GetBValue(face)+10;

    face = PALETTERGB(r,g,b);

    // Таким же образом выщитываем цвет выделенной
кнопки...


    cbtn = GetSysColor(COLOR_3DFACE);

    r = GetRValue(cbtn)-10;

    g = GetGValue(cbtn)-10;

    b = GetBValue(cbtn)-10;

    cbtn = PALETTERGB(r,g,b);

    // и цвет рамки

    shdw = GetSysColor(COLOR_3DSHADOW);

    r = GetRValue(shdw)+10;

    g = GetGValue(shdw)+10;

    b = GetBValue(shdw)+10;

    shdw = PALETTERGB(r,g,b);

    // Заполняем тол-бар бэкграундом

    dc.FillSolidRect(rt, face);

    // Создаём перо

    CPen pen;

    pen.CreatePen(0, 1, shdw);

    dc.SelectObject(&pen);



    TBBUTTON btn;

    BtnLength = LOWORD(GetToolBarCtrl().GetButtonSize());//
Получаем ширину кнопки


    // Перебираем все кнопки

    for(int i = 0, x =
0, n = 0; i != GetToolBarCtrl().GetButtonCount(); i++)

    {

        GetToolBarCtrl().GetButton(i, &btn);// Получаем
данные о кнопке


        if(btn.fsStyle & TBSTYLE_SEP)//
Сепаратор ?


        {

            dc.MoveTo(x+2, 2);// Рисуем вертикальную линию

            dc.LineTo(x+2, 20);



            x += 6;

        }

        if(m_nSelected == i)//
На кнопке мышка?


        {

            // Создаём кисть и перо

            CPen pn;

            CBrush br;

            pn.CreatePen(0, 1, shdw);

            br.CreateSolidBrush(cbtn);

            dc.SelectObject(&pn);

            dc.SelectObject(&br);

            // Получаем рект кнопки

            GetItemRect(i, rItem);

            // Рисуем рамку

            dc.Rectangle(rItem);

            // Рисуем иконку кнопки

            GetToolBarCtrl().GetImageList()->Draw(&dc, n, CPoint(x+2, 2), 0);

            x += BtnLenght;

            n++;

        }

        else if(!btn.fsStyle & TBSTYLE_SEP)//
Кнопка в обычном состоянии


        {

            GetToolBarCtrl().GetImageList()->Draw(&dc, n, CPoint(x+3, 3), 0);

            x += BtnLenght;

            n++;

        }

    }

    // Do not call CToolBarCtrl::OnPaint() for painting
messages


}



 

Так, сразу пока не отвлёкся - в класс надо добавить переменную:


class CToolBarXP
: public CToolBarCtrl

{

//***********************************************

protected:

    int m_nSelected;// Номер
кнопки под мышкой :-)


    //{{AFX_MSG(CToolBarXP)

    afx_msg void OnPaint();

    //}}AFX_MSG




    DECLARE_MESSAGE_MAP()

};



 

В конструкторе класса надо надо инициализировать сию переменную
числом -1.

Теперь добавляем через КлассВизард обработку перемещений мышкой:


void
CToolBarXP::OnMouseMove(UINT nFlags, CPoint point)

{

    CToolBar::OnMouseMove(nFlags, point);



    CRect rt;

    TBBUTTON btn;

    // Перебираем кнопки

    for(int i = 0; i
!= GetToolBarCtrl().GetButtonCount(); i++)

    {

        GetToolBarCtrl().GetButton(i, &btn);// Получаем
данные о кнопке


        GetItemRect(i, rt);// Получаем рект кнопки

        if(btn.fsStyle & TBSTYLE_SEP)
continue;// Сепараторы
пропускаем


        if(rt.PtInRect(point) && m_nSelected != i)//
Мышка над этой?


        {

            m_nSelected = i;// Сохраняем выделение

            Invalidate();// Перерисовываем

            SetTimer(11, 100, NULL);// Пускаем таймер

            return;

        }

    }

}



 

Так... Ну и, собственно таймер:


void
CToolBarXP::OnTimer(UINT nIDEvent)

{

    if(nIDEvent == 11)// На
всякий пожарный


    {

        // Так где же мышка ???

        CPoint p(GetMessagePos());

        ScreenToClient(&p);

        // Берём границы кнопки

        CRect rect;

        GetClientRect(rect);

        // Проверка на наличие внутри курсора

        if (!rect.PtInRect(p))

        {

            // Если мыши нет то оставляем слежение


            m_nSelected = -1;

            // И убиваем таймер ("А зачем нам кузнец? Нам
кузнец не нужен...") ;)


            KillTimer(11);

            // Не забыть перерисовать кнопку

            Invalidate();

        }

    }

}



 

Фу... Вроде всё. А! Теперь лезем в MainFrame.h и меняем тип
переменной m_wndToolBar с CToolBar на CToolBarXP, незабыв перед этим #include'ть
файл с нашим тулбаром. Теперь всё! Жмём F7, ждём пока проект скомпилируется и
F5. Лицезреем красочный тулбар.


ReBarXP

Так, тулбар есть. Далее - CReBarXP. Ну это вообще проще пареной репы: создаём
MFC проект с помеченной галочкой Internet Explorer ReBars. Добавляем новы класс
CReBarXP, наследованный от CReBar, перегружаем у него WM_PAINT и вписываем туда
вот что:


void
CReBarXP::OnPaint()

{

    CPaintDC dc(this); //
device context for painting




    // TODO: Add your message handler code here

    CRect rt, rBand;

    COLORREF face, shdw;

    BYTE r,g,b;

    // Цвета(идеинтично CToolBarXP)

    GetClientRect(rt);

    face = GetSysColor(COLOR_3DFACE);

    r = GetRValue(face)+10;

    g = GetGValue(face)+10;

    b = GetBValue(face)+10;

    face = PALETTERGB(r,g,b);



    shdw = GetSysColor(COLOR_3DSHADOW);

    r = GetRValue(shdw)+10;

    g = GetGValue(shdw)+10;

    b = GetBValue(shdw)+10;

    shdw = PALETTERGB(r,g,b);



    CPen pen;

    pen.CreatePen(0, 1, shdw);

    // Заливаем область

    dc.FillSolidRect(rt, face);

    dc.SelectObject(&pen);

    // Перебираем все бары

    for(UINT i = 0; i != GetReBarCtrl().GetBandCount();
i++)

    {

        GetReBarCtrl().GetRect(i, rBand);// Получаем рект

        for(int y = 4;
y != rBand.Height()-4; y+=2)// Ресуем симпатичную закраску

        {

            dc.MoveTo(rBand.left+3,rBand.top+y);

            dc.LineTo(rBand.left+6,rBand.top+y);

        }

    }

    // Do not call CReBar::OnPaint() for painting messages

}

 

Всё! Теперь только меняем тип ReBar на CReBarXP(обязательно
вставив перед объявлением класса include-команду).


StatusBarXP

Так, так... ToolBarXP и ReBarXP есть. Теперь StatusBar'ом займёмся. Проект
как создавать я писать не буду, сразу переходим к делу.

Добавляем новый класс CStatusBarXP, наследованный от CStatusBar. В нём
переопределяем OnPaint и пишим тудыва:


void
CStatusBarXP::OnPaint()

{

    CPaintDC dc(this); //
device context for painting




    CRect rt, rPane;

    COLORREF face, shdw;

    CString Text;

    CFont* Font;

    BYTE r,g,b;

    // Высчитываем цвета(большая часть кода:))

    GetClientRect(rt);



    face = GetSysColor(COLOR_3DFACE);

    r = GetRValue(face)-10;

    g = GetGValue(face)-10;

    b = GetBValue(face)-10;

    face = PALETTERGB(r,g,b);



    shdw = GetSysColor(COLOR_3DSHADOW);

    r = GetRValue(shdw)+10;

    g = GetGValue(shdw)+10;

    b = GetBValue(shdw)+10;

    shdw = PALETTERGB(r,g,b);



    CPen pen;

    CBrush br;

    pen.CreatePen(0, 1, shdw);

    br.CreateSolidBrush(face);

    Font = GetFont();



    dc.SelectObject(Font);

    dc.FillSolidRect(rt, face);

    dc.SelectObject(&pen);

    dc.SelectObject(&br);

    // А вот непосредственно рисование:

    for(int i = 0; i
!= GetCount(); i++)

    {// Перебираем все индикаторы

        GetStatusBarCtrl().GetRect(i, rPane);

        GetPaneText(i, Text);// Получаем текст

        rPane.bottom--;

        dc.Rectangle(rPane);// Рисуем рамку

        // И текст, если надо:

        if(GetPaneStyle(i)) dc.TextOut(rPane.left+3,
rPane.top+1, Text);

        rPane.top += 1;

        rPane.left += 3;

        rPane.right -= 1;

        if(GetPaneStyle(i)) dc.DrawText(Text, rPane,
0);

    }

}

 

Усё! Теперь только меняем тип переменной с CStatusBar на
CStatusBarXP и глядим. Вид, конечно, до первых двух классов не дотягивает, но...
"сойдёт для сельской местности".


Красивого вам программирования!

Архив примера лежит
здесь.


Автор: ManiaK
www.mnk.vitgroup.com

16.02.2006

Телефон

+7 8636 237-836

Поиск

VSESMI.ru — новости в СМИ.
Один из больших по объему информации проектов, работающих под управлением HostCMS.

Tur-Hotel.ru — отзывы об отелях
На сайте представлено описание отелей, рейтинг отелей с отзывами туристов.