Notepad++源码剖析(四)

来源:互联网 发布:平安科技java面试题 编辑:程序博客网 时间:2024/05/22 17:17

这里说一下Notepad++在工具栏中显示图标的功能源码.与显示图标功能相关的类比较多,主要集中在ImageListSet.h/cpp, ToolBar.h/cpp这几个文件中.至于ToolBar中包含哪些图标由Notepad_plus.cpp部分代码定义.我们从基础开始先看看ImageListSet.h/cpp里面的内容,了解其底层的一些机制后.再说一下ToolBar.h/cpp的定义.然后就很容易看懂Notepad_plus.cpp中代码的意思了.

 

ImageListSet.h中首先定义了IconList类,源码如下

class IconList{public :IconList() : _hImglst(NULL) {};void create(HINSTANCE hInst, int iconSize) {_iconSize = iconSize;_hInst = hInst;InitCommonControls(); _hImglst = ImageList_Create(iconSize, iconSize, ILC_COLOR32 | ILC_MASK, 0, nbMax);if (!_hImglst)throw int(25);};void create(int iconSize, HINSTANCE hInst, int *iconIDArray, int iconIDArraySize) {create(hInst, iconSize);for (int i = 0 ; i < iconIDArraySize ; i++)addIcon(iconIDArray[i]);};void destroy() {ImageList_Destroy(_hImglst);};HIMAGELIST getHandle() const {return _hImglst;};void addIcon(int iconID) const {HICON hIcon = ::LoadIcon(_hInst, MAKEINTRESOURCE(iconID));//HBITMAP hBmp = (HBITMAP)::LoadImage(_hInst, MAKEINTRESOURCE(iconID), IMAGE_ICON, _iconSize, _iconSize, LR_LOADMAP3DCOLORS);if (!hIcon)throw int(26);ImageList_AddIcon(_hImglst, hIcon);//ImageList_AddMasked(_hImglst, (HBITMAP)hBmp, RGB(0, 0, 0));::DeleteObject(hIcon);//::DeleteObject(hBmp);};private :HIMAGELIST _hImglst;HINSTANCE _hInst;int _iconSize;};

这个类中主要定义了一下几个功能:

a. 首先定义了两个create函数,第一个create主要的功能为创建了image list对象,并将image list handle保存在类型为HIMAGELIST的_hImglit变量中,用_iconSize变量保存图标大小,_hInst保存传入的一个实例句柄.第二个create函数的主要的功能不经初始化IconList类中的三个私有变量(_hImglst, _hInst, _iconSize),而且用图标标号数组来往Image list对象中添加icon对象.这个工作有addIcon函数完成,不过值得注意的是LoadIcon函数,以及被作者注释掉的LoadImage函数.

b. 实现获取image list handle的函数,以及destory函数.

 

接下来定义了一个ToolButtonUnit结构体,咋一开始我还没有看懂他是什么意思,如果你也一时半会儿没有看懂什么意思,就先放着吧,看到后面就明白什么意思了.在这个结构体定义之后,定义了ToolBarIconIDs,IconListVector两个vector容器类型.

 

类IconLists的定义源码如下:

class IconLists{public :IconLists() {};HIMAGELIST getImageListHandle(int index) const {return _iconListVector[index].getHandle();};protected :IconListVector _iconListVector;};


这个IconLists类中主要定义了从_iconListVector容器对象中获取IconList对象的handle.

貌似前面几个类的定义不疼不痒,至少没有看到图片是怎么添加显示以及判断其状态的,下面就看看ToolBarIcons类的定义吧,

const int HLIST_DEFAULT = 0;const int HLIST_HOT = 1;const int HLIST_DISABLE = 2;class ToolBarIcons : public IconLists{public :ToolBarIcons() : _nbCmd(0) {};void init(ToolBarButtonUnit *buttonUnitArray, int arraySize);void create(HINSTANCE hInst, int iconSize);void destroy();HIMAGELIST getDefaultLst() const {return IconLists::getImageListHandle(HLIST_DEFAULT);};HIMAGELIST getHotLst() const {return IconLists::getImageListHandle(HLIST_HOT);};HIMAGELIST getDisableLst() const {return IconLists::getImageListHandle(HLIST_DISABLE);};int getNbCommand() const {return _nbCmd;};int getCommandAt(int index) const {return _cmdArray[index];};void resizeIcon(int size) {reInit(size);};void reInit(int size) {ImageList_SetIconSize(getDefaultLst(), size, size);ImageList_SetIconSize(getHotLst(), size, size);ImageList_SetIconSize(getDisableLst(), size, size);for (int i = 0 ; i < int(_tbiis.size()) ; i++){//_cmdArray[_nbCmd++] = _tbiis[i]._cmdID;if (_tbiis[i]._defaultIcon != -1){_iconListVector[HLIST_DEFAULT].addIcon(_tbiis[i]._defaultIcon);_iconListVector[HLIST_HOT].addIcon(_tbiis[i]._hotIcon);_iconListVector[HLIST_DISABLE].addIcon(_tbiis[i]._grayIcon);}}};private :ToolBarIconIDs _tbiis;int _cmdArray[nbMax];int _nbCmd;};


 

ToolBarIcons类继承了IconLists类,然后对IconLists类得getImageListHandle函数进行了封装,得到了getDefaultLst(), getHotList(), getDisableLst()函数, reInit()函数作用是设置了Image list中所有图标的大小后,往_iconListVector对象中添加图标.其他几个函数意图应该比较明显看出了.

 

下面我们就看看ToolBar.h/cpp中对我们的工具栏的功能是怎样定义和实现的.

#include <commctrl.h>#include "ImageListSet.h"const bool REDUCED = true;const bool ENLARGED = false;class ToolBar : public Window{public :ToolBar():Window(),/*_pToolBarIcons(NULL),*/ _pTBB(NULL){};virtual ~ToolBar(){};//virtual bool init(HINSTANCE hInst, HWND hPere, ToolBarIcons *pToolBarIcons);virtual bool init(HINSTANCE hInst, HWND hPere, int iconSize, ToolBarButtonUnit *buttonUnitArray, int arraySize);virtual void destroy() {delete [] _pTBB;::DestroyWindow(_hSelf);_hSelf = NULL;_toolBarIcons.destroy();};void enable(int cmdID, bool doEnable) {::SendMessage(_hSelf, TB_ENABLEBUTTON, cmdID, (LPARAM)doEnable);};int getHeight() const {if (!::IsWindowVisible(_hSelf))return 0;return Window::getHeight();};void reduce() {if (_state == REDUCED)return;_toolBarIcons.resizeIcon(16);reset();Window::redraw();_state = REDUCED;};void enlarge() {if (_state == ENLARGED)return;_toolBarIcons.resizeIcon(32);reset();Window::redraw();_state = ENLARGED;};bool getCheckState(int ID2Check) const {return bool(::SendMessage(_hSelf, TB_GETSTATE, (WPARAM)ID2Check, 0) & TBSTATE_CHECKED);};void setCheck(int ID2Check, bool willBeChecked) const {::SendMessage(_hSelf, TB_CHECKBUTTON, (WPARAM)ID2Check, (LPARAM)MAKELONG(willBeChecked, 0));};private :TBBUTTON *_pTBB;//ToolBarIcons *_pToolBarIcons;ToolBarIcons _toolBarIcons;bool _state;void setDefaultImageList() {::SendMessage(_hSelf, TB_SETIMAGELIST , (WPARAM)0, (LPARAM)_toolBarIcons.getDefaultLst());};void setHotImageList() {::SendMessage(_hSelf, TB_SETHOTIMAGELIST , (WPARAM)0, (LPARAM)_toolBarIcons.getHotLst());};void setDisableImageList() {::SendMessage(_hSelf, TB_SETDISABLEDIMAGELIST, (WPARAM)0, (LPARAM)_toolBarIcons.getDisableLst());};/*void setButtonSizeByDefault() {::SendMessage(_hSelf, TB_SETBUTTONSIZE , (WPARAM)0, (LPARAM)MAKELONG (w, h));};void removeAllButton() {int nCount = SendMessage(_hSelf, TB_BUTTONCOUNT, 0, 0);for (int i = nCount ; i >= 0 ; i--)::SendMessage(_hSelf, TB_DELETEBUTTON, (WPARAM)i, (LPARAM)0);};*/void setButtonSize(int w, int h) {::SendMessage(_hSelf, TB_SETBUTTONSIZE , (WPARAM)0, (LPARAM)MAKELONG (w, h));};void reset() {setDefaultImageList();setHotImageList();setDisableImageList();::SendMessage(_hSelf, TB_AUTOSIZE, 0, 0);};};


a. 首先说一下setDefaultImageList(), setHotImageList(), setDisableImageList()这三个函数,这三个函数是将不同的Image list 给了三种情况.至于这三种情况是什么,是这样的.

  TB_SETIMAGELIST:设置工具按扭默认状态下的图形
   wParam = 0;
   lParam = (LPARAM)(HIMAGELIST) himlNew;
  TB_SETHOTIMAGELIST:设置工具按扭取得热点后的图形
   wParam = 0;
   lParam = (LPARAM)(HIMAGELIST) himlNewHot;
  TB_SETDISABLEDIMAGELIST:设置工具按扭无效时的图形
   wParam = 0;
   lParam = (LPARAM)(HIMAGELIST) himlNewDisabled;(摘自 http://www.wangchao.net.cn/bbsdetail_26458.html)

b. 在init()函数中,根据ToolBarButtonUnit *buttonUnitArray,来初始化TBBUTTON* _pTBB对象,然后通过::SendMessage(_hSelf, TB_ADDBUTTONS, (WPARAM)nbElement, (LPARAM)_pTBB); 表示将与Icon图标相关联的cmd(这个cmd由对应着TBUTTON中的idCommand).

c. 剩下的enable()控制着工具栏上的按钮是否处于激活状态,剩下的几个函数的逻辑就比较好理解了

 

虽然ToolBar的是实现已经说完了,但是Notepad++是怎么显示这些具体的图标还是没有说清楚,我们知道用一个ToolBarButtonUnit *buttonUnitArray对象就可以实现Toolbar了,具体ToolBarButtonUnit的结构我们在前文掠过了.这里我们对比一下NotePad_plus.cpp以及ToolBarButtonUnit的定义.来看看里面的蹊跷.

ToolBarButtonUnit toolBarIcons[] = {{IDM_FILE_NEW,IDI_NEW_OFF_ICON,IDI_NEW_ON_ICON,IDI_NEW_OFF_ICON},{IDM_FILE_OPEN,IDI_OPEN_OFF_ICON,IDI_OPEN_ON_ICON,IDI_NEW_OFF_ICON},{IDM_FILE_SAVE,IDI_SAVE_OFF_ICON,IDI_SAVE_ON_ICON,IDI_SAVE_DISABLE_ICON},{IDM_FILE_SAVEALL,IDI_SAVEALL_OFF_ICON,IDI_SAVEALL_ON_ICON,IDI_SAVEALL_DISABLE_ICON},{IDM_FILE_CLOSE,IDI_CLOSE_OFF_ICON,IDI_CLOSE_ON_ICON,IDI_CLOSE_OFF_ICON},{IDM_FILE_CLOSEALL,IDI_CLOSEALL_OFF_ICON,IDI_CLOSEALL_ON_ICON,IDI_CLOSEALL_OFF_ICON}, //-------------------------------------------------------------------------------------//{0,IDI_SEPARATOR_ICON,IDI_SEPARATOR_ICON,IDI_SEPARATOR_ICON},//-------------------------------------------------------------------------------------//


 

typedef struct {int _cmdID;int _defaultIcon;int _hotIcon;int _grayIcon;}ToolBarButtonUnit;


这里我们知道了原来_cmdID定义了按钮的ID,而按钮的Icon图标由_defaultIcon,_hotIcon,_grayIcon来制定.

 

ToolBar中按钮的响应函数如果对Notepad_plus.cpp的源码仔细看看的话,就会发现Notefiy,Command消息响应函数中,case ID,均是_cmdID.

 

呵呵~~现在我们应该明白了ToolBar从定义,到响应的一系列动作了吧.好吧就写到这里吧.

原创粉丝点击