macro im macro aufrufen

Anfängerfragen zum Programmieren mit PureBasic.
galileo
Beiträge: 5
Registriert: 02.07.2009 14:12

macro im macro aufrufen

Beitrag von galileo »

Ich habe folgendes Problem. Bsp:

macro Test_eins(param)
ProcedureReturn Func_#param(param)
endmacro

macro Test_zwei(param)
ProcedureReturn Func_#param(param)
endmacro

usw.

macro Test(param)
Test_#param(param)
endmacro

Test(eins) Ergebnis soll ProcedureReturn Func_eins(param) sein ist aber Test_eins(param)

ich möchte diese macro's nachbauen

#define HANDLE_MSG(hwnd, message, fn) \
case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))

#define HANDLE_WM_CLOSE(hwnd, wParam, lParam, fn) \
((fn)(hwnd), 0L)

HANDLE_MSG(hwnd, WM_CLOSE, Main_OnClose);

Hat jemand eine Idee wie das geht ?
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

es liegt vermutlich daran das du den eigentlichen Parameter genauso genannt hast wie den Parameter der den FUnktionsnaman hat.

da komms also auch zur einsetzung.

außerdem kannst du dir die marcos doch sparen ...

Code: Alles auswählen

macro Test(param) 
ProcedureReturn Func_#param(param) 
endmacro 
denn die anderen sachen sind ja eh gleich.

Aber du musst dir die namensgebung noch mal angucken ...
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

Willkommen an Board! :D

dein Beispiel ist nicht klar, denn du verwendest überall nur "param".
bei den teilen
Func_#param(param)
und
Test_#param(param)
wird ja wohl kaum in den Klammern das identische wie in der Ergänzung stehen sollen.


generell: das ist auf diesem Wege nicht lösbar.

PureBasic ist ein One-Pass-Compiler, also Macros werden genau ein mal ersetzt.
es ist nicht möglich, dass aus Test_#param erst Test_zwei wird, und aus Test_zwei dann Func_Rhabarber wird.

das musst du anders lösen.

die Macros, die du nachbauen willst... sind die ganz präsise so wie du gezeigt hast?

Code: Alles auswählen

#define HANDLE_MSG(hwnd, message, fn)    \
    case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))

#define HANDLE_WM_CLOSE(hwnd, wParam, lParam, fn) \
    ((fn)(hwnd), 0L)

HANDLE_MSG(hwnd, WM_CLOSE, Main_OnClose);
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
galileo
Beiträge: 5
Registriert: 02.07.2009 14:12

Beitrag von galileo »

Danke erst einmal für die Anworten.

Das waren nur abstrakte Beispiele. Die C-Makros stehen in der windowsx.h und erleichtern die Verarbeitung der Message in WindowCallback(). Hier ein komplettes Beispiel:

Code: Alles auswählen

Macro HANDLE_WM_CLOSE(hwnd, fn)
  ProcedureReturn fn(hwnd)
EndMacro


Macro HANDLE_MSG(hwnd, message, fn)
  Case #message : HANDLE_#message(hwnd, fn)
EndMacro  


Procedure main_onclose(hwnd)
  End
EndProcedure

Procedure Callback(WindowID, Message, wParam, lParam)
    Result = #PB_ProcessPureBasicEvents
    Select Message
      HANDLE_MSG(WindowID, WM_CLOSE, main_onclose) 
    Default
        ProcedureReturn Result
     EndSelect   
  EndProcedure

 
