Issue with tab key in multiline edit (Win32)

Started by
7 comments, last by philipbennefall 14 years, 1 month ago
Hi folks, I am having a bit of an issue with a multiline edit control that I am making with the CreateWindow function. I'm basically creating a dialog box with a large multiline edit field and a few buttons, and I want the user to be able to tab between these. If I make it a single line edit field it works fine (e.g. the tabbing behavior is just like in any standard dialog box which is what I want), but as soon as I change it to multiline then it captures the keyboard focus and then won't let go of it. In short, if I set default focus to one of the buttons then I can tab around, but as soon as the edit field gets the keyboard focus then it keeps it exclusively. This, of course, is what one would expect in an application such as notepad where the idea is to be able to do text processing, but this is not what I want in this case; I want standard dialog box tabbing functionality but with the multiline edit field. Any advice would be highly appreciated. Thanks! Kind regards, Philip Bennefall
Advertisement
This is because multi-line edit controls are built to process the tab key internally. You will want to subclass the control (pass in a custom wndproc), and within that capture the WM_KEYDOWN message. When you encounter the tab key, simply swap focus to the next highest tabstop.

Hopefully this helps.
Hello there,

Thank you very much for the quick reply. I wonder if you would be able to show a quick example of how to subclass the control like you mention and how the code in the callback might be written? GUI programming is not a field in which I have much experience as I only code audio based games for the blind and visually impaired, and so it's extremely rare that I have to do anything with windows. So any code examples would be highly appreciated. I'm using C++ and calling CreateWindowEx.

Thanks in advance.

Kind regards,

Philip Bennefall
Subclassing is really easy:
WNDPROC		oldEditWndProc; // ptr to old window proc....// after creation:oldEditWndProc = ( WNDPROC ) SetWindowLong( hWndEdit, GWL_WNDPROC, ( long ) NewEditWndProc );...LONG WINAPI NewEditWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {	// catch the messages here..	// else:	return CallWindowProc( oldEditWndProc, hWnd, uMsg, wParam, lParam );}

notice how you call CallWindowProc instead of DefWindowProc
Hello again,

Thank you very much, that code snippet makes perfect sense. However I am not entirely certain how I would go about setting the keyboard focus to the next or previous tabstop if the user pressed tab or shift+tab respectively. Basically I want it to work like a regular dialog box where shift+tab moves you to the previous item, and tab to the next. If I capture the WM_KEYDOWN message, won't I get two separate notifications for shift and tab for instance? And how exactly does one programatically switch focus to the next or previous tabstop? SetFocus works on a specified window handle, of course, but I do not know how to get handles to the previous and the next tabstop in relation to the currently focused control, nor do I know how to check for multiple keys being down at one time in the callback. All my previous experience is with DirectInput where one simply polls the device and then asks it whether a particular key is held down. Any hints?

Kind regards,

Philip Bennefall
You should be able to delegate the TAB key functionality to IsDialogMessage.

To manually find the next/previous control use GetNextDlgTabItem.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Hello again,

Looking at the GetNextDlgTabItem function it seems perfectly logical, however I don't quite understand what you mean by delegating the tab behavior to the dialog message function. I call this function in my main message loop already, as that was required to get it to tab between the other controls in the window. In short, what I need to find out is if the user tried to get focus away from the edit control by pressing either tab or shift+tab.

Thanks again for all the help.

Kind regards,

Philip Bennefall
I thought of letting the IsDialogMessage doing the tab behaviour, but in this case you'd also need to override WM_GETDLGCODE when subclassing.

Probably easier to check for TAB yourself with WM_KEYDOWN. Check for VK_TAB and use GetAsyncKeyState to check if Shift is currently pressed to differ between the two cases.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Hi all,

I have now managed to get this working, thanks once again for the help!

Kind regards,

Philip Bennefall

This topic is closed to new replies.

Advertisement