程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 類似MSN帶轉義字符的信息發送框的制作(下)

類似MSN帶轉義字符的信息發送框的制作(下)

編輯:關於VC++

一、實現了上回說到的多功能文本框之後,接下去的任務就是做一個表情符號選擇器。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);
          
           ///設置按鈕的圖標 本文發表於http://bianceng.cn(編程入門網)
           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)

    只是一個自畫按鈕而已,感應鼠標事件,自畫,貼圖等等都是老生常談了。我就不一一贅述了。若有疑問請看本文附

    帶的源代碼。最後的效果如下圖所示:

    這樣,一個圖標/圖片選擇器就基本完成了。呵呵,由於水平有限再加上時間倉卒,功能還很不完善,代碼也亂七八糟,大家別用雞蛋砸我,雞蛋用來砸我多可惜啊(要砸也別砸臉,砸我郵箱 :[email protected] :)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved