Callback

Just starting out? Need help? Post your questions and find answers here.
User avatar
Zizaco
User
User
Posts: 26
Joined: Tue May 16, 2006 8:20 pm
Contact:

Callback

Post by Zizaco »

What is the Callback parameters?
"(hWnd, Msg, wParam, lParam)" what means each one?

Im trying to make a windows "waitevent" in a callback, to use in a .DLL
Can someone help me with that?

To make a callback function instead of a main loop.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Having a 'waitevent' in a callback doesn't really (depending on exactly what it is you're trying to do?) make sense because you have no control over when the callback is called; that is Window's job in conjunction with your message retrieval loop.

Now, standard Purebasic code hides the GetMessage/DespatchMessage construct behind the WaitWindowEvent() command and it really wouldn't make sense to place this within a callback.

The window who's events you wish to process, is it created inside or outside of the dll?
I may look like a mule, but I'm not a complete ass.
milan1612
Addict
Addict
Posts: 894
Joined: Thu Apr 05, 2007 12:15 am
Location: Nuremberg, Germany
Contact:

Post by milan1612 »

hWnd = the handle of the window/gadget
Msg = the arriving message
wParam = message-specific parameter
lParam = message-specific parameter

And now: time for the professionals :lol: :lol: :lol:
Windows 7 & PureBasic 4.4
User avatar
Zizaco
User
User
Posts: 26
Joined: Tue May 16, 2006 8:20 pm
Contact:

Post by Zizaco »

