I have a win32api application written in c here. All controls in main window are created manually like this:
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);
At first I didn't apply IsDialogMessage test in main message loop so all controls' tab stop won't work. Now I have it done, every control are OK except the multi-line textbox above. Indeed nothing happens when press tab in it. No focus moving, no tab charactor inserting(it will discard read-only style afterwards).
Other textboxes are all single-line ones, looks like this:
editSearch = CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT", NULL,
WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL | WS_TABSTOP,
someLeft, someTop, someWidth, someHeight,
hWndMain, NULL, hInst, NULL);
It seems sth related to multiple line style is the cause. But in C# winform, it is very easy to create a multi-line edit with working tab-stop (it is the default behavior of a textbox, whether it is multi-line). I have tried to use spy++, to find if there is any clue in window style. However, 2 textboxes' window style are indentical if the only difference is the "Accept Tab" property.
Rightnow I cannot find another way to locate the root cause. Does anyone have a clue? Any help will be appreciated.
The behaviour of the IsDialogMessage
is influenced by how the controls respond to WM_GETDLGCODE
. As documented, for a multi-line edit control the following is returned by the default window procedure:
DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS | DLGC_WANTALLKEYS
The inclusion of DLGC_WANTALLKEYS
stops IsDialogMessage
from responding to TAB and moving the focus to the next control. So, you will need to subclass your multi-line edit control and remove that flag. The sub-classed window procedure might look like this:
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;
}