Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17



Posted on 1998-12-24
Medium Priority
Last Modified: 2008-02-01
I am working with VC++ 5.0 on a Win98 system, but have run into this same problem on a Win95 machine.  When I create a window and a group of controls on that window with the following code:

HWND hWnd = CreateWindowEx(WS_EX_NOPARENTNOTIFY, "RegScreen", "Install Pro 1.0", WS_VISIBLE | WS_CAPTION | WS_BORDER | WS_SYSMENU, pt.x, pt.y, 500, 400, NULL, NULL, hInst, NULL);


CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", WS_TABSTOP | WS_CHILD | WS_BORDER| WS_VISIBLE | ES_LEFT, 165, 93, 305, 27, hWnd, (HMENU)IDC_COMPANY, hInst, NULL);      

CreateWindow("BUTTON", "<< Back", WS_TABSTOP | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 210, 325, 65, 27, hWnd, (HMENU)IDC_BACK, hInst, NULL);

CreateWindow("BUTTON", "Next >>", WS_TABSTOP | WS_DISABLED | WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 275, 325, 65, 27, hWnd, (HMENU)IDC_NEXT, hInst, NULL);

CreateWindow("BUTTON", "Cancel", WS_TABSTOP | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 410, 325, 65, 27, hWnd, (HMENU)IDC_CANCEL, hInst, NULL);

Why is it that the Tab button COMPLETLY REFUSES to work under any circumstances?  I was under the impression that if all the controls were created with the WS_TABSTOP style that the tab key would move between them.  However this does not happen on the window that I have created.
Question by:dirtdart
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2

Expert Comment

ID: 1181005
I think...

The parent window for the controls needs to handle the WM_NEXTDLGCTL message.  The reason you don't need to include this code for dialog boxes, is that the default dialog procedure (DefDlgProc) handles this by default.  In your case, your parent window isn't a dialog, so you have to put in this code yourself in the parent window (the one you create first).

BTW if you are thinking of changing to use a dialog/modeless dialog box for the parent, watch out - I seem to recall that DefDlgProc only handles WM_NEXTDLGCTL message correctly for controls that are in the dialog's resource template at least under some versions of Windows.  Sorry I can't be more specific on this (extra) comment, as I simply don't remember too well!

Author Comment

ID: 1181006
Well, this seems like a logical answer, but I'm going to need a bit more information before I can grade it.  I attempted to process the message with what little information I can find on it in the Win32 SDK, but it certainly didn't work in the way I need it to.  My code:

            SetFocus(GetDlgItem(hWnd, wParam));
            return 0;

Since wParam supposedly returns the ID of the control that should receive focus, this seems to be a logical conclusion.  Whenever the Tab is pressed, it fires the message and the message pump sets the focus to the next provided control.  However.  When run, the above code simply prevents any of the controls on the form from receiving focus.

Author Comment

ID: 1181007
Well, I've waited two weeks for more of an explination, so I guess now I'll have to open the question back up.
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.


Accepted Solution

SaGS earned 800 total points
ID: 1181008
For the TAB key to work, you must call IsDialogMessage() in the main message loop. And call DefDlgProc() for default message processing, instead of DefWindowProc().

From your question&comment I see you are not using MS Foundation Classes. In this case, you have the control on the message loop - just insert IsDialogMessage() there (see help for details).

With MFC (the version I have, at least), CDialog accomplishes this by calling IsDialogMessage() from it's PreTranslateMessage() member function. You can define a CDialog-derived class (to provide the message table), and still create the window with CreateWindow(); just Attach() the HWND to the CDialog-derived object.

What you obtain is the equivalent of using a modeless dlgbox with a private class as the main window (I often use dlgboxes as main windows, it works fine), only that you don't rely on a template and CreateDialog() to create the window and the controls.

Author Comment

ID: 1181009
Well, that looks great, and it certainly answers my question.  However, I'd appreciate it if you'd give me one more piece of advice to go with this.  My main message loop processes messages for at least 12 different windows (kind of a wizard type thing).  How do I tell which window handle is currently being processed so that I can pass it to IsDialogMessage?

Expert Comment

ID: 1181010
The key is the WM_ACTIVATE message. Define a global variable:

HWND hActiveWnd = NULL;

and inside all windows procedures (in fact, it's enough to do this only for windows that need the extra processing) handle the WM_ACTIVATE message. When the window is activated (WA_ACTIVE, WA_CLICKACTIVE), store the window's handle into the global variable; when deactivated (WA_INACTIVE), set the global handle to NULL (Windows takes care to send these messages in the proper order - first deactivates the old window, then activates the new one). In the main message loop, examine the global variable to decide what to do (NULL => nothing to do, the active win does not belong to your app or needs nothing special, !=NULL => your window, the value is the active window's HWND).

Note: You can use a similar trick to implement a window-specific accelerators table (a global "HACCEL hActiveWndAccel = NULL;", and so on).

Author Comment

ID: 1181011
Sounds great.  Thanks for all the help.  Now maybe I can get this junk finished!

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

721 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question