C語言Windows程序設計 -> 第十四天 -> 文本輸入框


C語言Windows程序設計 -> 第十四天 -> 文本輸入框



一、文本輸入框的介紹
    從用戶那里獲取文字信息是與用戶進行交互的一個重要組成部分, 輸入框的作用則是搭建起用戶與軟件交互的一個直接橋梁之一。
    
    通常, 當我們點擊輸入框的編輯區域時, 輸入框中會出現插入光標,我們可以直接在輸入框中輸入文字或文本信息。 我們還可以使用一些快捷鍵例如Ctrl + C(復制)、Ctrl + V(粘貼)等快捷鍵操作, 前提是如果你想允許用戶這么做的話。
    
    文本輸入框分為單行輸入框和多行輸入框, 單行輸入框即不能進行換行操作, 所有內容都將在一行寫完, 常用來輸入一些較短的文本, 例如常見的用戶名/密碼輸入框。
    多行文本輸入框常用於輸入較長的段落時文本, 用戶可以使用回車鍵進行換行, 例如Windows自帶的記事本的文本編輯窗口。
    
    多行文本輸入框通常會在緊靠右側的地方帶上一個垂直滾動條, 或者在底部帶上一個水平滾動條, 方面用戶快速查看輸入框中的內容。圖示中是一個帶有水平滾動條和垂直滾動條的多行文本輸入框:


    
    在本篇隨筆的最后, 我們還將使用輸入框以及按鈕、組合框等已學到的控件來完成一個簡易的文本編輯器。
    
    
   


二、文本輸入框的創建
    創建文本輸入框的步驟與創建一個按鈕類似, 只需要調用CreateWindows創建一個輸入框子窗口控件就可以了, 如果已經掌握了如何創建一個按鈕, 那么創建一個文本輸入框就會感覺很簡單。
    
    創建一個編輯類控件的窗口類名為"edit", 例如創建一個上圖中所演示的輸入框的CreateWindow函數中的參數為:

    case WM_CREATE:
        hwndInput = CreateWindow( TEXT("edit"), NULL,
            WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | WS_BORDER |
            ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
            20, 20, 350, 100,
            hwnd, (HMENU)1, ((LPCREATESTRUCT) lParam) -> hInstance, NULL ) ;
        return 0 ;

   
    創建一個帶有輸入框的窗口, 完整示例代碼如下(已折疊):

