类似 MSN 带转义字符的信息发送框的制作(下)

王朝vc·作者佚名  2006-01-17
窄屏简体版  字體: |||超大  

类似 MSN 带转义字符的信息发送框的制作(下)

作者:北方工业大学 阙荣文 (querw)

下载源代码

一、实现了上回说到的多功能文本框之后,接下去的任务就是做一个表情符号选择器。CIconPicker。

说明:本来是想实现图标选择的,但是后来有需要改成了位图选择器,但是类名没有改过来,还是叫 CIconPicker。附带工程中有图标选择器。

二、图标/位图选择器(以下简称选择器)的实现原理

当用户按下选择器的时候,应该把所有的图像用一个图片列表显示出来;如果用户选择了其中一个图片,则记录该图片的编号,并把图片列表关闭。如果用户没有选择图片

,那么直接把图片列表关闭 ( 响应

WM_KILLFOCUS 消息 )。

首先,从 CButton 派生一个类 CIconPicker 。给它增加一些成员用来实现"选择器"的功能。如下所述:

1、图片列表:CArray 存放所有下拉图片,每个图片都有一个编号,即它在图片数组中的序号

2、GetBitmapAt():顾名思义,按序号获取图片

3、AddBitmap():添加一张图片

4、GetCurrentBitmapIndex():返回选中图片的序号

当 CIconPicker 收到 WM_LBUTTONDOWN 消息时先不忙给父窗体发送 WM_COMMAND消息

,而是创建一个图片列表CIconContainer(容器),然后在容器上面创建和图片数量一样多的按钮,每个按钮显示一张图片。当然,为了

实现这个功能还得从CButton再派生一个类CInnerButton用来显示图片,感应鼠标事件。

三、源代码说明

1、创建容器

void CIconPicker::OnLButtonDown(UINT nFlags, CPoint point)

{

if(m_bState) return ;

m_bState=TRUE;

this-SetState(TRUE);

RECT rect;

this-GetWindowRect(&rect);

POINT pt;

pt。x=rect。left;pt。y=rect。bottom;

//创建一个图片列表容器

m_pIconContainer=new CIconContainer;

///把图片数组当作参数传过去

if(m_pIconContainer-Create(pt,this,&m_BitmapArray))

{

m_pIconContainer-ShowWindow(SW_SHOW);

m_pIconContainer-UpdateWindow();

m_pIconContainer-SetFocus();

}

}

2、为每一张图片在容器内创建一个按钮CInnerButton。我把这个工作交给容器来完成。重载容器(CIconContainer)的Create()函数,如下:

BOOL CIconContainer::Create(POINT pt,CButton* pParentButton,CArray *pBitmapArray)

