打造自己的專業圖像工具-Visual C++ 2005圖像編程系列【五】(上)

2.1.2 字體設置工具欄

       在字體設置工具欄中也有一個靜態文本框和二個組合框,一個是字體大小的組合框,它可以用普通的CComboBox實現。字體名稱選擇組合框,如果考慮簡單一些的做法也可以用CComboBox,這種方法只是需要枚舉出系統的字體名稱就可以了。爲了使界面更加美觀和方便使用,我們這裏用了CComboBox的派生類,建立了一個更美觀、完善的字體選擇組合框,先看看效果:

圖2-2

這個組合框與普通的CComboBox有兩個區別:一個是下拉列表的寬度不是固定的,和本身的控件不一樣;另一個是每個字體名稱前有不同的圖標了,有的沒有圖標。下面將詳細介紹如何實現這個組合框。

首先我們需要定義一個工具類,用來保存系統字體信息,這個工具類包含有字體的名稱、字體類型、字體圖像索引。

class CFontInfo

{

public:

       CFontInfo(){}

       ~CFontInfo(){}

public:

       int           GetImage() const { return m_nImage; }

       void        SetImage(int nImage) { m_nImage = nImage; }

       CString   GetFontName() const { return m_szName ; }

       void        SetFontName(CString str) { m_szName = str; }

       int           GetFontType() const { return m_nFontType; }

       void        SetFontType(int Type) { m_nFontType = Type; }

private:

       CString   m_szName;

       int           m_nFontType;

       int           m_nImage;

};

       我先給出字體組合框的頭文件內容,然後介紹每個函數的作用:

class CFontComboBox : public CComboBox

{

public:

       CFontComboBox();

       virtual ~CFontComboBox();

       virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);

       virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);

void FillFontList();

       static int CALLBACK EnumFontProc(ENUMLOGFONTEX *lpelfe,

                                                                NEWTEXTMETRICEX *lpntme,

                                                                DWORD FontType,

                                                                LPARAM lParam);

       static bool CompareFontName(const CFontInfo *pInfo1, const CFontInfo *pInfo2);

       HBITMAP      m_FontBmp;

protected:

       afx_msg void OnDropdown();

       afx_msg void OnDestroy();

       DECLARE_MESSAGE_MAP()

public:

       std::vector<CFontInfo *>      m_pFontVec;

};

       CFontComboBox頭文件裏先用vector保存了一個字體工具類的列表,表示所有字體的信息,這裏採用vector是爲了方便用戶選擇某個字體後可以根據索引進行快速的隨機訪問,而list是不支持隨機訪問的。

       FillFontList函數是枚舉出系統的字體並添加到組合框。枚舉的時候需要定義回調函數,也就是我們在頭文件看到的EnumFontProc靜態函數。在枚舉出所有的字體後,我們再根據字體名稱進行排序,排序直接使用標準程序庫的sort算法,因爲排序的對象是CFontInfo,所以需要我們定義一個排序的比較函數:CompareFontName。函數的參數就是兩個CFontInfo對象。然後把排序後的字體名稱用AddString方法加入到組合框。在字體組合框名稱前面還有字體圖片,這個圖片是系統保存的,以ID=38保存在COMDLG32.DLL中,我們只需要加載到這個圖片,然後根據字體信息中圖片類型就可以畫出來。

void CFontComboBox::FillFontList()

{

       //根據桌面DC的屬性枚舉系統的字體信息

       CDC* pDesktopDC = GetDesktopWindow()->GetWindowDC();       //DC

       HDC hdc = pDesktopDC->GetSafeHdc();

       LOGFONT lf;

       ::ZeroMemory(&lf, sizeof(lf));

       lf.lfCharSet = DEFAULT_CHARSET;

       ::EnumFontFamilies(hdc,NULL, (FONTENUMPROC)EnumFontProc,(LPARAM)this);

       GetDesktopWindow()->ReleaseDC(pDesktopDC);      //釋放DC

       //運用STL算法進行自定義的對象排序

       std::sort(m_pFontVec.begin(), m_pFontVec.end(), CFontComboBox::CompareFontName);

       InitStorage(300, LF_FACESIZE);

       //加入字體名稱到組合框

       for(int N=0; N<m_pFontVec.size(); ++N)

              AddString(m_pFontVec[N]->GetFontName());

       //加載COMDLG32.DLL

       HMODULE hModule = ::LoadLibraryEx(_T("COMDLG32.DLL"), NULL,

 DONT_RESOLVE_DLL_REFERENCES);

       ASSERT (hModule != NULL);

       //加載成功後從這個DLL中加載字體圖片

       m_FontBmp = (HBITMAP)::LoadImage(hModule, MAKEINTRESOURCE(38),

IMAGE_BITMAP, 100, 24, LR_DEFAULTCOLOR);

       ASSERT(m_FontBmp != NULL);

       ::FreeLibrary(hModule);

}

       也許你已經注意到了加載DLLLoadLibraryEx函數,沒有直接用LoadLibrary。因爲它不能設置DONT_RESOLVE_DLL_REFERENCES參數,這個參數有什麼意義呢。根據DLL的結構,加載DLL時會調用DLLDllMain進行初始化,釋放的時候會調用DllMain進行釋放工作。而DONT_RESOLVE_DLL_REFERENCES參數就是不允許調用DllMain函數,我們這裏只是需要DLL中的一張圖片不需要任何的其他東西,所以傳遞這個參數能加快DLL的加載和釋放速度。避免不必要的資源消耗。 
發佈了77 篇原創文章 · 獲贊 0 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章