View Code - CreateWditBox-Demo.c
 1 /*C語言Windows程序設計 -> 創建文本輸入框 -> 演示*/
 2 
 3 #include <windows.h>
 4 
 5 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ;
 6 
 7 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )
 8 {
 9     static TCHAR szAppName[] = TEXT( "demo" ) ;
10     HWND        hwnd ;
11     MSG            msg ;
12     WNDCLASS    wndclass ;
13 
14     wndclass.lpfnWndProc    = WndProc ;
15     wndclass.style            = CS_HREDRAW | CS_VREDRAW ;
16     wndclass.hInstance        = hInstance ;
17     wndclass.cbClsExtra        = 0 ;
18     wndclass.cbWndExtra        = 0 ;
19     wndclass.hbrBackground    = (HBRUSH) GetStockObject(WHITE_BRUSH) ;
20     wndclass.hCursor        = LoadCursor( NULL, IDC_ARROW ) ;
21     wndclass.hIcon            = LoadIcon( NULL, IDI_APPLICATION ) ;
22     wndclass.lpszClassName    = szAppName ;
23     wndclass.lpszMenuName    = NULL ;
24     
25     if( !RegisterClass(&wndclass) )
26     {
27         MessageBox( NULL, TEXT("無法注冊窗口類!"), TEXT("錯誤"), MB_OK | MB_ICONERROR ) ;
28         return 0 ;
29     }
30 
31     hwnd = CreateWindow( szAppName, TEXT("C語言Windows程序設計 -> 創建文本輸入框 -> 演示"), WS_OVERLAPPEDWINDOW,
32         CW_USEDEFAULT, CW_USEDEFAULT,
33         CW_USEDEFAULT, CW_USEDEFAULT,
34         NULL, NULL, hInstance, NULL ) ;
35 
36     ShowWindow( hwnd, iCmdShow ) ;
37     UpdateWindow( hwnd ) ;
38 
39     while( GetMessage(&msg, NULL, 0, 0) )
40     {
41         TranslateMessage( &msg ) ;
42         DispatchMessage( &msg ) ;
43     }
44 
45     return msg.wParam ;
46 }
47 
48 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
49 {
50     static HWND hwndInput ;
51 
52     switch( message )
53     {
54     case WM_CREATE:
55         hwndInput = CreateWindow( TEXT("edit"), NULL,
56             WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | WS_BORDER |
57             ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
58             20, 20, 350, 100,
59             hwnd, (HMENU)1, ((LPCREATESTRUCT) lParam) -> hInstance, NULL ) ;
60         return 0 ;
61 
62     case WM_DESTROY:
63         PostQuitMessage(0) ;
64         return 0 ;
65     }
66 
67     return DefWindowProc( hwnd, message, wParam, lParam ) ;
68 }

   
    如果想創建一個單行輸入框, 很簡單, 去掉 ES_MULTILINE 屬性就行了, 當然, 在單行輸入的情況下也就沒必要使用 ES_AUTOVSCROLL 屬性了。
    
    關於CreateWindow函數部分的一些解釋:
    
    1>. 輸入框的樣式:
        除了 WS_CHILD 樣式外, 該子窗口控件還具有以下屬性:

            WS_VISIBLE    //初始時是可見的
            WS_VSCROLL    //帶有一個垂直滾動條
            WS_HSCROLL    //帶有一個水平滾動條
            WS_BORDER     //擁有四周的邊界線
 ES_LEFT //編輯區的文本為左對齊
            ES_MULTILINE       //多行輸入框
            ES_AUTOHSCROLL     //當單行輸入的文本總寬度大於輸入框的寬度時自動水平滾動
            ES_AUTOVSCROLL     //當輸入行數總高度大於輸入框的高度時自動垂直滾動

        其中, 以 WS_ (Windows Style)為前綴的標識符為窗口樣式, 以 ES_ (Edit Style)為前綴的標識符為編輯類樣式。


        更多窗口樣式以及編輯框樣式的介紹可以參見筆者的另一篇補充博文: C語言Windows程序設計 -> 補充 -> Windows窗口樣式與編輯框樣式
        


    2>. 輸入框的坐標與輸入框的大小
        在子窗口樣式后緊跟的屬性就是初始坐標位置, 如上面代碼中的 20, 20 就是說明當該輸入框控件初始創建時將在相對於客戶區坐標(20, 20)的位置。
        在坐標參數的后面, 也就是上面代碼中的 350, 100 就是輸入框的大小了, 說明該輸入框子窗口的寬和高分別為350和100。
        
        如果要創建一個像記事本那樣鋪滿窗口客戶區的多行輸入框, 我們可以先創建一個無邊框(WS_BORDER)的輸入框, 初始位置和大小都置為0, 然后在處理 WM_SIZE 消息時使用 GetClientRect 函數獲取窗口客戶區的大小, 然后調整輸入框子窗口大小使其能夠完全鋪滿客戶區。像下面這樣:

    case WM_CREATE:
        hwndInput = CreateWindow( TEXT("edit"), NULL,
            WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL |
            ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
            0, 0, 0, 0,
            hwnd, (HMENU)1, ((LPCREATESTRUCT) lParam) -> hInstance, NULL ) ;
        return 0 ;

    case WM_SIZE:
        GetClientRect(hwnd, &rect) ;
        MoveWindow( hwndInput, 0, 0, rect.right, rect.bottom, TRUE ) ;
        return 0 ;

        完整代碼(已折疊):