If OpenWindow(0, 100, 100, 500,400, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  Textbox=StringGadget(0,  10, 10, 480, 380, "Codeguru is there!",#ES_AUTOVSCROLL|#WS_VSCROLL |#WS_HSCROLL)
EndIf

SetWindowCallback(@callback(),0)
Aber du hast meine Frage schon beantwortet Purebasic ist ein One-Pass-Compiler. :cry:

Gibt es eine die Möglichkeit über den Umweg FASM-Macro oder andere Lösungsvorschläge.

Code-Tags ergänzt - Bitte nächstes Mal selber einfügen - Kaeru fecit
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

ermn... also mir ist das alles recht cryptisch im Moment...

ich seh auch den Nutzen nicht im Mindesten.

ein Macro wird zur Compilerzeit ersetzt, es steht also dort im Code exakt ein Eintrag.

wo ist also der Nutzen, dort

Code: Alles auswählen

Macro HANDLE_WM_CLOSE(hwnd, fn)
  ProcedureReturn fn(hwnd)
EndMacro


Macro HANDLE_MSG(hwnd, message, fn)
  Case #message : HANDLE_#message(hwnd, fn)
EndMacro  

;...

    Select Message
      HANDLE_MSG(WindowID, WM_CLOSE, main_onclose)
    Default
        ProcedureReturn Result
     EndSelect    
zu schreiben, anstatt

Code: Alles auswählen

    Select Message
      Case WM_Close
        ProcedureReturn main_onlose( hwnd)
    Default
        ProcedureReturn Result
     EndSelect
du ersetzt allen Ernstes nur "Case"+"ProcedureReturn" durch "HANDLE_", brauchst dafür aber ein Basis-Macro PLUS eins für jede Message.

also, das ist krytisches Rumgetippsel für nicht mal schreibfaule Heimlichtuer, sorry.

mit Copy/Paste wärst du schon tausendmal fertig, anstatt dich damit rumzuschlagen, wie du diese Macros übersetzen kannst.


PS:

also, das jetzt bitte nicht als Ignoranz erachten!

ich habe selber mehrere Jahre in C programmiert, und ich weiß sehr genau,
dass man manche Sache nur so schreibt wie man es schreibt weil man es kann und es kewl ist,
und nicht weil es einen wesentlich tiefer gehenden Nutzen hätte.


PPS:

davon ab, was spricht eigentlich gegen

Code: Alles auswählen

Macro HANDLE_MSG(hwnd, message, fn)
  Case #message :  ProcedureReturn #fn(hwnd)
EndMacro  
... mal davon abgesehen, dass ich nicht sicher bin, ob das Verknüpfungszeichen mit ner Leerstelle davon überhaupt funzt.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
galileo
Beiträge: 5
Registriert: 02.07.2009 14:12

Beitrag von galileo »

Sorry erst einmal, habe jetzt ein komplettes Beispiel, dass hoffentlich auch den Nutzen zeigt.

Code: Alles auswählen

Macro HiWord(Long)
  ((Long >> 16) & $FFFF)
EndMacro

Macro LoWord(Long)
  (Long & $FFFF)
EndMacro

Macro HANDLE_WM_CLOSE(hwnd, lParam, wParam, fn)
  ProcedureReturn fn(hwnd)
EndMacro

Macro HANDLE_WM_MOVE(hwnd, lParam, wParam, fn)
  ProcedureReturn fn(hwnd, LoWord(lParam), HiWord(lParam))
EndMacro

Macro HANDLE_MSG(hwnd, message, fn)
  Case #message : HANDLE_#message(hwnd, wParam, lParam, fn)
EndMacro  

Procedure main_onmove(hwnd, x, y)
  ;tue was
EndProcedure

Procedure main_onclose(hwnd)
  End
EndProcedure

Procedure Callback(WindowID, Message, wParam, lParam)
    Result = #PB_ProcessPureBasicEvents
    Select Message
      HANDLE_MSG(WindowID, WM_CLOSE, main_onclose) ; Ergebnis -> case #WM_CLOSE : Procedurereturn main_close( hwnd )
      HANDLE_MSG(WindowID, WM_MOVE, main_onmove)  ;Ergebnis -> case #WM_MOVE : ProcedureReturn main_move( hwnd, x, y)
    Default
        ProcedureReturn Result
     EndSelect   
  EndProcedure

 
If OpenWindow(0, 100, 100, 500,400, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  Textbox=StringGadget(0,  10, 10, 480, 380, "Codeguru is there!",#ES_AUTOVSCROLL|#WS_VSCROLL |#WS_HSCROLL)
EndIf

SetWindowCallback(@callback(),0)
Also im Parameter lParam verstecken sich die Cursorpostion x, y. So wollte ich die Ereignisroutinen aufbauen, das ich nicht erst überlegen muss, dass bei WM_CREATE sich die Struktur LPCREATESTRUCT usw verschlüsselt ist.

Aber trotzdem Danke, werde es wie vorgeschlagen machen. Immer 4 Parameter an die Ereignisprozeduren mit übergeben. Oder hat noch einer eine andere Idee?
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

> Immer 4 Parameter an die Ereignisprozeduren mit übergeben.

ja, das muss man halt machen, auch wenn's nur Dummies sind notfalls.

btw, die Structure POINT ist in PureBasic vorhanden, ebenso COORD, beides sind vordefinierte Structures.

du kannst dir mit StructureUnion einen Container basteln, um komfortabel umzuwandeln:

Code: Alles auswählen

Structure ContainerL
  StructureUnion
    V.l
    C.COORD
  EndStructureUnion
EndStructure

Define Cont.ContainerL
Define Test.ContainerL

Cont\C\X = 320
Cont\C\Y = 240

lParam = Cont\V

Test\V = lParam

Debug Test\C\X
Debug Test\C\Y
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

Dein Beispiel funktioniert mit PB v4.31 nicht wegen Macro nicht ersetzt.

Habe es mal anderes gelöst mit ein Macro, sowie das alle Parameters an die Procedure übergeben wird. Man kann auch den Zeiger auf den Parameterstack als Pointer übergeben.

Code: Alles auswählen

Macro HiWord(Long)
  ((Long >> 16) & $FFFF)
EndMacro

Macro LoWord(Long)
  (Long & $FFFF)
EndMacro


Structure udtArgs
  hWnd.i
  uMsg.i
  wParam.i
  lParam.i
EndStructure

Macro HANDLE_MSG(hwnd, message, fn)
  Case #message : ProcedureReturn fn#_on_#message(@hwnd)
EndMacro 

Procedure main_on_wm_move(*Args.udtArgs)
  
  Debug "x=" + Str(LoWord(*args\lParam))
  Debug "y=" + Str(HiWord(*args\lParam))
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure main_on_wm_close(*Args.udtArgs)
  Debug "Close"
  End
EndProcedure

Procedure Callback(WindowID, Message, wParam, lParam)
    Result = #PB_ProcessPureBasicEvents
    Select Message
      HANDLE_MSG(WindowID, WM_CLOSE, main) ; Ergebnis -> case #WM_CLOSE : Procedurereturn main_close(*Args)
      HANDLE_MSG(WindowID, WM_MOVE, main)  ;Ergebnis -> case #WM_MOVE : ProcedureReturn main_move(*Args)
    Default
        ProcedureReturn Result
     EndSelect   
  EndProcedure

 
If OpenWindow(0, 100, 100, 500,400, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  Textbox=StringGadget(0,  10, 10, 480, 380, "Codeguru is there!",#ES_AUTOVSCROLL|#WS_VSCROLL |#WS_HSCROLL)
EndIf

SetWindowCallback(@callback(),0)

Repeat
  WaitWindowEvent()
ForEver
FF :wink:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
galileo
Beiträge: 5
Registriert: 02.07.2009 14:12

Beitrag von galileo »

Danke mk-soft, eine tolle Lösung des Problems.

Zum Abschluss noch mal ein erweitertes Beispiel zum ausprobieren.

Code: Alles auswählen

Macro HiWord(Long)
  ((Long >> 16) & $FFFF)
EndMacro

Macro LoWord(Long)
  (Long & $FFFF)
EndMacro


Structure udtArgs
  hWnd.i
  uMsg.i
  wParam.i
  lParam.i
EndStructure

#IDM_TEST = 1
Global Textbox_1.l
Global Textbox_2.l

Macro HANDLE_MSG(hwnd, message, fn)
  Case #message : ProcedureReturn fn#_on_#message(@hwnd)
EndMacro

Procedure main_on_wm_create(*Args.udtArgs)
  Debug "wm_create"
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure main_on_wm_move(*Args.udtArgs)
  Debug "x=" + Str(LoWord(*args\lParam))
  Debug "y=" + Str(HiWord(*args\lParam))
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure main_on_wm_close(*Args.udtArgs)
  Debug "Close"
  End
EndProcedure

Procedure main_on_wm_setfocus(*Args.udtArgs)
  Debug "#WM_SETFOCUS_MAIN"
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure main_on_wm_killfocus(*Args.udtArgs)
  Debug "#WM_KILLFOCUS_MAIN"
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure main_on_wm_size(*Args.udtArgs)
  Debug "#WM_SIZE_MAIN"
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure main_on_wm_command(*Args.udtArgs)
  Debug "#WM_COMMAND"
  Debug "id des Steuerelements "+Str(LoWord(*args\wParam))
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure stringgadget1_on_wm_keydown(*Args.udtArgs)
  Debug "#WM_keydown_stringgadget1"
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure stringgadget2_on_wm_setfocus(*Args.udtArgs)
  Debug "#WM_SETFOCUS_stringgadget2"
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure


Procedure Callback(WindowID, Message, wParam, lParam)
    Result = #PB_ProcessPureBasicEvents
    Select Message

      HANDLE_MSG(WindowID, WM_CREATE, main)  ;wird nach CreateWindow gesendet, also von PureBasic nich weitergesendet ... richtig ?
      HANDLE_MSG(WindowID, WM_CLOSE, main) ; Ergebnis -> case #WM_CLOSE : Procedurereturn main_close(*Args)
      HANDLE_MSG(WindowID, WM_MOVE, main)  ;Ergebnis -> case #WM_MOVE : ProcedureReturn main_move(*Args)
      HANDLE_MSG(WindowID, WM_SETFOCUS, main)
      HANDLE_MSG(WindowID, WM_COMMAND, main)  
      HANDLE_MSG(WindowID, WM_KILLFOCUS, main)
      HANDLE_MSG(WindowID, WM_SIZE, main)

      HANDLE_MSG(WindowID, WM_KEYDOWN, stringgadget1)  
      HANDLE_MSG(WindowID, WM_SETFOCUS, stringgadget2)  

    Default
        ProcedureReturn Result
     EndSelect   
  EndProcedure

 
If OpenWindow(0, 100, 100, 500,400, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  Textbox_1=StringGadget(1,  10, 10, 400, 80, "Codeguru is there!",#ES_AUTOVSCROLL|#WS_VSCROLL |#WS_HSCROLL)
  Textbox_2=StringGadget(2,  10, 100, 400, 80, "Codeguru is there!",#ES_AUTOVSCROLL|#WS_VSCROLL |#WS_HSCROLL)
EndIf

SetWindowCallback(@callback(),0)

Repeat
  event.l = WaitWindowEvent()
  If event = #PB_Event_Gadget
    If EventGadget() = 1
      If EventType() = #PB_EventType_Focus
        SetGadgetText(1,"Neuer Text")
      EndIf  
    EndIf  
  EndIf
ForEver 
Hinweise, Kritiken erwünscht. :|
Antworten