编辑类是最简单的预定义窗口类,而另一方面却又是最复杂的。当你用“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时,表示空间不足或者超出最大输入字符数。