View Code - FullClientEdit-Demo.c
 1 /*C語言Windows程序設計 -> 鋪滿客戶區的輸入框 -> 演示*/
 2 
 3 #include <windows.h>
 4 
 5 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ;
 6 
 7 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )
 8 {
 9     static TCHAR szAppName[] = TEXT( "demo" ) ;
10     HWND        hwnd ;
11     MSG            msg ;
12     WNDCLASS    wndclass ;
13 
14     wndclass.lpfnWndProc    = WndProc ;
15     wndclass.style            = CS_HREDRAW | CS_VREDRAW ;
16     wndclass.hInstance        = hInstance ;
17     wndclass.cbClsExtra        = 0 ;
18     wndclass.cbWndExtra        = 0 ;
19     wndclass.hbrBackground    = (HBRUSH) GetStockObject(WHITE_BRUSH) ;
20     wndclass.hCursor        = LoadCursor( NULL, IDC_ARROW ) ;
21     wndclass.hIcon            = LoadIcon( NULL, IDI_APPLICATION ) ;
22     wndclass.lpszClassName    = szAppName ;
23     wndclass.lpszMenuName    = NULL ;
24     
25     if( !RegisterClass(&wndclass) )
26     {
27         MessageBox( NULL, TEXT("無法注冊窗口類!"), TEXT("錯誤"), MB_OK | MB_ICONERROR ) ;
28         return 0 ;
29     }
30 
31     hwnd = CreateWindow( szAppName, TEXT("C語言Windows程序設計 -> 鋪滿客戶區的輸入框 -> 演示"), WS_OVERLAPPEDWINDOW,
32         CW_USEDEFAULT, CW_USEDEFAULT,
33         CW_USEDEFAULT, CW_USEDEFAULT,
34         NULL, NULL, hInstance, NULL ) ;
35 
36     ShowWindow( hwnd, iCmdShow ) ;
37     UpdateWindow( hwnd ) ;
38 
39     while( GetMessage(&msg, NULL, 0, 0) )
40     {
41         TranslateMessage( &msg ) ;
42         DispatchMessage( &msg ) ;
43     }
44 
45     return msg.wParam ;
46 }
47 
48 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
49 {
50     static HWND hwndInput ;
51     RECT rect ;
52 
53     switch( message )
54     {
55     case WM_CREATE:
56         hwndInput = CreateWindow( TEXT("edit"), NULL,
57             WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL |
58             ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
59             0, 0, 0, 0,
60             hwnd, (HMENU)1, ((LPCREATESTRUCT) lParam) -> hInstance, NULL ) ;
61         return 0 ;
62 
63     case WM_SIZE:
64         GetClientRect(hwnd, &rect) ;
65         MoveWindow( hwndInput, 0, 0, rect.right, rect.bottom, TRUE ) ;
66         return 0 ;
67 
68     case WM_DESTROY:
69         PostQuitMessage(0) ;
70         return 0 ;
71     }
72 
73     return DefWindowProc( hwnd, message, wParam, lParam ) ;
74 }

        運行效果:

    


    3>. ((LPCREATESTRUCT) lParam) -> hInstance
        在這個參數中, 我們需要的是WinMain函數中的 HINSTANCE hInstance 這個實例句柄, 在 WM_CREATE 消息里的 lParam 實際上是指向 CREATESTRUCT 結構類型的指針, hInstance 則是這個結構的一個成員。因此我們先將 lParam 轉換成 LPCREATESTRUCT 結構, 再從中取得 hInstance 成員。
        
        除了上面的方法獲取 hInstance 外, 還可以使用 GetWindowLong 函數來獲取, 該函數能夠獲得有關指定窗口的信息, 函數的原型:
            LONG GetWindowLong(HWND hWnd, int nlndex) ;
        第二個參數nlndex即為要獲取的信息, 例如:

            GWL_STYLE          //獲得窗口風格
            GWL_WNDPROC        //獲得窗口過程的地址
            GWL_HINSTANCE      //獲得應用實例句柄
            GWL_HWNDPARENT     //如果父窗口存在, 獲得父窗口句柄
            GWL_ID            //獲得窗口標識ID

        等等。
        當調用成功時, 返回的即為所要獲取的32位值, 失敗時返回值為0。
        
        這里我們需要的是 hInstance, 所以就這樣寫:

