Как я могу прослушать сообщения устройства в проекте C # - PullRequest
0 голосов
/ 05 апреля 2019

это снова я!

Этот вопрос довольно сложный, потому что я сделаю все возможное, чтобы объяснить его: как я упоминал в предыдущем вопросе, я работаю в управлении сканером на C #, используяC ++ dll отправлено провайдером.Согласно руководству API, при определенных условиях отправляются определенные сообщения.Например: после запуска сканера он должен отправить сообщение DEVICE_CONNECTED (со значением 0), а затем изменить его состояние.

Значения этих сообщений определены в .dll

Моя проблема пытается получить эти сообщения в моем проекте C #

Я искал информацию о передаче сообщений, и я обнаружил, что есть WndProc, который обрабатывает сообщения Windows, потому что я попытался следовать их примеру:

private const int DEVICE_CONNECTED = 0;
/*Some code*/
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
protected override void WndProc(ref Message m)
{
    if (m.Msg == DEVICE_CONNECTED)
       listBox1.Items.Add("Connected");
    base.WndProc(ref m);
}

Конечно, этот сбой.

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

// This is how is defined at .dll (C++)
DWORD StartUp( HWND Handle, UINT SorterMessage )

Где «Ручка» - это дескриптор окна назначения сообщений приложения.

Итак, мой импорт на C # выглядит следующим образом:

[DllImport(path, EntryPoint = "?StartUp@@YGKPAUHWND__@@I@Z")]
public static extern int StartUp(IntPtr HWMD, uint SorterMessage);

Теперь я получил указатель, откуда я мог извлечь сообщения,Мой вопрос: как?

Я нашел этот пример на другом форуме:

[Serializable, StructLayout(LayoutKind.Sequential)]
public struct MSG
{
    public IntPtr hwnd;
    public int message;
    public IntPtr wParam;
    public IntPtr lParam;
    public int time;
    public int pt_x;
    public int pt_y;
};

[DllImport("user32.dll", CharSet = CharSet.Ansi)]
public static extern bool GetMessage([In, Out] ref MSG msg, IntPtr hWnd, int uMsgFilterMin, int uMsgFilterMax);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr DispatchMessage([In] ref MSG msg);

MSG msg = new MSG();
while (GetMessage(ref msg, IntPtr.Zero, 0, 0))
    DispatchMessage(ref msg);

Я пытался использовать его следующим образом:

// Added a constructor inside of the struct:
public MSG(IntPtr hwndPtr)
{
    hwnd = hwndPtr;
    message = -1;
    wParam = new IntPtr();
    lParam = new IntPtr();
    time = 0;
    pt_x = 0;
    pt_y = 0;
}

// Left the dll imports like in their example (although I fixed the path)

// Calling the method in my main
int ID, st;
ID = Class1.StartUp(hwnd, 10); // Just used 10 like in the API's manual
Console.WriteLine("Turning on device");
MSG msg = new MSG(hwnd);
while(Class1.GetMessage(ref msg, IntPtr.Zero, 0, 0))
    Class1.DispatchMessage(ref msg);
Console.WriteLine(msg.message);

do { Class1.GetState(ID, out st); }
while (st != (int) DevStates.chgParams);
Console.WriteLine("Device on");

Что я ожидаю?После печати «Включение устройства» я должен получить сообщение (потому что во время запуска, и в соответствии с руководством, оно отправляет сообщение перед изменением состояния), а затем строку «Устройство включено».

Что делатьЯ получил?Сразу после печати программа «Включение устройства» ничего не делает, кроме мигания курсора (и, конечно, строка «Устройство вкл.» Никогда не отображается).Похоже, он ждет любого сообщения.Пробовал размещать сообщения, звонить в разные места и поведение одинаковое.

Есть какие-нибудь советы?Заранее спасибо.

1 Ответ

0 голосов
/ 10 апреля 2019

Решил это (наконец-то)

Вот как я это сделал:

  1. Используются формы окон, поскольку у него есть класс "Сообщение"
  2. Импортировано.dll, над которой я работал, чтобы упростить задачу, поместил все методы в класс «ScanMgr».
using ...
using APIcsharp;

class ScanMgr
{
  int ID = 0;

  public string startUp(IntPtr hwmd, uint wmApp)
  {
    int state;
    ID = NativeAPI.StartUp(hwmd, wmApp);
    if(ID != 0)
    {
      do { NativeAPI.GetState(ID, out state); }
      while(state == (int)(DevStates.StartingUp)); // DevStates is a enum
      return "Device on";
    }
    return "Error turning on";
  }

  /* Other stuff to do */
}
Затем определен метод переопределения для сообщений
public partial class Form1 : Form
{
  const uint wm_channel = 0x8000 + 1;
  ScanMgr scanner = new ScanMgr();

  public Form1()
  { InitializeComponent(); }

  private void StartBtn_Click(object sender, EventArgs e)
  { log.Items.Add(scanner.startUp(this.Handle, wm_channel)); }

  /* Other stuff yadda yadda */

  protected override void WndProc(ref Message m)
  {
    base.WndProc(ref m);
    if(m.Msg == wm_channel)
    { /* To do stuff with m.WParam and m.LParam */ }
  }
}
...