it's me again!
This question is quite hard, for I'll do my best explaining it: As I mentioned in a previous question, I'm working in a scanner management on C#, using a C++ dll sent by provider. According to the API's manual, there are certain messages sent under certain conditions. In example: After Starting up the scanner, it should send the message DEVICE_CONNECTED (with a value of 0), and then change it state.
Those messages values are defined in the .dll
My issue is trying to get those messages on my C# project
I been looking for information about messages transfering, and I found out there's a WndProc that processes Windows messages, for I tried following their example:
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);
}
Of course, that one failed.
Later, I been checking the API's manual, and I think I got a clue where I can get the messages from:
// This is how is defined at .dll (C++)
DWORD StartUp( HWND Handle, UINT SorterMessage )
Where "Handle" is the handle to the application's messages destination window.
So my C# import is as follows:
[DllImport(path, EntryPoint = "?StartUp@@YGKPAUHWND__@@I@Z")]
public static extern int StartUp(IntPtr HWMD, uint SorterMessage);
Now I got a pointer from where I could extract the messages. My question is: How?
I found this example in another forum:
[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);
I tried to use it, as follows:
// 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");
What I expect? After printing "Turning on device" I shoud get the message (because during start up, and according to manual, it sends a message before change the state), and then the "Device on" string.
What do I get? Just after printing "Turning on device" program does nothing but blink the cursor (and of course, the "Device on" string never shows up). Looks like it's waiting for any message. Tried placing the messages call in different places and the behaviour is the same.
Any advices? Thanks in advance.
Solved it (finally)
This is how I did it:
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 */ }
}
}