Member 7912784 Ответов: 2

Как исправить ошибку с помощью этого кода C#


Я пытаюсь создать клавишу presser для игры, она требует нажатия (пробел + число), чтобы сделать какое-то действие я попробовал этот код

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {

        [DllImport("user32.dll", SetLastError = true)]
        static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);

        [DllImport("user32.dll")]
        public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        const uint WM_KEYDOWN = 0x100;
        const uint WM_KEYUP = 0x101;

        public Form1()
        {
            InitializeComponent();
            LoadProcess();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Process p = (Process)comboBox1.SelectedItem;
            keybd_event((byte)Keys.Space, 0, 1, 0);
            Thread.Sleep(50);
            PostMessage(p.MainWindowHandle, WM_KEYDOWN, (IntPtr)Keys.D1, IntPtr.Zero);
            PostMessage(p.MainWindowHandle, WM_KEYUP, (IntPtr)Keys.D1, IntPtr.Zero);
            keybd_event((byte)Keys.Space, 0, 0, 0);
        }

        private void LoadProcess()
        {
            comboBox1.Items.Clear();
            comboBox1.DisplayMember = "MainWindowTitle";
            foreach (Process item in Process.GetProcesses())
            {
                try
                {
                    if (!string.IsNullOrEmpty(item.MainWindowTitle))
                        comboBox1.Items.Add(item);
                }
                catch { }
            }
        }
    }
}


это работает, но продолжайте нажимать пробел

когда я пытаюсь освободить его с помощью этой команды



keybd_event((byte)Keys.Space, 0, 2, 0);


приложение постоянно повторяет нажатие всех клавиш

а если не добавить эту строку то пробел не реален

как это исправить?

Что я уже пробовал:

//this code problem is repeat all the keys
const int KeyDown = 0x0001;
const int KeyUp = 0x0002;
.......

private void button1_Click(object sender, EventArgs e)
        {
            Process p = (Process)comboBox1.SelectedItem;
            keybd_event((byte)Keys.Space, 0, KeyDown, 0);
            Thread.Sleep(50);
            PostMessage(p.MainWindowHandle, WM_KEYDOWN, (IntPtr)Keys.D1, IntPtr.Zero);
            PostMessage(p.MainWindowHandle, WM_KEYUP, (IntPtr)Keys.D1, IntPtr.Zero);
            keybd_event((byte)Keys.Space, 0, KeyUp, 0);
        }


//this code problem is not release the space
const uint WM_KEYDOWN = 0x100;
const uint WM_KEYUP = 0x101;

.........

private void button1_Click(object sender, EventArgs e)
        {
            Process p = (Process)comboBox1.SelectedItem;
            keybd_event((byte)Keys.Space, 0, (int)WM_KEYDOWN, 0);
            Thread.Sleep(50);
            PostMessage(p.MainWindowHandle, WM_KEYDOWN, (IntPtr)Keys.D1, IntPtr.Zero);
            PostMessage(p.MainWindowHandle, WM_KEYUP, (IntPtr)Keys.D1, IntPtr.Zero);
            keybd_event((byte)Keys.Space, 0, (int)WM_KEYUP, 0);
        }


//this code problem is not release the space
const uint WM_KEYDOWN = 0x100;
const uint WM_KEYUP = 0x101;

.........

private void button1_Click(object sender, EventArgs e)
        {
            Process p = (Process)comboBox1.SelectedItem;
            keybd_event((byte)Keys.Space, 0, (int)WM_KEYDOWN, 0);
            Thread.Sleep(50);
            PostMessage(p.MainWindowHandle, WM_KEYDOWN, (IntPtr)Keys.D1, IntPtr.Zero);
            PostMessage(p.MainWindowHandle, WM_KEYUP, (IntPtr)Keys.D1, IntPtr.Zero);
            keybd_event((byte)Keys.Space, 0, 0, 0);
        }


//this code problem is it do nothing
const uint WM_KEYDOWN = 0x100;
const uint WM_KEYUP = 0x101;

.........

private void button1_Click(object sender, EventArgs e)
        {
            Process p = (Process)comboBox1.SelectedItem;
            keybd_event((byte)Keys.Space, 0, 1, 0);
            Thread.Sleep(50);
            keybd_event((byte)Keys.D1, 0, 1, 0);
            keybd_event((byte)Keys.D1, 0, 2, 0);
            keybd_event((byte)Keys.Space, 0, 2, 0);
        }


//this code problem is it do nothing
const uint WM_KEYDOWN = 0x100;
const uint WM_KEYUP = 0x101;
const int KeyDown = 0x0001;
const int KeyUp = 0x0002;

.........

private void button1_Click(object sender, EventArgs e)
        {
            keybd_event((byte)Keys.Space, 0, KeyDown, 0);
            Thread.Sleep(50);
            keybd_event((byte)Keys.D1, 0, KeyDown, 0);
            Thread.Sleep(50);
            keybd_event((byte)Keys.D1, 0, KeyUp, 0);
            keybd_event((byte)Keys.Space, 0, KeyUp, 0);
        }

