Как избавиться от 16-ти цветов в панели инструментов ?
В главном окне любого современного профессионально написанного приложения имеется как минимум два дополнительных инструмента, значительно облегчающих работу, - это панель инструментов (Toolbar) и строка состояния (Statusbar). Но нас интересует только первое панель инструментов. С появлением Microsoft Windows 95\98 большинство приложений использовали 16-ти цветные битмапы в панелях инструментов, но с приходом Microsoft Windows 2000\XP всё изменилось и приложения стали использовать 256 и больше цветов в битмапах. Ну, а мы чем хуже !
Но есть небольшая проблема, редактор панелей инструментов в Visual Studio не поддерживает больше 16 цветов :( ! Так что придётся всё делать ручками ! Битмап с изображением панели инструментов придётся рисовать самому в каком-нибудь графическом редакторе, например в Adobe Photoshop. Да, фон этого битмапа должен быть следующего цвета : RGB (192,192,192). Панель инструментов придётся прописывать в ручную в файле ресурсов (*.rc), например :
IDR_MAINFRAME TOOLBAR 16,16 BEGIN BUTTON ID_FILE_NEW BUTTON ID_FILE_OPEN BUTTON ID_FILE_SAVE SEPARATOR BUTTON ID_EDIT_CUT BUTTON ID_EDIT_COPY BUTTON ID_EDIT_PASTE SEPARATOR BUTTON ID_FILE_PRINT BUTTON ID_APP_ABOUT END
После загрузки панели инструментов функцией CToolBar::LoadToolBar, Вам придётся загрузить в ручную битмап панели инструментов с помощью LoadImage образом :
HBITMAP hBitmap=(HBITMAP)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(nIDResource), IMAGE_BITMAP, 0, 0,LR_CREATEDIBSECTION|LR_LOADMAP3DCOLORS);
После создать два обьекта CBitmap и присоединить к ним hBitmap :
CBitmap BitmapNormal; CBitmap BitmapDisabled; if (!BitmapNormal.Attach(hBitmap)) { TRACE("Can't attach BitmapNormal !\n"); return false; } if (!BitmapDisabled.Attach(hBitmap)) { TRACE("Can't attach BitmapDisabled !\n"); return false; }
А зачем BitmapDisabled спросите Вы ?
Кнопки панели инструментов иногда бывают заблокированы, например когда у кнопки нет обработчика, нет конечно можно самому нарисовать Disabled Bitmap, но согласитесь тратить время когда все можно сделать программно. Да, но перед тем как что-то делать, с этими битмапами необходимо заменить их фон RGB(192.192.192) на фон который можно получить с помощью функции ::GetSysColor(COLOR_BTNFACE). Далее создать два объекта типа CImageList, добавим с помощью функции int Add(CBitmap* pbmImage, CBitmap* pbmMask) наши битмапы (BitmapNormal и BitmapDisabled), причём вторым параметром будем передавать reinterpret_cast<CBitmap*>(NULL). Для того чтобы закончить нашу работу по созданию панели инструментов нам необходимо добавить наши image list's, созданные выше, к панели инструментов. Для того чтобы добавить эти необходимо воспользоваться функцией GetToolBarCtrl() которая вернёт ссылку на объект класса CToolBarCtrl. У данного класса (CToolBarCtrl) есть две функции:
CImageList* SetImageList(CImageList* pImageList); CImageList* SetDisabledImageList(CImageList* pImageList); Вот ими-то мы и воспользуемся : GetToolBarCtrl().SetImageList(&m_NormalImageList); GetToolBarCtrl().SetDisabledImageList(&m_DisabledImageList);
Всё наша панель инструментов готова !
Ну и в завершении данной стать я приведу полный текст класса которой в краткой форме описал выше :
AdvToolBar.h #pragma once // CAdvToolBar #ifndef ADVTOOLBAR_H #define ADVTOOLBAR_H class CAdvToolBar : public CToolBar { DECLARE_DYNAMIC(CAdvToolBar) public: enum { ADVT_COLOR_256=0, ADVT_COLOR_TRUE }; CAdvToolBar(); virtual~CAdvToolBar(); // Создаёт панель инструментов и присоединяет к ней необходимые ресурсы bool CreateAdvToolBar(CWnd* pParentWnd,UINT nIDResource, const int nColorType=CAdvToolBar::ADVT_COLOR_256, DWORD dwCtrlStyle = TBSTYLE_FLAT,DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP); CImageList* GetNormalImageList() { return reinterpret_cast<CImageList*>(&m_NormalImageList); } CImageList* DisabledImageList() { return reinterpret_cast<CImageList*>(&m_DisabledImageList); } private : COLORREF LightenColor(COLORREF color,COLORREF color2); void GetDisabledBitmap(CBitmap &Bitmap); void ReplaceBackgroundColor(CBitmap& Bitmap); CImageList m_NormalImageList; CImageList m_DisabledImageList; DECLARE_MESSAGE_MAP() }; #endif //ADVTOOLBAR_H AdvToolBar.cpp #include "stdafx.h" #include "ToolBar.h" #include "AdvToolBar.h" #include <AfxPriv.h> //для ASSERT_VALID_IDR // CAdvToolBar IMPLEMENT_DYNAMIC(CAdvToolBar, CToolBar) CAdvToolBar::CAdvToolBar() {} CAdvToolBar::~CAdvToolBar() {} BEGIN_MESSAGE_MAP(CAdvToolBar, CToolBar) END_MESSAGE_MAP() bool CAdvToolBar::CreateAdvToolBar(CWnd* pParentWnd, UINT nIDResource, const int nColorType/*=CAdvToolBar::ADVT_COLOR_256*/, DWORD dwCtrlStyle/* = TBSTYLE_FLAT*/, DWORD dwStyle/* = WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP*/) { ASSERT(pParentWnd); ASSERT_VALID_IDR(nIDResource); if(!CToolBar::CreateEx(pParentWnd,dwCtrlStyle,dwStyle,CRect(0,0,0,0), nIDResource)) { TRACE("Can't create tolbar %d !\n",nIDResource); return false; } if(!CToolBar::LoadToolBar(nIDResource)) { TRACE("Can't load tool bar %d !",nIDResource); return false; } SendMessage(TB_SETEXTENDEDSTYLE,0,TBSTYLE_EX_DRAWDDARROWS); HBITMAP hBitmap=(HBITMAP)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(nIDResource), IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_LOADMAP3DCOLORS); if(!hBitmap) { TRACE("Can't load image tool bar from bitmap !\n"); return false; } CBitmap BitmapNormal; CBitmap BitmapDisabled; if(!BitmapNormal.Attach(hBitmap)) { TRACE("Can't attach BitmapNormal !\n"); return false; } if(!BitmapDisabled.Attach(hBitmap)) { TRACE("Can't attach BitmapDisabled !\n"); return false; } ReplaceBackgroundColor(BitmapNormal); ReplaceBackgroundColor(BitmapDisabled); UINT uImagesListsFlag=0; switch(nColorType) { case 0: uImagesListsFlag|=ILC_COLOR8; break; case 1: uImagesListsFlag|=ILC_COLOR24; break; default: ASSERT(FALSE); } m_NormalImageList.DeleteImageList(); if(!m_NormalImageList.Create(16,16,uImagesListsFlag,0,0)) { TRACE("Can't create m_NormalImageList !\n"); return false; } m_DisabledImageList.DeleteImageList(); if(!m_DisabledImageList.Create(16,16,uImagesListsFlag,0,0)) { TRACE("Can't create m_DisabledImageList !\n"); return false; } m_NormalImageList.Add(&BitmapNormal,reinterpret_cast<CBitmap*>(NULL)); GetToolBarCtrl().SetImageList(&m_NormalImageList); GetDisabledBitmap(BitmapDisabled); m_DisabledImageList.Add(&BitmapDisabled,reinterpret_cast<CBitmap*>(NULL)); GetToolBarCtrl().SetDisabledImageList(&m_DisabledImageList); SetSizes(CSize(23,23),CSize(16,16)); CString strTitle; if(strTitle.LoadString(nIDResource)) SetWindowText(strTitle); return true; } COLORREF CAdvToolBar::LightenColor(COLORREF color,COLORREF color2) { BYTE r=0; BYTE g=0; BYTE b=0; int avgcol=0; double factor=0; r = GetRValue(color2); g = GetGValue(color2); b = GetBValue(color2); avgcol = (r+g+b)/3; factor = avgcol/255.0; if(factor>0.0 && factor<=1.0) { BYTE red,green,blue,lightred,lightgreen,lightblue; red = GetRValue(color); green = GetGValue(color); blue = GetBValue(color); lightred = (BYTE)((factor*(255-red)) + red); lightgreen = (BYTE)((factor*(255-green)) + green); lightblue = (BYTE)((factor*(255-blue)) + blue); color = RGB(lightred,lightgreen,lightblue); } return color; } void CAdvToolBar::GetDisabledBitmap(CBitmap& Bitmap) { CDC dc; COLORREF bgcolor,color,disabledcolor; BITMAP BitMap; Bitmap.GetBitmap(&BitMap); dc.CreateCompatibleDC(NULL); CBitmap * pdcOldBmp = dc.SelectObject(&Bitmap); CDC dc2; CBrush brush; CBitmap Bitmap2; dc2.CreateCompatibleDC(NULL); Bitmap2.CreateCompatibleBitmap(&dc,BitMap.bmWidth,BitMap.bmHeight); color=GetSysColor(COLOR_3DFACE); brush.CreateSolidBrush(color); CBitmap * pdcOldBmp2 = dc2.SelectObject(&Bitmap2); CRect rect(0,0,BitMap.bmWidth,BitMap.bmHeight); dc2.FillRect(rect,&brush); bgcolor=dc2.GetPixel(1,1); brush.DeleteObject(); dc2.SelectObject(pdcOldBmp2); disabledcolor=GetSysColor(COLOR_BTNSHADOW); for(int i=0;i<BitMap.bmWidth;i++) { for(int j=0;j<BitMap.bmHeight;j++) { color=dc.GetPixel(i,j); if(color!=bgcolor) { dc.SetPixel(i,j,LightenColor(disabledcolor,color)); } } } dc.SelectObject(pdcOldBmp); } void CAdvToolBar::ReplaceBackgroundColor (CBitmap& Bitmap) { CDC dc; COLORREF bgcolor,color,NormalColor; bgcolor=RGB(192,192,192); NormalColor=::GetSysColor(COLOR_BTNFACE); BITMAP BitMap; Bitmap.GetBitmap(&BitMap); dc.CreateCompatibleDC(NULL); CBitmap * pdcOldBmp = dc.SelectObject(&Bitmap); for(int i=0;i<BitMap.bmWidth;i++) { for(int j=0;j<BitMap.bmHeight;j++) { color=dc.GetPixel(i,j); if(color==bgcolor) { dc.SetPixel(i,j,NormalColor); } } } dc.SelectObject(pdcOldBmp); }
P.S. Напоследок небольшая программа, демонстрирующая работу данного класса. Загрузить (48 КБ)