windows開發(fā)記事本程序紀(jì)實(二)邏輯篇1
1. 主要內(nèi)容
從本節(jié)開始介紹windows開發(fā)實現(xiàn)記事本程序的邏輯實現(xiàn)部分。本節(jié)的主要內(nèi)容有以下3點:
1. 主窗口定義 —— 主要介紹記事本主界面窗口對應(yīng)的窗口類及實現(xiàn)方案
2. RichEdit控件的選用及初始化 —— 記事本程序中編輯控件的選擇及使用
3. 整個程序ICON的選擇?!?程序ICON設(shè)置
2. 實際開發(fā)
2.1 主窗口實現(xiàn)
在上一篇介紹界面的實現(xiàn)中只是給出了運行界面的效果,但是當(dāng)時那個界面程序不能響應(yīng)任何的windows消息,因為當(dāng)時的窗口在創(chuàng)建時將窗口對應(yīng)的過程處理函數(shù)設(shè)置為NULL。現(xiàn)在,我們需要將相應(yīng)的過程處理函數(shù)添加上使得這個記事本應(yīng)用程序可以響應(yīng)我們發(fā)出的一系類操作指令。為此,本文在開發(fā)時,單獨設(shè)計了一個用于保存主界面窗口的類CMainWnd。這個類定義了整個窗口的過程處理函數(shù)Main_Porc。在Main_Proc中可以對傳入的任何消息進(jìn)行處理(包括初始化窗口消息,窗口中其他控件的消息,關(guān)閉窗口消息等等)。以windows 自帶記事本為例,如圖1所示
圖1 windows主窗口消息效應(yīng)區(qū)域
如上圖所示,在windows記事本主界面中,需要響應(yīng)紅色矩形區(qū)域內(nèi)的菜單控件的各類消息、響應(yīng)黃色矩形區(qū)域內(nèi)系統(tǒng)按鈕的相關(guān)消息,以及相應(yīng)編輯控件Edit中的消息。對于主窗口中的各類控件的消息,windows會以WM_COMMAND消息進(jìn)行傳輸,這也是整個程序的核心處理區(qū)域。系統(tǒng)按鈕關(guān)閉的消息則是WM_CLOSE。窗口初始化消息WM_INITDIALOG則是構(gòu)建對話框窗口前發(fā)出的初始化消息。為了能夠響應(yīng)上述各類消息,需要在CMainWnd中添加對于這幾類消息的響應(yīng)函數(shù),因此整個CMainWnd的基本實現(xiàn)形式如下:
頭文件聲明:
/************************************************************************/ /* file : CMainWnd.h * author : Huagang Li * date : 2014-8-30 15:29:42 * blogs : http://www.cnblogs.com/lhglihuagang/ * tips : 主窗口實現(xiàn)類, 實現(xiàn)窗口的過程函數(shù),消息響應(yīng)函數(shù)等 */ /************************************************************************/ #ifndef _MAIN_WND_H #define _MAIN_WND_H #include <Windows.h> ////////////////////////////////////////////////////////////////////////// // CMainWnd 主窗口類,提供 class CMainWnd { public: static BOOL WINAPI Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static BOOL Main_OnInitDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam); static void Main_OnCommand(HWND hWnd, int id, HWND hWndCtl, LPARAM lParam); static void Main_OnClose(HWND hWnd); private: static HWND hMainWnd; // 主窗口句柄 }; #endif
CMainWnd具體定義:
#include "MainWnd.h" include <WindowsX.h> ////////////////////////////////////////////////////////////////////////// // static data members HWND CMainWnd::hMainWnd = NULL; ////////////////////////////////////////////////////////////////////////// // static function members // 主窗口的過程函數(shù),根據(jù)消息類型處理各類消息 BOOL WINAPI CMainWnd::Main_Proc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch (uMsg) { HANDLE_MSG(hWnd, WM_INITDIALOG, Main_OnInitDialog); HANDLE_MSG(hWnd, WM_COMMAND, Main_OnCommand); HANDLE_MSG(hWnd, WM_CLOSE, Main_OnClose); } </span><span style="color: #0000ff">return</span><span style="color: #000000"> FALSE; } BOOL CMainWnd::Main_OnInitDialog( HWND hWnd, HWND hWndFocus, LPARAM lParam ) { return TRUE; } // id為具體空間的ID號,可以在resource中定義有意義的控件ID,如“打開文件”可以設(shè)置 // 為ID_FILE_OPEN void CMainWnd::Main_OnCommand( HWND hWnd, int id, HWND hWndCtl, LPARAM lParam ) { switch (id) { // } } void CMainWnd::Main_OnClose( HWND hWnd ) { ::EndDialog(hWnd, NULL); }
在定義了CMainWnd后,在main函數(shù)處的DialogBox處添加主窗口的過程處理函數(shù)
::DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, CMainWnd::Main_Proc);
完成上述步驟運行后,就可以看到啟動后的主界面可以響應(yīng)窗口上系統(tǒng)按鈕“關(guān)閉”,但是對于菜單控件的消息,因為消息響應(yīng)此還是函數(shù)中數(shù)什么都沒有做,因此還是不會進(jìn)行任何處理。
2.2 RichEdit控件的選用
對于一個記事本程序來說,主界面上核心區(qū)域還是編輯區(qū)域。但是當(dāng)前記事本程序中還沒有選擇任何編輯控件。通過觀察現(xiàn)有windows控件列表可以看出,適合編輯控件的有Edit Control以及Rich Edit2.0 Control。對于這兩種編輯控件,Edit Control較為簡單,但是響應(yīng)的功能也較少。Rich Edit2.0 Control實現(xiàn)起來較為復(fù)雜,但是對應(yīng)的功能也多了不少(例如可以改變字體顏色,字號等等)。本文希望能夠?qū)崿F(xiàn)一個功能較強的記事本,因此選擇了Rich Edit2.0 Control進(jìn)行后續(xù)開發(fā)。插入了Rich Edit2.0 Control后,主界面窗口對應(yīng)的資源視圖如圖2所示:
圖2 IDD_MAIN中插入Rich Edit2.0 Control
上述步驟運行后,本以為可以看到帶有編輯界面的記事本程序,可是實際上程序運行后沒有任何效果,甚至主界面都不能正常啟動了。百度后發(fā)現(xiàn),對于richedit啟動失敗的方法都是針對MFC程序來說的,需要添加初始化函數(shù)AfxInitRichEdit2。但是現(xiàn)在使用windows API 開發(fā),并沒有AfxInitRichEdit2這個函數(shù),只能另尋他路了。終于在一篇博文中http://blog.csdn.net/dijkstar/article/details/7953816提到,原來上面那個初始化函數(shù)中主要是加載RichEdit依賴的dll,那么整個問題就豁然開朗了,我們只需要在主窗口啟動前手動的載入這個dll就可以了。因此在主函數(shù)的DialogBox前添加了依據(jù)載入dll的操作如下:
::LoadLibrary(T("riched20.dll"));
MAIN的properties中:
此時再運行程序時,可以正常啟動記事本了,且能夠在richedit中進(jìn)行編輯,效果如圖3所示:
圖3 手動加載Riched20.dll后出現(xiàn)主界面窗口
在啟動主界面后,可以正常進(jìn)行編輯。貌似這個控件可以正常工作了。但在實際測試時,發(fā)現(xiàn)了以下幾個問題:
1. 界面運行后RichEdit邊框棱角過于分明
處理方法: Richedit控件的properties -> Boarder –> Flase
2.輸入Enter 不能換行(手動輸入時一直在同一行編輯)
處理方法: Richedit控件的properties -> Multiline–> True
Richedit控件的properties -> Want Return–> True
3. 沒有滾動條(橫向以及縱向的)
這個在主界面屬性上,IDD
處理方法: IDD_MAIN-> properties -> Horizontal Scrollbar–> True
IDD_MAIN –> properties -> Vertical Scrollbar–> True
4. 不能隨窗口大小伸縮
在對窗口進(jìn)行伸縮時,RichEdit控件的大小還是保持原來的大小,如圖4所示:
圖4 主界面大小變化時RichEdit控件大小不變
這個問題其實很好理解,因為伸縮主界面窗口時,windows將發(fā)送WM_SIZE消息通知窗口。這個過程類似于windows對主界面窗口說“hi, 你的大小已經(jīng)變了,你根據(jù)改變后的大小變一下”。現(xiàn)在我們的主窗口過程處理函數(shù)中并沒有針對WM_SIZE消息對RichEdit進(jìn)行特殊處理,因此主界面下面的RichEdit一直保持自己原來的大小,才會出現(xiàn)上面的情況。那么具體的解決方案為:在InitDialog中添加RichEdit大小自適應(yīng)功能,同時針對WM_SIZE消息,添加Main_OnSize函數(shù)來處理這種獨立的控件。具體的代碼實現(xiàn)如下:
void CMainWnd::Main_OnSize( HWND hWnd, UINT state, int cx, int cy ) { RECT stRect; ::GetClientRect(hWnd, &stRect); // 獲取窗口客戶區(qū)大小 </span><span style="color: #008000">//</span><span style="color: #008000"> 將RichEdit大小調(diào)整為客戶區(qū)大小</span> ::MoveWindow(::GetDlgItem(hWnd, IDC_RICHEDIT), stRect.left, stRect.top, stRect.right-stRect.left, stRect.bottom-stRect.top, TRUE); }
這里只是在CMainWnd中添加了對于WM_SIZE的消息響應(yīng)函數(shù),要讓RichEdit響應(yīng)這個消息,還需要在Main_Proc中添加相應(yīng)過程
HANDLE_MSG(hWnd, WM_SIZE, Main_OnSize);
這樣,RichEdit也就可以跟著主窗口大小自由伸縮了。上述過程處理函數(shù)中,主要調(diào)用了三個基本的API接口。
1. GetClientRect,這個API用于獲取客戶區(qū)大小,RichEdit伸縮的大小就是這個大小值
2. GetDlgItem 獲取窗口下某一個控件的句柄,例如GetDlgItem(hWnd, IDC_RICHEDIT),就可以獲得主窗口下RichEdit控件對應(yīng)的句柄。
3. MoveWindow。它的第一個參數(shù)就是需要進(jìn)行位置大小變化的窗口句柄。我們這里將2中的RichEdit句柄傳入,后面的參數(shù)分別是矩形區(qū)域的left點,top點,width值以及height值。最后一個參數(shù)用來表示大小改變后要不要重繪窗口。注意,這里選擇了TRUE。如果選擇FALSE,會出現(xiàn)以下這種情況:當(dāng)將窗口變小后,在進(jìn)行變大操作,RichEdit并沒有立即適應(yīng)變大后的區(qū)域,還是保留在原來變小的區(qū)域。效果如圖5所示:
圖5 MoveWindows中參數(shù)repaint設(shè)置為FALSE后潛在問題
基于此,我們在用MoveWindow改變窗口大小時,最好使得repaint為TRUE,保證實時改變。
2.3 主程序ICON設(shè)計
在上述截圖中可以看出,主界面的左上角ICON一直是windows自帶的ICON。為了與windows自帶記事本做到類似,直接到網(wǎng)上找了一個類似的JPG圖標(biāo)轉(zhuǎn)為ICO,然后設(shè)置了程序的ICON。具體的圖標(biāo)設(shè)置方法請參考http://www.cnblogs.com/lhglihuagang/p/3927283.html
在圖標(biāo)設(shè)置后,可以運行程序查看下最新的效果,如圖6所示
圖6 設(shè)置程序圖標(biāo)后的結(jié)果
最后,對話框窗口的標(biāo)題Dialog實在顯得有些另類,這里根據(jù)windows自帶記事本的標(biāo)題“無標(biāo)題 - 記事本”,將這個值進(jìn)行了相應(yīng)的修改,具體為IDD_MAIN-> properties -> Caption –> 無標(biāo)題 - 記事本最后,對話框.
3. 運行結(jié)果
在添加了CMainWnd以及RichEdit后,整個程序的運行后效果如下圖7所示:
圖7 本節(jié)程序改動后的效果
4. 結(jié)論
1. 使用RichEdit控件時,需要手動加載riched20.dll,否則程序運行后沒有任何界面效果
2. RichEdit換行、滾動條、邊框都可以通過properties中相應(yīng)字段進(jìn)行設(shè)置
3. 需要在CMainWnd中添加WM_SIZE消息響應(yīng)函數(shù),保證RichEdit自由伸縮。
5. 參考鏈接
[1] http://blog.csdn.net/dijkstar/article/details/7953816
[2] http://www.cnblogs.com/lhglihuagang/p/3927283.html
[3] http://msdn.microsoft.com/en-us/library/ms633534(VS.85).aspx
6. 說明
這將是一個系列博文,后面會繼續(xù)補充邏輯功能的開發(fā)的步驟。希望能與更多博友交流。 如果你覺得這篇文章還可以,請點贊,哈哈~~
聲明:未作說明,則本文為年糕原創(chuàng)。 注意:轉(zhuǎn)載須保留全文,如需修改請 聯(lián)系作者。
相關(guān)文章
asp php 清空access mysql mssql數(shù)據(jù)庫的代碼
php清空mysql asp情況access或mssql2008-12-12VSCode遠(yuǎn)程SSH免密登錄配置實現(xiàn)
這篇文章主要介紹了VSCode遠(yuǎn)程SSH免密登錄配置實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04git?push?origin?HEAD:refs/for/master?的意思分析
這篇文章主要介紹了git?push?origin?HEAD:refs/for/master?的意思,補充介紹了git?提交代碼常用命令,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-01-012022編程語言需求排名出爐:第一不是Python,也不是Java
編程語言的流行程度、發(fā)展前景、就業(yè)市場這些一直都是程序員們非常關(guān)注的話題,需求排名是程序員們關(guān)注學(xué)習(xí)的風(fēng)向標(biāo),畢竟是市場經(jīng)濟(jì),學(xué)以致用,如果熱門編程不了解,都不好意思告訴別人你是程序員。編程語言的種類有超過200+,但還有很多不為人知。2022-12-12