Ampersand accelerators cause a beep in a Win32 dialog - c++

I have a dynamically created toolbar on a plain Win32 dialog. My buttons are added with & shortcuts which correctly puts underscore to characters following ampersand but pressing Alt+(char) causes a beep and the button is not clicked.
It has been a while since I have done Win32 API development. Is there something that needs to be done to a dynamically created child window (toolbar) in order for the accelerator keys to work?
This could be something really obvious that I am missing...

Well... You have to write code to handle these keypresses and convert them into WM_COMMAND messages. The traditional way to do this is to define an accelerator table and process them using TranslateAccelerator() - but of course, you're free to do it however you like... Just make sure the keys you handle jibe with the keys you underline!
You might also find this KB article helpful: How to use accelerator keys within a modal dialog box in Visual C++... Or, for a more in-depth (and MFC-free) look at implementing custom message processing in dialogs, check out Raymond Chen's articles on the dialog manager, specifically part 4: The dialog loop and part 9: Custom accelerators in dialog boxes (but seriously, read the whole thing, you know you want to...)

The beep indicates that the command isn't handled by any window in your app.
Since you created the toolbar dynamically, I would guess that the toolbar window isn't set up properly as a child window of your main window (i.e., it's parent and owner window are not set).
To test: click on the toolbar so it has the focus, then press Alt- and it should work.

Related

Adding custom controls to a console window

Is it possible to add custom controls to a console window? You can use GetConsoleWindow() to get the window's handle, and then add your own menu items or consume all its events. I can't find any examples of people adding extra controls though.
I am developing a small, high performance serial terminal app. It is a console application - RichTextBox is too slow and has issues that make it unsuitable for VT100 terminal emulation.
I want to add some little graphics to show the state of the serial control lines (RTS/CTS/DTR/RI etc.) and perhaps a capture on/off toggle button. Ideally I'd like to add them to the window title bar. Bitmaps are all that are required.
After lots of research I found that it isn't easy, or even possible really.
You can add controls to the window with CreateWindow(), but of course only in the client area which is taken up entirely by the console text box. However, you can at least create floating controls that way, which hover over the text to provide status info etc.
You can put controls in the window borders but only with some hacking on XP or a new API that was introduced with Vista. The problem with this API is that it requires you to draw your own program icon and title text, and the console window doesn't seem to cope with it very well.
You can't add your own menu items because the console window doesn't pass the messages.
In the end I used the function keys for everything and gave a status indication by changing the console window icon.

Keyboard messages from child controls

I am currently developing a user interface DLL that uses the WIN32 API. The DLL must work for numerous platforms, XP, WIN CE, etc. I have managed to incorporate docking, anchoring and so on but appear to have a problem regarding owner-drawn buttons. I can draw the button's correct state, focus, clicked, default. However, I cannot receive key notifications. I specifically want to perform a click operation on a button that currently has focus, should the user press enter.
Note that I am using a windows message loop rather than a dialog message loop. I use windows hooks to hook into the window creation and set the user data to 'point' to my control instance. If I test for WM_KEYDOWN in the main message loop I can get a handle to my button control instance and could forward the message to the relevant control. Unfortunately, I am dealing with a lot of legacy code and this may not be an ideal solution.
So, my question is what is the best way forward. Is subclassing the button control's window procedure a viable option or is there an easier way?
Many thanks in advance.
The comments above are correct. The button with focus should be getting the key messages. But buttons don't (by themselves) respond to Enter--they respond to Space. It sounds like what you're missing is the typical dialog keyboard navigation, like Tab key moving the focus and Enter activating the "default" button.
If you've got a typical Windows message pump, and you want the keyboard behavior normally associated with dialogs, then you need to use the IsDialogMessage API in your message loop. This means your window is essentially a "modeless dialog".
Looks like standard window proc subclassing should do the trick. See http://msdn.microsoft.com/en-us/library/windows/desktop/ms633591(v=vs.85).aspx for details.

How to prevent arrow keys from changing the UI state?

