views:

168

answers:

3

Like the title says, I've got a Child form being shown with it's TopLevel property set to False and I am unable to click a MaskedTextBox control that it contains (in order to bring focus to it). I can bring focus to it by using TAB on the keyboard though.

The child form contains other regular TextBox controls and these I can click to focus with no problems, although they also exhibit some odd behavior: for example if I've got a value in the Textbox and I try to drag-click from the end of the string to the beginning, nothing happens. In fact I can't use my mouse to move the cursor inside the TextBox's text at all (although they keyboard arrow keys work).

I'm not too worried about the odd TextBox behavior, but why can't I activate my MaskedTextBox by clicking on it?

Below is the code that shows the form:

Dim newReportForm As New Form
Dim formName As String
Dim FullTypeName As String
Dim FormInstanceType As Type

formName = TreeView1.SelectedNode.Name

FullTypeName = Application.ProductName & "." & formName

FormInstanceType = Type.GetType(FullTypeName, True, True)

newReportForm = CType(Activator.CreateInstance(FormInstanceType), Form)
Try
   newReportForm.Top = CType(SplitContainer1.Panel2.Controls(0), Form).Top + 25
   newReportForm.Left = CType(SplitContainer1.Panel2.Controls(0), Form).Left + 25
Catch
End Try
newReportForm.TopLevel = False
newReportForm.Parent = SplitContainer1.Panel2
newReportForm.BringToFront()                
newReportForm.Show()
+1  A: 

The text box behavior is a symptom of the same problem. Something is swallowing mouse down notifications. It isn't explained by your code snippet. Forms indeed swallow the mouse click that activates them, but that is a one-time behavior and is turned off by setting its TopLevel property to False.

Not much left. One candidate is the Control.Capture property, turned on at the MouseDown event for a button so that the button can see the MouseUp event, no matter where the mouse moved. That's a one-time effect as well. Watch out for controls that set the Focus in a MouseDown event.

The other is some kind of IMessageFilter code in your form(s) that's eating WM_LBUTTONDOWN messages.

Hans Passant
Thanks for your insight Hans. I can contribute that I set TopLevel to True, and the weird behavior is no longer present. I haven't been able to find any dead-giveaways of Handlers that might swallow the event, use of the Control.Capture property, or any IMessageFilter code. Unfortunately I did not write the code for the Parent form so I may be missing something. Would it help if I posted the rest of the code for the Parent Form? It's about 300 Lines.
Overhed
Doubtful. Use Spy++ to see where that click is going.
Hans Passant
Looks like the click is getting all the way to the Parent Form. I'm not 100% sure what I'm looking for, but the events that are fired when clicking the Masked Text Box all seem to match those fired when clicking a regular Text Box (that does gain focus correctly).
Overhed
+2  A: 

I tried your code and got a good repro this time. As I mentioned in my original post, this is indeed a window activation problem. You can see this in Spy++, note the WM_MOUSEACTIVATE messages.

This happens because you display the form with a caption bar. That convinces the Windows window manager that the window can be activated. That doesn't actually work, it is no longer a top-level window. Visible from the caption bar, it never gets drawn with the "window activated" colors.

You will have to remove the caption bar from the form. That's best done by adding this line to your code:

    newReportForm.FormBorderStyle = Windows.Forms.FormBorderStyle.None

Which will turn the form into a control that's otherwise indistinguishable from a UserControl. You can still make it distinctive by using this code instead:

    newReportForm.ControlBox = False
    newReportForm.Text = ""

Either fix solves the mouse click problem.

Hans Passant
You were right and both of those suggestions fix the issue. However it displays the form in a way we don't want. Really what we're trying to do is display this form (modelessley) within a panel of a SplitContainer (so that the form is not draggable outside of this splitcontainer panel).At this point I'm fairly certain we're going about it the wrong way and we'll need to adjust how we're showing the form. Many thanks for all your help.
Overhed
+1  A: 

This is a miserable bug and it took me a long time to find this question. We're doing exactly the same thing as the OP, displaying a Form inside a split container. My workaround was to add an event handler to the MaskedTextBox's Click event:

    private void MaskedTextBoxSetFocus(object sender, EventArgs e)
    {
        var mtb = (MaskedTextBox)sender;
        mtb.Focus();
    }

This works for the MaskedTextBox but I'm concerned about other odd behavior due to this bug so I will probably set the border style as in the accepted answer.

Jamie Ide
We're doing the exact same thing as a workaround. However, as I'm sure you've noticed, you can't select which character to position your cursor at when you focus. So it will go to the last known position every time you click. Annoying if you're trying to click on a different part of the Text entered.
Overhed