(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE)        //將所需的32位值轉換成HINSTANCE型, 否則使用時會產生警告

 

 


      
三、編輯控件的通知消息
    當用戶在編輯控件上進行操作時, 編輯控件會向父窗口發送 WM_COMMAND 消息, 其中的 wParam 值與 lParam 值的含義與按鈕控件中的含義一致:
        LOWORD(wParam)            //子窗口ID
        HIWORD(wParam)            //通知碼
        lParam                    //子窗口句柄
        
    文本編輯框所能產生的不同通知碼以及其含義如下:

        EN_ALIGN_LTR_EC            //文本排列順序更變為從左到右
        EN_ALIGN_RTL_EC            //文本排列順序更變為從右到左
        EN_CHANGE                  //輸入框中的內容將發生改變
        EN_ERRSPACE                //內存不足
        EN_HSCROLL                 //用戶點擊水平滾動條
        EN_KILLFOCUS               //輸入框失去焦點
        EN_MAXTEXT                 //輸入框沒有足夠地方輸入了
        EN_SETFOCUS                //輸入框獲取焦點
        EN_UPDATE                  //輸入框中的內容已變化
        EN_VSCROLL                 //用戶點擊縱向滾動條


    例如, 當我們建立一個多行, 但不能水平/垂直滾動的輸入框, 處理內容改變和輸入框已滿的消息:

    case WM_COMMAND:
        switch(LOWORD(wParam))
        {
        case 1:
                switch(HIWORD(wParam))
                {
                case EN_UPDATE:
                    MessageBox(NULL, TEXT("輸入內容已改變!"), TEXT("輸入"), MB_OK) ;
                    break ;
                case EN_MAXTEXT:
                    MessageBox(NULL, TEXT("輸入框已滿!"), TEXT("輸入"), MB_OK) ;
                    break ;
                default:
                    break ;
                }
                return 0 ;
        /*case 其他子窗口控件的ID*/
        }
        return 0 ;

 


        
       
四、使用文本輸入框
    一些常用的操作:
    
    1>. 獲取輸入內容 GetWindowText
        該函數將指定窗口的標題文本拷貝到一個緩存區內。如果指定的窗口是一個控件, 則拷貝控件的文本。因此可以用來獲取輸入框的文字, 函數原型:

            int GetWindowText(
                HWND hWnd,            //帶文本的窗口或控件的句柄
                LPTSTR lpString,    //指向接收文本的緩沖區的指針
                int nMaxCount        //允許保存在緩沖區內字符的最大個數, 超過部分被截斷
            ) ;

        調用成功時函數返回已拷貝的字符串的字符個數
    


    2>. 獲取輸入框中文本的長度 GetWindowTextLength
        該函數用來獲得指定編輯控件中的字符數, 函數原型: int GetWindowTextLength( HWND hWnd );
        需要注意的是, 該函數獲取到的文本長度不一定是准確的, 在一定的條件下, 函數GetWindowTextLength的返回值可能比實際的文本實際長度要大。這是由於ANSI和Unlcode的混和使用以及系統允許DBCS字符在文本內存在的原因。
        
        如果要獲取准確的文本長度可以利用 GetWindowText 函數。


    3>. 設置輸入框中的文字內容 SetWindowText
        在窗口有標題欄時, 該函數用於改變指定窗口的標題欄的文本內容。如果指定的窗口句柄為一個控件, 則改變控件的文本內容。
        函數原型: BOOL SetWindowText(HWND hwnd,LPCTSTR lpString) ;
        
        參數說明:
            hWnd :要改變文本內容的窗口或控件的句柄。
          lpString : 指向一個以空結束的字符串指針, 該字符串將作為窗口或控件的新文本。
        當調用成功時返回非0, 失敗時返回0。
        
    4>. WINDOWSX.H 頭文件中的一些常用操作
        下面這些宏定義在 WINDOWSX.H 頭文件中, 所以使用時需要 #include <windowsx.h>
        
        ①. 獲取文本行數 Edit_GetLineCount
            原型: int Edit_GetLineCount( HWND hwndCtl );
            
        ②. 獲取某一行的文本內容 Edit_GetLine
            原型:

         int Edit_GetLine(
                    HWND hwndCtl,        //編輯框句柄
                    int line,            //從0開始的索引行
                    LPTSTR lpch,        //指向緩沖區的指針
                    int cchMax            //最大復制的字符數量
                );

            其返回值為實際復制的字符數量, 適用於多行輸入框。
            
        ③. 限制輸入框最大輸入數量 Edit_LimitText
            原型:

            void Edit_LimitText(
                HWND hwndCtl,        //編輯框句柄
                int cchMax            //所允許輸入的字符長度
            );

            當第二個參數值為0時, 字符長度設置為64000。 沒有返回值。
            
        ④. 禁用輸入框 Edit_Enable
            原型:

            BOOL Edit_Enable(
                HWND hwndCtl,        //編輯框句柄
                BOOL fEnable        //TRUE啟用, FALSE禁用
            );

    更多關於編輯框控制函數以及宏的使用可以查閱MSDN Library。
    


    

