Nachricht via Postmessage senden/empfangen [erledigt]

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

Antworten
Benutzeravatar
ingo
UDF-Programmierer
UDF-Programmierer
Beiträge: 62
Registriert: Fr, 19. Okt 2007 10:20
Wohnort: Lüneburg
Danksagung erhalten: 1 Mal
Kontaktdaten:

Nachricht via Postmessage senden/empfangen [erledigt]

Beitrag von ingo »

Moin!
Ich bin auf der Suche nach einer Lösung für dieses Problem:

Mein XBase-Programm wird über einen Link aus z.B. einer Mail mit einem Parameter gestartet.
Das Programm schaut sich den Parameter an und startet daraufhin eine Function / Procedure mit übergebenen Parametern.

Wenn das Programm bereits gestartet ist, wird der User gefragt ob er eine neue Instanz starten will - und dann klappt das wie gewünscht.

Aber wenn keine neue Instanz gestartet wird, beendet sich das Programm wieder und holt die laufende Instanz in den Vordergrund.
Vor dem beenden möchte ich der laufenden Instanz die Parameter durchreichen, damit es die geforderte Aktion ausführt.

Ich dachte, ich könnte es so probieren:

PostMessageA( hTmp, 134217729, "wParamI", "lParamI" ) oder
SendMessageA( hTmp, 134217729, "wParamI", "lParamI" )

Wobei:

(1) hTmp das Handle der laufenden Instanz ist (über das es in den Vordergrund geholt wurde)

(2) 134217729 ein "benutzerdefinierter Ereigniscode" sein soll.
In Appevent.ch steht:
// *****************************************************************************
// Benutzerdefinierte Ereigniscodes müssen > xbeP_User sein.
// *****************************************************************************

#define xbeP_User 134217728
(3) wParamI und lParamI erst mal dummies sind

(4) Diese Definitionen sind vorhanden:
DLLFUNCTION SendMessageA( hwnd, Msg, wParam, lParam ) USING STDCALL FROM USER32.DLL
DLLFUNCTION PostMessageA( hwnd, Msg, wParam, lParam ) USING STDCALL FROM USER32.DLL


In der Eventschleife der laufenden Instanz habe wollte ich testen, ob das Ereignis empfangen wird:

Code: Alles auswählen

   DO WHILE .T.
      nEvent := AppEvent( @mp1, @mp2, @oXbp )
      IF nEvent = 134217729
         AltD()
      ENDIF
      oXbp:handleEvent( nEvent, mp1, mp2 )
   ENDDO

...aber da passiert nichts.
Bin ich mit der Idee auf dem Holzweg?
Zuletzt geändert von ingo am Di, 26. Apr 2016 10:46, insgesamt 1-mal geändert.
Schönen Gruß, Ingo
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2125
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 30 Mal
Danksagung erhalten: 75 Mal

Re: Nachricht via Postmessage/Sendmessage senden/empfangen

Beitrag von Werner_Bayern »

Servus Ingo,

Du darfst xbeP_User nicht neu definieren, sondern so:

Code: Alles auswählen

#define MEINEVENT1     xbeP_User +1
oder auch ohne #define

und dann

Code: Alles auswählen

nEvent := AppEvent( @mp1, @mp2, @oXbp )
   if nEvent == xbeP_User + 1
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
ingo
UDF-Programmierer
UDF-Programmierer
Beiträge: 62
Registriert: Fr, 19. Okt 2007 10:20
Wohnort: Lüneburg
Danksagung erhalten: 1 Mal
Kontaktdaten:

Re: Nachricht via Postmessage/Sendmessage senden/empfangen

Beitrag von ingo »

Moin Werner,

danke für den Tipp - klappt allerdings leider auch nicht:

Code: Alles auswählen

PostMessageA( hTmp, MEINEVENT1, "wParamI", "lParamI" )
SendMessageA( hTmp, MEINEVENT1, "wParamI", "lParamI" )
in der laufenden Instanz:

Code: Alles auswählen

   DO WHILE .T.
      nEvent := AppEvent( @mp1, @mp2, @oXbp )
      IF nEvent == MEINEVENT1 // via SendMessage
         MsgBox( "geklappt!" )
      ENDIF
      oXbp:handleEvent( nEvent, mp1, mp2 )
   ENDDO
...aber ich probiere damit auch noch weiter herum.
Schönen Restsonntag!
Schönen Gruß, Ingo
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2125
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 30 Mal
Danksagung erhalten: 75 Mal

Re: Nachricht via Postmessage/Sendmessage senden/empfangen

Beitrag von Werner_Bayern »

es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
ingo
UDF-Programmierer
UDF-Programmierer
Beiträge: 62
Registriert: Fr, 19. Okt 2007 10:20
Wohnort: Lüneburg
Danksagung erhalten: 1 Mal
Kontaktdaten:

Re: Nachricht via Postmessage/Sendmessage senden/empfangen

Beitrag von ingo »

Moin Werner,
dann muss ich mir mal ot4xb & XppCbk von Pablo anschauen(?)
Obwohl der Beispielcode ja eigentlich auch nur "PostMessageA" benutzt - und sogar mit 1090 unter dem "UserEvent" liegt?
Ich werde mir das anschauen und berichten - danke!
Schönen Gruß, Ingo
Benutzeravatar
ingo
UDF-Programmierer
UDF-Programmierer
Beiträge: 62
Registriert: Fr, 19. Okt 2007 10:20
Wohnort: Lüneburg
Danksagung erhalten: 1 Mal
Kontaktdaten:

Re: Nachricht via Postmessage/Sendmessage senden/empfangen

Beitrag von ingo »

...ich habe ja mitbekommen, dass Pablo hier hoch geachtet wird - aber auf der Seite ot4xb.xbwin.com finde ich weder Rechtliches zur Nutzung noch eine Beschreibung, was der Code kann.
Muss man sich durch alle angebotenen Downloads arbeiten um zu verstehen worum es geht?
Finde ich schon merkwürdig...
Schönen Gruß, Ingo
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15696
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Nachricht via Postmessage/Sendmessage senden/empfangen

Beitrag von brandelh »

Da er als Autor die DLL frei zur Verfügung stellt brauchst du dir wegen "rechtlich" keine Sorgen machen, ...
das Aussehen seiner neuen Web-Seite verwirrt mich aber immer noch :-)

Es gibt eine CHM Hilfedatei von der ot4xb und viel Beispiel Code.
Gruß
Hubert
Benutzeravatar
ingo
UDF-Programmierer
UDF-Programmierer
Beiträge: 62
Registriert: Fr, 19. Okt 2007 10:20
Wohnort: Lüneburg
Danksagung erhalten: 1 Mal
Kontaktdaten:

Re: Nachricht via Postmessage/Sendmessage senden/empfangen

Beitrag von ingo »

Moin Hubert,
na dann werde ich mal versuchen, ob ich damit zurecht komme - danke!
Schönen Gruß, Ingo
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Nachricht via Postmessage/Sendmessage senden/empfangen

Beitrag von AUGE_OHR »

ingo hat geschrieben:dann muss ich mir mal ot4xb & XppCbk von Pablo anschauen(?)
ot4xb JA, XppCbk() ist obsolet seit es ot4xb_subclasswindow() gibt
ingo hat geschrieben:Obwohl der Beispielcode ja eigentlich auch nur "PostMessageA" benutzt - und sogar mit 1090 unter dem "UserEvent" liegt?
eine andere Instanze ist wie ein anderes Programm.
SendMessageA() / PostMessageA() gehen zwar in die Windows Queue aber mit AppEvent bekommst du nur Xbase++ Events.
PostAppEvent() wiederum wirkt nur innerhalb einer Xbase++ App ... an eine andere Xbase++ App kommst du damit nicht.
gruss by OHR
Jimmy
Benutzeravatar
ingo
UDF-Programmierer
UDF-Programmierer
Beiträge: 62
Registriert: Fr, 19. Okt 2007 10:20
Wohnort: Lüneburg
Danksagung erhalten: 1 Mal
Kontaktdaten:

Re: Nachricht via Postmessage/Sendmessage senden/empfangen

Beitrag von ingo »

Hi Jimmy, danke, das erklärt's:
SendMessageA() / PostMessageA() gehen zwar in die Windows Queue aber mit AppEvent bekommst du nur Xbase++ Events.
Dann werde ich in ot4xb also etwas finden, was das Ereignis aus der Windows Queue in meine Anwendung "durchreicht"
oder
sowas wie einen Extra-Thread, der das Windows Ereignis "abgreift", so dass ich darauf reagieren kann.
Ich bin gespannt!
Schönen Gruß, Ingo
Benutzeravatar
ingo
UDF-Programmierer
UDF-Programmierer
Beiträge: 62
Registriert: Fr, 19. Okt 2007 10:20
Wohnort: Lüneburg
Danksagung erhalten: 1 Mal
Kontaktdaten:

Re: Nachricht via Postmessage/Sendmessage senden/empfangen

Beitrag von ingo »

Moin!
Ich komme mir inzwischen schon ein wenig dämlich vor, weil ich mit den bisherigen Antworten/Tipps nicht weiter gekommen bin.
Wenn noch mal jemand was dazu sagen könnte, wäre das toll:

