編輯類是最簡單的預定義窗口類,而另一方面卻又是最復雜的。當你用“edit”作為類名創建子窗口時,可以基于CreateWindow調用的x坐標、y坐標、寬度和高度參數定義一個矩形。這個矩形包含可編輯的文本。一旦子窗口控件獲得輸入焦點,你就可以輸入文本,移動光標,使用鼠標或Shift鍵和光標鍵選擇部分文本,按快捷鍵 Ctrl - X刪除選中的文本并將其放入剪貼板中,按快捷鍵Ctrl - C復制文本,按快捷鍵Ctrl - V 從剪貼板粘貼文本。
本節必須掌握的知識點:
??? ????編輯類
??? ????第53練:編輯控件
8.4.1 編輯類
?????? ■編輯類的樣式
編輯類窗口(Edit Control)是用于接收和顯示文本輸入的窗口控件。可以使用樣式設置來改變編輯類窗口的外觀和行為。
以下是一些常用的編輯類窗口樣式:
ES_LEFT:文本左對齊(默認)。
ES_CENTER:文本居中對齊。
ES_RIGHT:文本右對齊。
ES_MULTILINE:多行編輯框,允許輸入多行文本。
ES_READONLY:只讀模式,禁止編輯。
ES_PASSWORD:密碼模式,輸入的文本以密碼字符顯示。
ES_NUMBER:數字模式,只允許輸入數字。
ES_AUTOHSCROLL:自動水平滾動,當文本超出控件寬度時自動水平滾動。
ES_AUTOVSCROLL:自動垂直滾動,當文本超出控件高度時自動垂直滾動。
ES_WANTRETURN:希望回車鍵產生換行效果,適用于多行編輯框。
這些樣式可以通過在創建編輯類窗口時使用 CreateWindowEx 或 CreateWindow 函數的 dwStyle 參數來設置。例如:
HWND hEdit = CreateWindowEx(
??? 0,????????????????????? // 擴展窗口樣式
??? L"EDIT",??????????????? ? // 窗口類名
??? L"Sample Text",???????? ?? // 窗口標題(初始文本)
??? WS_VISIBLE | WS_CHILD | WS_BORDER | ES_LEFT,? // 窗口樣式
??? x, y, width, height,??? ??????? // 窗口位置和尺寸
??? hWndParent,???????????? // 父窗口句柄
??? (HMENU)IDC_EDIT,??????? // 控件標識符
??? hInstance,????????????? ?? // 應用程序實例句柄
??? NULL?????????????????? // 創建參數
);
在上述示例中,我們創建了一個編輯類窗口,并設置了一些常用的樣式,如可見、子窗口、帶邊框和左對齊。可以根據需求自由組合和設置其他樣式。
除了創建時設置樣式,還可以使用 SetWindowLongPtr 或 SetWindowLongPtr 函數來動態修改編輯類窗口的樣式。例如:
DWORD dwStyle = GetWindowLongPtr(hEdit, GWL_STYLE);
dwStyle |= ES_READONLY;? // 設置只讀樣式
SetWindowLongPtr(hEdit, GWL_STYLE, dwStyle);
在上述示例中,我們首先獲取編輯類窗口的當前樣式,然后通過按位或運算符將 ES_READONLY 樣式添加到樣式中,最后使用 SetWindowLongPtr 函數設置新的樣式。
需要注意的是,應在窗口創建之前或之后進行樣式修改。有些樣式只能在創建時設置,而有些樣式可以在創建后動態修改。
■編輯控件的通知消息
編輯控件向其父窗口過程發送WM_COMMAND消息。相應的wParam和IParam變量的含義與其在按鈕控件中的含義一致:
LOWORD (wParam)???? 子窗口 ID
HIWORD (wParam)????? 通知碼
IParam??? 子窗口句柄
通知碼如下所示:??????
EN_SETFOCUS????? 編輯控件得到了輸入焦點
ENJ_KILLFOCUS??? 編輯控件失去了輸入焦點
EN_CHANGE? ?????? 編輯控件的內容將變化
EN_UPDATE?? ?????? 編輯控件的內容已變化
EN_ERRSPACE?????? 編輯控件沒有空間了
EN_MAXTEXT ?????? 編輯控件沒有空間完成插入了
EN_HSCROLL ?????? 編輯控件水平滾動條被單擊了
EN_VSCROLL ?????? 編輯控件垂直滾動條被單擊了
■使用編輯控件
如果在主窗口上使用了多個單行編輯控件,則需要利用窗口子類來將輸入焦點從一個 控件移到另一個控件。這可以通過攔截Tab和Shifl-Tab擊鍵來完成,就和COLORS 1程序 一樣。(另一個窗口子類的例子會在本章稍后的HEAD程序中討論* )如何處理回車鍵由你 自己決定。可以使用和處理Tab鍵相同的方式,或將其作為一個信號傳遞給程序,通知程 序所有的編輯框已經準備就緒。
如果要把文本插入編輯框,可以使用SetWindowText函數。從編輯控件中讀取文本涉 及調用GetWindowTextLength和GetWindowText。我們會在以后改進的POPPAD版本中看見一些這方面的實例。
■傳遞給編輯控件的消息
可以使用SendMessage發送給編輯控件的消息,因為這些消息太多了,下面是一個概括的介紹。
●下面這些消息可以讓你剪切、復制或清除當前選擇的內容。用戶可以使用鼠標或Shift 鍵加光標鍵來選擇需要的文本,從而高亮顯示編輯控件中所選的文本:
SendMessage (hwndEdit, WM_CUT, 0, 0);
SendMessage (hwndEdit, WM_COPY, 0, 0) ;
SendMessage (hwndEdit, WM_CLEAR, 0, 0);
WM_CUT把當前選擇從編輯控件中移走并發送給剪貼板。WM_COPY把當前選擇從編輯 控件_中復制到剪貼板并保留在原地。WM_CLEAR把當前選擇從編輯控件中刪除并且不傳遞給剪貼板。
還可以把剪貼板上的文本插入到編輯控件的當前位置:
SendMessage (hwndEdit, WM_PASTE, 0, 0);
●可以用如下函數獲得當前選擇文本的初始位置和終止位置:
SendMessage (hwndEdit, EM_GETSEL, (WPARAM) &iStart, (LPARAM) &iEnd) ;
終止位置其實是你選擇的最后一個字符的位置加1。
●可以如下選擇文本:
SendMessage (hwndEdit, EM_SETSEL, iscart, iEnd);
也可以用其他文本取代當前選擇的文本:
SendMessage (hwndEdit, EM_REPLACESEL, 0, (LPARAM) szString);
●對于多行編輯器,可以如下得到編輯器的行數:
iCount = SendMessage (hwndEdit,EM_GETLINECOUNT, 0, 0);
●對于某一個指定的行,可以獲得從編輯緩沖區的起點到這行的位移量:
iOffset = SendMessage (hwndEdit, EM_LINEINDEX, iLine, 0) ;
行從0開始計數。如果傳入-1給iLine,可以返回插入符號所在行的位移量。如下可得到行的長度:
iLength = SendMessage (hwndEdit, EM_LINELENGTH, iLine, 0);
●可以用如下函數來復制某行到緩沖區:
iLength = SendMessage (hwndEdit, EM_GETLINE, iLine, (LPARAM) szBuffer);
8.4.2 第53練:編輯控件
/*------------------------------------------------------------------
053? WIN32 API 每日一練
???? 第53個例子POPPAD1.C:編輯控件
???? 創建編輯控件
???? WM_COMMAND消息處理
(c) www.bcdaren.com, 2020
----------------------------------------------------------------*/
#include <windows.h>
#define ID_EDIT 1
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
TCHAR szAppName[] = TEXT ("PopPad1") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
?PSTR szCmdLine, int iCmdShow)
{
???? HWND hwnd;
??? …(略)
???? return msg.wParam;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM
lParam)
{
???? static HWND hwndEdit;
???? switch (message)
???? {
???? case WM_CREATE:
????????? hwndEdit = CreateWindow(TEXT("edit"),NULL,
?????????????? WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL |
?????????????? WS_BORDER | ES_LEFT | ES_MULTILINE |
?????????????? ES_AUTOHSCROLL | ES_AUTOVSCROLL,
?????????????? 0, 0, 0, 0, hwnd, (HMENU)ID_EDIT,
?????????????? ((LPCREATESTRUCT)lParam)->hInstance, NULL);
//輸入的最大文本量(TCHAR)默認大小32,767 個字符(包括空字符)
??????? ? SendMessage(hwndEdit,EM_SETLIMITTEXT,0,1);
????????? return 0;
???? case WM_SETFOCUS:
????????? SetFocus(hwndEdit);//設為焦點
????????? return 0;
???? case WM_SIZE:
//重新繪制編輯框
????????? MoveWindow(hwndEdit,0,0,LOWORD(lParam),HIWORD(lParam),TRUE);
????????? return 0;
???? case WM_COMMAND:
????????? if (LOWORD(wParam) == ID_EDIT)
????????? {//編輯控件中輸入的文本量的默認限制為32,767 個字符(包括空字符)。
//應用程序可以通過發送 _ SETLIMITTEXT 消息的控件來更改默認限制。
?????????????? if (HIWORD(wParam) == EN_ERRSPACE || HIWORD(wParam)
== EN_MAXTEXT)//已滿
?????????????? {
??????????????????? MessageBox(hwnd,TEXT("Edit control out of space."),
??????????????????? szAppName,MB_OK | MB_ICONSTOP);
?????????????? }
????????? }
????????? return 0;
???? case WM_DESTROY:
????????? PostQuitMessage(0);
????????? return 0;
???? }
???? return DefWindowProc(hwnd, message, wParam, lParam);
}
/******************************************************************************
創建編輯控件
hwndEdit = CreateWindow(TEXT("edit"), NULL,
???? WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
???? WS_BORDER | ES_LEFT | ES_MULTILINE |
???? ES_AUTOHSCROLL | ES_AUTOVSCROLL,
???? 0, 0, 0, 0, hwnd, (HMENU)ID_EDIT,
???? ((LPCREATESTRUCT)lParam)->hInstance, NULL);
窗口樣式是WS_CHILD,外加幾個選項。和在靜態子窗口控件中一樣,
編輯控件中的文本也可以左對齊、右對齊或居中。
這些格式可以通過ES_LEFT, ES_RIGHT或ES_CENTER窗口樣式來指定。
ES_MULTILINE:創建一個多行編輯控件
ES_AUTOHSCROLL:自動水平滾動
ES_AUTOVSCROLL:自動垂直滾動
*******************************************************************************
WM_COMMAND消息處理
//字符已滿情形的處理
if (LOWORD(wParam) == ID_EDIT)
? ?if (HIWORD(wParam) == EN_ERRSPACE || HIWORD(wParam) == EN_MAXTEXT)//空間不足
????????? MessageBox(hwnd, TEXT("Edit control out of space."),
?????????????? szAppName, MB_OK | MB_ICONSTOP);
*/
?????? 運行結果:
圖8-6 編輯控件
?
總結
?????? 實例POPPAD1.C非常簡單。窗口過程處理WM_CREATE消息時,創建一個”edit”控件,窗口樣式為WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | WS_BORDER | ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL。接著調用SendMessage向編輯控件發送一個EM_SETLIMITTEXT消息,設置編輯控件輸入最大字符數為默認值32767個字符。
?????? WM_SETFOCUS消息:調用SetFocus函數將焦點交給編輯控件。
?????? WM_SIZE消息:調整編輯控件大小。
?????? WM_COMMAND消息:WM_COMMAND消息參數wParam低字為控件ID,高字為控件通知碼。如果通知碼為EN_ERRSPACE 或 EN_MAXTEXT時,表示空間不足或者超出最大輸入字符數。