2 Ответов

Рейтинг:
5

Member 7912784

я нахожу способ решить эту проблему

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace SendKeysWithModefire
{
   public class KeysTest
    {
        [DllImport("user32.dll", SetLastError = true)]
        static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);

        [DllImport("user32.dll")]
        public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        const uint WM_KEYDOWN = 0x100;
        const uint WM_KEYUP = 0x101;
        const uint Key_Down = 0x0001;
        const uint Key_Up = 0x0002;
        private volatile bool _shouldStop;
        private Process _sroProcess;
        private Keys _modefirKey;
        private Keys _pressKey;

        public KeysTest(Process targetSro,Keys modKey,Keys pressKey)
        {
            _sroProcess = targetSro;
            _modefirKey = modKey;
            _pressKey = pressKey;
        }

        public void SendKeys()
        {
            SendKeyWithModefir(_sroProcess, (byte)_modefirKey, (byte)_pressKey);
        }

        public void SendKeyWithModefir(Process _p, byte ModKey, byte PressKey)
        {
            while (!_shouldStop)
            {
                keybd_event(ModKey, 0, Key_Down, 0);
                Thread.Sleep(50);
                PostMessage(_p.MainWindowHandle, WM_KEYDOWN, (IntPtr)(PressKey), (IntPtr)(0));
                PostMessage(_p.MainWindowHandle, WM_KEYUP, (IntPtr)(PressKey), (IntPtr)(0));
                Thread.Sleep(50);
                keybd_event(ModKey, 0, Key_Up, 0);
            }
        }

        public void RequestStop()
        {
            _shouldStop = true;
        }

        ~KeysTest()
        {
            GC.Collect();
        }
    }
}


и это как раз то, что нужно

private KeysTest sendingKeys;
private Thread startSending;

...............

//that code send Left Control + 1
//s is the target process
sendingKeys = new KeysTest(s, Keys.LControlKey, Keys.D1);
startSending = new Thread(sendingKeys.SendKeys); 
startSending.Start();
while (!startSending.IsAlive) ;
Thread.Sleep(2000);
sendingKeys.RequestStop();
startSending.Join();
startSending.Abort();


Рейтинг:
2

Richard MacCutchan

Смотрите примечание в верхней части документации для функция keybd_event (Windows)[^].


Member 7912784

если u означает {обратите внимание, что эта функция была заменена. Вместо этого используйте SendInput.}

я пытаюсь SendInput и та же ошибка приложение продолжает повторять ключи

Richard MacCutchan

Значения, которые вы отправляете в keybd_event, неверны. Посмотрите на документацию более внимательно.

Member 7912784

const uint WM_KEYDOWN = 0x100;
const uint WM_KEYUP = 0x101;
константный инт клавиша вниз = 0х0001;
константный инт клавиша вверх = 0х0002;
const байт VK_SPACE = 0x20;
const байт SpaceSC = 39;


частный недействительными обработчика button1_click(объект отправителя, EventArgs в электронной)
{
Process p = (Process)comboBox1.SelectedItem;
keybd_event(VK_SPACE, SpaceSC, KeyDown, 0);
Нить.Сон(50);
Метод postMessage(стр. MainWindowHandle, WM_KEYDOWN, (указателя IntPtr)ключи.Д1, Указателя IntPtr.Ноль);
Метод postMessage(стр. MainWindowHandle, WM_KEYUP, (указателя IntPtr)ключи.Д1, Указателя IntPtr.Ноль);
keybd_event(VK_SPACE, SpaceSC, KeyUp, 0);
}

код u пожалуйста укажите на неправильные значения в этом коде потому что он постоянно повторяет клавиши

Richard MacCutchan

Вы отправляете неверное значение для KeyDown - пожалуйста, еще раз прочтите документацию.

Member 7912784

const uint Key_Down = 0x0001;
const uint Key_Up = 0x0002;
const байт VK_SPACE = 0x20;
const байт SpaceSC = 39;




частный недействительными обработчика button1_click(объект отправителя, EventArgs в электронной)
{
Process p = (Process)comboBox1.SelectedItem;
keybd_event(VK_SPACE, 0x45, Key_Down | 0, 0);
Нить.Сон(50);
Метод postMessage(стр. MainWindowHandle, WM_KEYDOWN, (указателя IntPtr)ключи.Д1, Указателя IntPtr.Ноль);
Метод postMessage(стр. MainWindowHandle, WM_KEYUP, (указателя IntPtr)ключи.Д1, Указателя IntPtr.Ноль);
keybd_event(VK_SPACE, 0x45, Key_Down| Key_Up, 0);
}


--------------------------------------------------------------

const uint Key_Down = 0x0001;
const uint Key_Up = 0x0002;
const байт VK_SPACE = 0x20;
const байт SpaceSC = 39;