{

if(pBitmapArray-GetSize()<=0)return FALSE;

m_pParentButton=pParentButton;

///根据每张图片的大小创建IconContainer

m_nCol=int(sqrt(pBitmapArray-GetSize()))+1; //计算列数

BITMAP bm;

pBitmapArray-GetAt(0)-GetBitmap(&bm); //以图片列表中的第0号图片的大小为

基准

m_nCellWidth=bm。bmWidth+4; //内部单元的宽度

m_nCellHeight=bm。bmHeight+4; //内部单元的高度

CRect rect;

rect。left=pt。x,rect。top=pt。y;

rect。right=pt。x+m_nCellWidth*m_nCol; //容器的宽度

if(pBitmapArray-GetSize()%m_nCol==0) //计算行数

{

m_nRow=pBitmapArray-GetSize()/m_nCol;

}

else

{

m_nRow=pBitmapArray-GetSize()/m_nCol+1;

}

rect。bottom=pt。y+m_nCellHeight*m_nRow+2+46; ///容器的高度=(行数+2)*单元宽度

//pParentButton-GetParent()-ScreenToClient(&rect);

///创建容器

//CWnd::Create(NULL, NULL, WS_VISIBLE | WS_CHILD,

//rect,pParentButton-GetParent(),IDC_ICONCONTAINER, NULL);

CWnd::CreateEx(WS_EX_LEFT,AfxRegisterWndClass(0),NULL,WS_VISIBLE|WS_POPUP,rect,NULL,NULL );

///创建图片张数+2个按钮

for(int i=0;i<m_nRow;i++)

{

for(int j=0;j<m_nCol&& i*m_nCol+j<pBitmapArray-GetSize();j++)

{

///计算按钮的位置

CRect innerrect;

innerrect。left=j*m_nCellWidth;

innerrect。top=i*m_nCellHeight;

innerrect。right=innerrect。left+m_nCellWidth;

innerrect。bottom=innerrect。top+m_nCellHeight;

innerrect。DeflateRect(2,2);

///新建按钮

CInnerButton *pInnerButton;

pInnerButton=new CInnerButton;

pInnerButton-Create(NULL,WS_CHILD |WS_VISIBLE,

innerrect,this,IDC_INNERBUTTON+i*m_nCol+j);

///设置按钮的图标

pInnerButton-SetBitmap(pBitmapArray-GetAt(i*m_nCol+j));

pInnerButton-ShowWindow(SW_SHOW);

///记录该按钮的指针

m_InnerButtonArray。Add(pInnerButton);

}

}

////创建两个扩展功能按钮

this-GetClientRect(&rect);

CInnerButton *pInnerButton;

pInnerButton=new CInnerButton;

rect。left=2;

rect。right-=2;

rect。top=m_nRow*m_nCellHeight+3;

rect。bottom=rect。top+20; //按钮的高度为22

pInnerButton-Create(NULL,WS_CHILD |WS_VISIBLE,

rect,this,IDC_INNERBUTTON-1);

pInnerButton-SetFont(m_pParentButton-GetParent()-GetFont());

pInnerButton-SetWindowText("显示更多的图释");

pInnerButton=new CInnerButton;

rect。top=rect。bottom+3;

rect。bottom=rect。top+20;

pInnerButton-Create(NULL,WS_CHILD |WS_VISIBLE,

rect,this,IDC_INNERBUTTON-2);

pInnerButton-SetWindowText("我的自定义图释");

pInnerButton-SetFont(m_pParentButton-GetParent()-GetFont());

return TRUE;

}

当用户单击了其中的一个按钮时,把序号记录下来(可以根据InnerButton的ID,创建的时候ID是递增的)并给父窗体(CIconPicker)发送一个消息,把序号送过去。BOOL CIconContainer::OnCommand(WPARAM wParam, LPARAM lParam)

{

if(LOWORD(wParam)-IDC_INNERBUTTON==-1)

{

////在这里响应"显示更多的图释"

}

if(LOWORD(wParam)-IDC_INNERBUTTON==-2)

{

////在这里响应"我的自定义图释"

CFileDialog SelectFileDlg(TRUE,"bmp","noname",OFN_FILEMUSTEXIST,

"Bitmap File(*。bmp)|*。bmp",m_pParentButton);

if(SelectFileDlg。DoModal()==IDOK)

{

((CIconPicker*)m_pParentButton)-AddBitmap(SelectFileDlg。GetPathName());

}

}

///关闭本窗口

Close(LOWORD(wParam)-IDC_INNERBUTTON); ///在这里根据ID取得序号

///消息发送的语句在Close()中

return TRUE;

}

这样容器的任务就完成了。如何显示图片那是内部按钮(CInnerButton)的事。

3、实现内部按钮(CInnerButton)

只是一个自画按钮而已,感应鼠标事件,自画,贴图等等都是老生常谈了。我就不一一赘述了。若有疑问请看本文附

带的源代码。最后的效果如下图所示:

这样,一个图标/图片选择器就基本完成了。呵呵,由于水平有限再加上时间仓卒,功能还很不完善,代码也乱七八糟,大家别用鸡蛋砸我,鸡蛋用来砸我多可惜啊(要砸也别砸脸,砸我邮箱

:querw@sina.com :)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
© 2005- 王朝網路 版權所有 導航