Mfc Mousewheel not spinning spin button controlled textbox - mfc

I have a MFC application form as the figure:
And I was wondering why the mousewheel was working on the "Base angle:" field (for controlling the spin control), but not on the "Angle" and "Range" fields. Clicking directly on the spin buttons was working perfectly.
The same was happening for the "Base angle" and "±" fields of the Nesting form:
My hypothesis: it is happening because the fields are inside a groupbox
What I did to test it: I changed the groupbox dimensions in the teo froms, in a way that the non-working fields are not overlaping it:
The results: The mouse wheel began to work on the controls of the Part Orientation dialog. But in the Nesting dialog it continued to refuse to work.
Notes:
The textboxes are CEdits. They DDX with CString variables.
Part Orientation is a Modal Dialog.
Nesting is a form inside a CMFCTabControl, inside CDialogBar, inside a CDockablePane, inside the CMainFrame(this one is derived from CFrameWndEx)
Now, my suspects:
For the form Part Orientation Dialog, I suspect the groupbox is eating the mouse wheel event.
For the Nesting Dialog, I suspect the DockablePane is eating the mousewheel event. Or maybe an implicit CTabbed Pane, created by the Layout of panes I've designed; or even the MainFrame.
My question is: How can I make the mousewheel work on spin button controlled textboxes that are inside groupboxes? I have many more cases of this in my App Dialogs.
Is there a way that I can make the mouse wheel movement being processed by who should do it? The same question applies to the Nesting Form controls which groupbox area has been removed and mouse wheel continued to not make the spinbutton move!
Thanks in advance,
Sérgio

The first step this was to disable a little software I have here called WizMouse.
The mouse wheel became to work immediatly in the spinner controlled textboxes of the Part Orientation Dialog.
To Make the others work I had to change the spinner RC definition from
UDS_ARROWKEYS
to
UDS_SETBUDDYINT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK
This made the mouse wheel move, but in undesired manner: it was stepping by one unit, moving up was decrementing, and it had an upper limit of 100!
Why? Because, I have a function for handling UDN_DELTAPOS to manipulate the offset of the spinner. It defines to step the value as a double with a delta of 5.0. And this was happening also when clicking direcly on the two spinner buttons!
In that function, all I had to do is to set *pResult to 1 instead of 0.
Now everything works fine :)
Thanks, one more time.

Related

Capture mouse clicks on text boxes in a Win32 game

Using C++, I am making a Tic-Tac-Toe game using the Win32 API. To mark a square (X or O) I want the player to click the square which then changes to an X or O.
What I am doing right now is having a button click event which turns a static text box to X or O. However, when I place the button on top of the text box and make it not visible, I can't click it.
What I really need is an invisible button that still functions. So it's not set WS_VISIBLE, but you can still click it.
Is this possible or is there another way around this problem?
I can see a couple of reasonable possibilities here.
The first and most obvious would be to skip using a button at all, and just have the underlying window process the WM_LBUTTONDOWN message, and set the "X" or "O" in the correct location. For this, you don't even need static controls -- you can just detect the mouse clicks directly on the parent window, and draw your "X" or "O" in the corresponding square.
Another possibility would be a button that's marked as "visible", but happens to be transparent. IMO, this is a fairly poor choice though. To do it, you'd need to either create a transparent button control on your own, or subclass a button control to disable its drawing.
At least IMO, the obvious route would be to skip using the static control at all. Instead, just use the buttons directly -- a button normally has a caption. Start with that caption as an empty string. When the button is clicked, change its caption to "X" or "O" as appropriate. It should probably also disable itself in response to the button click, so clicking it again won't have any further effect.
There's no way to make an invisible button that still functions. Imagine all of the ways that could be abused if it were possible! Not to mention how confusing to have invisible, yet functional, UI.
What Mark Ransom posted is exactly right: you need to get your existing control to respond to mouse click events, just like a button does. Then you can do whatever you want in response to clicks. You don't need a button just to be clickable.
You say that you have a "static text box", but I'm not really sure what that is. There are text boxes (which are not static), and then there are static controls (which can display text). I'm going to assume that you have the latter.
In that case, you don't need to handle the WM_LBUTTONDOWN and WM_LBUTTONUP messages directly, which would require that you subclass the control. Although that's probably the best approach design-wise (separation of responsibilities and all that), it's also a lot more trouble.
Instead, you can handle the click events from the parent's window procedure by setting the SS_NOTIFY style for your static control (you can do this either in the Dialog Editor or in your call to CreateWindow, depending on how you create the control). This causes the control to notify its parent in four cases: when it is clicked (STN_CLICKED), when it is double-clicked (STN_DBLCLK), when it is enabled (STN_ENABLE), and when it is disabled (STN_DISABLE).
So at the parent, you need to process WM_COMMAND messages. The message you're looking for will have a HIWORD(wParam) of STN_CLICKED (indicating that a static control with the SS_NOTIFY style has been clicked), a LOWORD(wParam) corresponding to your static control's ID (set either in the Dialog Editor or specified as the hMenu parameter in your call to CreateWindow), and an lParam containing a handle to your static control.
If you use SW_HIDE, it doesn't just make the window invisible but makes it behave like that too. What you really wanted is probably just make the button transparent. I never did that, you may find this or this helpful.
You may just scrap the textbox just use the button, i mean a button-looking checkbox with ownerdraw or bitmaps. Or scrapping the button and handle the mouse events Like Mark suggests.

