9

I am trying to receive messages from QCollector as explained in the QCollector Data Interface developer guide. The process consists of registering predefined messages, finding the QCollector server window, and exchanging data through the registered messages.

My WndProc callback receives lost of messages, but none of those are recognized as one of the registered messages. I'm passing my Form's this.Handle in the request, but I'm unsure if this is correct.

What am I doing wrong?

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HistDataManager
{

    public partial class Form1 : Form
    {
        [DllImport("user32.dll", EntryPoint = "FindWindow")]
        private static extern int FindWindow(string sClass, string sWindow);

        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern uint RegisterWindowMessage(string lpString);

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

        int nWinHandle = FindWindow("QCDataInterfaceWndClass", null);

        uint wm_QCollectorClientDataRequest = RegisterWindowMessage("QCOLLECTOR_CLIENT_DATA_REQUEST");
        uint wm_QCollectorClientPortfolioListRequest = RegisterWindowMessage("QCOLLECTOR_CLIENT_PORTFOLIO_LIST_REQUEST");
        uint wm_QCollectorPortfolioListRequestComplete = RegisterWindowMessage("QCOLLECTOR_PORTFOLIO_LIST_REQUEST_COMPLETE ");

        public void TestQC()
        {
            SendMessage(new IntPtr(nWinHandle), wm_QCollectorClientPortfolioListRequest, UIntPtr.Zero, this.Handle);

        }

        protected override void WndProc(ref Message m)
        {
            Console.WriteLine(m.HWnd + "," + m.Msg + "," + m.LParam + "," + m.WParam);
            base.WndProc(ref m);

            if (m.Msg == wm_QCollectorClientPortfolioListRequest || m.Msg == wm_QCollectorPortfolioListRequestComplete)
            {
                Console.WriteLine("Message from specified application found!");
            }

        }

    }
}

EDIT 1:

Just to be sure that I have the basics working in c# I created a second version of this app and got them to talk to each other. This works, so I know my handles and message structures are correct.

BUT I never get a response from qCollector. Does anyone have experience of using this in any other language perhaps? I suspect qCollector was written in c++.

ManInMoon
  • 6,795
  • 15
  • 70
  • 133
  • What do you mean by _TargetApp_? – Joshua Drake Feb 15 '17 at 15:10
  • Try using PostMessage instead. – Peter Ritchie Feb 15 '17 at 15:12
  • @JoshuaDrake TargetApp is the wnd I find with FindWindow("QCDataInterfaceWndClass", null) – ManInMoon Feb 15 '17 at 15:13
  • @PeterRitchie PostMessage doesn't work either. – ManInMoon Feb 15 '17 at 15:19
  • 2
    You never verify, whether `nWinHandle` holds a valid handle. – IInspectable Feb 15 '17 at 18:05
  • Why do you expect that your window proc gets any messages from a different window. You ddin't subclass anything and you didn't register your window as a target for messages. (Cross application subclassing isn't allowed). – xMRi Feb 15 '17 at 18:51
  • @IInspectable Actually I do - but in this snippet I had stripped it out. I definitely get a positive,non-zero number back – ManInMoon Feb 15 '17 at 18:59
  • @xMRi I thought WndProc got everything! What do I use to "register my window as a target"? – ManInMoon Feb 15 '17 at 19:01
  • What I see is just a normal window procedure. To receive specific notifications you need to register your window for this. I don't know the library you use. You have registered messages, so who is sending them. Ask the guy who wrotes the stuff you want to use... – xMRi Feb 16 '17 at 08:01
  • @xMRi: Link to the documentation is in the question. Including the answer from *"the guy who wrotes the stuff"*. – IInspectable Feb 16 '17 at 11:53
  • I don't know if this matters, but it looks like typo: `"QCOLLECTOR_PORTFOLIO_LIST_REQUEST_COMPLETE ". Note the space between COMPLETE and the closing quote. – TnTinMn Feb 22 '17 at 21:59
  • @TnTinMn Good spot - I do get something back now - but it is a number in lParam not a string as the Documentation says – ManInMoon Feb 23 '17 at 17:35
  • ManInMoon, Are saying that your `Console.WriteLine` is yielding a number for lParam or that the string that you retrieve using the pointer is a number? If it is the 1st one, then you have a fundamental misunderstanding of how to work with this. It should be something like: `stringVar = System.Runtime.InteropServices.PtrToStringAuto(m.lParam)` – TnTinMn Feb 23 '17 at 19:32
  • 2
    @TnTinMn: `PtrToStringAuto` interprets the input as a pointer to a zero-terminated character array. That's not what `LParam` is, though. The value is an [atom](https://msdn.microsoft.com/en-us/library/windows/desktop/ms649053.aspx) to deal with the cross-process marshaling. It can be retrieved calling by [GlobalGetAtomName](https://msdn.microsoft.com/en-us/library/windows/desktop/ms649063.aspx). – IInspectable Feb 24 '17 at 09:38

1 Answers1

-1

I dont know if it is fine in .Net but i would like to suggest you to call all the functions in either constructor or in init() function.

Suggested Design

int nWinHandle=0;
uint wm_QCollectorClientDataRequest=0;
uint wm_QCollectorClientPortfolioListRequest=0;
uint wm_QCollectorPortfolioListRequestComplete=0;

void init()
{
    nWinHandle = FindWindow("QCDataInterfaceWndClass", null);
    wm_QCollectorClientDataRequest = RegisterWindowMessage("QCOLLECTOR_CLIENT_DATA_REQUEST");
    wm_QCollectorClientPortfolioListRequest = RegisterWindowMessage("QCOLLECTOR_CLIENT_PORTFOLIO_LIST_REQUEST");
    wm_QCollectorPortfolioListRequestComplete = RegisterWindowMessage("QCOLLECTOR_PORTFOLIO_LIST_REQUEST_COMPLETE ");
}
Mandar
  • 1,006
  • 11
  • 28
  • 1
    The question is not: "How do I improve my design?" The question is: "How do I retrieve a value returned in a message across processes?" This proposed answer does not address the question. Not even remotely. Nor does it add anything useful otherwise. – IInspectable Feb 26 '17 at 12:13