Search code examples
c#mouse-cursortoolstripdropdown

Mouse cursor disappears when textbox at ToolStripDropDown editing


I have a user control with RichTextBox and two buttons on it. I'm trying to show that at ToolStripDropDown on ToolStripButton click. I'm using ToolStripControlHost to put my control at ToolStripDrowDown. When I click ToolStripButton at form toolbar, I show dropdown at some position and make focus at ToolStripControlHost control. Mouse pointer stays above ToolStripButton and cursor is at RichTextBox. But when I start editing RichTextBox mouse pointer disappears and I can see it only when it's out of form rectangle. How can I fix it?

Here is my code:

private void toolBtnNote_Click(object sender, EventArgs e)
{

   dropDownClosed = false;
   noteChanged = false;

   tsdd = new ToolStripDropDown();
   this.tsdd.Opened += new EventHandler(tsdd_Opened);
   this.tsdd.AutoSize = true;

   NoteEdit ne = new NoteEdit();
   ne.NoteText = note ?? "";
   // appears when user clicks first button at my control
   ne.OkClick += new NoteEdit.NoteEditEvent(ne_OkClick);
   // appears when user clicks second button at my control
   ne.CancelClick += new NoteEdit.NoteEditEvent(ne_CancelClick);

   this.tbh = new ToolStripControlHost(ne, "noteEdit");
   this.tbh.Padding = new Padding(0);
   this.tbh.AutoSize = false;
   this.tbh.Size = ne.Size;

   this.tsdd.Items.Add(tbh);
   this.tsdd.Padding = new Padding(0);
   this.tsdd.Closing += new ToolStripDropDownClosingEventHandler(tsdd_Closing);
   // show toolstripdrowdown at specific position at DataGridView         
   this.tsdd.Show(dgvMarks, cellRect.Location + new Size(0, cellRect.Height));

   while (!this.dropDownClosed)
   {
       Application.DoEvents();
   }

   if(noteChanged) {...}
}

void ne_CancelClick()
{
    tsdd.Close();
}

void ne_OkClick()
{
    noteChanged = true;
    tsdd.Close();
}

void tsdd_Opened(object sender, EventArgs e)
{
    tbh.Focus();
}

void tsdd_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
    dropDownClosed = true;
}

Solution

  • I found the solution. Not best but it works. I just simulate click at shown RichTextBox with WinApi like that:

    public class WinApiHelper
    {
        private const UInt32 MOUSEEVENTF_LEFTDOWN = 0x0002;
        private const UInt32 MOUSEEVENTF_LEFTUP = 0x0004;
    
        [DllImport("user32.dll")]
        private static extern void mouse_event(
            UInt32 dwFlags, // motion and click options
            UInt32 dx, // horizontal position or change
            UInt32 dy, // vertical position or change
            UInt32 dwData, // wheel movement
            IntPtr dwExtraInfo // application-defined information
            );
    
        public static void SendClick(Point location)
        {
            Cursor.Position = location;
            mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, new System.IntPtr());
            mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, new System.IntPtr());
        }     
    }
    
    private void toolBtnNote_Click(object sender, EventArgs e)
    {
            dropDownClosed = false;
            noteChanged = false;
    
            dgvMarks.Focus();
            tsdd = new ToolStripDropDown();
            this.tsdd.Opened += new EventHandler(tsdd_Opened);
            this.tsdd.AutoSize = true;
    
            NoteEdit ne = new NoteEdit();
            ne.NoteText = note ?? "";
            ne.OkClick += new NoteEdit.NoteEditEvent(ne_OkClick);
            ne.CancelClick += new NoteEdit.NoteEditEvent(ne_CancelClick);
    
            this.tbh = new ToolStripControlHost(ne, "noteEdit");
            this.tbh.Padding = new Padding(0);
            this.tbh.AutoSize = false;
            this.tbh.Size = ne.Size;
    
            this.tsdd.Items.Add(tbh);
            this.tsdd.Padding = new Padding(0);
            this.tsdd.Closing += new ToolStripDropDownClosingEventHandler(tsdd_Closing);
    
            this.tsdd.Show(dgvMarks, cellRect.Location + new Size(0, cellRect.Height));
            // emulate click on richtextbox at dropdown 
            WinApiHelper.SendClick(tsdd.Location + new Size(ne.Rtb.Location) + new Size(5, 5));
    
            while (!this.dropDownClosed)
            {
                Application.DoEvents();
            }
    
            if (noteChanged)
            {...}
     }