-
tab has stopped working
As I have posted before, Im creating my own GUI class wrappers.
Im having a annoying problem that I just cant figure out.
Somewhere along the process I lost the ability to cycle through the child windows on the form using the tab key.
Every class's createwindow has WS_TABSTOP passed as style. And Im not doing anything with the keypressed events or tab.
So im totally confused as to what has happened.
Ill post the relevant sections of the classes.
Base class for controls message handler
Code:
LRESULT CALLBACK vCtrlWindow::baseCtrlMsgHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT callreturn;
vCtrlWindow* pWnd;
//get the class instance from the window
// using the static member GetObjectFromWindow
pWnd = GetObjectFromWindow(hwnd);
//if a valid class object
if (pWnd)
{
//if we getting a left,right,middle button down
if ( ((uMsg==WM_LBUTTONDOWN) || (uMsg==WM_RBUTTONDOWN) || (uMsg==WM_MBUTTONDOWN)) && (hwnd==pWnd->m_hwnd))
{
int xpos=0;
int ypos=0;
long flags=0;
int shift=0;
int button=0;
//set flags to wPara. Need to check it to tell if shift or ctrl key
//was being pressed when control was click
flags=wParam;
//xpos=left-right position of mouse
xpos=LOWORD(lParam);
//ypos=up-down position of mouse
ypos=HIWORD(lParam);
//I know, I know. This should be improved.
//shift key
if ((flags | MK_SHIFT)==flags)
{
shift=shift+1;
}
//ctrl key
if ((flags | MK_CONTROL)==flags)
{
shift=shift+2;
}
//what button was pressed.
if (uMsg==WM_LBUTTONDOWN)
{
pWnd->lastMessage=uMsg;
button=1;
}
if (uMsg==WM_RBUTTONDOWN)
{
pWnd->lastMessage=uMsg;
button=2;
}
if (uMsg==WM_MBUTTONDOWN)
{
pWnd->lastMessage=uMsg;
button=4;
}
//you must call the windows procedure before making
//the function call or the message gets lost. So I assume.
//callreturn=CallWindowProc((WNDPROC)pWnd->originalProc,hwnd, uMsg, wParam, lParam);
callreturn=pWnd->CtrlMsgHandler(hwnd, uMsg, wParam, lParam);
//call this objects OnMouseDown Function
pWnd->OnMouseDown(button,shift,xpos,ypos);
return callreturn;
}
return pWnd->CtrlMsgHandler(hwnd, uMsg, wParam, lParam);
}
//else we couldnt get a valid pointer to a class object
else
{
//so call the original windows procedure
return CallWindowProc((WNDPROC)pWnd->originalProc,hwnd, uMsg, wParam, lParam);
}
}
textbox control is derived from vctrlwindow
Code:
LRESULT CALLBACK vTextBox::CtrlMsgHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT callreturn;
long hwParam=0;
long lwParam=0;
long tttt; //debug only
hwParam=HIWORD(wParam);
lwParam=LOWORD(wParam);
//******************* USED FOR DEBUG ONLY ****************
if ((uMsg==WM_CHAR) && (wParam==9))
{
tttt=0;
}
//*************************************************************
//if the current message is left button up and the last message was
//SetFocus or left button down then treat this as a click.
if ((uMsg==WM_LBUTTONUP) && ((lastMessage==WM_SETFOCUS) || (lastMessage==WM_LBUTTONDOWN)))
{
//call the original message first
callreturn=CallWindowProc((WNDPROC)originalProc,hwnd, uMsg, wParam, lParam);
//set the lastmessage to this message
lastMessage=uMsg;
//call this instance Click member function
OnClick();
//return what the original procedure
return callreturn;
}
//if the messages hwnd is this control parent
if (hwnd==p_hwnd)
{
//and if the message is a command
if (uMsg==WM_COMMAND)
{
//if the command is update
if (hwParam==EN_UPDATE)
{
//call the original message first
callreturn=CallWindowProc((WNDPROC)originalProc,hwnd, uMsg, wParam, lParam);
//set the lastmessage to this message
lastMessage=uMsg;
//call the OnChange member function
OnChange();
//return what the original procedure return with
return callreturn;
}
}
}
//call the original proc
return CallWindowProc((WNDPROC)originalProc,hwnd, uMsg, wParam, lParam);
}
base class for main windows message handler
Code:
LRESULT CALLBACK vBaseWindow::baseWinMsgHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
vBaseWindow* pWnd;
if (uMsg==WM_NCCREATE)
{
// use the pointer to the window from lpCreateParams which was set in CreateWindow
SetWindowLong(hwnd, GWL_USERDATA, (long)((LPCREATESTRUCT(lParam))->lpCreateParams));
}
pWnd = GetObjectFromWindow(hwnd);
if ((uMsg==WM_CLOSE) && (pWnd))
{
pWnd->OnClose(hwnd);
return false;
}
if ((uMsg==WM_DESTROY) && (pWnd))
{
pWnd->OnDestroy(hwnd);
return false;
}
if (pWnd)
{
pWnd->WinMsgHandler(hwnd, uMsg, wParam, lParam);
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
else
{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
//return false;
}
main window is derived from vbasewindow
Code:
BOOL CALLBACK vForm::WinMsgHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
long hwParam=0;
long lwParam=0;
int tttt;
hwParam=HIWORD(wParam);
lwParam=LOWORD(wParam);
if (uMsg==258)
{
tttt=0;
}
if ((m_hwnd!=0) && (uMsg==WM_COMMAND))
{
HWND cwnd;
cwnd=HWND(lParam);
long resIdent;
resIdent=GetWindowLong(HWND(lParam),GWL_ID);
if (resIdent==lwParam)
{
tcontrol=GetObjectFromCtrl(HWND(lParam));
if ((tcontrol))
{
//call the child control message handler
tcontrol->CtrlMsgHandler(hwnd,uMsg,wParam,lParam);
return false;
}
}
}
return false;
}
Everything else works fine. Any help would be great.
Also would it be better to attach the full src?
Thanks
Packetvb
-
I think there's an extended style, WSEX_CONTROLPARENT or something like that, that the parent should have.
-
CornedBee,
I tried the WS_EX_CONTROLPARENT and it didnt work either. But I did figure something out.
Before I had in message pump (i guess its called) a IsDialogMessage. Then I moved it to its own class and took it out. It seems that the IsDialogMessage has something to do with using tab to cycle through the controls. I had to pass the the HWND of the main window to the message function and use it in the IsDialogMessage API. I couldnt just use the hwnd member of the message struct because once the API got a HWND of a child window control as parameter it stopped handing the tab cycle. Very very odd.
by the way: you seem to know alot about c++ and API's, may I ask if programming is your profession?
Thanks for the suggestions.
packetvb
-
I'm studying Software & Information Engineering, so Programming will be my profession. And I make some money with it even now.