Pergunta

I'm am dealing with the exact same situation as This Question.

There were no answers and the question was too old, so I could not leave any comments seeing if the OP found a solution.

I am just now learning the basics of p/invoke, and hardly understand it at the least.

I have been doing quite a bit of searching. I found This question which linked me to This question/answer but am still not able to understand what I need to do.

I guess i'm asking for a way to manipulate the WM_IME commands, or atleast disable the WM_IME_ENDCOMPOSITION on mouse clicks.

Thank you in advance

Foi útil?

Solução

No expert in IME, but couldn't you just override the 'WndProc' but not pass the "message" as it were preventing other applications / controls from processing it? WndProc captures the hundreds of 'Windows Messages' that are generated by the operating system that can be captured to 'whoever' is listening, one approach would be to selectively ignore that message when the conditions are right...

protected override void WndProc(ref Message m)
  {
    switch(m.Msg)
    {
      case WM_IME_ENDCOMPOSITION :
        // Gobble this up or ignore
        break;
      default:
        // Continue as normal
        base.WndProc (ref m);
        break;
    }
  }

For instance, if you're dealing with a Control, you could override the WndProc for the control, capture the mouse down event (or WM_MOUSEDOWN), set a variable to ignore the WM_IME_ENDCOMPOSITION and then reenable that variable on the mouse up (or WM_MOUSEUP)? Alternatively you could utilise a MouseHook but this might be a bit of overkill...

Outras dicas

What I ended up doing, as WM_IME_ENDCOMPOSITION apparently wasn't firing, I tried disabled the mouseactivate winproc instead.

        private const int WM_MOUSEACTIVATE = 0x0021;
        private const int MA_NOACTIVATEANDEAT = 0x0004;

        protected override void WndProc(ref Message m)
        {
            if (mousestatus == 0)
            {
                if (m.Msg == WM_MOUSEACTIVATE)
                {
                    m.Result = (IntPtr)MA_NOACTIVATEANDEAT;
                    return;
                }
                base.WndProc(ref m);
            }
        }

and then changed all my panel click event handlers to mouse over events. Because there were parts of the application that did need to be clicked, I added a mousestatus variable so that only when mousestatus was 0 would the mouse clicks be disabled. This was defined by mouse position (as with the mouseclicks disabled, I wouldn't be able to click anything to enable it).

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);

    private void timer1_Tick(object sender, EventArgs e)
    {
        if ((Cursor.Position.X - Location.X) >= 904 && (Cursor.Position.X - Location.X) <= 963 && (Cursor.Position.Y - Location.Y) >= 145 && (Cursor.Position.Y - Location.Y) <= 167)
        {
            mousestatus = 1;

            mouse_event(MOUSEEVENTF_LEFTDOWN, Cursor.Position.X, Cursor.Position.Y, 0, 0);
            mouse_event(MOUSEEVENTF_LEFTUP, Cursor.Position.X, Cursor.Position.Y, 0, 0);


            timer4.Start();

        }
    }

I was pretty sure that the click would come before the mousestatus=1 was defined, so just to make sure the spot I needed was clicked, I put in a virtual mouse click. the timer4 was just a timer that set mousestatus back to 0.

The code may be a bit messy, and i'm sure there are some shortcuts I could have used, but as of now, it works for what I need. =D

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top