Blitzeigene CallbackProc-Funktion addressieren?
Übersicht

![]() |
KnorxThieusBetreff: Blitzeigene CallbackProc-Funktion addressieren? |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo,
Wie bereits in einem weiteren Thread ersichtlich, setze ich mich gerade mit API-Funktionen auseinander und widme mich neben der TaskDialog-Funktion jetzt auch der TaskDialogIndirect-Funktion. (Userlib-Code: [AUSKLAPPEN] .lib "Comctl32.dll"
Achtung: Lässt sich nur als kompilierte Exe mit durch den Resource Hacker beigelegter Manifest-Resource ausführen: Code: [AUSKLAPPEN] api_TaskDialogIndirect%(pTaskConfig*, pnButton*, pnRadioButton*, pfVerificationFlagChecked*) : "TaskDialogIndirect" <?xml version="1.0" encoding="UTF-8" standalone="no"?>
)
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="MyCompany.MyLabel.MyAppName" type="win32" /> <description>MultiMedia BoardCast/Scheduler.</description> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="X86" publicKeyToken="6595b64144ccf1df" language="*" /> </dependentAssembly> </dependency> </assembly> Mit geringen C++-Kenntnissen habe ich mich da erstmalig versucht einzulesen, Structs, Pointer, … ich bin aber letztendlich auf den theoretischen Rohcode wie folgt gekommen: BlitzBasic: [AUSKLAPPEN] ;Fenster: für B+ler hier auskommentiert, der Rest kann es 1:1 mit einem Grafikfenster nachvollziehenTheoretisch soweit. Aber praktisch musste ich feststellen, dass man da die auf programmeigene Callbackfunktion verweisen muss! (Dicke Markierung bei etwa Zeile 40) ![]() Ich weiß gerade noch so, dass diese Prozedurfunktion, die alle Messages und Notifications von Windows abarbeitet, per Zeiger übergeben wird, um dann von Win aufgerufen zu werden … aber weder von den CallbackData habe ich eine Ahnung, noch irgendeine Idee, wie ich diese bei BB doch intern verwalteten Funktionszeiger auslesen soll! Eine Funktion wie GetWindowCallback habe ich nicht gefunden. Habt ihr noch irgendwelche Ideen? ![]() ![]() Mit freundlichen Grüßen, KnorxThieus @Moderation: Ich denke schon, dass ich hier unter Allgemein richtig bin, schließlich läuft ja auch B3D in Fenster und müsste daher ein WindowProc haben, richtig? |
||
![]() |
Silver_Knee |
![]() Antworten mit Zitat ![]() |
---|---|---|
Callback-Funktion heißt, du schreibst selbst eine Funktion, gibst die der api_TaskDialogIndirect mit und die api_TaskDialogIndirect ruft in Ihrem aufruf, deine Funktion auf.
Das geht mit B3D Boardmitteln nicht. Es gibt aber verschiedene "Hacks", die verschieden gut sowas realisieren können. Das Stichwort heißt hierzu "function pointer". Da gibt's lösungen hier und im englischen Forum. Ohne solche Hacks, musst du eine DLL schreiben, die api_TaskDialogIndirect aufruft in einer Sprache die Funktionspointer unterstützt. In der selbstgeschriebene DLL kannst du dann in den Callback-Funktionen variablen setzen, die du dan mit B3D wieder abrufen kannst. |
||
![]() |
KnorxThieus |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo,
Danke für deine Antwort. Ich dachte, da könnte ich die Blitz-Standard-Callback-Funktion nehmen, die es eh schon gibt! Oder muss die hier tatsächlich etwas Spezifisches tun, was sie nicht automatisch täte? Wenn ich einen Hack verwende, muss ich die Funktion dann selber schreiben? Und wenn ja, was gehört da rein? Nach "function pointer" habe ich in beiden Foren gesucht, das einzige Brauchbare schien mir die FastPointer-Bibliothek hier. Tut es die? ![]() Na ja, für meine Kenntnisse kommt selber eine DLL Schreiben nicht infrage ![]() Mit freundlichen Grüßen, KnorxThieus |
||
Version: BlitzPlus / Blitz+ |
![]() |
Silver_Knee |
![]() Antworten mit Zitat ![]() |
---|---|---|
So. Ich hab jetzt deinen ersten Thread gelesen und die API von MS überflogen.
Was du machen willst ist zunächst in Blitz3D einfach nicht vorgesehen. api_TaskDialog arbeitet synchron. Es hält dein Programm an und du kannst den Rückgabewert auswerten. Ein Thread. Ein Programmablauf. Ganz einfach. Das wäre ein typischer Blitz3D-Ansatz. api_TaskDialogIndirect will das asynchron lösen. Du rufst die Funktion auf und die ruft dann irgendwann eine Funktion in deinem Code auf. Wie die Funktion aussehen muss, kannst du auch nachlesen: https://msdn.microsoft.com/en-...85%29.aspx Da siehst du übrigens den Parameter dwRefData und unten steht dann, dass der das lpCallbackData ist. Du kannst also bei deinem Aufruf von api_TaskDialogIndirect etwas übergeben, was deine Callback-Funktion bekommt, damit sie weiß von wo der Aufruf ursprünglich kam (kann z.B. ein Pointer auf einen Type sein) "Ist ja alles schön und gut aber wie komm ich an den Funktionspointer?" - Die FastPointer-Dll ist ganz okay, ob du aber die Übergabeparameter rein bekommst, wenn du deine Funktion gemäß der API schreibst, kann ich dir nicht sagen. Das müsstest du ausprobieren, ansonsten müsstest du nen anderen Hack ausprobieren. Außerdem weiß ich nicht "wann" die Callback-Funktion aufgerufen wird: Zitat: [TaskDialogCallbackProc] receives messages from the task dialog when various events occur. könnte heißen während Flip (Bei B3D) oder WaitEvent (Bei BlitzPlus) oder in einem ganz eigenen Thread. Das würde es gelten herauszufinden.
|
||
![]() |
KnorxThieus |
![]() Antworten mit Zitat ![]() |
---|---|---|
Uff, scheint das aufwendig … kann man das als C- oder Java-Programmierer mit wenig Aufwand in eine kompakte DLL fassen? Dann könnte ich mal herumbitten ![]() Silver_Knee hat Folgendes geschrieben: Das würde es gelten herauszufinden. Und wie, wo ich ja die Funktion mangels Zeiger gar nicht erst ausführen kann? ![]() |
||
Version: BlitzPlus / Blitz+ |
![]() |
Silver_Knee |
![]() Antworten mit Zitat ![]() |
---|---|---|
Eine passende DLL in C zu schreiben, geht normalerweise. Nennt sich Wrapper. Bin leider selbst kein C-Programmierer, kenne nur das grobe Konzept.
In Java hast du mit DLLs meist nix am Hut, weil es für fast alles eine fertige, plattformunabhängige, eingebaute Lösung gibt (etwa wie BlitzMax' MaxGUI oder Monkey es versuchen). Wenn du doch an DLLs musst, kommst du, glaube ich, bei callback-Funktionen auch nicht weiter. Da hast du normalerweise auch Wrapper für Java. In Java kannst du keine Wrapper schreiben, weil du keine DLLs compilen kannst - rein von der Art, wie Java funktioniert schon nicht. Du kannst eine Funktion schreiben, die der Definition in dem Link entspricht, dir mit FastPointer den Funktionspointer holen und ihn an die entsprechende Stelle in der config schreiben. Wenn du Glück hast, kommen die Parameter an, wenn du Pech hast, schmiert dein Programm ab. Dann kannst du noch andere Hacks versuchen. Zitat: Das würde es gelten herauszufinden.
...war an dich gerichtet. Wenn du einen B3D-Hack gefunden hast, mit dem du die Parameter bekommst, kannst du mal austesten, wo und wann die Funktion aufgerufen wird und ob sie dir Probleme macht. Das mit dem zweiten Thread kriegst du raus, wenn du in deine Hauptschleife Stop schreibst, der Dialog immernoch funktioniert und beim Klick auf nen Button deine Callback-Funktion aufgerufen wird, obwohl ja eigentlich dein Programm stehen sollte. Dann ist ein zweiter Thread am Werk, der unabhängig von deinem Programm/Hauptthread arbeitet. Da wird's etwas knifflig. Ansonsten ist DebugLog dein Freund. Wenn alles nichts hilft, bleibt ja auch die Frage, ob das Problem, was du mit der Windows-Funktion lösen willst, nicht auch einfach mit Blitz-Mitteln zu lösen ist. |
||
![]() |
Thunder |
![]() Antworten mit Zitat ![]() |
---|---|---|
Oder ob nicht Visual Basic .NET für deine Zwecke geeigneter ist, wenn dir die Windows API so am Herzen liegt... | ||
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit |
![]() |
KnorxThieus |
![]() Antworten mit Zitat ![]() |
---|---|---|
Morgen!
Silver_Knee hat Folgendes geschrieben: Du kannst eine Funktion schreiben [… und] dir mit FastPointer den Funktionspointer holen […] Ich habe mir Pummelies Code noch einmal genauer angeschaut und es mal versucht:
Oben, unter der Fensterinitialisierung, füge den Code ein: BlitzBasic: [AUSKLAPPEN] cwp = FunctionPointer()Unten, ersetze die beiden Zeile bzgl. CallbackProc durch BlitzBasic: [AUSKLAPPEN] PokeInt bank, 78, CWP ;<--- HIER! pfCallback Leider stürzt dies – kompiliert – immer bei der FastPointer.dll ab … was mache ich falsch? Und abgesehen davon, verstehe ich immer noch nicht wie FunctionPointer() funktioniert! Was hat das mit GoTo ![]() Zum Sinn in BB: Nun ja, generell fühle ich in BlitzPlus ja (trotz der grottenmäßigen IDE …) ziemlich wohl, wenngleich ich für die GUI-mäßigen Feinheiten schwärme … ich bin wohl einfach zu faul, umzurüsten. Aber wenn es hier klappt, lerne ich dazu noch etwas! ![]() |
||
Version: BlitzPlus / Blitz+ |
![]() |
Silver_Knee |
![]() Antworten mit Zitat ![]() |
---|---|---|
Die Funktion WaitEvent ist nicht aufgebaut wie in der API beschrieben. Die funktion in der Goto-Klammer sollte so aussehen.
Code: [AUSKLAPPEN] TaskDialogCallbackProc(
_In_ HWND hwnd, _In_ UINT uNotification, _In_ WPARAM wParam, _In_ LPARAM lParam, _In_ LONG_PTR dwRefData ); Das ergibt dann so etwas wie: BlitzBasic: [AUSKLAPPEN] cwp = FunctionPointer() Der Trick mit Goto bewirkt, dass Blitzbasic zwar den code "rufe die Funktion MeinCallback auf" mit in dein Programm packt, aber dank Goto da dran vorbei läuft und die Funktion gar nicht aufruft. Die Funktion FunctionPointer() liest in deiner CPU die aktuelle Code-Stelle raus, geht an dem Goto vorbei und schaut sich die Addresse der Funktion MeinCallback an. Die steht ja in "rufe die Funktion MeinCallback auf". Die Addresse bekommst du dann als Rückgabewert. Das ist ein ziemliches rumgefrickel auf Seite der FunctionPointer-Funktion. Jetzt gibst du die Addresse in der Config an die richtige Stelle und dann versucht TaskDialogIndirect zu gegebener Zeit die übergebene Addresse als Funktion aufzurufen. Wenn dein Programm gar nicht erst startet und die FastPointer.dll vermisst, musst du die DLL in dein decls-Verzeichns kopieren und später deiner EXE mitgeben. |
||
![]() |
Thunder |
![]() Antworten mit Zitat ![]() |
---|---|---|
Abstürzen dürfte es trotz der falschen Funktionssignatur nicht.
Außer die Funktion erwartet per stdcall aufgerufen zu werden (imho unwahrscheinlich), aber dann hast du mit BB ein weiteres Problem, das schwer zu lösen ist... |
||
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit |
![]() |
KnorxThieus |
![]() Antworten mit Zitat ![]() |
---|---|---|
So, ich habe jetzt (wiederum an anderer Stelle) den Hinweis erhalten, einmal das Beispiel auf dem MSDN-Artikel zu betrachten – kurz, dort wird überhaupt keine CallbackProc-Funktion angegeben; es ist ja wohl davon auszugehen, dass das Beispiel von Microsoft trotzdem läuft (oder?), der Parameter also optional ist.
Ich habe mir jetzt nochmal den Rest angeschaut und festgestellt: Die Absturzmeldung rührte von den nicht nach Unicode kodierten Strings her. Passt man sie mit dem hier an: BlitzBasic: [AUSKLAPPEN] Function AnsiToUnicode$(ansi$)(Benutzung dürfte sich verstehen) , so stürzt nix mehr ab. Stattdessen erhalte ich kein TaskDialog-Fenster und einen Rückgabewert von -2147024809 (entspräche einem Wert von -458839 als UNSIGNED_INT – das ergibt (auch) keinen Sinn.). Irgendjemand eine Ahnung, was das heißt? S_OK, E_OUTOFMEMORY, E_INVALIDARG und E_FAIL sind meiner Erinnerung nach alle positiv. Silver_Knee hat Folgendes geschrieben: Wenn dein Programm gar nicht erst startet und die FastPointer.dll vermisst, musst du die DLL in dein decls-Verzeichns [sic!] kopieren und später deiner EXE mitgeben. So viel weiß ich auch schon … Nein, ich meinte, dass der Fehlermodulname mit FastPointer.dll beschriftet war.
|
||
Version: BlitzPlus / Blitz+ |
![]() |
Thunder |
![]() Antworten mit Zitat ![]() |
---|---|---|
1. Ein unsigned int ist immer positiv
2. Wenn ein unsigned int nicht positiv ist, tritt Regel 1 inkraft ![]() du hast dich irgendwie verrechnet: (unsigned int) -2147024809 == +2147942487 = 0x80070057 Das entspricht genau E_INVALIDARG, siehe Liste: https://msdn.microsoft.com/en-...p/aa378137(v=vs.85).aspx Der C++ Code funktioniert übrigens - hab ihn getestet. In BlitzPlus kann ich ja wie schon gesagt nichts testen... Ich vermute aber (da das ja nicht dokumentiert ist, muss ich spekulieren), dass TaskDialogIndirect auf die Nutzereingabe wartet, wenn du keinen Callback übergibst. Also dein restliches Programm wäre währenddessen angehalten. |
||
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit |
![]() |
KnorxThieus |
![]() Antworten mit Zitat ![]() |
---|---|---|
Thunder hat Folgendes geschrieben: 1. Ein unsigned int ist immer positiv
Okay, dann habe ich mich wohl verrechnet 2. Wenn ein unsigned int nicht positiv ist, tritt Regel 1 inkraft ![]() ![]() Ungültiges Argument? Super. An welchem es bloß liegen mag …? Nun ja, ich werde nach her mal versuchen, möglichst viele Parameter rauszustreichen (die optionalen). Zitat: Also dein restliches Programm wäre währenddessen angehalten. Super, das ist ja genau das, was ich will! ![]() Edit oder AW folgt später, wenn ich weitere Ergebnisse habe. –KnorxThieus |
||
Version: BlitzPlus / Blitz+ |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group