我这里有一个用 c 编写的 win32api 应用程序。主窗口中的所有控件都是手动创建的,如下所示:
hEditSource = CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT", NULL,
WS_VISIBLE | WS_CHILD | WS_TABSTOP | ES_MULTILINE | ES_READONLY,
someLeft, someTop, someWidth, someHeight,
hWndMain, NULL, hInst, NULL);
起初我没有在主消息循环中应用 IsDialogMessage 测试,因此所有控件的制表位都不起作用。现在我已经完成了,除了上面的多行文本框之外,每个控件都可以。事实上,当按下 Tab 键时什么也没有发生。不移动焦点,不插入制表符(之后会丢弃只读样式)。
其他文本框都是单行的,如下所示:
editSearch = CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT", NULL,
WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL | WS_TABSTOP,
someLeft, someTop, someWidth, someHeight,
hWndMain, NULL, hInst, NULL);
看来与多种线条样式有关的东西是原因。但在 C# winform 中,创建带有工作制表位的多行编辑非常容易(这是文本框的默认行为,无论是多行)。我尝试使用spy++来查找窗口样式是否有任何线索。但是,如果唯一的区别是“Accept Tab”属性,则两个文本框的窗口样式是相同的。
目前我找不到其他方法来定位根本原因。有人有线索吗?任何帮助将不胜感激。
IsDialogMessage
的行为受控件对 WM_GETDLGCODE
的响应方式影响。正如记录的那样,对于多行编辑控件,默认窗口过程返回以下内容:
DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS | DLGC_WANTALLKEYS
包含 DLGC_WANTALLKEYS
会阻止
IsDialogMessage
响应TAB 并将焦点移至下一个控件。因此,您需要对多行编辑控件进行子类化并删除该标志。子类窗口过程可能如下所示:
LRESULT CALLBACK MultiLineEditWndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
LRESULT res = CallWindowProc(wpOld, hWnd, message, wParam, lParam);
switch (message)
{
case WM_GETDLGCODE:
res &= ~DLGC_WANTALLKEYS;
}
return res;
}