Keyboard focus: looking for a general strategy

My application has a big graphics area with some controls (sliders, buttons, text edit controls) in a side panel. The graphics area understands some keyboard commands.
My problem is that when a control in the side panel is in focus, the main graphics area won't receive any keyboard commands, so this confuses the users. However, for some controls, this is intended, e.g. text edit controls.
What I want is the focus to automatically return to the graphics area at the earliest possible occasion (which I call "greedy" focus) -- e.g. when text editing is finished (Enter key), or when the user has selected an item from a combo box.
I am looking for a clean and robust strategy for dealing with the problem, either using Windows API or Borland Vcl.
I'd appreciate if you want to share your ideas.
I haven't fully solved the problem yet, but a very useful message to intercept on form level is CM_DIALOGKEY (Borland Vcl only). It gets sent for every key that is normally used for navigating within the UI. That is, cursor keys, tab and shift-tab, Enter and possibly others.
I've added an event handler for CM_DIALOGKEY that returns the focus to the graphics area and also forwards the key press to that component. This way the user can still control the UI elements via keyboard (important for text entry), but cursor keys are handled by the graphics area.
I know what you mean I had similar problem with some BIG apps lice CAD/CAM ...
My solution is simple, robust and I use it for years.
1.all keystrokes handling for that gfx area
must be done in events of the Form where the area is located
not in panels,paint box whatever...
2.create unfocus function (preferably member of form but it is not required)
this function will loose focus of any VCL item
so the focus goes to form itself which is what you want
I am using this:
//---------------------------------------------------------------------------
void main_unfocus()
{
Main->bt_unfocus->Visible=true;
Main->bt_unfocus->SetFocus();
Main->bt_unfocus->Visible=false;
}
//---------------------------------------------------------------------------
Main is the Form pointer
bt_unfocus is button (can be any focusable VCL component)
I place this button usually on the left upper corner of App and set its size to 2x2 pixels
it is invisible at start
the idea is to set focus to it (but first unhide it so no exception is thrown)
and then hide it so it loses focus
work well in BCB5 and BDS2006 (did not used it with any other IDE)
as you can see most of the time is this component invisible
4.now when to call main_unfocus ?
when you go with mouse from outside to inside of your gfx area (OnMouseMove event)
or when you click on it
also you can combine this with remembering if the focus is or not in gfx area
that can be done with events like OnExit ...
or when you hit Esc while focus is inside edit box ...\
I am sure you grasp the idea and adjust this to your needs
Hope it helps

Use dialog controls without stealing focus