Wie am Anfang beschrieben, will ich von einem XBase-Programm eine Nachricht an eine andere Instanz des selben XBase-Programms senden.
Und dachte, das würde mit PostMessageA() gelingen.
Jedenfalls hatte ich den Thread:
http://www.xbaseforum.de/viewtopic.php? ... geA#p90210
...so verstanden, dass das gehen müsste.

ot4xb wird in dem o.g. Thread nur dafür benutzt um über den Namen das Fensterhandle zu bekommen - Verweis auf die Funktion WildFindWindow().
Das geht aber auch ganz simpel ohne ot4xb mit
nWinHandle = FindWindowA( 0, cWindowName )
(Jedenfalls, wenn ich den Namen genau kenne. Wenn das nicht der Fall ist, hilft ot4xb weiter.)

Jetzt nehme ich an, dass ich zwar mit PostMessageA() eine Nachricht an ein beliebiges Windows-Fensterhandle schicken kann, aber eben nicht an ein XBase-Programm?
Jimmy hatte geschrieben:
SendMessageA() / PostMessageA() gehen zwar in die Windows Queue aber mit AppEvent bekommst du nur Xbase++ Events.
Im o.g. Thread steht noch "einfach das Beispiel ansehen" - was ich aber nicht finde. (Nur den Link auf Pablo's Download-Bereich.)

Auch die Alternative mit dem Link auf BAP von Alaska finde ich nicht, weil ich jedenfalls mit meinem Konto keinen Zugriff auf den FTP-Server bekomme. Da stehen aber auch nur "alte" Versionen von BAP.
Hat jemand einen Tipp wie ich an BAP rankomme? Ich habe sogar eine aktive professional subcription...

Habe ich das jetzt richtig verstanden oder laufe ich stumpf um die Lösung herum?
Schönen Gruß, Ingo
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Nachricht via Postmessage/Sendmessage senden/empfangen

Beitrag von AUGE_OHR »

hi,

ich fürchte du stellst dir das zu einfach vor. mit den beiden API Befehlen erreichst du "so" gar nichts.
was geht durch die Windows Queue ... auf jeden Fall keine "Mengen" von Informationen.

Daten werden in einer Structure "verpackt" und der Empfänger erhält beim Event XYZ einen Pointer (Zeiger) "wo" (im Speicher) sich die Information befindet.
Der Empfänger muss auch die Structure kennen damit er die Daten richtig "auspacken" kann.

bei einem SendMessageA(Handle, Konstante,wp,lp) besagt die Konstate meistens zu welcher Class / Structure es gehört und / oder welche Member Variabel gemeint ist. wenn du nun eine eigene Structure erstellst "kennt" die Windows nicht ... und es gibt auch keine Konstante dafür.

mit XppCbk() kannst du eine selbst erstellte Structure zu einem OBJ compilieren welcher als Callback Slot zwischen "Windows" und Xbase++ genutzt werden kann.
ein Callback Slot "reagiert" ja auf eine "Benachrichtigung" ( Notify Event ) und wird da durch "ausgelöst"

du "füllst" als Absender deine Structure und schickst eine Message mit dem Pointer an den Empfänger.
der Callback Slot des Empfänger reagiert nun darauf und holt an der "Stelle" (wo der Pointer hin zeigt), per PEEK/POKE, die Daten aus dem Speicher.

hier nun ein Beispiel von Pablo wie so etwas aussieht ( WM_COPYDATA )
TestWmCopyData.zip
need ot4xb
(5.99 KiB) 236-mal heruntergeladen
wenn du zu ot4xb Fragen hast dann solltest du über die Newsgroup

Code: Alles auswählen

news.xbwin.com
gehen. dort kann dir dann Pablo direkt antworten ( wenn er Lust/Zeit hat )


---


das was du vorhast habe ich noch nicht probiert und noch bei keinem gesehen ...


ich würde es mit einem Thread versuchen.
der prüft ob es eine DBF / XPF Datei gibt welche die Parameter enthält.

Code: Alles auswählen

Programm startet und Datei anlegen/füllen. wenn 1st Instanze wird die Datei gelöscht.
Thread starten.

2nd Instanze wird gestartet und legt Datei an und füllt die. 
nun "merkt" er das schon eine Instanze läuft -> QUIT aber Datei wird nicht gelöscht.

Der Thread "merkt" nun das die Datei existiert, liest die Daten aus und löscht die Datei.
gruss by OHR
Jimmy
Benutzeravatar
ingo
UDF-Programmierer
UDF-Programmierer
Beiträge: 62
Registriert: Fr, 19. Okt 2007 10:20
Wohnort: Lüneburg
Danksagung erhalten: 1 Mal
Kontaktdaten:

Re: Nachricht via Postmessage/Sendmessage senden/empfangen

Beitrag von ingo »

Hi Jimmy,
nochmal: vielen Dank!

Im Schlaf hatte ich noch eine andere Idee, die ich ausprobieren will, weil mir die simpler erscheint:
- Instanz1 des Programms läuft
- Instanz2 wird gestartet, merkt dass Instanz1 bereits läuft,
erzeugt eine Textdatei mit relevanten Informationen zu dem Aufrufparameter,
holt Instanz1 in den Vordergrund,
beendet sich
- in Instanz1 müsste ich ja auf das Ereignis xbeP_SetDisplayFocus reagieren können, prüfen ob die Textdatei existiert und auswerten.

...mal schauen, ob das funktioniert, ich sage dann Bescheid.
Schönen Gruß, Ingo
Benutzeravatar
ingo
UDF-Programmierer
UDF-Programmierer
Beiträge: 62
Registriert: Fr, 19. Okt 2007 10:20
Wohnort: Lüneburg
Danksagung erhalten: 1 Mal
Kontaktdaten:

Re: Nachricht via Postmessage/Sendmessage empfangen [erledig

Beitrag von ingo »

Moin & danke an alle, die geholfen haben!
Ich hab's jetzt ganz einfach gemacht, zum Abschluss meine Lösung in Kürze:

Mein Programm prüft standardmässig in der Methode :ToTopIfRuns() ob es bereits gestartet ist und ob es mehrfach gestartet werden darf.
Der Aufrufparameter enthält z.B. die Anweisung die Auftragsbearbeitung zu öffnen und einen Auftrag zu aktivieren.
Der Parameter (xParameter1) wird an die Methode durchgereicht, der Benutzer entscheidet ggf. (falls das Programm mehrfach gestartet werden darf bei ::lMehrfachaufruf = true) ob er eine neue Instanz starten will.
Wenn keine neue Instanz gestartet werden soll, erzeugt das Programm eine temporäre Textdatei, die nur den Parameter enthält.
Die laufende Instanz erhält den Displayfokus und in der Methode wird die Textdatei ausgewertet und wieder gelöscht.
(Das Ganze ist dazu gut, innerhalb der Firma Links in Mails zu verschicken, die auf z.B. einen Auftrag zu verweisen. Der Link startet über einen Registry-Eintrag das jeweilige Programm mit einem variablen Parameter der den Namen einer Prozedur oder Funktion mit Aufrufparameter für diese enthält.)

Code: Alles auswählen

METHOD IKSDialog:IKS_ToTopIfRuns( xParameter1 )
MEMVAR PRN
LOCAL hTmp,  cWindowName, h:=0
   ****
   cWindowName = self:getTitle()
   // damit dieses Fenster anders heisst:
   ::setTitle( "Programm wird auf Doppelstart gecheckt..." )
   hTmp = FindWindowA( 0, cWindowName )
   IF hTmp <> 0
      // Doppelaufruf zulässig?
      IF ::lMehrfachaufruf
         h = Meldung({"Achtung:",;
                      "Das Programm ist bereits gestartet!",;
                      "Der Mehrfachaufruf ist laut .ini gestattet, möchten Sie",;
                      "eine weitere Instanz des Programms starten?",;
                      "Klicken Sie 'Nein' um die laufende Instanz zu aktivieren,",;
                      "'Ja' um eine weitere Instanz zu starten."},;
                      {{27,"~Nein"},{13,"~Ja"}},,,,, MSG_FZ_S)
      ELSE
         h = 27
      ENDIF
      IF h = 27
         // ggf. Startparameter in Textdatei ablegen; 'alte' Instanz wertet das im setDisplayFocus aus
         IF VALTYPE( xParameter1 ) = "C"
            IKS_CreateFile( ::IKS_Local_Home + PRN + "_iks_start_parameter.txt", { xParameter1 }, .T. )
         ENDIF
         // in den Vordergrund setzen
         SetForegroundWindow( hTmp )
         // ggf. maximieren!
         ShowWindow( hTmp, SW_SHOWMAXIMIZED )
         // und anzeigen
         BringWindowToTop( hTmp )
         // dieses beenden!
         AppQuit()
      ENDIF
   ENDIF
   ::setTitle( cWindowName )
RETURN
********************************************************************************
METHOD IKSDialog:setDisplayFocus()
MEMVAR PRN
LOCAL aZeilen:={}
LOCAL cAutoStartFile:=::IKS_Local_Home + PRN + "_iks_start_parameter.txt"
   IF FILE( cAutoStartFile )
      aZeilen = IKS_ReadFile( cAutoStartFile )
      IKS_FileDelete( cAutoStartFile, .T. )
      IF LEN( aZeilen ) = 1
         ::AutoStart( aZeilen[1] )
      ENDIF
   ENDIF
RETURN self
Schönen Gruß, Ingo
Antworten