in my main window i've created child windows as edit controls, but I can't move from one control to another using the TAB, how could this be done?
thank you.
Printable View
in my main window i've created child windows as edit controls, but I can't move from one control to another using the TAB, how could this be done?
thank you.
Dialog Box Programming Considerations
2nd topic.
gg
my problem is that instead of switching focus to the next control with WS_TAB is puts the tab char in the editbox...
Well I took Codeplug's advice and wrote the next code, but still nothing, my problem is still:
Quote:
...instead of switching focus to the next control with WS_TABSTOP is puts the tab char in the editbox...
This works fine, as long an non of the editbox controls has the focus, becasue then the WM_CHAR doesn't recieve the message. Please Help.Code:case WM_CREATE:
CreateWindowEx(NULL, "Edit", "", WS_CHILD | WS_VISIBLE | WS_BORDER
| WS_TABSTOP | ES_AUTOHSCROLL | ES_MULTILINE, 99, 81, 285, 40, hwnd,
(HMENU)IDC_EDIT_FIRST, GetModuleHandle(NULL), NULL);
CreateWindowEx(NULL, "Edit", "", WS_CHILD | WS_VISIBLE | WS_BORDER
| WS_TABSTOP | ES_AUTOHSCROLL | ES_MULTILINE, 99, 122, 370, 40, hwnd,
(HMENU)IDC_EDIT_SECOND, GetModuleHandle(NULL), NULL);
break;
case WM_CHAR:
if (LOWORD(wParam)==VK_TAB)
SetFocus(GetNextDlgTabItem(hwnd, NULL, FALSE));
break;
Thank you.
Are you using IsDialogMessage in your 'main window' procedure as described in the section of the article Codeplug provided a link to?
No i am not.
Also, I don't think I understand how the function works, and how can it help me.
That's what's actually responsible for default dialog message handling (like 'tabbing', assuming the WS_TABSTOP style bit is applied, that is).
Put it in your message loop:Where hwnd is the handle of your window/dialog; GetActiveWindow can be useful here, too.Code:MSG msg;
while (GetMessage(&msg,0,0,0)>0)
{
if (!IsDialogMessage(hwnd,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
I would strongly advise you to go back and re-read the article Codeplug initially and helpfully directed you to.
I've added the code with the IsDialogMessage
And now the Tab is no longer used as char in the editbox control, but nothing else happens.
I've read The WS_GROUP Style section, and I am alittle confused, do I need to use WM_GETDLGCODE or the GetNextDlgTabItem, or should the Tabbing be done on it's own (on controls with the WS_TABSTOP style)
Tabbing should be automatic - try to create a simple, minimalist example that replicates the problem and post the code for that, if necessary (sometimes by doing this you may see an error that you maybe missed in a larger project).
Well, when you're right you're right.
I've wrote a simple example, and I've found the problem...
1) The Editboxes contain the ES_MULTILINE style.
So in the simple example, once i've removed the style the TABing worked just fine.
So I guess the IsDialogMessage(hwnd, &Msg) creates a conflict that disables the ES_MULTILINE function.
please help, it's killing me :confused:
Subclass the edit control(s) with the ES_MULTILINE style, handle the WM_KEYDOWN message and SetFocus with the window handle returned from GetNextDlgTabItem; something like:Code:LRESULT CALLBACK EditProc(HWND hwnd,....)
{
case WM_KEYDOWN:
if (wParam==VK_TAB)
{
SetFocus(GetNextDlgTabItem(GetParent(hwnd), hwnd,0));
}
return 0;
default:
CallWindowProc(....);
}
can you please explain this part
How do i use it?Quote:
Subclass the edit control(s)
Subclassing simply replaces the existing window procedure with another you supply. This is done with SetWindowLongPtr using the GWLP_WNDPROC flag; you need to store the return value of the function call and use it with CallWindowProc (there's an example of subclassing at the foot of that page) in order to get default message processing.
See also Safe subclassing in Win32.
My standard subclassing example...
Code:#include <windows.h>
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK NewEditProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE hInst;
WNDPROC OriginalEditProc;
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst,
LPSTR Args, int WinMode)
{
HWND hWnd;
MSG Message;
WNDCLASSEX Wcl;
hInst = hThisInst;
Wcl.cbSize = sizeof(WNDCLASSEX);
Wcl.hInstance = hThisInst;
Wcl.lpszClassName = "Window";
Wcl.lpfnWndProc = WindowFunc;
Wcl.style = 0;
Wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
Wcl.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
Wcl.hCursor = LoadCursor(NULL, IDC_ARROW);
Wcl.lpszMenuName = NULL;
Wcl.cbClsExtra = 0;
Wcl.cbWndExtra = 0;
Wcl.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
if(!RegisterClassEx(&Wcl)) return 0;
hWnd = CreateWindow(
"Window",
"Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
HWND_DESKTOP,
NULL,
hThisInst,
NULL
);
ShowWindow(hWnd, WinMode);
UpdateWindow(hWnd);
while(GetMessage(&Message, NULL, 0, 0))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return Message.wParam;
}
LRESULT CALLBACK WindowFunc(HWND hWnd,UINT Message,WPARAM wParam,LPARAM lParam)
{
static HWND hEditBox;
switch(Message)
{
case WM_CREATE:
hEditBox = CreateWindowEx(0,
"EDIT",
NULL,
WS_CHILD | WS_VISIBLE | WS_BORDER,
10,
10,
300,
20,
hWnd,
(HMENU) 500,
hInst,
NULL);
OriginalEditProc = (WNDPROC) SetWindowLong(hEditBox,
GWL_WNDPROC,
(LONG) NewEditProc);
SetFocus(hEditBox);
break;
case WM_DESTROY:
SetWindowLong(hEditBox,
GWL_WNDPROC,
(LONG) OriginalEditProc);
DestroyWindow(hEditBox);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, Message, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK NewEditProc(HWND hWnd,UINT Message,WPARAM wParam,LPARAM lParam)
{
const int TAB = '\x09';
const int CR = '\x0d';
const int ESC = '\x1b';
if (Message == WM_CHAR)
{
if (wParam == TAB)
{
CallWindowProc(OriginalEditProc,
hWnd,
Message,
(WPARAM) '<',
lParam);
CallWindowProc(OriginalEditProc,
hWnd,
Message,
(WPARAM) 'T',
lParam);
CallWindowProc(OriginalEditProc,
hWnd,
Message,
(WPARAM) 'A',
lParam);
CallWindowProc(OriginalEditProc,
hWnd,
Message,
(WPARAM) 'B',
lParam);
CallWindowProc(OriginalEditProc,
hWnd,
Message,
(WPARAM) '>',
lParam);
return 0;
}
else if (wParam == CR)
{
CallWindowProc(OriginalEditProc,
hWnd,
Message,
(WPARAM) '<',
lParam);
CallWindowProc(OriginalEditProc,
hWnd,
Message,
(WPARAM) 'C',
lParam);
CallWindowProc(OriginalEditProc,
hWnd,
Message,
(WPARAM) 'R',
lParam);
CallWindowProc(OriginalEditProc,
hWnd,
Message,
(WPARAM) '>',
lParam);
return 0;
}
else if (wParam == ESC)
{
CallWindowProc(OriginalEditProc,
hWnd,
Message,
(WPARAM) '<',
lParam);
CallWindowProc(OriginalEditProc,
hWnd,
Message,
(WPARAM) 'E',
lParam);
CallWindowProc(OriginalEditProc,
hWnd,
Message,
(WPARAM) 'S',
lParam);
CallWindowProc(OriginalEditProc,
hWnd,
Message,
(WPARAM) 'C',
lParam);
CallWindowProc(OriginalEditProc,
hWnd,
Message,
(WPARAM) '>',
lParam);
return 0;
}
}
return CallWindowProc(OriginalEditProc,
hWnd,
Message,
wParam,
lParam);
}
In other words, you invade into the window's procedure do whatever you want and every else goes the way it should, am i right?