частный недействительными обработчика button1_click(объект отправителя, EventArgs в электронной)
{
Process p = (Process)comboBox1.SelectedItem;
keybd_event(VK_SPACE, 0, 0, 0);
Нить.Сон(50);
Метод postMessage(стр. MainWindowHandle, WM_KEYDOWN, (указателя IntPtr)ключи.Д1, Указателя IntPtr.Ноль);
Метод postMessage(стр. MainWindowHandle, WM_KEYUP, (указателя IntPtr)ключи.Д1, Указателя IntPtr.Ноль);
keybd_event(VK_SPACE, 0, Key_Up, 0);
}

-------------------------------------------------------------

const uint Key_Down = 0x0001;
const uint Key_Up = 0x0002;
const байт VK_SPACE = 0x20;
const байт SpaceSC = 39;




частный недействительными обработчика button1_click(объект отправителя, EventArgs в электронной)
{
Process p = (Process)comboBox1.SelectedItem;
keybd_event(VK_SPACE, 0, Key_Down , 0);
Нить.Сон(50);
Метод postMessage(стр. MainWindowHandle, WM_KEYDOWN, (указателя IntPtr)ключи.Д1, Указателя IntPtr.Ноль);
Метод postMessage(стр. MainWindowHandle, WM_KEYUP, (указателя IntPtr)ключи.Д1, Указателя IntPtr.Ноль);
keybd_event(VK_SPACE, 0, Key_Up, 0);
}

----------------------------------------------------------------

я пробую все это и многое другое, но та же ошибка и msdn говорят, что значение ключа вниз равно
KEYEVENTF_EXTENDEDKEY
0х0001
как мой Key_Down я не получил ошибку в своем коде, почему он продолжает повторять все нажатия

Member 7912784

я пытаюсь использовать третью часть dll inputsimulator & inputsimulator plus

InputSimulator sss = new InputSimulator();
Process p = (Process)comboBox1.SelectedItem;            sss.Keyboard.KeyDown(VirtualKeyCode.SPACE);            Thread.Sleep(50);            PostMessage(p.MainWindowHandle, WM_KEYDOWN, (IntPtr)Keys.D1, IntPtr.Zero);            PostMessage(p.MainWindowHandle, WM_KEYUP, (IntPtr)Keys.D1, IntPtr.Zero);            sss.Keyboard.KeyUp(VirtualKeyCode.SPACE);


та же ошибка продолжайте повторять нажатие

Richard MacCutchan

Это действительно время, чтобы увидеть, что происходит в вашем коде. И это то, что только вы можете сделать, используя свой отладчик.

Member 7912784

когда я удаляю линию :

keybd_event(VK_SPACE, 0, Key_Up, 0);

приложение остановилось повторило код поставило пробел не отпустило я теперь не знаю почему

Member 7912784

я использую отладчик в первом он ничего не показывает так же как обычный метод start и finished
нет повторения или что-то в этом роде

мой последний поступок таков

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace KeysWithModefier
{
    public class Class2
    {
        private Process _p;

        [DllImport("user32.dll", SetLastError = true)]
        static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);

        [DllImport("user32.dll")]
        public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        const uint WM_KEYDOWN = 0x100;
        const uint WM_KEYUP = 0x101;
        const uint Key_Down = 0x0001;
        const uint Key_Up = 0x0002;

        public Class2(Process p)
        {
            _p = p;
        }

        public void SendKeyWithModefir(Keys ModKey, Keys PressKey)
        {
            keybd_event((byte)ModKey, 0, 0, 0);
            Thread.Sleep(50); ;
            PostMessage(_p.MainWindowHandle, WM_KEYDOWN, (IntPtr)(PressKey), (IntPtr)(0));
            PostMessage(_p.MainWindowHandle, WM_KEYUP, (IntPtr)(PressKey), (IntPtr)(0));
            keybd_event((byte)ModKey, 0, Key_Up, 0);
        }

        ~Class2()
        {
            GC.Collect();
        }
    }
}

----------------------------------------------------------------------------------

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using KeysWithModefier;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            LoadProcess();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Class2 ccc = new Class2((Process)comboBox1.SelectedItem);
            ccc.SendKeyWithModefir(Keys.Space, Keys.D1);
            ccc = null;
        }

        private void LoadProcess()
        {
            comboBox1.Items.Clear();
            comboBox1.DisplayMember = "MainWindowTitle";
            foreach (Process item in Process.GetProcesses())
            {
                try
                {
                    if (!string.IsNullOrEmpty(item.MainWindowTitle))
                        comboBox1.Items.Add(item);
                }
                catch { }
            }
        }
    }
}




но он также же клавиши нажимайте рассказать, как я закрываю приложение у меня идей, как сделать этот класс, как приложение закрывается вне его закрыть?

Richard MacCutchan

Я не использовал keybd_event, но, возможно, смешивание этого с PostMessage вызывает проблему. Но Смотрите также последний комментарий в вашем другом вопросе.