The window who's events you wish to process, is it created inside or outside of the dll?
Inside. :(

I will explain what im trying to do. Maybe you knows a better way to do it.

I have an application in a 3D engine, and it needs to have some windows to control the options. These windows should been made in WinApi. So i chose the PB for it.
So i have a DLL with procedures like, InitWindows() and LoopWindows().
The LoopWindows() is a function to process al the events, my idea was to put the LoopWindows() function in the 3D application main loop. But it didn't works cause it makes the window dont respond to every command.

Now im trying to make a callback to run the LoopWindows() only when needed.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

This is an all-API solution, if that's what you're looking for:

Code: Select all

Procedure WindowCallback(Window, Message, wParam, lParam) 
  Select Message 
    Case #WM_CLOSE 
      If MessageBox_(Window, "You sure?", "EXIT", #MB_YESNO) = #IDYES 
        DestroyWindow_(Window) 
      Else 
        Result  = 0 
      EndIf 
    Case #WM_DESTROY 
      PostQuitMessage_(0) 
      Result  = 0 
    Default 
      Result  = DefWindowProc_(Window, Message, wParam, lParam) 
  EndSelect 
  ProcedureReturn Result 
EndProcedure 

#Style  = #WS_VISIBLE | #WS_CAPTION | #WS_SYSMENU 
WindowClass.s  = "Button" 
wc.WNDCLASSEX 
wc\cbSize  = SizeOf(WNDCLASSEX) 
wc\hbrBackground = CreateSolidBrush_(GetSysColor_(#COLOR_BTNFACE))
wc\hCursor = LoadCursor_(0, #IDC_ARROW)
wc\lpfnWndProc  = @WindowCallback() 
wc\lpszClassName  = @WindowClass 
RegisterClassEx_(@wc) 

screenx = GetSystemMetrics_(#SM_CXSCREEN)/2-320/2
screeny = GetSystemMetrics_(#SM_CYSCREEN)/2-240/2


hWndMain  = CreateWindowEx_(0, WindowClass, "Test-Window", #Style, screenx, screeny, 320, 240, 0, 0, 0, 0) 

While GetMessage_(msg.MSG, #Null, 0, 0 ) 
  TranslateMessage_(msg) 
  DispatchMessage_(msg) 
Wend 
Adapted from various codes found on this forum and PureArea.net
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

I'm not really sure I understand.

If you're using win api to create the windows (rather than native Purebasic commands) then, by a callback you mean a Window Procedure (and not using SetWindowCallback() which is only for windows created by PB commands).

Window's created in a dll can be a little fiddly when it comes to the main application recognising the window and visa versa if the windows are created using PB commands.

Try the following example. you'll see that when the dll window is open, you cannot close the main window until after you close the dll one.

In my next post I'll give a better version using a callback:

Compile to "test.dll"

Code: Select all

ProcedureDLL OpenWinDll()
  OpenWindow(0, 0, 0, 230, 90, "Window from dll", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    CreateGadgetList(WindowID(0))
    ButtonGadget  (1, 10, 10, 200, 20, "Click me")
    Repeat
    Event = WaitWindowEvent()
     
     Select Event
     
       Case #PB_Event_Gadget
         Select EventGadget()
           Case 1
            MessageRequester("Hi!", "Hello from dll!")
         EndSelect
       
     EndSelect
   Until Event = #PB_Event_CloseWindow
   CloseWindow(0)
EndProcedure
Compile to "test.exe"

Code: Select all

If OpenLibrary(0, "test.dll")
  OpenWindow(0, 0, 0, 230, 90, "Demo", #PB_Window_SystemMenu)
    CreateGadgetList(WindowID(0))
    ButtonGadget  (1, 10, 10, 200, 20, "Click me")
    Repeat
    Event = WaitWindowEvent()
     
     Select Event
       Case #PB_Event_Gadget
         Select EventGadget()
           Case 1
            CallFunction(0, "OpenWinDll")
         EndSelect
       
     EndSelect
   Until Event = #PB_Event_CloseWindow

    CloseLibrary(0)

  EndIf

A better example will follow... :)
I may look like a mule, but I'm not a complete ass.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Second example.

This one uses a callback in the dll to process windows messages for the window opened in the dll.

This allows the main application to continue running and processing events whilst the dll window remains open. Try it, compile the dll and run the client program. Click the button and this time you'll be able to close the main window whilst the dll one remains open.

"test.dll

Code: Select all

Procedure.l MyCallback(hWnd, uMsg, wParam, lParam)
  Result = #PB_ProcessPureBasicEvents
  Select uMsg
    Case #WM_CLOSE
      CloseWindow(0)
      result=0
    Case #WM_COMMAND
      If wParam>>16=#BN_CLICKED 
        MessageRequester("Hi!", "Hello from dll!")
      EndIf 
  EndSelect
  ProcedureReturn result
EndProcedure

ProcedureDLL OpenWinDll()
  OpenWindow(0, 0, 0, 230, 90, "Window from dll", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    CreateGadgetList(WindowID(0))
    ButtonGadget  (1, 10, 10, 200, 20, "Click me")
    SetWindowCallback(@MyCallback(),0)
EndProcedure
"test.pb"

Code: Select all

If OpenLibrary(0, "test.dll")
  OpenWindow(0, 0, 0, 230, 90, "Demo", #PB_Window_SystemMenu)
    CreateGadgetList(WindowID(0))
    ButtonGadget  (1, 10, 10, 200, 20, "Click me")
    Repeat
    Event = WaitWindowEvent()
     
     Select Event
       Case #PB_Event_Gadget
         Select EventGadget()
           Case 1
            CallFunction(0, "OpenWinDll")
         EndSelect
       
     EndSelect
   Until Event = #PB_Event_CloseWindow

    CloseLibrary(0)
  EndIf
If you prefer to use api to open the window in the dll then you'll simply need to combine this (with a few alterations) with netmaestro's code above.

Personally I tend to always use callbacks rather than Purebasic event loops anyhow. More flexible.
I may look like a mule, but I'm not a complete ass.
User avatar
Zizaco
User
User
Posts: 26
Joined: Tue May 16, 2006 8:20 pm
Contact:

Post by Zizaco »

I'm not really sure I understand.
Sorry for my bad inglish, i will reformulate the question:

I have an application, made in a 3D engine. (irrilich per example.)
The 3d application doesn't have a WaitWindowsEvent(), it just have a main loop that doesn't wait nothing.

This aplication needs a interface to give to the user the controls, A interface in form of Windows

I chose the PureBasic for it. Now i'm using the native purebasic commands to create that windows.
Now every command button or radio in the windows created should affect the 3D application.

The 3D application structure is something like this:

Code: Select all

StartTheNeededThings

InitTheDLL()

MainLoop
    
    Result=ReciveAnswerFromDLL()

    ReactUsingResult(Result)

    RefreshGraphics()

EndLoop

End
The Init the DLL loads the dll and open the windows.
The ReciveAnswerFromDLL is a function in the DLL that will return the last action done, Example: "0=Nothing 1=Changed Resolution, 2=Move Forward, 3=TurnRight" etc
Then the ReactUsingResult will make the result happen in the application.


Until here no problem, but here comes the pain.

When i call the dll, it starts perfectly, but it doesn't refresh after that. No Re-Draw, No Button Clicks, Nothing! Cause the only way to make the window reacts is through a callback inside the DLL (i think).
I need to do the dll have it's own reactions, when the users clicks on it, and the 3D applications needs to still running the loop.

It's like a WaitWindowEvent() select inside the callback.

But its important to denote that the netmaestro example uses a callback to react in a fully WinApi Commands based window.

So how can i get the EventGadget(), EventType() of an occured event inside a callback?[/code]
User avatar
Zizaco
User
User
Posts: 26
Joined: Tue May 16, 2006 8:20 pm
Contact:

Post by Zizaco »

Any ideas?
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Right, my last attempt to figure out what it is you want! :wink:

If you wish to open a window in a dll, but have the main application respond to events in the dll window, then you're better of sticking the callback in the main application.

Now because the following uses PB commands in the dll to open the window, there may be a small memory leak. This is because the dll uses it's own memory to store info on open windows etc. and the main application will not see this data and has no access to the dll's Window#'s etc. I can get around this, but the best way would be to use native win api in the dll to create the windows and controls etc.

'test.dll'

Code: Select all

ProcedureDLL OpenWinDll(callbackaddress) 
  MainWinProc = callbackaddress
  OpenWindow(0, 0, 0, 230, 90, "Window from dll", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) 
    CreateGadgetList(WindowID(0)) 
    ButtonGadget  (1, 10, 10, 200, 20, "Click me") 
    oldcallback = GetWindowLong_(WindowID(win), #GWL_WNDPROC) 
    SetProp_(WindowID(win), "__oldProc", oldcallback)
    SetWindowLong_(WindowID(win), #GWL_WNDPROC, callbackaddress) 
EndProcedure 
'client.pb'

Code: Select all

Procedure.l MyCallback(hWnd, uMsg, wParam, lParam) 
  oldproc = GetProp_(hWnd, "__oldProc")
  Select uMsg 
    Case #WM_CLOSE
      DestroyWindow_(hWnd)

    Case #WM_NCDESTROY
      RemoveProp_(hWnd, "__oldProc")


    Case #WM_COMMAND 
      If wParam>>16=#BN_CLICKED 
        MessageRequester("Hi!", "Hello from Main program!") 
      EndIf 
      result = CallWindowProc_(oldproc, hWnd, uMsg, wParam, lParam)
    Default
      result = CallWindowProc_(oldproc, hWnd, uMsg, wParam, lParam)


  EndSelect 
  ProcedureReturn result 
EndProcedure 


If OpenLibrary(0, "test.dll")
  OpenWindow(0, 0, 0, 230, 90, "Demo", #PB_Window_SystemMenu)
    CreateGadgetList(WindowID(0))
    ButtonGadget  (1, 10, 10, 200, 20, "Click me")
    Repeat
    Event = WaitWindowEvent()
     
     Select Event
       Case #PB_Event_Gadget
         Select EventGadget()
           Case 1
            CallFunction(0, "OpenWinDll", @MyCallback())
         EndSelect
       
     EndSelect
   Until Event = #PB_Event_CloseWindow

    CloseLibrary(0)

  EndIf
If this doesn't help, then I give up and I'm going to join the French foreign legion! :)
I may look like a mule, but I'm not a complete ass.
kinglestat
Enthusiast
Enthusiast
Posts: 746
Joined: Fri Jul 14, 2006 8:53 pm
Location: Malta
Contact:

Post by kinglestat »

I dont think there is another foreign legion besides the french one!
thats to say the topic was mostly over my head....so this is my only contribution alas
User avatar
aston
User
User
Posts: 64
Joined: Wed Nov 18, 2009 11:18 pm

Re: Callback

Post by aston »

I know that this post is old but i read somewhere on forum that:
WaitWindowEvent hide API GetMessage/DispatchMessage functions.
As i know and see WaitWindowEvent return Message,right?

So my question is how look in a API way this WaitWindowEvent function/procedure..
because there is no default return of DefWindowProc hwnd,wMsg,wParam,lParam.
Any ideas?
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Callback

Post by netmaestro »

You can't return anything in response to a message received in a WaitWindowEvent() loop, however you can examine wParam and lParam with EventWparam() and EventlParam(). Also bear in mind that not all of the messages received in a callback will appear in the PB loop. Best approach is to use either all API or all PureBasic event processing.
BERESHEIT
User avatar
aston
User
User
Posts: 64
Joined: Wed Nov 18, 2009 11:18 pm

Re: Callback

Post by aston »

Thanks...
no i understand that i cannot return nothing to loop,of course but as i said
I am interested what kind of API functions contain PB function WaitWindowEvent
and it is obvious that WaitWindowEvent return event (message),right?

I really will appreciate if someone can explain me this method with pure APi coding.

thanks... :D
Post Reply