Announcement

Collapse
No announcement yet.

Passing parameters to Dialog Callbacks

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Bern Ertl
    replied
    OK. Thanks everyone. I think I've got a handle on it now.



    ------------------
    Bernard Ertl

    Leave a comment:


  • Lance Edmonds
    replied
    No, since their value is known at compile time, the compiler should be able to optimize things nicely!


    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Borje Hagsten
    replied
    Ah, now I understand (finally)..

    As for equates - doesn't that take away the memory advantage of using
    bitmask? Here is little sample that shows how easy and clean it can be:
    (once a good tip from you Lance, as always, and I thank you for it - I
    often use this way nowadays)
    Code:
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Example of how to use one global variable to store settings for
    ' a bunch of checkboxes, via BIT statement/function.
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    #COMPILE EXE
    #INCLUDE "WIN32API.INC"
    GLOBAL chk AS LONG
     
    DECLARE CALLBACK FUNCTION DlgProc() AS LONG
    DECLARE CALLBACK FUNCTION DlgProc2() AS LONG
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Create dialog and controls, etc
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    FUNCTION PBMAIN () AS LONG
      LOCAL hDlg AS LONG
      DIALOG NEW 0, "Main Dlg",,, 70, 22, %WS_CAPTION OR %WS_SYSMENU TO hDlg
      CONTROL ADD BUTTON, hDlg, 10, "Settings..", 5,  5, 60, 14, %WS_TABSTOP
      BIT SET chk, 0 : BIT SET chk, 2 : BIT SET chk, 5 '<- sample: pre-set some bits at startup
      DIALOG SHOW MODAL hDlg CALL DlgProc              '   for the checkboxes in Setup dlg.
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Main callback
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    CALLBACK FUNCTION DlgProc() AS LONG
      IF CBMSG = %WM_COMMAND THEN
         IF CBCTL = 10 THEN       'create and show settings dialog
            LOCAL hDlg2 AS LONG, I AS LONG
            DIALOG NEW CBHNDL, "Settings",,, 80, 150, %WS_CAPTION OR %WS_SYSMENU TO hDlg2
            FOR I = 0 TO 11
               CONTROL ADD CHECKBOX, hDlg2, I + 30, "Check" + STR$(I + 1), 5,  I * 12 + 4, 60, 12, %WS_TABSTOP
               CONTROL SET CHECK hDlg2, I + 30, BIT(chk, I) '<- get settings from variable's different bits
            NEXT I
            DIALOG SHOW MODAL hDlg2 CALL DlgProc2
         END IF
      END IF
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Main callback for dialog 2
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    CALLBACK FUNCTION DlgProc2() AS LONG
      IF CBMSG = %WM_DESTROY THEN
         LOCAL I AS LONG, lRes AS LONG
         FOR I = 0 TO 11
            CONTROL GET CHECK CBHNDL, I + 30 TO lRes  'get checkbox settings
            IF lRes THEN
               BIT SET chk, I  'store all settings in variable's different bits
            ELSE
               BIT RESET chk, I
            END IF
         NEXT I
      END IF
    END FUNCTION

    ------------------

    Leave a comment:


  • Lance Edmonds
    replied
    Borje, we seem to be talking at cross-purposes. When discussing the blocking operation of DIALOG SHOW MODAL, I'm referring to the section of code that creates the dialog, not the actual operation of the callbacks.

    The BIT array technique is a good one - it can work on a block of data of up to approx 2 billion bits!. Tracking the definition of the individual bits is easy with equates...
    Code:
    %Flag1 = 0
    %Flag2 = 1
    ...
    %Flag2147483647 = 2147483646
       
    DIM lValue1 AS LONG
    DIM lValue2(0:2147483647 \ 8) ' give or take 1!   [img]http://www.powerbasic.com/support/forums/wink.gif[/img]
    IF BIT(lValue1, %Flag1) THEN <DoSomething>
    IF BIT(lValue2(0), %Flag2147483647) THEN <DoSomethingElse>
    This is off the top of my head without a manual nearby, so the format of the second IF..THEN line may need minor alteration.

    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Borje Hagsten
    replied
    So in theory, the sample above - where two modal DDT dialogs send
    messages to each other - sholdn't work? Think this is over my head,
    so better leave it at that..

    To return to original subject: Bern, something I like to do in large
    app's is to use a type declared structure to hold global data. Have
    found this to be much cleaner and easier to maintain and use.
    One global, nothing more - like:
    Code:
    TYPE DLGDATA
      hWnd   AS LONG
      hInst  AS LONG
      value1 AS LONG
      value2 AS LONG
      value3 AS LONG 'etc, whatever I need
    END TYPE
    GLOBAL dd AS DLGDATA
    Then I have access to dd.hWnd, etc. all over the program and I can
    easily add members when/if I need more, without cluttering the code
    with lots of globals. Sort of puts them all under the same roof.

    Tip2 is one Lance once gave me. If you need to keep track of many 0 and 1
    values (like for check- or option controls), one LONG can hold 32 values
    via for example the BIT statement/function. Good way to optimize memory
    usage, but it can be a "bit" messy to keep track of what bit belongs to
    what value..


    ------------------

    Leave a comment:


  • Lance Edmonds
    replied
    Originally posted by Borje Hagsten:
    When is a DDT message loop suspended? Maybe I have misunderstood, but..
    The DIALOG SHOW MODAL statement is a "blocking" statement - internally it executes a message pump loop. The section of code that uses this statement is "suspended" until the target Dialog is dismissed, and the DIALOG SHOW MODAL statement completes execution.



    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Semen Matusovski
    replied
    Indirect call w/o subclassing
    Code:
    CallWindowProc CodePtr(DlgProc), x&, %WM_USER + 999&, 0, 0
    Direct call w/o subclassing
    Code:
    Dim y As Dword
    y = CodePtr(DlgProc)
    Call Dword y Using DefWindowProc(x&, %WM_USER + 999&, 0, 0)


    ------------------
    E-MAIL: [email protected]

    Leave a comment:


  • Borje Hagsten
    replied
    When is a DDT message loop suspended? Maybe I have misunderstood, but..
    Code:
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Declares
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    #COMPILE EXE
    #INCLUDE "WIN32API.INC"
     
    GLOBAL hDlg AS LONG
    DECLARE CALLBACK FUNCTION DlgProc() AS LONG
    DECLARE CALLBACK FUNCTION DlgProc2() AS LONG
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Create dialog and controls, etc
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    FUNCTION PBMAIN () AS LONG
      LOCAL hTimer AS LONG
      DIALOG NEW 0, "Modal 1..",,, 200, 50, %WS_CAPTION OR %WS_SYSMENU TO hDlg
      CONTROL ADD BUTTON, hDlg, 10, "Button",    4,  4, 60, 14, %WS_TABSTOP
      hTimer = SetTimer(hDlg, 11, 1000, BYVAL %NULL )
      DIALOG SHOW MODAL hDlg CALL DlgProc
      KillTimer hDlg, hTimer
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Main callback
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    CALLBACK FUNCTION DlgProc() AS LONG
      STATIC I AS LONG
      IF CBMSG = %WM_COMMAND THEN
         IF CBCTL = 10 THEN
            STATIC hDlg2 AS LONG
            DIALOG NEW CBHNDL, "Modal 2..",,, 70, 20, %WS_CAPTION OR %WS_SYSMENU TO hDlg2
            CONTROL ADD BUTTON, hDlg2, 20, "Button", 4,  4, 60, 14, %WS_TABSTOP
            DIALOG SHOW MODAL hDlg2 CALL DlgProc2
            hDlg2 = 0
         END IF
     
      ELSEIF CBMSG = %WM_TIMER THEN     '<- Send to 2:nd modal dialog
         IF hDlg2 THEN SendMessage hDlg2, %WM_USER + 1, 0, 0
     
      ELSEIF CBMSG = %WM_USER + 1 THEN  '<- receive from 2:nd modal dialog
         INCR I
         CONTROL SET TEXT CBHNDL, 10, "Clicked" & STR$(I)
         BEEP
      END IF
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Main callback for dialog 2
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    CALLBACK FUNCTION DlgProc2() AS LONG
      STATIC J AS LONG
      IF CBMSG = %WM_COMMAND THEN
         IF CBCTL = 20 THEN             '<- send to 1:st modal dialog
            SendMessage hDlg, %WM_USER + 1, 0, 0
         END IF
     
      ELSEIF CBMSG = %WM_USER + 1 THEN  '<- received from 1:st modal dialog's timer
         INCR J
         CONTROL SET TEXT CBHNDL, 20, "Clicked" & STR$(J)
         SendMessage hDlg, %WM_USER + 1, 0, 0  '<- send back to 1:st modal dialog
      END IF
    END FUNCTION

    ------------------

    Leave a comment:


  • Lance Edmonds
    replied
    Ok, I see where YOU are coming from now too! No, you can't queue a non-queued message.

    I guess I should have been a little clearer. Yes, if you wish to pass (non-control) "data" to a modal dialog ahead of the DIALO SHOW MODAL statement, you'll have to jump through a few hoops with either using global variables, or using hidden controls.

    Simple manipulations of controls (size, text, location, etc) can be done ahead of DIALOG SHOW MODAL, but once that DIALOG SHOW MODAL executes, the main code is suspended until the dialog is dismissed.

    Using a modeless dialog is the easiest solution by far, but how can you do it with a MODAL dialog?

    Subclassing the dialog is one possible way, since you can use a specific callback ahead of the DIALOG SHOW MODAL.

    Here is a very simplistic example, but hopefully it may give you some ideas...
    Code:
    #COMPILE EXE
    #INCLUDE "win32api.inc"
     
    %Btn1 = 100
    GLOBAL OldProc&
     
    CALLBACK FUNCTION cb
        IF CBMSG = %WM_USER + 999& THEN
            CONTROL SET TEXT CBHNDL, %Btn1, "Set in &Subclass"
            CONTROL SET SIZE CBHNDL, %Btn1, 50, 14
     
        ELSEIF CBMSG = %WM_DESTROY THEN
            SetWindowLong x&, %GWL_WNDPROC, OldProc&
     
        ELSEIF CBMSG = %WM_COMMAND AND CBCTL = %Btn1 THEN
            DIALOG END CBHNDL, 1
     
        END IF
    
        FUNCTION = DefDlgProc(CBHNDL, CBMSG, CBWPARAM, CBLPARAM)
    END FUNCTION
     
    FUNCTION PBMAIN
        DIM x&, y&
        DIALOG NEW 0, "test",,,100,100, %WS_SYSMENU TO x&
        OldProc& = SetWindowLong(x&, %GWL_WNDPROC, CODEPTR(CB))
        CONTROL ADD BUTTON, x&, 100&, "", 10, 10, 5,5 ' empty 5x5 button
        DIALOG SEND x&, %WM_USER + 999&, 0, 0 ' trigger our subclass proc
        DIALOG SHOW MODAL x& ' no callback in this simple case, just use the subclass
    END FUNCTION


    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Bern Ertl
    replied
    OK. Now I see where you are coming from. I put all the CONTROL ADD
    statements in the WM_INIT handler of the dialog proc. I'd have to move
    them (copies of them) into each SUB which could use that dialog (proc).

    How does the execution flow work for posting/sending messages to a control
    / dialog before the dialog is associated with a callback procedure? Are the
    messages just queued up until the DIALOG SHOW statement?



    ------------------
    Bernard Ertl

    Leave a comment:


  • Lance Edmonds
    replied
    You can use CONTROL SEND and DIALOG SEND immediately after each control is created, and before the DIALOG SHOW.

    Try it... it works!



    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Bern Ertl
    replied
    Hi Lance,

    I'm not using any threads, so once I execute a DIALOG SHOW MODAL
    statement, control passes to the dialog/callback and I cannot
    send/post messages to it. Or can I??

    So far, I'm mostly passing flags (yes/no) through checkboxes. For
    instance, I've created a "generic" dialog which can be called by
    several different SUBs in my app. Depending on which SUB is calling
    it, I want to use different defaults. I'll set a flag to indicate
    which defaults to use.

    Are additional messages generated for a callback Fn for disabled (and
    invisible) controls?



    ------------------
    Bernard Ertl

    Leave a comment:


  • Lance Edmonds
    replied
    When you send a message (SendMessage or Control Send/Dialog Send), Windows actually performs an indirect call to the appropriate callback function (that is, it does not create a queued message, but the call is made to the callback and returns a value to the calling code). PostMessage does create a queued message and does not return a value to the calling code.

    In either case, whether the dialog is modal or modeless is totally irrelevent.

    If you are using controls just to hold or pass data, then the overhead will be significantly higher than using global variables, since each of these controls will be using GDI resources, memory, etc, and very likely contribute to the number of callback messages that are generated (slowing the app slightly).

    How much additional overhead is difficult to measure, but even a simple tool like Win2K's TaskManager can help you count memory and GDI object usage.

    Finally, you may be able to use Window Properties to hold data (see SetProp(), GetProp(), etc). However, sending custom messages is still the easiest way to pass data to a callback and/or subclass/superclass function.

    Alternatively, %WM_COPYDATA may work weel for you too, although it is really designed for inter-process communication.

    So, what sort of data are you passing/storing? If we knew more, maybe we could offer more specific suggestions.

    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Bern Ertl
    replied
    OK. Thanks Lance. I suppose that approach will only work for
    MODELESS dialogs...

    Any idea how much overhead I'm carrying using hidden checkboxes
    / labels / textboxes versus GLOBAL vars?



    ------------------
    Bernard Ertl

    Leave a comment:


  • Lance Edmonds
    replied
    Personally, I prefer to send/post custom messages. ie,
    Code:
    DIALOG SEND hDlg, %WM_USER + 999&, wparam&, lparam&
    or 
    PostMessage hDlg, %WM_USER + 999&, wparam&, lparam&
    and in the callback:
    Code:
    SELECT CASE CBMSG
      CASE %WM_USER + 999&
        ' do something with CBWPARAM and CBLPARAM
    ...
    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Bern Ertl
    started a topic Passing parameters to Dialog Callbacks

    Passing parameters to Dialog Callbacks

    I have started creating hidden controls (size 0, disabled) in
    order to pass flags & data to dialogs. After the DIALOG NEW,
    I'll add the controls, set data in them and then DIALOG SHOW.
    It appears to be working just fine, but I'd appreciate any
    feedback if there is any potential problems with doing this.

    Sometimes this approach makes more sense to me than using GLOBALs.



    ------------------
    Bernard Ertl
Working...
X