Page 1 of 1

Callback

Posted: Tue Jul 10, 2007 8:56 pm
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.

Posted: Tue Jul 10, 2007 9:10 pm
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?

Posted: Tue Jul 10, 2007 9:12 pm
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:

Posted: Tue Jul 10, 2007 9:38 pm
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.

Posted: Tue Jul 10, 2007 9:50 pm
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

Posted: Tue Jul 10, 2007 9:56 pm
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... :)

Posted: Tue Jul 10, 2007 10:07 pm
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.

Posted: Wed Jul 11, 2007 2:52 pm
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]

Posted: Fri Jul 13, 2007 12:29 pm
by Zizaco
Any ideas?

Posted: Fri Jul 13, 2007 1:18 pm
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! :)

Posted: Fri Jul 13, 2007 9:42 pm
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

Re: Callback

Posted: Mon Sep 17, 2012 12:27 am
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?

Re: Callback

Posted: Mon Sep 17, 2012 12:42 am
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.

Re: Callback

Posted: Mon Sep 17, 2012 12:58 pm
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