I have a modeless CDialog that contains controls, some CButtons and a CScrollbar. The CDialog is parented off of an edit box that I want to keep focus at all times. The problem is that whenever the user uses the controls, clicking a button or on the scrollbar, the control steals focus from the edit box, causing both the parent window to draw without focus (grayed-out header bar), and causing the control to take all the keyboard input. Is there a way for the controls to respond to mouse actions but not steal focus?
The controls and the dialog are all created with WS_CHILD. The controls are parented off the dialog, and the dialog is parented off of the edit box.
I've tried setting focus back after the controls are used, but that causes the parent window to flicker as it loses and then regains focus. Basically I want something that works like a combo box, where the scroll bar can be clicked or dragged around, but keyboard input still goes to the dialog itself, not just the scroll bar, and the whole thing never loses focus.
I haven't done anything like this for a long time, so I'm sure there are a million little details, but I think the starting point is to override the handling of WM_MOUSEACTIVATE.
I am a little confused about child-parent relationship you described.
Can you explain what do you mean by:
The CDialog is parented off of an edit box that I want to keep focus at all times
Any window hosting other windows inside of the client area is a parent of those windows. It is impossible to create window without WS_CHILD that is contained by other window.
Therefore all dialog’s controls are children of this dialog. It is also possible that child window hosts another child window.
CDialog is just an MFC representation of a dialog window; the same applies to other controls. For example CButton is an MFC class that wraps handle of the window’s window that is predefined as window button control.
Dialog never has focus unless is empty (does not have any controls). If dialog contains even one control, this control always has focus.
What focus means is that any given window receives mouse and keyboard messages. Only one control can have focus at any given time. In order for scroll bar to process mouse click or keyboard to move slider, scroll bar must have focus; therefore some other control must give it up.
Combo box drop box (I think this is what you are referring to) is not a child of the dialog. It is a popup window that for the duration has keyboard focus and captures mouse. When it drops down, dialog is deactivated and once dropdown hides, dialog state is changed back to active hence focus never changes, it returns to the control that had focus when dialog was deactivated.
What you are trying to do is probably possible but it would require a lot of coding. Probably hooking messages would do the job but I think it would be going against the stream.

Avoid Flickering on a dialog that moves its controls on resize

I have a popup dialog( CDialog ) that handles WM_CTLCOLOR message to color itself. It is having some controls (like bitmap buttons) that draws themselves using OwnerDraw. It is also having a control that displays an image with size that takes up to 70% of the dialog.
When user re-sizes the dialog, some of the controls in the dialog should be re-positioned (not re-sized). It also involves re-sizing of the image inside the dialog. As the re-sizing of image makes the whole process slow, individual re-positioning of the controls are causing a visual effect of flickering.
I need to get rid of these. One idea is to put the controls as the children of an intermediate dialog that is the child of the original popup dialog. So, when there is a re-size, I can re-position the dialog only instead of moving each controls individually. (Re-position happens only in one direction (x or y), so moving the intermediate dialog should be enough.
As it involves some coding effort, before going this way, I need answers to the following questions:
Will this work?
If yes, whats the complexity involved in this method?
Is there a better way?
Please help!
Simple fixes are:
creating the slow window last so that it doesn't hold up drawing of the simple controls
turning on the WS_EX_COMPOSITED style flag so Windows double-buffers the entire window, including its children. Beware of painting artifacts
turning off the WS_CLIPCHILDREN style flag so the holes are not so noticeable. Making the background white would accomplish the same
keeping the drawing of slow controls simple between WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE
using less controls, burning up an expensive window on a simple string or image is unnecessary
It will probably work, but you should try solutions that don't alter your control hierarchy before, because it has other subtle consequences (focus, tab order, message notifications, etc).
Try one or all of the following:
Use BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos functions to move the children.
Set the WS_CLIPCHILDREN style flag in the dialog.
Set the WS_EX_LAYERED extended style flag in the dialog.

Custom dropdown for CComboBox

I'm trying to create a custom dropdown for a derivative of CComboBox. The dropdown will be a calendar control plus some 'hotspots', e.g.
So I figure the best way to achieve this is to have a simple CWnd-derived class which acts as the parent to the calendar control, and have it paint the hotspots itself.
The window needs to be a popup window - I think - rather than a child window so that it isn't clipped. But doing this causes the dialog (on which the combobox control is placed) to stop being the topmost (foreground?) window, leading to its frame being drawn differently:
alt text http://img693.imageshack.us/img693/3474/35148785.png
This spoils the illusion that the dropdown is part of the combobox since its acting more like a modal dialog at this point. Any suggestions on how I make the custom dropdown behave like the regular dropdown?
Are there any other pitfalls I need to watch out for, e.g. focus and mouse capture issues?
When you create your popup window, you need to specify its owner. Owned popup windows will activate their owner when you activate them. Not specifying an owner will cause your window to get activated, which causes the change in the owner you're seeing.
Yeah I had this problem once. A quick google makes me suspect I solved this by using CreateWindowEx() and specifying WS_EX_NOACTIVATE. I have some other code that achieves the same effect by making the window with WS_EX_TOOLWINDOW rather than as a popup window, but I'm not sure of why that was done that way, my intuition would say that making it a popup window would be the way to go.
You can find in the following links two sample project that put in the CComboBox dropdown window a CTreeCtrl or a CListCtrl controls ... similar, you can put whatever you need there. Here is the links:
Tree ComboBox Control
and
List ComboBox Control
I hope this help you.