I am developing a Tetris game using C++ in combination with the plain old WinAPI, GDI and GDI+. The applications window contains a few UI controls along with a static control that is used for painting the game state. I am using a keyboard hook so that I can respond to the arrow keys to move the current block and the space bar to drop the block.
However, the keystrokes also affect the UI. Moving the arrow keys may change the radio or combobox selection state and pressing the space bar may trigger a button or checkbox, depending on which control currently has focus.
Is there a way to prevent this from happening? My temporary hack is to force focus on a hidden textbox. I would appreciate a cleaner solution.
If you're using a WH_KEYBOARD_LL or a WH_KEYBOARD keyboard hook, you can return 1 from the hookproc to prevent the key from being passed to the rest of the system.
Do no call the next hookproc in that case.
However, this could play havoc with things that use hooks and come after you in the hook chain.
If you're writing a GDI app, you have a message loop already, is there any reason you're not using the message loop to look for KEY_UP/KEY_DOWN messages?
You can set other controls so they will not take focus...
Is this a real hook (set with SetWindowsHook)? If so, you could return a non zero value from the hookproc when you handle the message, and Windows will not pass the message along to the dialog.

button keyboard focus issues

How would one prevent the little dotted square that appears on a button when it has the keyboard focus in a dialog. (w/ apologies for the technical jargon). At one point I hacked together a solution by subclassing a button WindowProc and subverting some windows messages, but wanted to know the correct way.
There's actually a problem with another control in the dialog also involving the keyboard. This other control is actually also a button, but being used as a group box or panel, not as a functioning button. But when I hit the tab key in the dialog, this group box "button" comes to the foreground obscuring the static controls on top of it, so I wanted to prevent that.
For both of the above, I tried turning off WS_TABSTOP - didn't help.)
Both of my problems mentioned above were solved by subclassing the WndProcs and returning 0 in response to message 0x128 and discarding it. Even Spy++ could not identify this message 0x128, and I don't have it in any header. But its sent to every control in the dialog the first time tab is hit in the dialog.
(I did try BN_SETFOCUS as described above and also WM_SETFOCUS but it didn't help.)
So if anyone knows where to find what windows message 0x128 is...
The correct way is to write your own button control instead of using the default Windows one.
Alternatively, you can prevent if from ever getting keyboard focus.

DLL plugin that creates a parented window doesn't handle messages correctly

I'm creating a plugin framework, where my application loads a series of plugin DLL's, then creates a new window and pass this new window's handle to the plugin. The plugin can, then, use this handle to create their own GUI.
Everything seems to be working very well. The only problem is that when I press TAB on a plugin widget (An editbox, for example), it doen't jump to another widget. I figured out that some Windows messages are passed, and some others aren't. The WM_KEYDOWN is passed for other keys, because I can type on the editbox, but this message doesn't handle TAB key.
Hope somebody has a hint.
I'm using Borland VCL with CBuilder, but I think I could use any framework under WIN32 to create these plugins, since they never know how their parent windows were created.
It's very complex matter indeed.
When you hit TAB focus jumps to another control only when these controls belong to a Modal Dialog Box. In fact there are some buttons like ESC, LEFT, RIGHT, DOWN, UP, TAB which modal dialog message function treats in a special way. If you want these keys to behave in similar way with modeless dialog box or any other window you should change you message processing function and use IsDialogMessage inside. You'll find more information about IsDialogMessage function in MSDN also to better understand this stuff you may check as well Dialog Boxes section.
And, as was mentioned before, you should set WS_TABSTOP and WS_GROUP styles when needed.
Good luck!
I believe you'll have to take the following steps:
Subclass your edit controls (and other controls as needed).
Capture the WM_KEYDOWN message in your edit control's WndProc.
Check to see if the shift key is currently held down (using GetKeyState or similar).
Call GetWindow, passing in a handle to your edit control and either GW_HWNDPREV or GW_HWNDNEXT depending on whether shift is held down. This will give you the handle to the window that should receive focus.
Call SetFocus and pass in the window handle you got in step 4.
Make sure you handle the case where your edit controls are multiline, as you might want to have a real tab character appear instead of moving to the next control.
Hope that helps!
I believe you suffer from having a different instance of the VCL in each of your dlls and exes. Classes from the dll are not the same as the ones from your exe, even if they are called the same. Also global variables (Application, Screen) are not shared between them. Neither is the memory since they both have their own memory manager.
The solution is to have the dlls and the exe share the VCL library and the memory manager. I am not a BCB developer, but a Delphi developer. In Delphi we would just use the rtl and the vcl as runtime packages. Maybe you could do the BCB equivalent.
A DLL has its own TApplication object.
to provide uniform key handling. when the DLL Loads.
assign the DLL::TApplication to the EXE::TApplication
Be sure to do the reverse on exit.
--
Michael