五、向編輯框傳遞消息
    與普通窗口一樣, 向編輯框控件發送消息可以使用 SendMessage 函數, 由於可發送的消息太多, 這里僅介紹幾個較為常用的, 其他完整的消息介紹可查閱 MSDN Library。
    消息:

        WM_CUT          //剪切選中文本
        WM_COPY         //復制選中文本
        WM_CLEAR        //刪除選中文本
        WM_PASTE        //將剪貼板上的文字粘貼到當前輸入位置

    選中的文本是指用戶用鼠標或者Shift鍵加方向鍵選擇的文本, 這部分文本會以高亮顯示來與其他未選中的部分區別開來。
    例如我們要將當前剪切板上的內容粘貼到編輯框只需要:

        SendMessage(hwndInput, WM_PASTE, 0, 0) ;        

    我們也可以向編輯框發送消息來自己選中文本:

        SendMessage(hwndInput, EM_SETSEL, iStart, iEnd) ;

    還可以通過發送消息 EM_REPLACESEL 用其他文本來替代選中的文本:

        SendMessage(hwndInput, EM_REPLACESEL, 0, (LPARAM)szString) ;

   
    在上面"四、使用文本輸入框"部分介紹了如何通過宏定義統計輸入的行數, 通過發送 EM_GETLINECOUNT 消息也可以達到相同的目的:

        iCount = SendMessage(hwndInput, EM_GETLINECOUNT, 0, 0) ;

 

 



六、實例: 一個簡易的文本編輯器
    功能要求:
        這個簡易的文本編輯器包含如下功能:
            1>. 能夠保存編輯的文字 ;
            2>. 自動統計已輸入的字符的個數和行數 ;
            3>. 有快速清空編輯區功能 ;
            
    功能分析:
        1>. 由於還沒有學習打開文件和保存文件的標准對話框, 所以目前在保存文件時我們需要用戶自己手動輸入保存或讀取的路徑 ;
        2>. 統計輸入的字符個數與行數可以通過上文中講的宏或者向編輯框發送消息獲得 ;
        3>. 快速清空編輯區可以用一個清空按鈕來代替。
    
    細節處理:
        1>. 只有當編輯區的內容不為空時才能保存 ;
        2>. 當用戶沒有輸入保存路徑時點擊"保存"按鈕提示用戶輸入路徑。
    
    其完整的實現代碼如下(已折疊):

