Je travaille sur une application Windows uniquement, et je dois recevoir des données d’un plug-in Microsoft OneNote. Le plugin est écrit en C # et peut envoyer des messages WM_COPYDATA. Comment recevoir ces messages dans une application C ++ Qt?
J’ai besoin de:
Cela peut être traité dans Qt:
Étendez QWidget avec une classe qui capturera les messages WM_COPYDATA:
class EventReceiverWindow : public QWidget { Q_OBJECT public: EventReceiverWindow(); signals: void eventData(const QSsortingng & data); private: bool winEvent ( MSG * message, long * result ); };
Générez un GUID à définir en tant que fenêtre de QWidget. Titre:
EventReceiverWindow::EventReceiverWindow() { setWindowTitle("ProjectName-3F2504E0-4F89-11D3-9A0C-0305E82C3301::EventReceiver"); }
Remplacez winEvent pour gérer la structure WM_COPYDATA et émettre un signal lorsque vous l’obtenez:
bool EventReceiverWindow::winEvent ( MSG * message, long * result ) { if( message->message == WM_COPYDATA ) { // extract the ssortingng from lParam COPYDATASTRUCT * data = (COPYDATASTRUCT *) message->lParam; emit eventData(QSsortingng::fromAscii((const char *)data->lpData, data->cbData)); // keep the event from qt *result = 0; return true; } // give the event to qt return false; }
Dans une autre classe, vous pouvez utiliser cette classe pour recevoir les chaînes de message:
EventReceiverWindow * eventWindow = new EventReceiverWindow; QObject::connect(eventWindow, SIGNAL(eventData(const QSsortingng &)), this, SLOT(handleEventData(const QSsortingng &)));
…
void OneNoteInterface::handleEventData(const QSsortingng &data) { qDebug() << "message from our secret agent: " << data; }
Et dans le programme qui envoie les messages, trouvez simplement la fenêtre par la légende unique de la fenêtre. Voici un exemple en C #:
private struct COPYDATASTRUCT { public IntPtr dwData; public int cbData; [MarshalAs(UnmanagedType.LPStr)] public ssortingng lpData; } private const int WM_COPYDATA = 0x4A; [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)] static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, ssortingng lpWindowName); [DllImport("User32.dll", EntryPoint = "SendMessage")] private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam); private void sendMessageTo(IntPtr hWnd, Ssortingng msg) { int wParam = 0; int result = 0; if (hWnd != IntPtr.Zero ) { byte[] sarr = System.Text.Encoding.Default.GetBytes(msg); int len = sarr.Length; COPYDATASTRUCT cds; cds.dwData = IntPtr.Zero; cds.lpData = msg; cds.cbData = len + 1; result = SendMessage(hWnd, WM_COPYDATA, wParam, ref cds); } }
Ensuite vous pouvez:
IntPtr hwnd = FindWindowByCaption(IntPtr.zero, "ProjectName-3F2504E0-4F89-11D3-9A0C-0305E82C3301::EventReceiver"); sendMessageTo(hwnd, "omg hai");
Vous pouvez également créer une fenêtre factice uniquement pour recevoir ce message avec l’API Win32. Je suppose que vous n’aurez pas access à un proc de fenêtre de Qt-Window, cela devrait donc être le moyen le plus simple.
Vous pourriez (je ne le ferais pas) également sous-classer la fenêtre en définissant un nouveau WndProc (avec SetWindowLong(Ptr)
, le handle de la fenêtre peut être obtenu avec QWidget::winId()
). Dans ce WndProc, vous pouvez simplement gérer votre WM_COPYDATA spécifique et transmettre tous les autres messages de fenêtre à l’ancien WndProc.
Pour gérer les messages que votre fenêtre reçoit, remplacez votre QCoreApplication :: winEventFilter . Si cela ne fonctionne pas, vous pouvez consulter QAbstractEventDispatcher .
Pour le nom de la classe, vous pouvez essayer d’utiliser QWidget :: winId avec l’API Win32. Je voudrais essayer de le trouver pour vous mais je ne peux pas maintenant, peut-être essayer GetClassName .
Vous pouvez utiliser QWinHost from Qt solutions pour créer une fenêtre factice. En suivant le guide , vous apprendrez à spécifier le nom de votre classe et à vérifier la boucle de l’événement pour votre message.