View Code - SimpleEdit-Demo.c
  1 /*C語言Windows程序設計 -> 簡易文本編輯器 -> 演示*/
  2 
  3 #include <windows.h>
  4 #include <stdio.h>
  5 
  6 /*各控件所使用的ID*/
  7 #define ID_EDITBOX    1        //文本編輯框控件
  8 #define ID_TXTPATH    2        //路徑編輯框控件
  9 #define ID_SAVEBTN    3        //保存文件按鈕
 10 #define ID_CLSBTN    4        //清空編輯區按鈕
 11 #define ID_GROUP    5        //組合框
 12 
 13 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ;
 14 int CreateChildWindow(HWND, HWND *, LPARAM ) ;                //創建將使用到的子窗口控件
 15 int SavaInputContent( TCHAR *, TCHAR * ) ;                    //保存輸入的文字到文件
 16 
 17 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )
 18 {
 19     static TCHAR szAppName[] = TEXT( "demo" ) ;
 20     HWND        hwnd ;
 21     MSG            msg ;
 22     WNDCLASS    wndclass ;
 23 
 24     wndclass.lpfnWndProc    = WndProc ;
 25     wndclass.style            = CS_HREDRAW | CS_VREDRAW ;
 26     wndclass.hInstance        = hInstance ;
 27     wndclass.cbClsExtra        = 0 ;
 28     wndclass.cbWndExtra        = 0 ;
 29     wndclass.hbrBackground    = CreateSolidBrush(RGB(236, 233, 216)) ;
 30     wndclass.hCursor        = LoadCursor( NULL, IDC_ARROW ) ;
 31     wndclass.hIcon            = LoadIcon( NULL, IDI_APPLICATION ) ;
 32     wndclass.lpszClassName    = szAppName ;
 33     wndclass.lpszMenuName    = NULL ;
 34     
 35     if( !RegisterClass(&wndclass) )
 36     {
 37         MessageBox( NULL, TEXT("無法注冊窗口類!"), TEXT("錯誤"), MB_OK | MB_ICONERROR ) ;
 38         return 0 ;
 39     }
 40 
 41     hwnd = CreateWindow( szAppName, TEXT("C語言Windows程序設計 -> 簡易文本編輯器 -> 演示"), WS_OVERLAPPEDWINDOW,
 42         CW_USEDEFAULT, CW_USEDEFAULT,
 43         CW_USEDEFAULT, CW_USEDEFAULT,
 44         NULL, NULL, hInstance, NULL ) ;
 45 
 46     ShowWindow( hwnd, iCmdShow ) ;
 47     UpdateWindow( hwnd ) ;
 48 
 49     while( GetMessage(&msg, NULL, 0, 0) )
 50     {
 51         TranslateMessage( &msg ) ;
 52         DispatchMessage( &msg ) ;
 53     }
 54 
 55     return msg.wParam ;
 56 }
 57 
 58 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
 59 {
 60     static        HWND hwndChild[5] ;
 61     HDC            hdc ;
 62     PAINTSTRUCT ps ;
 63 
 64     RECT    rect ;
 65     static    TCHAR *szBuffer ;        //緩沖區
 66     static    TCHAR szPath[256] ;        //文本路徑
 67     static  TCHAR szLineNum[32] ;
 68     static    TCHAR szCharNum[32] ;
 69     static int        iLength ;
 70     int iLineCount, iCharCount ;
 71 
 72     switch( message )
 73     {
 74     case WM_CREATE:
 75         CreateChildWindow( hwnd, hwndChild, lParam ) ;
 76         return 0 ;
 77 
 78     case WM_SIZE:
 79         GetClientRect(hwnd, &rect) ;
 80         MoveWindow( hwndChild[ID_EDITBOX], 0, 0, rect.right, rect.bottom-50, TRUE ) ;        //調整文本編輯區
 81         MoveWindow( hwndChild[ID_TXTPATH], 60,  rect.bottom-31, 200, 20, TRUE ) ;            //調整文本路徑輸入框
 82         MoveWindow( hwndChild[ID_SAVEBTN], 280, rect.bottom-35, 50,  25, TRUE ) ;            //調整保存按鈕
 83         MoveWindow( hwndChild[ID_CLSBTN ], 400, rect.bottom-35, 50,  25, TRUE ) ;            //調整清空按鈕
 84         MoveWindow( hwndChild[ID_GROUP  ], 10,  rect.bottom-50, 330, 48, TRUE ) ;            //調整組合框
 85         return 0 ;
 86 
 87     case WM_PAINT:
 88         GetClientRect(hwnd, &rect) ;
 89         hdc = BeginPaint( hwnd, &ps ) ;
 90         TextOut( hdc, 20, rect.bottom-30, TEXT("路徑:"), lstrlen(TEXT("路徑:")) ) ;
 91         TextOut( hdc, 500, rect.bottom-30, szLineNum, lstrlen(szLineNum) ) ;
 92         EndPaint( hwnd, &ps ) ;
 93         return 0 ;
 94 
 95     case WM_COMMAND:
 96         switch(LOWORD(wParam))
 97         {
 98         case ID_EDITBOX:
 99             switch(HIWORD(wParam))
100             {
101             case EN_UPDATE:
102                 iLineCount = SendMessage( hwndChild[ID_EDITBOX], EM_GETLINECOUNT, 0, 0 ) ;
103                 iCharCount = GetWindowTextLength( hwndChild[ID_EDITBOX] ) ;
104                 wsprintf(szLineNum, "行數: %i    字符數量: %i", iLineCount, iCharCount) ;
105                 InvalidateRect(hwnd, NULL, FALSE) ;
106                 break ;
107             default:
108                 break ;
109             }
110             return 0 ;
111 
112         case ID_SAVEBTN:
113             iLength = GetWindowTextLength(hwndChild[ID_EDITBOX]) ;
114             if( iLength != 0)
115                 szBuffer = malloc(iLength*2) ;
116             else
117                 return -1 ;
118             GetWindowText( hwndChild[ID_EDITBOX], szBuffer, GetWindowTextLength(hwndChild[ID_EDITBOX]) + 1 ) ;
119             if(GetWindowText( hwndChild[ID_TXTPATH], szPath, 256 ) < 1)
120             {
121                 MessageBox(NULL, TEXT("路徑不能為空"), TEXT("提示"), MB_OK | MB_ICONINFORMATION) ;
122                 return -1 ;
123             }
124             SavaInputContent( szPath, szBuffer ) ;
125             return 0 ;
126 
127         case ID_CLSBTN:
128             SetWindowText( hwndChild[ID_EDITBOX], TEXT("") ) ;
129             return 0 ;
130 
131         default:
132             break ;
133         }
134         return 0 ;
135 
136     case WM_DESTROY:
137         PostQuitMessage(0) ;
138         return 0 ;
139     }
140 
141     return DefWindowProc( hwnd, message, wParam, lParam ) ;
142 }
143 
144 int CreateChildWindow(HWND hwnd, HWND *hwndChild, LPARAM lParam)
145 {
146     HINSTANCE hInst = ((LPCREATESTRUCT) lParam) -> hInstance ;
147 
148     //創建編輯區
149     hwndChild[ID_EDITBOX] = CreateWindow( TEXT("edit"), NULL,
150         WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL |
151         ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
152         0, 0, 0, 0,
153         hwnd, (HMENU)ID_EDITBOX, hInst, NULL ) ;
154 
155     //路徑輸入框
156     hwndChild[ID_TXTPATH] = CreateWindow( TEXT("edit"), NULL,
157         WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL,
158         0, 0, 0, 0,
159         hwnd, (HMENU)ID_TXTPATH, hInst, NULL ) ;
160 
161     //保存按鈕
162     hwndChild[ID_SAVEBTN] = CreateWindow( TEXT("button"), TEXT("保存"),
163         WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 0, 0, 0, 0,
164         hwnd, (HMENU)ID_SAVEBTN, hInst, NULL) ;
165 
166     //清空按鈕
167     hwndChild[ID_CLSBTN] = CreateWindow( TEXT("button"), TEXT("清空"),
168         WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 0, 0, 0, 0,
169         hwnd, (HMENU)ID_CLSBTN, hInst, NULL) ;
170     
171     //組合框
172     hwndChild[ID_GROUP] = CreateWindow( TEXT("button"), NULL,
173         WS_CHILD | WS_VISIBLE | BS_GROUPBOX, 0, 0, 0, 0,
174         hwnd, (HMENU)ID_GROUP, hInst, NULL) ;
175 
176     return 0 ;
177 }
178 
179 int SavaInputContent( TCHAR *path, TCHAR *content )
180 {
181     FILE *fSvae ;
182 
183     fSvae = fopen( path, "w" ) ;
184     if(fSvae == NULL)
185     {
186         MessageBox(NULL, TEXT("文件創建失敗!"), TEXT("提示"), MB_OK | MB_ICONINFORMATION) ;
187         return -1 ;
188     }
189     fputs( content, fSvae ) ;
190     fclose(fSvae) ;
191     MessageBox(NULL, TEXT("保存成功!"), TEXT("成功"), MB_OK | MB_ICONINFORMATION) ;
192 
193     return 0 ;
194 


    運行效果:

    

本篇隨筆中所有的DEMO代碼下載: http://files.cnblogs.com/mr-wid/Learn_WinC_day_14.rar




再長的路, 一步步也能走完, 再短的路, 不邁開雙腳也無法到達。2013, 期待你的到來!

 


--------------------


wid, 2012.12.31

 

上一篇: C語言Windows程序設計 -> 第十三天 -> 按鈕類控件

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM